OSDN Git Service

first commit
authorquiver2k <quiver2k@users.sourceforge.jp>
Sun, 7 Jun 2009 05:48:26 +0000 (14:48 +0900)
committerquiver2k <quiver2k@users.sourceforge.jp>
Sun, 7 Jun 2009 05:48:26 +0000 (14:48 +0900)
37 files changed:
jp.sourceforge.moreemacs.test/.classpath [new file with mode: 0755]
jp.sourceforge.moreemacs.test/.project [new file with mode: 0755]
jp.sourceforge.moreemacs.test/.settings/org.eclipse.jdt.core.prefs [new file with mode: 0755]
jp.sourceforge.moreemacs.test/META-INF/MANIFEST.MF [new file with mode: 0755]
jp.sourceforge.moreemacs.test/build.properties [new file with mode: 0755]
jp.sourceforge.moreemacs.test/src/jp/sourceforge/moreemacs/utils/CharacterUtilsTest.java [new file with mode: 0755]
jp.sourceforge.moreemacs/.classpath [new file with mode: 0755]
jp.sourceforge.moreemacs/.project [new file with mode: 0755]
jp.sourceforge.moreemacs/.settings/org.eclipse.jdt.core.prefs [new file with mode: 0755]
jp.sourceforge.moreemacs/LICENCE.txt [new file with mode: 0755]
jp.sourceforge.moreemacs/META-INF/MANIFEST.MF [new file with mode: 0755]
jp.sourceforge.moreemacs/build.properties [new file with mode: 0755]
jp.sourceforge.moreemacs/plugin.xml [new file with mode: 0755]
jp.sourceforge.moreemacs/src/jp/sourceforge/moreemacs/MoreEmacs.java [new file with mode: 0755]
jp.sourceforge.moreemacs/src/jp/sourceforge/moreemacs/handlers/BackwardKillWordExecution.java [new file with mode: 0755]
jp.sourceforge.moreemacs/src/jp/sourceforge/moreemacs/handlers/BackwardWordExecution.java [new file with mode: 0755]
jp.sourceforge.moreemacs/src/jp/sourceforge/moreemacs/handlers/CommandHandler.java [new file with mode: 0755]
jp.sourceforge.moreemacs/src/jp/sourceforge/moreemacs/handlers/Cursor.java [new file with mode: 0755]
jp.sourceforge.moreemacs/src/jp/sourceforge/moreemacs/handlers/DeleteHorizontalSpaceExecution.java [new file with mode: 0755]
jp.sourceforge.moreemacs/src/jp/sourceforge/moreemacs/handlers/Execution.java [new file with mode: 0755]
jp.sourceforge.moreemacs/src/jp/sourceforge/moreemacs/handlers/ForwardWordExecution.java [new file with mode: 0755]
jp.sourceforge.moreemacs/src/jp/sourceforge/moreemacs/handlers/KillLineExecution.java [new file with mode: 0755]
jp.sourceforge.moreemacs/src/jp/sourceforge/moreemacs/handlers/KillRectangleExecution.java [new file with mode: 0755]
jp.sourceforge.moreemacs/src/jp/sourceforge/moreemacs/handlers/KillWordExecution.java [new file with mode: 0755]
jp.sourceforge.moreemacs/src/jp/sourceforge/moreemacs/handlers/MoveBeginningOfLineExecution.java [new file with mode: 0755]
jp.sourceforge.moreemacs/src/jp/sourceforge/moreemacs/handlers/MoveEndOfLineExecution.java [new file with mode: 0755]
jp.sourceforge.moreemacs/src/jp/sourceforge/moreemacs/handlers/OpenLineExecution.java [new file with mode: 0755]
jp.sourceforge.moreemacs/src/jp/sourceforge/moreemacs/handlers/RectangleExecution.java [new file with mode: 0755]
jp.sourceforge.moreemacs/src/jp/sourceforge/moreemacs/handlers/TextEditorExecution.java [new file with mode: 0755]
jp.sourceforge.moreemacs/src/jp/sourceforge/moreemacs/handlers/TransposeCharsExecution.java [new file with mode: 0755]
jp.sourceforge.moreemacs/src/jp/sourceforge/moreemacs/handlers/TransposeWordsExecution.java [new file with mode: 0755]
jp.sourceforge.moreemacs/src/jp/sourceforge/moreemacs/handlers/YankRectangleExecution.java [new file with mode: 0755]
jp.sourceforge.moreemacs/src/jp/sourceforge/moreemacs/utils/CharacterUtils.java [new file with mode: 0755]
jp.sourceforge.moreemacs/src/jp/sourceforge/moreemacs/utils/CodePointIterator.java [new file with mode: 0755]
jp.sourceforge.moreemacs/src/jp/sourceforge/moreemacs/utils/ColumnUtils.java [new file with mode: 0755]
jp.sourceforge.moreemacs/src/jp/sourceforge/moreemacs/utils/DocumentCharSequence.java [new file with mode: 0755]
jp.sourceforge.moreemacs/src/jp/sourceforge/moreemacs/utils/DocumentTransaction.java [new file with mode: 0755]

