[Prime-cvs] CVS update: suikyo/ruby/src

アーカイブの一覧に戻る

Hiroyuki Komatsu komat****@users*****
2004年 12月 9日 (木) 16:05:36 JST


Index: suikyo/ruby/src/suikyo-composer.rb
diff -u suikyo/ruby/src/suikyo-composer.rb:1.2 suikyo/ruby/src/suikyo-composer.rb:1.3
--- suikyo/ruby/src/suikyo-composer.rb:1.2	Mon Dec  6 00:02:04 2004
+++ suikyo/ruby/src/suikyo-composer.rb	Thu Dec  9 16:05:36 2004
@@ -1,6 +1,6 @@
 # suikyo-composer.rb: Preedition composer using Suikyo.
 # This library is for input methods such as PRIME.
-# $Id: suikyo-composer.rb,v 1.2 2004/12/05 15:02:04 komatsu Exp $
+# $Id: suikyo-composer.rb,v 1.3 2004/12/09 07:05:36 komatsu Exp $
 #
 # Copyright (C) 2004 Hiroyuki Komatsu <komat****@taiya*****>
 #     All rights reserved.
@@ -45,16 +45,16 @@
 end
 
 class SuikyoComposerData
-  attr_reader :position, :head_chunk, :tail_chunk, :surface_mode, :typing_mode
-  def initialize (position, head_chunk, tail_chunk, surface_mode, typing_mode)
+  attr_reader :position, :head_chunk, :tail_chunk, :typing_mode
+  def initialize (position, head_chunk, tail_chunk, typing_mode)
     @position     = position
     @head_chunk   = head_chunk
     @tail_chunk   = tail_chunk
-    @surface_mode = surface_mode
-    @typing_mode  = typing_mode
+    @typing_mode = typing_mode
   end
 end
 
+## Main class of this file.
 class SuikyoComposer
   @@suikyo_katakana      = Suikyo.new("hiragana-katakana")
   @@suikyo_half_katakana = Suikyo.new("hiragana-halfkatakana")
@@ -63,17 +63,27 @@
   @@suikyo_half_katakana_reverse = Suikyo.new("halfkatakana-hiragana")
   @@suikyo_wide_ascii_reverse    = Suikyo.new("wideascii-ascii")
 
+  attr_accessor :mask, :hybrid_typing
   def initialize (table = nil, table_reverse = nil)
     @suikyo          = Suikyo.new(table)
     @suikyo_reverse  = Suikyo.new(table_reverse)
     
     reset_composer()
 
-    @surface_mode = :default  # :raw, :katakana, :wide_ascii, :half_katakana
-    @typing_mode  = :default  # :raw
+    ## @typing_mode means the current displaying method.  Its value is 
+    ## one of :default, :raw, :katakana, :wide_ascii, and :half_katakana.
+    @typing_mode = :default  
 
     @undo_data = []
     @redo_data = []  # not implemented yet.
+
+    ## If @mask is true, the surface of tail pending character will be masked
+    ## by "*".  For example "たいy" => "たい*".  This is usually for T-code.
+    @mask = false
+
+    ## If @hybrid_typing is true, Suikyo considers the validation of the
+    ## preedition.  ex). "あっplえ" => "apple".
+    @hybrid_typing = true
   end
 
   def reset_composer ()
@@ -100,7 +110,7 @@
   ## This method sets the current status to the undo buffer.
   def undo_set ()
     data = SuikyoComposerData.new(@position, @head_chunk, @tail_chunk,
-                                  @surface_mode, @typing_mode)
+                                  @typing_mode)
 #    @undo_data.push(data)
     @undo_data = [data]
   end
@@ -120,8 +130,7 @@
     @position     = data.position
     @head_chunk   = data.head_chunk
     @tail_chunk   = data.tail_chunk
-    @surface_mode = data.surface_mode
-    @typing_mode  = data.typing_mode
+    @typing_mode = data.typing_mode
 
     return true
   end
@@ -197,9 +206,9 @@
     end
 
     case @typing_mode
-    when :default then
+    when :default, :katakana, :half_katakana then
       @position = edit_backspace_internal_default(chunk)
-    when :raw then
+    else  # :raw, :wide_ascii
       @position = edit_backspace_internal_raw(chunk)
     end
     return @position
@@ -266,20 +275,15 @@
   def edit_display ()
     chunk = @head_chunk
     detail  = ""
-    surface = ""
     until chunk.chunk_next == @tail_chunk do 
       chunk     = chunk.chunk_next
       original  = chunk.original.nil? ? "*" : chunk.original.join()
       detail  += "[#{chunk.conversion.join}+#{chunk.pending.join}|#{original}]"
-      surface += chunk_get_surface(chunk)
     end
     puts(detail)
-    chars = surface.split(//)
-    if chars.length == 0 then
-      puts("|")
-    else
-      puts(chars[0, @ position].join + "|" + chars[@position..-1].join)
-    end
+
+    (left, cursor, right) = edit_get_preediting_string()
+    puts(left + "|" + cursor + right)
   end
 
   def get_position (chunk, offset = nil)
@@ -321,12 +325,81 @@
     return surface
   end
 
+  ## This method returns a translated string under the current mode.
+  ## If @mask is true, pending characters are masked by "*".
+  def edit_get_surface_string_masked ()
+    chunk = @head_chunk
+    surface = ""
+    until chunk.chunk_next == @tail_chunk do 
+      chunk    = chunk.chunk_next
+      surface += chunk_get_surface_masked(chunk)
+    end
+    return surface
+  end
+
+  ## This checks the validation of the preediting string.  If the preedition
+  ## is valid, it returns true.  If invalid, false.
+  ## ex). "apple (あっplえ)" => false, "ringo(りんご)" => true.
+  def hybrid_typing_check_validation ()
+    chunk = @head_chunk
+    (current_chunk, offset) = chunk_get_at(@position)
+    
+    flag_valid    = true
+    flag_original = true
+
+    until chunk.chunk_next == @tail_chunk do 
+      chunk = chunk.chunk_next
+
+      ## If pending characters exist in the preediting chunks except the last
+      ## chunk, the flag for validation becomes false.
+      if (chunk.pending.length > 0 and
+            chunk.chunk_next != @tail_chunk and chunk != current_chunk) or \
+        (chunk.pending.length + chunk.conversion.length == 0) then 
+        flag_valid = false
+      end
+
+      ## If there're chunks whose original value is nil, the flag for original
+      ## input becomes false.
+      if chunk.original.nil? then
+        flag_original = false
+      end
+    end
+
+    if flag_valid == false and flag_original == true then
+      return false
+    end
+    return true
+  end
+  
+  def hybrid_typing_update ()
+    unless @hybrid_typing then
+      return @typing_mode
+    end
+
+    new_mode = hybrid_typing_check_validation()  ?  :default  :  :raw
+
+    if new_mode == @typing_mode then
+      return @typing_mode
+    end
+
+    if new_mode == :default then
+      (chunk, offset) = edit_recover_conversion()
+    else  # @typing_mode == :raw
+      (chunk, offset) = edit_recover_original()
+    end
+    @typing_mode = new_mode
+    @position     = get_position(chunk, offset)
+    return @typing_mode
+  end
+
+
   ## This method returns a list of a translated string under the current mode.
   ## The list nodes are: [left-string, cursor-character, right-string]
   ## ex). "aiu|eo" => ["aiu", "e", "o"]
   def edit_get_preediting_string ()
-    surface = edit_get_surface_string()
-    chars = surface.split(//)
+    hybrid_typing_update()
+    surface = edit_get_surface_string_masked()
+    chars   = surface.split(//)
 
     left_string   = chars[0, @ position].join()
     cursor_string = (chars[@position] or "")
@@ -339,7 +412,7 @@
   ## Input Method Editor.  Basically it returns the original typed string,
   ## or the displayed string if the original string is broken.
   def edit_get_query_string ()
-    if @surface_mode != :default then
+    if @typing_mode != :default then
       return edit_get_surface_string()
     end
 
@@ -372,7 +445,7 @@
   ## preedition string.  For example, in the case the preedition is "sh",
   ## this returns ["sh", "しゃ", しゅ", "しょ"].
   def edit_get_expansion ()
-    if @typing_mode == :raw then
+    if @typing_mode == :raw  or  @typing_mode == :wide_ascii then
       return [ edit_get_surface_string() ]
     end
 
@@ -417,42 +490,46 @@
     return results
   end
 
+  def set_mode_hybrid ()
+    @hybrid_typing = true
+    hybrid_typing_update()
+  end
+
   def set_mode_default ()  # F6
+    @hybrid_typing = false
     (chunk, offset) = edit_recover_conversion()
-    @typing_mode  = :default
-    @surface_mode = :default
+    @typing_mode = :default
     @position = get_position(chunk, offset)
   end
 
   def set_mode_katakana ()  # F7
+    @hybrid_typing = false
     (chunk, offset) = edit_recover_conversion()
-    @typing_mode  = :default
-    @surface_mode = :katakana
+    @typing_mode = :katakana
     @position = get_position(chunk, offset)
   end
 
   def set_mode_half_katakana ()  # F8
+    @hybrid_typing = false
     (chunk, offset) = edit_recover_conversion()
-    @typing_mode  = :default
-    @surface_mode = :half_katakana
+    @typing_mode = :half_katakana
     @position = get_position(chunk, offset)
   end
 
   def set_mode_wide_ascii ()  # F9
+    @hybrid_typing = false
     (chunk, offset) = edit_recover_original()
-    @typing_mode  = :raw
-    @surface_mode = :wide_ascii
+    @typing_mode = :wide_ascii
     @position = get_position(chunk, offset)
   end
 
   def set_mode_raw ()  # F10
+    @hybrid_typing = false
     (chunk, offset) = edit_recover_original()
-    @typing_mode  = :raw
-    @surface_mode = :raw
+    @typing_mode = :raw
     @position = get_position(chunk, offset)
   end
 
-
   private
 
   ## This method converts the preedition string again and returns the
@@ -467,32 +544,39 @@
       offset = nil
     end
 
-    chunk   = @head_chunk
-    pending = ""
+    chunk         = @head_chunk
+    pending_chunk = nil
 
     until chunk.chunk_next == @tail_chunk do 
-      if chunk.chunk_next.conversion.length > 0 then
-        if pending != "" then
-          chunk = SuikyoCharChunk.new_next(chunk)
-          chunk = convert(chunk, pending)
+      if chunk.chunk_next.conversion.length > 0 or
+          chunk.chunk_next.pending.length > 0 then
+        if pending_chunk then
+          chunk = convert(pending_chunk, "")
         end
         chunk = chunk.chunk_next
-        pending = ""
+        pending_chunk = nil
       else  # chunk.chunk_next.conversion.length == 0
         chunk      = chunk.chunk_next
-        pending   += chunk.pending.join()
-        next_chunk = chunk_delete(chunk)
-        if cur_chunk == chunk then
-          cur_chunk = next_chunk
-          offset    = nil
+
+        if pending_chunk then
+          pending_chunk.pending += chunk.original
+          next_chunk = chunk_delete(chunk)
+
+          if cur_chunk == chunk then
+            cur_chunk = next_chunk
+            offset    = nil
+          end
+          chunk = next_chunk
+        else
+          pending_chunk = chunk
+          pending_chunk.conversion = []
+          pending_chunk.pending    = pending_chunk.original.dup
         end
-        chunk = next_chunk
       end
     end
 
-    if pending != "" then
-      chunk = SuikyoCharChunk.new_next(chunk)
-      chunk = convert(chunk, pending)
+    if pending_chunk then
+      chunk = convert(pending_chunk, "")
     end
     return [cur_chunk, offset]
   end
@@ -510,33 +594,41 @@
     end
 
     chunk     = @head_chunk
+    reconv_chunk = nil
     reconv    = ""
 
     until chunk.chunk_next == @tail_chunk do 
       if chunk.chunk_next.original then
-        if reconv != "" then
-          input = @suikyo_reverse.convert( reconv + " " )
-          chunk = SuikyoCharChunk.new_next(chunk)
-          chunk = convert(chunk, input)
+        if reconv_chunk then
+          input = @suikyo_reverse.convert( reconv_chunk.conversion.join + " " )
+          reconv_chunk.conversion = []
+          chunk = convert(reconv_chunk, input)
         end
         chunk = chunk.chunk_next
-        reconv = ""
+        reconv_chunk = nil
       else
-        chunk      = chunk.chunk_next
-        reconv    += chunk.conversion.join()
-        next_chunk = chunk_delete(chunk)
-        if cur_chunk == chunk then
-          cur_chunk = next_chunk
-          offset  = 0
+        chunk = chunk.chunk_next
+        if reconv_chunk then
+          reconv_chunk.conversion += chunk.conversion + chunk.pending
+          next_chunk = chunk_delete(chunk)
+          if cur_chunk == chunk then
+            cur_chunk = next_chunk
+            offset  = 0
+          end
+          chunk = next_chunk
+        else
+          reconv_chunk = chunk
+          reconv_chunk.conversion += reconv_chunk.pending
+          reconv_chunk.pending  = []
+          reconv_chunk.original = []
         end
-        chunk = next_chunk
       end
     end
 
-    if reconv != "" then
-      input = @suikyo_reverse.convert( reconv + " " )
-      chunk = SuikyoCharChunk.new_next(chunk)
-      chunk = convert(chunk, input)
+    if reconv_chunk then
+      input = @suikyo_reverse.convert( reconv_chunk.conversion.join + " " )
+      reconv_chunk.conversion = []
+      chunk = convert(reconv_chunk, input)
     end
 
     return [cur_chunk, offset]
@@ -559,17 +651,36 @@
   ## This function returns a string of the specified SuikyoChunk.for display.
   ## The string is depend on the current typing_mode.
   def chunk_get_surface (chunk)
-    if @typing_mode == :default then
+    case @typing_mode
+    when :default, :katakana, :half_katakana then
       string = chunk.conversion.join() + chunk.pending.join()
-    else  # @typing_mode == :raw
+    else  # @typing_mode == :raw, :wide-ascii
+      string = chunk.original.join()
+    end
+    return suikyo_convert(string)
+  end
+
+  ## This is basically the same with chunk_get_surface.  The difference is 
+  ## that if @mask is true this method masks pending characters with "*".
+  def chunk_get_surface_masked (chunk)
+    case @typing_mode
+    when :default, :katakana, :half_katakana then
+      if @mask then
+        string = chunk.conversion.join() + ("*" * chunk.pending.length())
+      else
+        string = chunk.conversion.join() + chunk.pending.join()
+      end
+    else  # @typing_mode == :raw, :wide-ascii
       string = chunk.original.join()
     end
     return suikyo_convert(string)
   end
 
+
+
   ## This returns the result of suikyo.convert in each surface mode.
   def suikyo_convert (string)
-    case @surface_mode
+    case @typing_mode
     when :default then        # F6
       retur****@suiky*****(string)
     when :katakana then       # F7
@@ -585,7 +696,7 @@
 
   ## This reconverts a string to the default surface and returns it.
   def suikyo_reconvert_to_default (string)
-    case @surface_mode
+    case @typing_mode
     when :default then        # F6
       return string
     when :katakana then       # F7
@@ -600,7 +711,7 @@
   end
 
   ## This function returns the length of the specified SuikyoChunk.
-  ## The value is depend on the current surface_mode.
+  ## The value is depend on the current typing_mode.
   def chunk_get_length (chunk)
     return chunk_get_surface(chunk).split(//).length()
   end
@@ -628,61 +739,13 @@
   ## and returns true.  If it failed, it returns false.
   def chunk_split (chunk, position)
     case @typing_mode
-    when :default then
+    when :default, :katakana, :half_katakana then
       return chunk_split_default(chunk, position)
-    when :raw then
+    else  # :raw,  :wide_ascii
       return chunk_split_raw(chunk, position)
     end
   end
 
-  def chunk_split_default2 (chunk, position)
-    puts "chunk_split_default (#{chunk}, #{position})"
-    puts "chunk_length = #{chunk_get_length(chunk)}"
-    if position > chunk_get_length(chunk) or position <= 0 then
-      return false
-    end
-
-    ### Separate into two chunks
-    ## Getting the pending and conversion data of left and right chunks.
-    original = chunk.original
-    if position > chunk.conversion.length then
-      position_pending = position - chunk.conversion.length
-      left_pending     = chunk.pending[0,position_pending]
-      left_conversion  = chunk.conversion
-      right_pending    = chunk.pending[position_pending..-1]
-      right_conversion = []
-    else  # position <= chunk.conversion.length
-      left_pending     = []
-      left_conversion  = chunk.conversion[0,position]
-      right_pending    = chunk.pending
-      right_conversion = chunk.conversion[position..-1]
-    end
-
-    ## Getting the data original of left and right chunks.
-    left_original  = nil
-    right_original = nil
-    if original != nil and right_conversion == [] then
-      index = original.join.rindex(right_pending.join)
-      if index != nil then
-        left_original  = original[0,index]
-        right_original = original[index..-1]
-      end
-    end
-
-    ## Reflecting the data to chunks.
-    chunk.conversion = suikyo_reconvert_to_default( left_conversion )
-    chunk.pending    = suikyo_reconvert_to_default( left_pending )
-    chunk.original   = left_original
-    if right_conversion.length > 0 or right_pending.length > 0 then
-      right_chunk = SuikyoCharChunk.new_next(chunk)
-      right_chunk.conversion = suikyo_reconvert_to_default( right_conversion )
-      right_chunk.pending    = suikyo_reconvert_to_default( right_pending )
-      right_chunk.original   = right_original
-    end
-
-    return true
-  end
-
   def chunk_split_default (chunk, position)
     if position > chunk_get_length(chunk) or position <= 0 then
       return false


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