diff --git a/jp.sourceforge.moreemacs.test/.classpath b/jp.sourceforge.moreemacs.test/.classpath
new file mode 100755 (executable)
index 0000000..8a8f166
--- /dev/null
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<classpath>\r
+       <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>\r
+       <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>\r
+       <classpathentry kind="src" path="src"/>\r
+       <classpathentry kind="output" path="bin"/>\r
+</classpath>\r
diff --git a/jp.sourceforge.moreemacs.test/.project b/jp.sourceforge.moreemacs.test/.project
new file mode 100755 (executable)
index 0000000..b162ec4
--- /dev/null
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<projectDescription>\r
+       <name>jp.sourceforge.moreemacs.test</name>\r
+       <comment></comment>\r
+       <projects>\r
+       </projects>\r
+       <buildSpec>\r
+               <buildCommand>\r
+                       <name>org.eclipse.jdt.core.javabuilder</name>\r
+                       <arguments>\r
+                       </arguments>\r
+               </buildCommand>\r
+               <buildCommand>\r
+                       <name>org.eclipse.pde.ManifestBuilder</name>\r
+                       <arguments>\r
+                       </arguments>\r
+               </buildCommand>\r
+               <buildCommand>\r
+                       <name>org.eclipse.pde.SchemaBuilder</name>\r
+                       <arguments>\r
+                       </arguments>\r
+               </buildCommand>\r
+       </buildSpec>\r
+       <natures>\r
+               <nature>org.eclipse.pde.PluginNature</nature>\r
+               <nature>org.eclipse.jdt.core.javanature</nature>\r
+       </natures>\r
+</projectDescription>\r
diff --git a/jp.sourceforge.moreemacs.test/.settings/org.eclipse.jdt.core.prefs b/jp.sourceforge.moreemacs.test/.settings/org.eclipse.jdt.core.prefs
new file mode 100755 (executable)
index 0000000..db8c259
--- /dev/null
@@ -0,0 +1,7 @@
+#Thu Jun 04 00:56:56 JST 2009\r
+eclipse.preferences.version=1\r
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6\r
+org.eclipse.jdt.core.compiler.compliance=1.6\r
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error\r
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error\r
+org.eclipse.jdt.core.compiler.source=1.6\r
diff --git a/jp.sourceforge.moreemacs.test/META-INF/MANIFEST.MF b/jp.sourceforge.moreemacs.test/META-INF/MANIFEST.MF
new file mode 100755 (executable)
index 0000000..c60f676
--- /dev/null
@@ -0,0 +1,9 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Test fragment
+Bundle-SymbolicName: jp.sourceforge.moreemacs.test
+Bundle-Version: 1.0.0
+Bundle-Vendor: quiver2k
+Fragment-Host: jp.sourceforge.moreemacs
+Bundle-RequiredExecutionEnvironment: JavaSE-1.6
+Require-Bundle: org.junit4;bundle-version="4.3.1"
diff --git a/jp.sourceforge.moreemacs.test/build.properties b/jp.sourceforge.moreemacs.test/build.properties
new file mode 100755 (executable)
index 0000000..41eb6ad
--- /dev/null
@@ -0,0 +1,4 @@
+source.. = src/\r
+output.. = bin/\r
+bin.includes = META-INF/,\\r
+               .\r
diff --git a/jp.sourceforge.moreemacs.test/src/jp/sourceforge/moreemacs/utils/CharacterUtilsTest.java b/jp.sourceforge.moreemacs.test/src/jp/sourceforge/moreemacs/utils/CharacterUtilsTest.java
new file mode 100755 (executable)
index 0000000..43cdbb8
--- /dev/null
@@ -0,0 +1,15 @@
+package jp.sourceforge.moreemacs.utils;\r
+\r
+import java.util.Locale;\r
+import static org.junit.Assert.*;\r
+import org.junit.Test;\r
+\r
+public class CharacterUtilsTest {\r
+    @Test\r
+    public void testGetWidth() {\r
+        String str = "α■";\r
+        for(int codePoint : CodePointIterator.each(str)) {\r
+            assertEquals(2, CharacterUtils.getWidth(codePoint, Locale.JAPANESE));\r
+        }\r
+    }\r
+}\r
diff --git a/jp.sourceforge.moreemacs/.classpath b/jp.sourceforge.moreemacs/.classpath
new file mode 100755 (executable)
index 0000000..8a8f166
--- /dev/null
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<classpath>\r
+       <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>\r
+       <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>\r
+       <classpathentry kind="src" path="src"/>\r
+       <classpathentry kind="output" path="bin"/>\r
+</classpath>\r
diff --git a/jp.sourceforge.moreemacs/.project b/jp.sourceforge.moreemacs/.project
new file mode 100755 (executable)
index 0000000..d069284
--- /dev/null
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<projectDescription>\r
+       <name>jp.sourceforge.moreemacs</name>\r
+       <comment></comment>\r
+       <projects>\r
+       </projects>\r
+       <buildSpec>\r
+               <buildCommand>\r
+                       <name>org.eclipse.jdt.core.javabuilder</name>\r
+                       <arguments>\r
+                       </arguments>\r
+               </buildCommand>\r
+               <buildCommand>\r
+                       <name>org.eclipse.pde.ManifestBuilder</name>\r
+                       <arguments>\r
+                       </arguments>\r
+               </buildCommand>\r
+               <buildCommand>\r
+                       <name>org.eclipse.pde.SchemaBuilder</name>\r
+                       <arguments>\r
+                       </arguments>\r
+               </buildCommand>\r
+       </buildSpec>\r
+       <natures>\r
+               <nature>org.eclipse.pde.PluginNature</nature>\r
+               <nature>org.eclipse.jdt.core.javanature</nature>\r
+       </natures>\r
+</projectDescription>\r
diff --git a/jp.sourceforge.moreemacs/.settings/org.eclipse.jdt.core.prefs b/jp.sourceforge.moreemacs/.settings/org.eclipse.jdt.core.prefs
new file mode 100755 (executable)
index 0000000..7a7d1f2
--- /dev/null
@@ -0,0 +1,7 @@
+#Thu Jun 04 00:52:23 JST 2009\r
+eclipse.preferences.version=1\r
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6\r
+org.eclipse.jdt.core.compiler.compliance=1.6\r
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error\r
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error\r
+org.eclipse.jdt.core.compiler.source=1.6\r
diff --git a/jp.sourceforge.moreemacs/LICENCE.txt b/jp.sourceforge.moreemacs/LICENCE.txt
new file mode 100755 (executable)
index 0000000..ddc98eb
--- /dev/null
@@ -0,0 +1,26 @@
+Copyright (c) 2009, quiver2k\r
+All rights reserved.\r
+\r
+Redistribution and use in source and binary forms, with or without\r
+modification, are permitted provided that the following conditions are met:\r
+\r
+  * Redistributions of source code must retain the above copyright notice,\r
+    this list of conditions and the following disclaimer.\r
+  * Redistributions in binary form must reproduce the above copyright notice,\r
+    this list of conditions and the following disclaimer in the documentation\r
+    and/or other materials provided with the distribution.\r
+  * Neither the name of the authors nor the names of its contributors may be\r
+    used to endorse or promote products derived from this software without\r
+    specific prior written permission.\r
+\r
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"\r
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\r
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\r
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE\r
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\r
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\r
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\r
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\r
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\r
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\r
+POSSIBILITY OF SUCH DAMAGE.\r
diff --git a/jp.sourceforge.moreemacs/META-INF/MANIFEST.MF b/jp.sourceforge.moreemacs/META-INF/MANIFEST.MF
new file mode 100755 (executable)
index 0000000..8d41486
--- /dev/null
@@ -0,0 +1,14 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: MoreEmacs plugin
+Bundle-SymbolicName: jp.sourceforge.moreemacs;singleton:=true
+Bundle-Version: 1.0.0
+Bundle-Activator: jp.sourceforge.moreemacs.MoreEmacs
+Bundle-Vendor: quiver2k
+Require-Bundle: org.eclipse.ui,
+ org.eclipse.core.runtime,
+ org.eclipse.ui.editors;bundle-version="3.4.0",
+ com.ibm.icu;bundle-version="3.8.1",
+ org.eclipse.jface.text;bundle-version="3.4.2"
+Bundle-RequiredExecutionEnvironment: JavaSE-1.6
+Bundle-ActivationPolicy: lazy
diff --git a/jp.sourceforge.moreemacs/build.properties b/jp.sourceforge.moreemacs/build.properties
new file mode 100755 (executable)
index 0000000..6f20375
--- /dev/null
@@ -0,0 +1,5 @@
+source.. = src/\r
+output.. = bin/\r
+bin.includes = META-INF/,\\r
+               .,\\r
+               plugin.xml\r
diff --git a/jp.sourceforge.moreemacs/plugin.xml b/jp.sourceforge.moreemacs/plugin.xml
new file mode 100755 (executable)
index 0000000..2e9bfda
--- /dev/null
@@ -0,0 +1,307 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<?eclipse version="3.4"?>\r
+<plugin>\r
+   <extension\r
+         point="org.eclipse.ui.commands">\r
+      <category\r
+            id="jp.sourceforge.moreemacs.category"\r
+            name="More Emacs">\r
+      </category>\r
+      <command\r
+            categoryId="jp.sourceforge.moreemacs.category"\r
+            id="jp.sourceforge.moreemacs.MoveBeginningOfLine"\r
+            name="move-beginning-of-line">\r
+      </command>\r
+      <command\r
+            categoryId="jp.sourceforge.moreemacs.category"\r
+            id="jp.sourceforge.moreemacs.MoveEndOfLine"\r
+            name="move-end-of-line">\r
+      </command>\r
+      <command\r
+            categoryId="jp.sourceforge.moreemacs.category"\r
+            id="jp.sourceforge.moreemacs.ForwardWord"\r
+            name="forword-word">\r
+      </command>\r
+      <command\r
+            categoryId="jp.sourceforge.moreemacs.category"\r
+            id="jp.sourceforge.moreemacs.BackwardWord"\r
+            name="backword-word">\r
+      </command>\r
+      <command\r
+            categoryId="jp.sourceforge.moreemacs.category"\r
+            id="jp.sourceforge.moreemacs.KillWord"\r
+            name="kill-word">\r
+      </command>\r
+      <command\r
+            categoryId="jp.sourceforge.moreemacs.category"\r
+            id="jp.sourceforge.moreemacs.BackwardKillWord"\r
+            name="backward-kill-word">\r
+      </command>\r
+      <command\r
+            categoryId="jp.sourceforge.moreemacs.category"\r
+            id="jp.sourceforge.moreemacs.DeleteHorizontalSpace"\r
+            name="delete-horizontal-space">\r
+      </command>\r
+      <command\r
+            categoryId="jp.sourceforge.moreemacs.category"\r
+            id="jp.sourceforge.moreemacs.KillLine"\r
+            name="kill-line">\r
+      </command>\r
+      <command\r
+            categoryId="jp.sourceforge.moreemacs.category"\r
+            id="jp.sourceforge.moreemacs.TransposeChars"\r
+            name="transpose-chars">\r
+      </command>\r
+      <command\r
+            categoryId="jp.sourceforge.moreemacs.category"\r
+            id="jp.sourceforge.moreemacs.TransposeWords"\r
+            name="transpose-words">\r
+      </command>\r
+      <command\r
+            categoryId="jp.sourceforge.moreemacs.category"\r
+            id="jp.sourceforge.moreemacs.KillRectangle"\r
+            name="kill-rectangle">\r
+      </command>\r
+      <command\r
+            categoryId="jp.sourceforge.moreemacs.category"\r
+            id="jp.sourceforge.moreemacs.YankRectangle"\r
+            name="yank-rectangle">\r
+      </command>\r
+      <command\r
+            categoryId="jp.sourceforge.moreemacs.category"\r
+            id="jp.sourceforge.moreemacs.OpenLine"\r
+            name="open-line">\r
+      </command>\r
+   </extension>\r
+\r
+   <extension\r
+         point="org.eclipse.ui.handlers">\r
+      <handler\r
+            commandId="jp.sourceforge.moreemacs.MoveBeginningOfLine">\r
+         <class\r
+               class="jp.sourceforge.moreemacs.handlers.CommandHandler">\r
+         </class>\r
+      </handler>\r
+      <handler\r
+            commandId="jp.sourceforge.moreemacs.MoveEndOfLine">\r
+         <class\r
+               class="jp.sourceforge.moreemacs.handlers.CommandHandler">\r
+         </class>\r
+      </handler>\r
+      <handler\r
+            commandId="jp.sourceforge.moreemacs.ForwardWord">\r
+         <class\r
+               class="jp.sourceforge.moreemacs.handlers.CommandHandler">\r
+         </class>\r
+      </handler>\r
+      <handler\r
+            commandId="jp.sourceforge.moreemacs.BackwardWord">\r
+         <class\r
+               class="jp.sourceforge.moreemacs.handlers.CommandHandler">\r
+         </class>\r
+      </handler>\r
+      <handler\r
+            commandId="jp.sourceforge.moreemacs.KillWord">\r
+         <class\r
+               class="jp.sourceforge.moreemacs.handlers.CommandHandler">\r
+         </class>\r
+      </handler>\r
+      <handler\r
+            commandId="jp.sourceforge.moreemacs.BackwardKillWord">\r
+         <class\r
+               class="jp.sourceforge.moreemacs.handlers.CommandHandler">\r
+         </class>\r
+      </handler>\r
+      <handler\r
+            commandId="jp.sourceforge.moreemacs.DeleteHorizontalSpace">\r
+         <class\r
+               class="jp.sourceforge.moreemacs.handlers.CommandHandler">\r
+         </class>\r
+      </handler>\r
+      <handler\r
+            commandId="jp.sourceforge.moreemacs.KillLine">\r
+         <class\r
+               class="jp.sourceforge.moreemacs.handlers.CommandHandler">\r
+         </class>\r
+      </handler>\r
+      <handler\r
+            commandId="jp.sourceforge.moreemacs.TransposeChars">\r
+         <class\r
+               class="jp.sourceforge.moreemacs.handlers.CommandHandler">\r
+         </class>\r
+      </handler>\r
+      <handler\r
+            commandId="jp.sourceforge.moreemacs.TransposeWords">\r
+         <class\r
+               class="jp.sourceforge.moreemacs.handlers.CommandHandler">\r
+         </class>\r
+      </handler>\r
+      <handler\r
+            commandId="jp.sourceforge.moreemacs.KillRectangle">\r
+         <class\r
+               class="jp.sourceforge.moreemacs.handlers.CommandHandler">\r
+         </class>\r
+      </handler>\r
+      <handler\r
+            commandId="jp.sourceforge.moreemacs.YankRectangle">\r
+         <class\r
+               class="jp.sourceforge.moreemacs.handlers.CommandHandler">\r
+         </class>\r
+      </handler>\r
+      <handler\r
+            commandId="jp.sourceforge.moreemacs.OpenLine">\r
+         <class\r
+               class="jp.sourceforge.moreemacs.handlers.CommandHandler">\r
+         </class>\r
+      </handler>\r
+\r
+   </extension>\r
+\r
+   <extension\r
+         point="org.eclipse.ui.bindings">\r
+      <scheme\r
+            description="provides more emacs like key binding."\r
+            id="jp.sourceforge.moreemacs.moreEmacsAcceleratorConfiguration"\r
+            name="More Emacs"\r
+            parentId="org.eclipse.ui.emacsAcceleratorConfiguration">\r
+      </scheme>\r
+      <key\r
+            commandId="org.eclipse.ui.edit.undo"\r
+            contextId="org.eclipse.ui.contexts.window"\r
+            schemeId="jp.sourceforge.moreemacs.moreEmacsAcceleratorConfiguration"\r
+            sequence="CTRL+/">\r
+      </key>\r
+      <key\r
+            commandId="org.eclipse.ui.edit.text.deletePrevious"\r
+            contextId="org.eclipse.ui.contexts.window"\r
+            schemeId="jp.sourceforge.moreemacs.moreEmacsAcceleratorConfiguration"\r
+            sequence="CTRL+H">\r
+      </key>\r
+      <key\r
+            commandId="org.eclipse.ui.window.nextEditor"\r
+            contextId="org.eclipse.ui.contexts.window"\r
+            schemeId="jp.sourceforge.moreemacs.moreEmacsAcceleratorConfiguration"\r
+            sequence="CTRL+TAB">\r
+      </key>\r
+      <key\r
+            commandId="org.eclipse.ui.window.nextEditor"\r
+            contextId="org.eclipse.ui.contexts.window"\r
+            schemeId="jp.sourceforge.moreemacs.moreEmacsAcceleratorConfiguration"\r
+            sequence="CTRL+X O">\r
+      </key>\r
+      <key\r
+            commandId="org.eclipse.ui.window.previousEditor"\r
+            contextId="org.eclipse.ui.contexts.window"\r
+            schemeId="jp.sourceforge.moreemacs.moreEmacsAcceleratorConfiguration"\r
+            sequence="CTRL+SHIFT+TAB">\r
+      </key>\r
+      <key\r
+            commandId="org.eclipse.ui.file.close"\r
+            contextId="org.eclipse.ui.contexts.window"\r
+            schemeId="jp.sourceforge.moreemacs.moreEmacsAcceleratorConfiguration"\r
+            sequence="CTRL+X 0">\r
+      </key>\r
+      <key\r
+            commandId="org.eclipse.ui.window.maximizePart"\r
+            contextId="org.eclipse.ui.contexts.window"\r
+            schemeId="jp.sourceforge.moreemacs.moreEmacsAcceleratorConfiguration"\r
+            sequence="CTRL+X 1">\r
+      </key>\r
+      <key\r
+            commandId="org.eclipse.ui.window.newEditor"\r
+            contextId="org.eclipse.ui.contexts.window"\r
+            schemeId="jp.sourceforge.moreemacs.moreEmacsAcceleratorConfiguration"\r
+            sequence="CTRL+X 2">\r
+      </key>\r
+      <key\r
+            commandId="org.eclipse.ui.edit.findReplace"\r
+            contextId="org.eclipse.ui.contexts.window"\r
+            schemeId="jp.sourceforge.moreemacs.moreEmacsAcceleratorConfiguration"\r
+            sequence="ALT+SHIFT+5">\r
+      </key>\r
+      <key\r
+            contextId="org.eclipse.ui.contexts.window"\r
+            schemeId="jp.sourceforge.moreemacs.moreEmacsAcceleratorConfiguration"\r
+            sequence="Ctrl+M">\r
+      </key>\r
+      <key\r
+            commandId="jp.sourceforge.moreemacs.MoveBeginningOfLine"\r
+            contextId="org.eclipse.ui.textEditorScope"\r
+            schemeId="jp.sourceforge.moreemacs.moreEmacsAcceleratorConfiguration"\r
+            sequence="Ctrl+A">\r
+      </key>\r
+      <key\r
+            commandId="jp.sourceforge.moreemacs.MoveEndOfLine"\r
+            contextId="org.eclipse.ui.textEditorScope"\r
+            schemeId="jp.sourceforge.moreemacs.moreEmacsAcceleratorConfiguration"\r
+            sequence="Ctrl+E">\r
+      </key>\r
+      <key\r
+            commandId="jp.sourceforge.moreemacs.ForwardWord"\r
+            contextId="org.eclipse.ui.textEditorScope"\r
+            schemeId="jp.sourceforge.moreemacs.moreEmacsAcceleratorConfiguration"\r
+            sequence="Alt+F">\r
+      </key>\r
+      <key\r
+            commandId="jp.sourceforge.moreemacs.BackwardWord"\r
+            contextId="org.eclipse.ui.textEditorScope"\r
+            schemeId="jp.sourceforge.moreemacs.moreEmacsAcceleratorConfiguration"\r
+            sequence="Alt+B">\r
+      </key>\r
+      <key\r
+            commandId="jp.sourceforge.moreemacs.KillWord"\r
+            contextId="org.eclipse.ui.textEditorScope"\r
+            schemeId="jp.sourceforge.moreemacs.moreEmacsAcceleratorConfiguration"\r
+            sequence="Alt+D">\r
+      </key>\r
+      <key\r
+            commandId="jp.sourceforge.moreemacs.BackwardKillWord"\r
+            contextId="org.eclipse.ui.textEditorScope"\r
+            schemeId="jp.sourceforge.moreemacs.moreEmacsAcceleratorConfiguration"\r
+            sequence="Alt+Backspace">\r
+      </key>\r
+      <key\r
+            commandId="jp.sourceforge.moreemacs.DeleteHorizontalSpace"\r
+            contextId="org.eclipse.ui.textEditorScope"\r
+            schemeId="jp.sourceforge.moreemacs.moreEmacsAcceleratorConfiguration"\r
+            sequence="Alt+\">\r
+      </key>\r
+      <key\r
+            commandId="jp.sourceforge.moreemacs.KillLine"\r
+            contextId="org.eclipse.ui.textEditorScope"\r
+            schemeId="jp.sourceforge.moreemacs.moreEmacsAcceleratorConfiguration"\r
+            sequence="CTRL+K">\r
+      </key>\r
+      <key\r
+            commandId="jp.sourceforge.moreemacs.OpenLine"\r
+            contextId="org.eclipse.ui.textEditorScope"\r
+            schemeId="jp.sourceforge.moreemacs.moreEmacsAcceleratorConfiguration"\r
+            sequence="CTRL+O">\r
+      </key>\r
+      <key\r
+            commandId="jp.sourceforge.moreemacs.TransposeChars"\r
+            contextId="org.eclipse.ui.textEditorScope"\r
+            schemeId="jp.sourceforge.moreemacs.moreEmacsAcceleratorConfiguration"\r
+            sequence="CTRL+T">\r
+      </key>\r
+      <key\r
+            commandId="jp.sourceforge.moreemacs.TransposeWords"\r
+            contextId="org.eclipse.ui.textEditorScope"\r
+            schemeId="jp.sourceforge.moreemacs.moreEmacsAcceleratorConfiguration"\r
+            sequence="ALT+T">\r
+      </key>\r
+      <key\r
+            commandId="jp.sourceforge.moreemacs.KillRectangle"\r
+            contextId="org.eclipse.ui.textEditorScope"\r
+            schemeId="jp.sourceforge.moreemacs.moreEmacsAcceleratorConfiguration"\r
+            sequence="CTRL+X R K">\r
+      </key>\r
+      <key\r
+            commandId="jp.sourceforge.moreemacs.YankRectangle"\r
+            contextId="org.eclipse.ui.textEditorScope"\r
+            schemeId="jp.sourceforge.moreemacs.moreEmacsAcceleratorConfiguration"\r
+            sequence="CTRL+X R Y">\r
+      </key>\r
+   </extension>\r
+\r
+</plugin>\r
diff --git a/jp.sourceforge.moreemacs/src/jp/sourceforge/moreemacs/MoreEmacs.java b/jp.sourceforge.moreemacs/src/jp/sourceforge/moreemacs/MoreEmacs.java
new file mode 100755 (executable)
index 0000000..e606a31
--- /dev/null
@@ -0,0 +1,50 @@
+package jp.sourceforge.moreemacs;\r
+\r
+import org.eclipse.ui.plugin.AbstractUIPlugin;\r
+import org.osgi.framework.BundleContext;\r
+\r
+/**\r
+ * The activator class controls the plug-in life cycle\r
+ */\r
+public class MoreEmacs extends AbstractUIPlugin {\r
+\r
+       // The plug-in ID\r
+       public static final String PLUGIN_ID = "jp.sourceforge.moreemacs";\r
+\r
+       // The shared instance\r
+       private static MoreEmacs plugin;\r
+       \r
+       /**\r
+        * The constructor\r
+        */\r
+       public MoreEmacs() {\r
+       }\r
+\r
+       /*\r
+        * (non-Javadoc)\r
+        * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext)\r
+        */\r
+       public void start(BundleContext context) throws Exception {\r
+               super.start(context);\r
+               plugin = this;\r
+       }\r
+\r
+       /*\r
+        * (non-Javadoc)\r
+        * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext)\r
+        */\r
+       public void stop(BundleContext context) throws Exception {\r
+               plugin = null;\r
+               super.stop(context);\r
+       }\r
+\r
+       /**\r
+        * Returns the shared instance\r
+        *\r
+        * @return the shared instance\r
+        */\r
+       public static MoreEmacs getDefault() {\r
+               return plugin;\r
+       }\r
+\r
+}\r
diff --git a/jp.sourceforge.moreemacs/src/jp/sourceforge/moreemacs/handlers/BackwardKillWordExecution.java b/jp.sourceforge.moreemacs/src/jp/sourceforge/moreemacs/handlers/BackwardKillWordExecution.java
new file mode 100755 (executable)
index 0000000..f9e416b
--- /dev/null
@@ -0,0 +1,25 @@
+package jp.sourceforge.moreemacs.handlers;\r
+\r
+import org.eclipse.jface.text.BadLocationException;\r
+import org.eclipse.swt.dnd.Clipboard;\r
+import org.eclipse.swt.dnd.TextTransfer;\r
+import org.eclipse.swt.dnd.Transfer;\r
+\r
+public final class BackwardKillWordExecution extends TextEditorExecution {\r
+\r
+       @Override\r
+       public void execute()throws BadLocationException {\r
+        if(!textEditor.isEditable()) {\r
+            return;\r
+        }\r
+\r
+               int current = cursor.offset();\r
+               int previous = BackwardWordExecution.getPreviousWordPosition(doc, current);\r
+               String word = doc.get(previous, current - previous);\r
+               Clipboard c = new Clipboard(window.getShell().getDisplay());\r
+               c.setContents(new String[] { word },\r
+                               new Transfer[] { TextTransfer.getInstance() });\r
+               doc.replace(previous, current - previous, "");\r
+\r
+       }\r
+}\r
diff --git a/jp.sourceforge.moreemacs/src/jp/sourceforge/moreemacs/handlers/BackwardWordExecution.java b/jp.sourceforge.moreemacs/src/jp/sourceforge/moreemacs/handlers/BackwardWordExecution.java
new file mode 100755 (executable)
index 0000000..d0f88b8
--- /dev/null
@@ -0,0 +1,37 @@
+package jp.sourceforge.moreemacs.handlers;\r
+\r
+import jp.sourceforge.moreemacs.utils.CodePointIterator;\r
+import jp.sourceforge.moreemacs.utils.DocumentCharSequence;\r
+\r
+import org.eclipse.jface.text.BadLocationException;\r
+import org.eclipse.jface.text.IDocument;\r
+\r
+public final class BackwardWordExecution extends TextEditorExecution {\r
+\r
+       @Override\r
+       public void execute() throws BadLocationException {\r
+               int current = cursor.offset();\r
+               cursor.move(getPreviousWordPosition(doc, current));\r
+       }\r
+       \r
+       public static int getPreviousWordPosition(IDocument doc, int offset) throws BadLocationException {\r
+        CharSequence seq = new DocumentCharSequence(doc, 0, offset);\r
+        CodePointIterator itr = new CodePointIterator(seq, seq.length());\r
+\r
+        for(; itr.hasPrevious(); ) {\r
+            if (Character.isLetterOrDigit(itr.previous())) {\r
+                itr.next();\r
+                break;\r
+            }\r
+        }\r
+        for(; itr.hasPrevious(); ) {\r
+            if (!Character.isLetterOrDigit(itr.previous())) {\r
+                itr.next();\r
+                break;\r
+            }\r
+        }\r
+        \r
+       return itr.index();\r
+       }\r
+\r
+}\r
diff --git a/jp.sourceforge.moreemacs/src/jp/sourceforge/moreemacs/handlers/CommandHandler.java b/jp.sourceforge.moreemacs/src/jp/sourceforge/moreemacs/handlers/CommandHandler.java
new file mode 100755 (executable)
index 0000000..fff2ca0
--- /dev/null
@@ -0,0 +1,63 @@
+package jp.sourceforge.moreemacs.handlers;\r
+\r
+import java.util.regex.Pattern;\r
+\r
+import org.eclipse.core.commands.AbstractHandler;\r
+import org.eclipse.core.commands.Command;\r
+import org.eclipse.core.commands.ExecutionEvent;\r
+import org.eclipse.core.commands.ExecutionException;\r
+import org.eclipse.ui.IWorkbenchWindow;\r
+import org.eclipse.ui.handlers.HandlerUtil;\r
+\r
+public final class CommandHandler extends AbstractHandler {\r
+\r
+    @Override\r
+    public Object execute(ExecutionEvent event) throws ExecutionException {\r
+        IWorkbenchWindow window = HandlerUtil.getActiveWorkbenchWindow(event);\r
+\r
+        Execution exe = newExecution(event);\r
+        if(!exe.init(window)) {\r
+            return null;\r
+        }\r
+        try {\r
+            exe.execute();\r
+        } catch (Exception e) {\r
+            throw new ExecutionException(e.getMessage(), e);\r
+        }\r
+\r
+        return null;\r
+    }\r
+    \r
+    private Execution newExecution(ExecutionEvent event) throws ExecutionException {\r
+        try {\r
+            String className = getExecutionClassName(event);\r
+            Class<?> clazz = Class.forName(className);\r
+            Object obj = clazz.newInstance();\r
+            if(!(obj instanceof Execution)) {\r
+                throw new ExecutionException("the class "+clazz.getName()+\r
+                        " does not implements Execution.");\r
+            }\r
+            return (Execution)obj;\r
+        } catch (ClassNotFoundException e) {\r
+            throw new ExecutionException(e.getMessage(), e);\r
+        } catch (InstantiationException e) {\r
+            throw new ExecutionException(e.getMessage(), e);\r
+        } catch (IllegalAccessException e) {\r
+            throw new ExecutionException(e.getMessage(), e);\r
+        }\r
+        \r
+    }\r
+    \r
+    // naming strategy will be separated to another class.\r
+    private static final String COMMAND_PREFIX_QUOTED = Pattern.quote("jp.sourceforge.moreemacs.");\r
+    private static final String HANDLER_PREFIX = "jp.sourceforge.moreemacs.handlers."; \r
+    private static final String HANDLER_SUFFIX = "Execution";\r
+    private static String getExecutionClassName(ExecutionEvent event) {\r
+        Command command = event.getCommand();\r
+        String className = command.getId()\r
+        .replaceFirst(COMMAND_PREFIX_QUOTED, HANDLER_PREFIX)\r
+        +HANDLER_SUFFIX;\r
+        return className;\r
+    }\r
+\r
+}\r
diff --git a/jp.sourceforge.moreemacs/src/jp/sourceforge/moreemacs/handlers/Cursor.java b/jp.sourceforge.moreemacs/src/jp/sourceforge/moreemacs/handlers/Cursor.java
new file mode 100755 (executable)
index 0000000..f01f763
--- /dev/null
@@ -0,0 +1,42 @@
+package jp.sourceforge.moreemacs.handlers;\r
+\r
+import org.eclipse.jface.text.ITextSelection;\r
+import org.eclipse.jface.text.ITextViewer;\r
+import org.eclipse.jface.text.ITextViewerExtension5;\r
+import org.eclipse.swt.custom.StyledText;\r
+import org.eclipse.ui.texteditor.ITextEditor;\r
+\r
+final class Cursor {\r
+    private final ITextEditor textEditor;\r
+    private final ITextViewerExtension5 textViewerEx5;\r
+    private final StyledText styledText;\r
+    \r
+    Cursor(ITextEditor textEditor, ITextViewer textViewer) {\r
+        this.textEditor = textEditor;\r
+        this.styledText = textViewer.getTextWidget();\r
+        this.textViewerEx5 = (textViewer instanceof ITextViewerExtension5)\r
+        ? (ITextViewerExtension5) textViewer: null;\r
+    }\r
+    \r
+    int offset() {\r
+        if(textViewerEx5 != null) {\r
+            return textViewerEx5.widgetOffset2ModelOffset(\r
+                    styledText.getCaretOffset());\r
+        }\r
+\r
+        ITextSelection selectoin =\r
+            (ITextSelection) textEditor.getSelectionProvider().getSelection();\r
+        int selectionBegin = selectoin.getOffset();\r
+        return selectionBegin;\r
+    }\r
+    \r
+    void move(int offset) {\r
+//        if(textViewerEx5 != null) {\r
+//            styledText.setCaretOffset(textViewerEx5.modelOffset2WidgetOffset(offset));\r
+//            return;\r
+//        }\r
+\r
+        textEditor.resetHighlightRange();\r
+        textEditor.setHighlightRange(offset, 0, true);\r
+    }\r
+}\r
diff --git a/jp.sourceforge.moreemacs/src/jp/sourceforge/moreemacs/handlers/DeleteHorizontalSpaceExecution.java b/jp.sourceforge.moreemacs/src/jp/sourceforge/moreemacs/handlers/DeleteHorizontalSpaceExecution.java
new file mode 100755 (executable)
index 0000000..9cc0ca2
--- /dev/null
@@ -0,0 +1,55 @@
+package jp.sourceforge.moreemacs.handlers;\r
+\r
+import jp.sourceforge.moreemacs.utils.CodePointIterator;\r
+import jp.sourceforge.moreemacs.utils.DocumentCharSequence;\r
+\r
+import org.eclipse.jface.text.BadLocationException;\r
+import org.eclipse.jface.text.IDocument;\r
+import org.eclipse.jface.text.IRegion;\r
+\r
+public final class DeleteHorizontalSpaceExecution extends TextEditorExecution {\r
+\r
+       @Override\r
+       public void execute() throws BadLocationException {\r
+        if(!textEditor.isEditable()) {\r
+            return;\r
+        }\r
+\r
+        int current = cursor.offset();\r
+        int start = skipBackwardSpaces(doc, current);\r
+        int end = skipForwardSpaces(doc, current);\r
+               doc.replace(start, end - start, "");\r
+       }\r
+       \r
+       int skipBackwardSpaces(IDocument doc, int offset) throws BadLocationException {\r
+        IRegion line = doc.getLineInformationOfOffset(offset);\r
+\r
+        CharSequence seq = new DocumentCharSequence(doc, \r
+                line.getOffset(), offset-line.getOffset());\r
+\r
+        int result = offset;\r
+        for(CodePointIterator itr = new CodePointIterator(seq, seq.length()); itr.hasPrevious(); ) {\r
+            int codePoint = itr.previous();\r
+            if (!Character.isWhitespace(codePoint)) {\r
+                break;\r
+            }\r
+            result = line.getOffset() + itr.index();\r
+        }\r
+           return result;\r
+       }\r
+       \r
+       int skipForwardSpaces(IDocument doc, int offset) throws BadLocationException {\r
+        IRegion line = doc.getLineInformationOfOffset(offset);\r
+        CharSequence seq = new DocumentCharSequence(doc, \r
+                offset,line.getOffset()+line.getLength()-offset);\r
+        int result = offset;\r
+        for(CodePointIterator itr = new CodePointIterator(seq); itr.hasNext(); ) {\r
+            int codePoint = itr.next();\r
+            if (!Character.isWhitespace(codePoint)) {\r
+                break;\r
+            }\r
+            result = offset + itr.index();\r
+        }\r
+           return result;\r
+       }\r
+}\r
diff --git a/jp.sourceforge.moreemacs/src/jp/sourceforge/moreemacs/handlers/Execution.java b/jp.sourceforge.moreemacs/src/jp/sourceforge/moreemacs/handlers/Execution.java
new file mode 100755 (executable)
index 0000000..7c83984
--- /dev/null
@@ -0,0 +1,8 @@
+package jp.sourceforge.moreemacs.handlers;\r
+\r
+import org.eclipse.ui.IWorkbenchWindow;\r
+\r
+public interface Execution {\r
+    boolean init(IWorkbenchWindow window);\r
+    void execute() throws Exception;\r
+}\r
diff --git a/jp.sourceforge.moreemacs/src/jp/sourceforge/moreemacs/handlers/ForwardWordExecution.java b/jp.sourceforge.moreemacs/src/jp/sourceforge/moreemacs/handlers/ForwardWordExecution.java
new file mode 100755 (executable)
index 0000000..345026b
--- /dev/null
@@ -0,0 +1,39 @@
+package jp.sourceforge.moreemacs.handlers;\r
+\r
+import jp.sourceforge.moreemacs.utils.CodePointIterator;\r
+import jp.sourceforge.moreemacs.utils.DocumentCharSequence;\r
+\r
+import org.eclipse.jface.text.BadLocationException;\r
+import org.eclipse.jface.text.IDocument;\r
+\r
+public final class ForwardWordExecution extends TextEditorExecution {\r
+\r
+       @Override\r
+       public void execute() throws BadLocationException {\r
+               int current = cursor.offset();\r
+               cursor.move(getNextWordPosition(doc, current));\r
+       }\r
+\r
+       public static int getNextWordPosition(IDocument doc, int offset) throws BadLocationException {\r
+           CharSequence seq = new DocumentCharSequence(doc, offset, doc.getLength()-offset);\r
+           CodePointIterator itr = new CodePointIterator(seq);\r
+\r
+\r
+           for(; itr.hasNext(); ) {\r
+               int codePoint = itr.next();\r
+            if (Character.isLetterOrDigit(codePoint)) {\r
+                itr.previous();\r
+                break;\r
+            }\r
+           }\r
+        for(; itr.hasNext(); ) {\r
+            if (!Character.isLetterOrDigit(itr.next())) {\r
+                itr.previous();\r
+                break;\r
+            }\r
+        }\r
+        \r
+        return offset + itr.index();\r
+       }\r
+       \r
+}\r
diff --git a/jp.sourceforge.moreemacs/src/jp/sourceforge/moreemacs/handlers/KillLineExecution.java b/jp.sourceforge.moreemacs/src/jp/sourceforge/moreemacs/handlers/KillLineExecution.java
new file mode 100755 (executable)
index 0000000..cfe1942
--- /dev/null
@@ -0,0 +1,51 @@
+package jp.sourceforge.moreemacs.handlers;\r
+\r
+import jp.sourceforge.moreemacs.utils.CodePointIterator;\r
+import jp.sourceforge.moreemacs.utils.DocumentCharSequence;\r
+\r
+import org.eclipse.jface.text.BadLocationException;\r
+import org.eclipse.jface.text.IDocument;\r
+import org.eclipse.jface.text.IRegion;\r
+import org.eclipse.swt.dnd.Clipboard;\r
+import org.eclipse.swt.dnd.TextTransfer;\r
+import org.eclipse.swt.dnd.Transfer;\r
+\r
+public final class KillLineExecution extends TextEditorExecution {\r
+\r
+       @Override\r
+       public void execute() throws BadLocationException {\r
+        if(!textEditor.isEditable()) {\r
+            return;\r
+        }\r
+\r
+               int current = cursor.offset();\r
+               int linePos = doc.getLineOfOffset(current);\r
+               IRegion line = doc.getLineInformation(linePos);\r
+               String delim = doc.getLineDelimiter(linePos);\r
+\r
+               int length = line.getOffset() + line.getLength() - current;\r
+               boolean allSpaces = isAllSpaces(doc, current, length);\r
+\r
+               int cutLength = length;\r
+               if (allSpaces && delim != null) {\r
+                       cutLength += delim.length();\r
+               }\r
+\r
+               String cut = doc.get(current, cutLength);\r
+               Clipboard c = new Clipboard(window.getShell().getDisplay());\r
+               c.setContents(\r
+                               new String[] { cut }, \r
+                               new Transfer[] { TextTransfer.getInstance() });\r
+               doc.replace(current, cutLength, "");\r
+       }\r
+       \r
+       private boolean isAllSpaces(IDocument doc, int offset, int length) throws BadLocationException {\r
+        CharSequence seq = new DocumentCharSequence(doc, offset, length);\r
+        for(int codePoint : CodePointIterator.each(seq)) {\r
+            if (!Character.isWhitespace(codePoint)) {\r
+                return false;\r
+            }\r
+        }\r
+        return true;\r
+       }\r
+}\r
diff --git a/jp.sourceforge.moreemacs/src/jp/sourceforge/moreemacs/handlers/KillRectangleExecution.java b/jp.sourceforge.moreemacs/src/jp/sourceforge/moreemacs/handlers/KillRectangleExecution.java
new file mode 100755 (executable)
index 0000000..ac81e69
--- /dev/null
@@ -0,0 +1,107 @@
+package jp.sourceforge.moreemacs.handlers;\r
+\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+\r
+import jp.sourceforge.moreemacs.utils.CodePointIterator;\r
+import jp.sourceforge.moreemacs.utils.ColumnUtils;\r
+import jp.sourceforge.moreemacs.utils.DocumentCharSequence;\r
+import jp.sourceforge.moreemacs.utils.DocumentTransaction;\r
+\r
+import org.eclipse.jface.text.BadLocationException;\r
+import org.eclipse.jface.text.DocumentRewriteSessionType;\r
+import org.eclipse.jface.text.IDocument;\r
+import org.eclipse.jface.text.IRegion;\r
+import org.eclipse.jface.text.ITextSelection;\r
+\r
+public final class KillRectangleExecution extends RectangleExecution {\r
+\r
+    @Override\r
+    public void execute() throws BadLocationException {\r
+\r
+        if(!textEditor.isEditable()) {\r
+            return;\r
+        }\r
+        \r
+        ITextSelection selection = getSelection(true);\r
+\r
+        int start = selection.getOffset();\r
+        int startRow = doc.getLineOfOffset(start);\r
+        int startColumn = ColumnUtils.getColumn(doc, start, getTabStop());\r
+\r
+        int end = start + selection.getLength();\r
+        int endRow = doc.getLineOfOffset(end);\r
+        int endColumn = ColumnUtils.getColumn(doc, end, getTabStop());\r
+        \r
+        if(startColumn > endColumn) {\r
+            int work = startColumn;\r
+            startColumn = endColumn;\r
+            endColumn = work;\r
+        }\r
+\r
+        DocumentTransaction transaction = new DocumentTransaction(doc); \r
+        transaction.begin(DocumentRewriteSessionType.UNRESTRICTED_SMALL);\r
+        try {\r
+            List<String> rectangle = killRectangle(doc, startRow, startColumn, endRow, endColumn);\r
+            setRectangle(rectangle);\r
+        } finally {\r
+            transaction.end();\r
+        }\r
+    }\r
+    private List<String> killRectangle(IDocument doc,\r
+            int startRow, int startColumn,\r
+            int endRow, int endColumn)\r
+            throws BadLocationException {\r
+\r
+        List<String> rectangle = new ArrayList<String>();\r
+\r
+        for(int i = startRow; i <= endRow; i++) {\r
+            String str = killString(doc, i, startColumn, endColumn);\r
+            rectangle.add(str);\r
+        }\r
+        return rectangle;\r
+    }\r
+    private String killString(IDocument doc, int row,\r
+            int startColumn, int endColumn) throws BadLocationException {\r
+        IRegion line = doc.getLineInformation(row);\r
+\r
+        StringBuilder builder = new StringBuilder();\r
+        int column = 0;\r
+        int cutOffset = 0;\r
+        int cutLength = 0;\r
+        \r
+        CharSequence seq = new DocumentCharSequence(doc, line.getOffset(), line.getLength());\r
+        \r
+        for(CodePointIterator itr = new CodePointIterator(seq); itr.hasNext(); ) {\r
+            if(column >= endColumn) {\r
+                break;\r
+            }\r
+            int offset = line.getOffset() + itr.index();\r
+            int codePoint = itr.next();\r
+\r
+            int nextColumn = ColumnUtils.getNextColumn(column, codePoint, getTabStop());\r
+            \r
+            if(nextColumn < startColumn+1) {\r
+                column = nextColumn;\r
+                continue;\r
+            }\r
+            if(cutLength == 0) { \r
+                cutOffset = offset;\r
+            }\r
+            builder.appendCodePoint(codePoint);\r
+            cutLength += Character.charCount(codePoint);\r
+            column = nextColumn;\r
+        }\r
+        \r
+        doc.replace(cutOffset, cutLength, "");\r
+        cursor.move(cutOffset);\r
+\r
+            \r
+        for(int i = 0; i < endColumn-column; i++) {\r
+            builder.append(' ');\r
+        }\r
+        \r
+        return builder.toString();\r
+    }\r
+\r
+}\r
diff --git a/jp.sourceforge.moreemacs/src/jp/sourceforge/moreemacs/handlers/KillWordExecution.java b/jp.sourceforge.moreemacs/src/jp/sourceforge/moreemacs/handlers/KillWordExecution.java
new file mode 100755 (executable)
index 0000000..321ae7c
--- /dev/null
@@ -0,0 +1,25 @@
+package jp.sourceforge.moreemacs.handlers;\r
+\r
+import org.eclipse.jface.text.BadLocationException;\r
+import org.eclipse.swt.dnd.Clipboard;\r
+import org.eclipse.swt.dnd.TextTransfer;\r
+import org.eclipse.swt.dnd.Transfer;\r
+\r
+public final class KillWordExecution extends TextEditorExecution {\r
+\r
+       @Override\r
+       public void execute() throws BadLocationException {\r
+        if(!textEditor.isEditable()) {\r
+            return;\r
+        }\r
+\r
+               int current = cursor.offset();\r
+               int next = ForwardWordExecution.getNextWordPosition(doc, current);\r
+               String word = doc.get(current, next-current);\r
+               Clipboard c = new Clipboard(window.getShell().getDisplay());\r
+               c.setContents(\r
+                               new String[] { word }, \r
+                               new Transfer[] { TextTransfer.getInstance() });\r
+               doc.replace(current, next-current, "");\r
+       }\r
+}\r
diff --git a/jp.sourceforge.moreemacs/src/jp/sourceforge/moreemacs/handlers/MoveBeginningOfLineExecution.java b/jp.sourceforge.moreemacs/src/jp/sourceforge/moreemacs/handlers/MoveBeginningOfLineExecution.java
new file mode 100755 (executable)
index 0000000..be3aaee
--- /dev/null
@@ -0,0 +1,13 @@
+package jp.sourceforge.moreemacs.handlers;\r
+\r
+import org.eclipse.jface.text.BadLocationException;\r
+import org.eclipse.jface.text.IRegion;\r
+\r
+public final class MoveBeginningOfLineExecution extends TextEditorExecution {\r
+       @Override\r
+       public void execute() throws BadLocationException {\r
+               IRegion line = doc.getLineInformationOfOffset(cursor.offset());\r
+               cursor.move(line.getOffset());\r
+       }\r
+}\r
+\r
diff --git a/jp.sourceforge.moreemacs/src/jp/sourceforge/moreemacs/handlers/MoveEndOfLineExecution.java b/jp.sourceforge.moreemacs/src/jp/sourceforge/moreemacs/handlers/MoveEndOfLineExecution.java
new file mode 100755 (executable)
index 0000000..6131cc2
--- /dev/null
@@ -0,0 +1,14 @@
+package jp.sourceforge.moreemacs.handlers;\r
+\r
+import org.eclipse.jface.text.BadLocationException;\r
+import org.eclipse.jface.text.IRegion;\r
+\r
+public final class MoveEndOfLineExecution extends TextEditorExecution {\r
+\r
+    @Override\r
+    public void execute() throws BadLocationException {\r
+        IRegion line = doc.getLineInformationOfOffset(cursor.offset());\r
+        cursor.move(line.getOffset()+line.getLength());\r
+    }\r
+\r
+}\r
diff --git a/jp.sourceforge.moreemacs/src/jp/sourceforge/moreemacs/handlers/OpenLineExecution.java b/jp.sourceforge.moreemacs/src/jp/sourceforge/moreemacs/handlers/OpenLineExecution.java
new file mode 100755 (executable)
index 0000000..a572e06
--- /dev/null
@@ -0,0 +1,16 @@
+package jp.sourceforge.moreemacs.handlers;\r
+\r
+import org.eclipse.jface.text.TextUtilities;\r
+\r
+public final class OpenLineExecution extends TextEditorExecution {\r
+\r
+    @Override\r
+    public void execute() throws Exception {\r
+        if(!textEditor.isEditable()) {\r
+            return;\r
+        }\r
+        String delim = TextUtilities.getDefaultLineDelimiter(doc);\r
+        doc.replace(cursor.offset(), 0, delim);\r
+    }\r
+\r
+}\r
diff --git a/jp.sourceforge.moreemacs/src/jp/sourceforge/moreemacs/handlers/RectangleExecution.java b/jp.sourceforge.moreemacs/src/jp/sourceforge/moreemacs/handlers/RectangleExecution.java
new file mode 100755 (executable)
index 0000000..e49ce60
--- /dev/null
@@ -0,0 +1,15 @@
+package jp.sourceforge.moreemacs.handlers;\r
+\r
+import java.util.List;\r
+\r
+abstract class RectangleExecution extends TextEditorExecution {\r
+    private static List<String> rectangle ;\r
+    \r
+    protected static void setRectangle(List<String> rect) {\r
+        rectangle = rect;\r
+    }\r
+    \r
+    protected static List<String> getRectangle() {\r
+        return rectangle;\r
+    }\r
+}\r
diff --git a/jp.sourceforge.moreemacs/src/jp/sourceforge/moreemacs/handlers/TextEditorExecution.java b/jp.sourceforge.moreemacs/src/jp/sourceforge/moreemacs/handlers/TextEditorExecution.java
new file mode 100755 (executable)
index 0000000..56f01ae
--- /dev/null
@@ -0,0 +1,84 @@
+package jp.sourceforge.moreemacs.handlers;\r
+\r
+import org.eclipse.jface.text.IDocument;\r
+import org.eclipse.jface.text.ITextOperationTarget;\r
+import org.eclipse.jface.text.ITextSelection;\r
+import org.eclipse.jface.text.ITextViewer;\r
+import org.eclipse.jface.text.ITextViewerExtension;\r
+import org.eclipse.ui.IEditorPart;\r
+import org.eclipse.ui.IWorkbenchWindow;\r
+import org.eclipse.ui.texteditor.ITextEditor;\r
+\r
+abstract class TextEditorExecution implements Execution {\r
+    protected IWorkbenchWindow window;\r
+    protected ITextEditor textEditor;\r
+    protected ITextViewer textViewer;\r
+    protected Cursor cursor;\r
+    protected IDocument doc;\r
+    \r
+    @Override\r
+    public boolean init(IWorkbenchWindow window) {\r
+        this.window = window;\r
+\r
+        IEditorPart editor = window.getActivePage().getActiveEditor();\r
+        if (editor instanceof ITextEditor) {\r
+            textEditor = (ITextEditor) editor;\r
+        } else {\r
+            textEditor = (ITextEditor) editor.getAdapter(ITextEditor.class);\r
+        }\r
+        if(textEditor == null) {\r
+            return false;\r
+        }\r
+        \r
+        doc = textEditor.getDocumentProvider().getDocument(\r
+                textEditor.getEditorInput());\r
+\r
+        ITextOperationTarget target =\r
+            (ITextOperationTarget)editor.getAdapter(ITextOperationTarget.class);\r
+        if(!(target instanceof ITextViewer)) {\r
+            return false;\r
+        }\r
+        textViewer = (ITextViewer) target;\r
+        \r
+        cursor = new Cursor(textEditor, textViewer);\r
+        \r
+        return true;\r
+    }\r
+    \r
+    protected ITextSelection getSelection(boolean fallbackToMark) {\r
+        ITextSelection selection =\r
+            (ITextSelection) textEditor.getSelectionProvider().getSelection();\r
+        \r
+        if(!fallbackToMark && selection.getLength() != 0) {\r
+            return selection;\r
+        }\r
+        \r
+        IEditorPart editor = window.getActivePage().getActiveEditor();\r
+        ITextOperationTarget target =\r
+            (ITextOperationTarget)editor.getAdapter(ITextOperationTarget.class);\r
+        \r
+        if(!(target instanceof ITextViewerExtension)) {\r
+            return selection;\r
+        }\r
+        \r
+        ITextViewerExtension viewerEx = (ITextViewerExtension) target;\r
+            \r
+        int mark = viewerEx.getMark();\r
+        \r
+        if(mark == -1) {\r
+            return selection;\r
+        }\r
+        \r
+        int current = selection.getOffset();\r
+        \r
+        int start = (mark < current) ? mark : current;\r
+        textEditor.selectAndReveal(start, Math.abs(mark - current));\r
+        \r
+        return (ITextSelection) textEditor\r
+        .getSelectionProvider().getSelection();\r
+    }\r
+\r
+    protected final int getTabStop() {\r
+        return textViewer.getTextWidget().getTabs();\r
+    }\r
+}\r
diff --git a/jp.sourceforge.moreemacs/src/jp/sourceforge/moreemacs/handlers/TransposeCharsExecution.java b/jp.sourceforge.moreemacs/src/jp/sourceforge/moreemacs/handlers/TransposeCharsExecution.java
new file mode 100755 (executable)
index 0000000..47c9b59
--- /dev/null
@@ -0,0 +1,52 @@
+package jp.sourceforge.moreemacs.handlers;\r
+\r
+import jp.sourceforge.moreemacs.utils.DocumentCharSequence;\r
+\r
+import org.eclipse.jface.text.BadLocationException;\r
+import org.eclipse.jface.text.IRegion;\r
+\r
+public final class TransposeCharsExecution extends TextEditorExecution {\r
+    @Override\r
+    public void execute() throws BadLocationException {\r
+        if(!textEditor.isEditable()) {\r
+            return;\r
+        }\r
+\r
+        int current = cursor.offset();\r
+        if(current == 0) {\r
+            // beginning of document\r
+            return;\r
+        }\r
+\r
+        int linePos = doc.getLineOfOffset(current);\r
+        IRegion line = doc.getLineInformation(linePos);\r
+        \r
+        DocumentCharSequence seq = new DocumentCharSequence(doc);\r
+\r
+        if(line.getOffset() + line.getLength() == current) {\r
+            // if end of line, adjust current position\r
+            current = (line.getOffset() == current)\r
+                    ? current - doc.getLineDelimiter(linePos-1).length() \r
+                    : seq.previousCodePointIndex(current);\r
+            linePos = doc.getLineOfOffset(current);\r
+            line = doc.getLineInformation(linePos);\r
+        }\r
+        if(current == 0) {\r
+            // beginning of document again\r
+            return;\r
+        }\r
+\r
+        int nextIndex = seq.nextCodePointIndex(current);\r
+        String forwardChars = (line.getOffset() + line.getLength() == current) \r
+        ? doc.getLineDelimiter(linePos) : doc.get(current, nextIndex - current);\r
+            \r
+        int prevIndex = seq.previousCodePointIndex(current);\r
+        String backwardChars = (line.getOffset() == current) \r
+            ? doc.getLineDelimiter(linePos-1) : doc.get(prevIndex, current-prevIndex);\r
+\r
+        doc.replace(current-backwardChars.length(), \r
+                backwardChars.length() + forwardChars.length(),\r
+                forwardChars+backwardChars);\r
+    }\r
+    \r
+}\r
diff --git a/jp.sourceforge.moreemacs/src/jp/sourceforge/moreemacs/handlers/TransposeWordsExecution.java b/jp.sourceforge.moreemacs/src/jp/sourceforge/moreemacs/handlers/TransposeWordsExecution.java
new file mode 100755 (executable)
index 0000000..2b57aff
--- /dev/null
@@ -0,0 +1,31 @@
+package jp.sourceforge.moreemacs.handlers;\r
+\r
+import org.eclipse.jface.text.BadLocationException;\r
+\r
+public final class TransposeWordsExecution extends TextEditorExecution {\r
+    @Override\r
+    public void execute() throws BadLocationException {\r
+        if(!textEditor.isEditable()) {\r
+            return;\r
+        }\r
+\r
+        int current = cursor.offset();\r
+        int previousBegin = BackwardWordExecution.getPreviousWordPosition(doc, current);\r
+        int previousEnd = ForwardWordExecution.getNextWordPosition(doc, previousBegin);\r
+        int nextEnd = ForwardWordExecution.getNextWordPosition(doc, current);\r
+        int nextBegin = BackwardWordExecution.getPreviousWordPosition(doc, nextEnd);\r
+        \r
+        if(nextBegin <= previousEnd) {\r
+            return;\r
+        }\r
+        \r
+        String previous = doc.get(previousBegin, previousEnd-previousBegin);\r
+        String simbols = doc.get(previousEnd, nextBegin-previousEnd);\r
+        String next = doc.get(nextBegin, nextEnd-nextBegin);\r
+\r
+        doc.replace(previousBegin,\r
+                nextEnd-previousBegin,\r
+                next+simbols+previous);\r
+        \r
+    }\r
+}\r
diff --git a/jp.sourceforge.moreemacs/src/jp/sourceforge/moreemacs/handlers/YankRectangleExecution.java b/jp.sourceforge.moreemacs/src/jp/sourceforge/moreemacs/handlers/YankRectangleExecution.java
new file mode 100755 (executable)
index 0000000..f570c0f
--- /dev/null
@@ -0,0 +1,97 @@
+package jp.sourceforge.moreemacs.handlers;\r
+\r
+import java.util.List;\r
+\r
+import jp.sourceforge.moreemacs.utils.CodePointIterator;\r
+import jp.sourceforge.moreemacs.utils.ColumnUtils;\r
+import jp.sourceforge.moreemacs.utils.DocumentCharSequence;\r
+import jp.sourceforge.moreemacs.utils.DocumentTransaction;\r
+\r
+import org.eclipse.jface.text.BadLocationException;\r
+import org.eclipse.jface.text.DocumentRewriteSessionType;\r
+import org.eclipse.jface.text.IDocument;\r
+import org.eclipse.jface.text.IRegion;\r
+import org.eclipse.jface.text.TextUtilities;\r
+\r
+public final class YankRectangleExecution extends RectangleExecution {\r
+    @Override\r
+    public void execute() throws BadLocationException {\r
+        if(!textEditor.isEditable()) {\r
+            return;\r
+        }\r
+        \r
+        List<String> rectangle = getRectangle();\r
+        if(rectangle == null) {\r
+            return;\r
+        }\r
+        \r
+        int current = cursor.offset();\r
+        int row = doc.getLineOfOffset(current);\r
+        int column = ColumnUtils.getColumn(doc, current, getTabStop());\r
+        \r
+        ensureLines(doc, row + rectangle.size());\r
+        \r
+        DocumentTransaction transaction = new DocumentTransaction(doc); \r
+        transaction.begin(DocumentRewriteSessionType.UNRESTRICTED_SMALL);\r
+        try {\r
+            yankRectangle(doc, row, column, rectangle);\r
+        } finally {\r
+            transaction.end();\r
+        }\r
+    }\r
+    \r
+    private void ensureLines(IDocument doc, int lines) throws BadLocationException {\r
+        int n = lines - doc.getNumberOfLines();\r
+        if(n <= 0) {\r
+            return;\r
+        }\r
+\r
+        StringBuilder builder = new StringBuilder();\r
+        String delim = TextUtilities.getDefaultLineDelimiter(doc);\r
+        for(int i = 0; i < n; i++) {\r
+            builder.append(delim);\r
+        }\r
+        doc.replace(doc.getLength(), 0, builder.toString());\r
+        \r
+    }\r
+\r
+    private void yankRectangle(IDocument doc,\r
+            int row, int column, List<String> rectangle)\r
+            throws BadLocationException {\r
+        for(int i = 0; i < rectangle.size(); i++) {\r
+            yankString(doc, row+i, column, rectangle.get(i));\r
+        }\r
+    }\r
+\r
+    private void yankString(IDocument doc, int row, int column, String str)\r
+    throws BadLocationException\r
+    {\r
+        IRegion line = doc.getLineInformation(row);\r
+        int col = 0;\r
+\r
+        CharSequence seq = new DocumentCharSequence(doc, line.getOffset(), line.getLength());\r
+        \r
+        for(CodePointIterator itr = new CodePointIterator(seq); itr.hasNext(); ) {\r
+            int offset = line.getOffset() + itr.index();\r
+            int codePoint = itr.next();\r
+            if(col >= column) {\r
+                doc.replace(offset, 0, str);\r
+                cursor.move(offset+str.length());\r
+                return;\r
+            }\r
+            col = ColumnUtils.getNextColumn(col, codePoint, getTabStop());\r
+        }\r
+        \r
+\r
+        StringBuilder builder = new StringBuilder();\r
+        for(int i = 0; i < column-col; i++) {\r
+            builder.append(" ");\r
+        }\r
+        builder.append(str);\r
+        doc.replace(line.getOffset()+line.getLength(), 0, builder.toString());\r
+        cursor.move(line.getOffset()+line.getLength()+builder.length());\r
+    }\r
+\r
+}\r
+\r
+\r
diff --git a/jp.sourceforge.moreemacs/src/jp/sourceforge/moreemacs/utils/CharacterUtils.java b/jp.sourceforge.moreemacs/src/jp/sourceforge/moreemacs/utils/CharacterUtils.java
new file mode 100755 (executable)
index 0000000..fe3db82
--- /dev/null
@@ -0,0 +1,44 @@
+package jp.sourceforge.moreemacs.utils;\r
+\r
+import java.util.Arrays;\r
+import java.util.List;\r
+import java.util.Locale;\r
+\r
+import com.ibm.icu.lang.UCharacter;\r
+import com.ibm.icu.lang.UProperty;\r
+\r
+public final class CharacterUtils {\r
+    private CharacterUtils() {}\r
+\r
+    private static List<String> EAST_ASIAN_LANGS =\r
+        Arrays.asList("ja", "vi", "kr", "zh");\r
+\r
+    public static int getWidth(int codePoint) {\r
+        return getWidth(codePoint, Locale.getDefault());\r
+    }\r
+\r
+    public static int getWidth(int codePoint, Locale locale) {\r
+        if(locale == null) {\r
+            throw new NullPointerException("locale is null");\r
+        }\r
+        int value = UCharacter.getIntPropertyValue(codePoint, \r
+                UProperty.EAST_ASIAN_WIDTH);\r
+        switch(value) {\r
+        case UCharacter.EastAsianWidth.NARROW:\r
+        case UCharacter.EastAsianWidth.NEUTRAL:\r
+        case UCharacter.EastAsianWidth.HALFWIDTH:\r
+            return 1;\r
+        case UCharacter.EastAsianWidth.FULLWIDTH:\r
+        case UCharacter.EastAsianWidth.WIDE:\r
+            return 2;\r
+        case UCharacter.EastAsianWidth.AMBIGUOUS:\r
+            if(EAST_ASIAN_LANGS.contains(locale.getLanguage())) {\r
+                return 2;\r
+            } else {\r
+                return 1;\r
+            }\r
+        default:\r
+            return 1;\r
+        }\r
+    }\r
+}\r
diff --git a/jp.sourceforge.moreemacs/src/jp/sourceforge/moreemacs/utils/CodePointIterator.java b/jp.sourceforge.moreemacs/src/jp/sourceforge/moreemacs/utils/CodePointIterator.java
new file mode 100755 (executable)
index 0000000..0d3ed8b
--- /dev/null
@@ -0,0 +1,69 @@
+package jp.sourceforge.moreemacs.utils;\r
+\r
+import java.util.Iterator;\r
+\r
+public final class CodePointIterator implements Iterator<Integer> {\r
+    private final CharSequence seq;\r
+    private int index;\r
+\r
+    public CodePointIterator(CharSequence seq) {\r
+        this(seq, 0);\r
+    }\r
+    \r
+    public CodePointIterator(CharSequence seq, int index) {\r
+        if(seq == null) {\r
+            throw new NullPointerException("seq is null");\r
+        }\r
+\r
+        this.seq = seq;\r
+        setIndex(index);\r
+    }\r
+    \r
+    public void setIndex(int index) {\r
+        if(index < 0 || index > seq.length()) {\r
+            throw new IndexOutOfBoundsException();\r
+        }\r
+        this.index = index;\r
+    }\r
+    \r
+    @Override\r
+    public boolean hasNext() {       \r
+        return index < seq.length();       \r
+    }\r
+    \r
+    public boolean hasPrevious() {       \r
+        return index > 0;\r
+    }\r
+    \r
+    public int index() {\r
+        return index;\r
+    }\r
+    \r
+    @Override\r
+    public Integer next() {      \r
+        int codePoint = Character.codePointAt(seq, index);        \r
+        index += Character.charCount(codePoint);     \r
+        return codePoint;        \r
+    }\r
+\r
+    public Integer previous() {      \r
+        int codePoint = Character.codePointBefore(seq, index);        \r
+        index -= Character.charCount(codePoint);     \r
+        return codePoint;        \r
+    }\r
+    \r
+    @Override\r
+    public void remove() {\r
+        throw new UnsupportedOperationException("unsupported");\r
+    }\r
+\r
+    public static Iterable<Integer> each(final CharSequence seq) {\r
+        return new Iterable<Integer>() {\r
+            @Override\r
+            public Iterator<Integer> iterator() {\r
+                return new CodePointIterator(seq);\r
+            }\r
+            \r
+        };\r
+    }\r
+}\r
diff --git a/jp.sourceforge.moreemacs/src/jp/sourceforge/moreemacs/utils/ColumnUtils.java b/jp.sourceforge.moreemacs/src/jp/sourceforge/moreemacs/utils/ColumnUtils.java
new file mode 100755 (executable)
index 0000000..8ad4470
--- /dev/null
@@ -0,0 +1,31 @@
+package jp.sourceforge.moreemacs.utils;\r
+\r
+import org.eclipse.jface.text.BadLocationException;\r
+import org.eclipse.jface.text.IDocument;\r
+import org.eclipse.jface.text.IRegion;\r
+\r
+public final class ColumnUtils {\r
+    private ColumnUtils() {}\r
+    \r
+    public static int getColumn(IDocument doc, int offset, int tabStop)\r
+    throws BadLocationException {\r
+        IRegion line = doc.getLineInformationOfOffset(offset);\r
+        int column = 0;\r
+        \r
+        CharSequence seq = new DocumentCharSequence(doc, line.getOffset(), offset - line.getOffset());\r
+        for(CodePointIterator itr = new CodePointIterator(seq); itr.hasNext(); ) {\r
+            int codePoint = itr.next();\r
+            column = getNextColumn(column, codePoint, tabStop);\r
+        }\r
+        \r
+        return column;\r
+    }\r
+    \r
+    public static int getNextColumn(int column, int codePoint, int tabStop) {\r
+        if(codePoint == '\t') {\r
+            return column - (column%tabStop) + tabStop;\r
+        } else {\r
+            return column + CharacterUtils.getWidth(codePoint);\r
+        }\r
+    }\r
+}\r
diff --git a/jp.sourceforge.moreemacs/src/jp/sourceforge/moreemacs/utils/DocumentCharSequence.java b/jp.sourceforge.moreemacs/src/jp/sourceforge/moreemacs/utils/DocumentCharSequence.java
new file mode 100755 (executable)
index 0000000..813b791
--- /dev/null
@@ -0,0 +1,64 @@
+package jp.sourceforge.moreemacs.utils;\r
+\r
+import org.eclipse.jface.text.BadLocationException;\r
+import org.eclipse.jface.text.IDocument;\r
+\r
+public final class DocumentCharSequence implements CharSequence {\r
+    private final IDocument doc;\r
+    private final int offset;\r
+    private final int length;\r
+\r
+    public DocumentCharSequence(IDocument doc) {\r
+        this(doc, 0, doc.getLength());\r
+    }\r
+    \r
+    public DocumentCharSequence(IDocument doc, int offset, int length) {\r
+        if(doc == null) {\r
+            throw new NullPointerException("doc is null");\r
+        }\r
+\r
+        this.doc = doc;\r
+        this.offset = offset;\r
+        this.length = length;\r
+\r
+        validate(offset, length, doc.getLength());\r
+    }\r
+    \r
+    private static void validate(int offset, int length, int capacity) {\r
+        if(offset < 0 || length < 0 || offset+length > capacity) {\r
+            throw new IndexOutOfBoundsException();\r
+        }\r
+    }\r
+\r
+    @Override\r
+    public char charAt(int index) {\r
+        if(index < 0 || index >= length) {\r
+            throw new IndexOutOfBoundsException();\r
+        }\r
+        try {\r
+            return doc.getChar(offset + index);\r
+        } catch (BadLocationException e) {\r
+            throw new IndexOutOfBoundsException(e.getMessage());\r
+        }\r
+    }\r
+\r
+    @Override\r
+    public int length() {\r
+        return length;\r
+    }\r
+\r
+    @Override\r
+    public CharSequence subSequence(int start, int end) {\r
+        validate(start, end-start, length);\r
+        return new DocumentCharSequence(doc, offset+start, end - start);\r
+    }\r
+\r
+    public int nextCodePointIndex(int index) {\r
+        int codePoint = Character.codePointAt(this, index);        \r
+        return index + Character.charCount(codePoint);     \r
+    }\r
+    public int previousCodePointIndex(int index) {\r
+        int codePoint = Character.codePointBefore(this, index);        \r
+        return index - Character.charCount(codePoint);     \r
+    }\r
+}\r
diff --git a/jp.sourceforge.moreemacs/src/jp/sourceforge/moreemacs/utils/DocumentTransaction.java b/jp.sourceforge.moreemacs/src/jp/sourceforge/moreemacs/utils/DocumentTransaction.java
new file mode 100755 (executable)
index 0000000..f0749bd
--- /dev/null
@@ -0,0 +1,43 @@
+package jp.sourceforge.moreemacs.utils;\r
+\r
+import org.eclipse.jface.text.DocumentRewriteSession;\r
+import org.eclipse.jface.text.DocumentRewriteSessionType;\r
+import org.eclipse.jface.text.IDocument;\r
+import org.eclipse.jface.text.IDocumentExtension4;\r
+\r
+public final class DocumentTransaction {\r
+    private IDocumentExtension4 sessionManager;\r
+    private DocumentRewriteSession session;\r
+    \r
+    public DocumentTransaction(IDocument doc) {\r
+        if(doc instanceof IDocumentExtension4) {\r
+            sessionManager = (IDocumentExtension4)doc;\r
+        }\r
+    }\r
+    \r
+    public boolean isAvailable() {\r
+        return sessionManager != null;\r
+    }\r
+    \r
+    public void begin(DocumentRewriteSessionType type) {\r
+        if(!isAvailable()) {\r
+            return;\r
+        }\r
+        if(session != null) {\r
+            throw new IllegalStateException("session already started");\r
+        }\r
+        session = sessionManager.startRewriteSession(type);\r
+    }\r
+    \r
+    public void end() {\r
+        if(!isAvailable()) {\r
+            return;\r
+        }\r
+        if(session == null) {\r
+            throw new IllegalStateException("session is not started");\r
+        }\r
+        sessionManager.stopRewriteSession(session);\r
+        session = null;\r
+    }\r
+\r
+}\r