*** empty log message ***
[m17n/m17n-lib-js.git] / xex.js
diff --git a/xex.js b/xex.js
index 7b1ab7e..1527050 100644 (file)
--- a/xex.js
+++ b/xex.js
@@ -183,9 +183,9 @@ Xex.Macro.prototype.Call = function (domain, vari, args)
       domain.Bind (this.args[i], args[i]);
     try {
       domain.Catch (Xex.CatchTag.Return);
-      for (var term in body)
+      for (var i in this.body)
         {
-         result = term.Eval (domain);
+         result = this.body[i].Eval (domain);
          if (domain.Thrown ())
            break;
        }
@@ -677,7 +677,9 @@ Xex.Funcall = function (func, vari, args)
 
   proto.Eval = function (domain)
   {
-    Xex.Log (this, domain.depth++);
+    if (! (this.func instanceof Xex.Subrountine))
+      Xex.Log (this, domain.depth);
+    domain.depth++;
     var result;
     try {
       result = this.func.Call (domain, this.vari, this.args);
@@ -1057,9 +1059,9 @@ Xex.LstTerm = function (list) { this.val = list; };
   {
     for (var i = 0; i < args.length; i++)
       {
-       var list = args[i].val;
-       var result = list.val[0].Eval (doamin);
-       if (result.isTrue ())
+       var list = args[i];
+       var result = list.val[0].Eval (domain);
+       if (result.IsTrue ())
          {
            for (var j = 1; j < list.val.length; j++)
              {
@@ -1436,6 +1438,8 @@ var MIM = {
   MIM.NamedMarker.prototype.Position = function (ic)
   {
     var p = ic.marker_positions[this.val];
+    if (p == undefined)
+      Xex.Log ('no position of ' + this.val);
     return (p == undefined ? 0 : p);
   }
   MIM.NamedMarker.prototype.Mark = function (ic)
@@ -1974,7 +1978,7 @@ MIM.im_domain.DefType (MIM.State.prototype);
       text = String.fromCharCode (args[0].val);
     else
       text = args[0].val;
-    domain.context.insert (text, null);
+    domain.context.ins (text, null);
     return args[0];
   }
 
@@ -1983,7 +1987,7 @@ MIM.im_domain.DefType (MIM.State.prototype);
     var ic = domain.context;
     var gsize = domain.variables['candidates_group_size'];
     var candidates = new MIM.Candidates (args, gsize ? gsize.Intval : 0);
-    ic.insert (candidates.Current (), candidates);
+    ic.ins (candidates.Current (), candidates);
     return args[0];
   }
 
@@ -1991,8 +1995,7 @@ MIM.im_domain.DefType (MIM.State.prototype);
   {
     var ic = domain.context;
     var pos = args[0].IsInt ? args[0].Intval : args[0].Position (ic);
-    ic.del (pos);
-    return new Xex.Term (ic.del (pos));
+    return new Xex.IntTerm (ic.del (pos));
   }
 
   function Fselect (domain, vari, args)
@@ -2002,12 +2005,12 @@ MIM.im_domain.DefType (MIM.State.prototype);
 
     if (can)
       {
-       var candidate = can.Current ();
-
-       ic.del (ic.cursor_pos - candidate.length);
-       candidate = can.Select (args[0]);
-       ic.insert (candidate, can);
+       var old_text = can.Current ();
+       var new_text = can.Select (args[0]);
+       ic.rep (old_text, new_text, can);
       }
+    else
+      Xex.Log ('no candidates');
     return args[0];
   }
 
@@ -2021,7 +2024,7 @@ MIM.im_domain.DefType (MIM.State.prototype);
     var ic = domain.context;
     var pos = args[0].IsInt ? args[0].val : args[0].Position (ic);
     ic.move (pos);
-    return args[0];
+    return new Xex.IntTerm (pos);
   }
 
   function Fmark (domain, vari, args)
@@ -2032,12 +2035,10 @@ MIM.im_domain.DefType (MIM.State.prototype);
 
   function Fpushback (domain, vari, args)
   {
-    var a = (args[0].IsInt ? args[0].Intval
+    var a = (args[0].IsInt ? args[0].Intval ()
             : args[0].IsStr ? new KeySeq (args[0])
             : args[0]);
-    Xex.Log ("pushing back: " + a);
     domain.context.pushback (a);
-    Xex.Log ("head key: " + domain.context.keys[domain.context.key_head]);
     return args[0];
   }
 
@@ -2280,7 +2281,13 @@ MIM.im_domain.DefType (MIM.State.prototype);
     this.target = target;
     this.domain = new Xex.Domain ('context', im.domain, this);
     this.active = true;
-    this.spot = 0;
+    this.range = new Array ();
+    this.range[0] = this.range[1] = 0;
+    this.state = null;
+    this.initial_state = this.im.initial_state;
+    this.keys = new MIM.KeySeq ();
+    this.marker_positions = {};
+    this.candidate_table = new MIM.CandidateTable ();
     this.reset ();
   }
 
@@ -2395,7 +2402,7 @@ MIM.im_domain.DefType (MIM.State.prototype);
            for (var i = this.state_key_head; i < this.key_head; i++)
              {
                Xex.Log ('inserting key:' + this.keys.val[i].key);
-               this.insert (this.keys.val[i].key, null);
+               this.ins (this.keys.val[i].key, null);
              }
          }
        if (! this.keymap.submaps)
@@ -2445,23 +2452,15 @@ MIM.im_domain.DefType (MIM.State.prototype);
   proto = {
     reset: function ()
     {
-      this.produced = null;
-      this.preedit = '';
-      this.preedit_saved = '';
       this.cursor_pos = 0;
-      this.marker_positions = {};
       this.candidates = null;
       this.candidate_show = false;
-      this.state = null;
       this.prev_state = null;
-      this.initial_state = this.im.initial_state;
       this.title = this.initial_state.title;
       this.state_preedit = '';
       this.state_key_head = 0;
       this.state_var_values = {};
       this.state_pos = 0;
-      this.keymap = null;
-      this.keys = new MIM.KeySeq ();
       this.key_head = 0;
       this.key_unhandled = false;
       this.unhandled_key = null;
@@ -2471,10 +2470,11 @@ MIM.im_domain.DefType (MIM.State.prototype);
       this.produced = '';
       this.preedit = '';
       this.preedit_saved = '';
-      this.marker_positions = {};
-      this.candidate_table = new MIM.CandidateTable ();
+      this.candidate_table.clear ();
       this.candidates = null;
       this.candidate_show = false;
+      for (var elt in this.marker_positions)
+       this.marker_positions[elt] = 0;
       this.shift (this.initial_state);
     },
 
@@ -2492,20 +2492,69 @@ MIM.im_domain.DefType (MIM.State.prototype);
 
     GetSurroundingChar: function (pos)
     {
-      pos += this.spot;
-      if (pos < 0 || pos >= this.target.value.length)
-       return 0;
+      if (pos < 0)
+       {
+         pos += this.range[0];
+         if (pos < 0)
+           return 0;
+       }
+      else
+       {
+         pos += this.range[1];
+         if (pos >= this.target.value.length)
+           return 0;
+       }
       return this.target.value.charCodeAt (pos);
     },
     
+    DelSurroundText: function (pos)
+    {
+      var text;
+      if (pos < 0)
+       {
+         pos += this.range[0];
+         if (pos <= 0)
+           {
+             pos = 0; text = '';
+           }
+         else
+           text = this.target.value.substring (0, pos);
+         if (this.range[0] < this.target.value.length)
+           text += this.target.value.substring (this.range[0]);
+         this.target.value = text;
+         this.range[1] -= this.range[0] - pos;
+         this.range[0] = pos;
+       }
+      else
+       {
+         pos += this.range[1];
+         text = this.target.value.substring (0, this.range[1]);
+         if (pos >= this.target.value.length)
+           pos = this.target.value.length;
+         else
+           text += this.target.value.substring (pos);
+         this.target.value = text;
+       }
+    },
+
     adjust_markers: function (from, to, inserted)
     {
       var diff = inserted - (to - from);
 
       for (var m in this.marker_positions)
-       if (this.marker_positions[m] > from)
-         this.marker_positions[m] = (this.marker_positions[m] >= to
-                                     ? pos + diff : from);
+       {
+         var pos = this.marker_positions[m];
+         if (pos > to)
+           {
+             this.marker_positions[m] = pos + diff;
+             Xex.Log ('Marker ' + m + ' = ' + this.marker_positions[m]);
+           }
+         else if (pos > from)
+           {
+             this.marker_positions[m] = from;
+             Xex.Log ('Marker ' + m + ' = ' + this.marker_positions[m]);
+           }
+       }
       if (this.cursor_pos >= to)
        set_cursor.call (this, 'adjust', this.cursor_pos + diff);
       else if (this.cursor_pos > from)
@@ -2522,31 +2571,46 @@ MIM.im_domain.DefType (MIM.State.prototype);
        this.candidate_table.put (from, from + text.length, candidates)
     },
 
-    insert: function (text, candidates)
+    ins: function (text, candidates)
     {
       this.preedit_replace (this.cursor_pos, this.cursor_pos, text, candidates);
       this.changed = MIM.ChangedStatus.Preedit | MIM.ChangedStatus.CursorPos;
     },
 
+    rep: function (old_text, new_text, candidates)
+    {
+      this.preedit_replace (this.cursor_pos - old_text.length,
+                           this.cursor_pos, new_text, candidates);
+      this.changed = MIM.ChangedStatus.Preedit | MIM.ChangedStatus.CursorPos;
+    },
+
     del: function (pos)
     {
       var deleted = pos - this.cursor_pos;
-      if (pos < 0)
+      if (pos < this.cursor_pos)
        {
-         this.DelSurroundText (pos);
-         pos = 0;
+         if (pos < 0)
+           {
+             this.DelSurroundText (pos);
+             deleted = - this.cursor_pos;
+             pos = 0;
+           }
+         if (pos < this.cursor_pos)
+           this.preedit_replace (pos, this.cursor_pos, '', null);
        }
-      else if (pos > this.preedit.length)
+      else
        {
-         this.DelSurroundText (pos - this.preedit.length);
-         pos = this.preedit.length;
+         if (pos > this.preedit.length)
+           {
+             this.DelSurroundText (pos - this.preedit.length);
+             deleted = this.preedit.length - this.cursor_pos;
+             pos = this.preedit.length;
+           }
+         if (pos > this.cursor_pos)
+           this.preedit_replace (this.cursor_pos, pos, '', null);
        }
-      if  (pos < this.cursor_pos)
-       this.preedit = (this.preedit.substring (0, pos)
-                       + this.preedit.substring (this.cursor_pos));
-      else
-       this.preedit = (this.preedit.substring (0, this.cursor_pos)
-                       + this.predit.substring (pos));
+      if (deleted != 0)
+       this.changed = MIM.ChangedStatus.Preedit | MIM.ChangedStatus.CursorPos;
       return deleted;
     },
 
@@ -2832,14 +2896,22 @@ MIM.debug_print = function (event, ic)
     MIM.debug_nodes['status' + index].innerHTML = 'no IM';
   MIM.debug_nodes['keymap' + index].innerHTML = ic.state.name;
   MIM.debug_nodes['preedit' + index].innerHTML = ic.preedit;
+  if (index == 0)
+    {
+      MIM.debug_nodes.keypress.innerHTML = '';
+      MIM.debug_nodes.status1.innerHTML = '';
+      MIM.debug_nodes.keymap1.innerHTML = '';
+      MIM.debug_nodes.preedit1.innerHTML = ''
+    }
 };
 
-MIM.get_range = function (target, range)
+MIM.get_range = function (target, ic)
 {
+  var from, to;
   if (target.selectionStart != null) // for Mozilla
     {
-      range[0] = target.selectionStart;
-      range[1] = target.selectionEnd;
+      from = target.selectionStart;
+      to = target.selectionEnd;
     }
   else                         // for IE
     {
@@ -2848,9 +2920,15 @@ MIM.get_range = function (target, range)
 
       rr.moveToElementText (target);
       rr.setEndPoint ('EndToEnd', range);
-      range[0] = rr.text.length - r.text.length;
-      range[1] = rr.text.length;
+      from = rr.text.length - r.text.length;
+      to = rr.text.length;
     }
+  if (ic.range[0] == from && ic.range[1] == to
+      || (to == from && target.value.substring (from, to) == ic.preedit))
+    return true;
+  ic.range[0] = from;
+  ic.range[1] = to;
+  return false;
 }
 
 MIM.set_caret = function (target, ic)
@@ -2858,45 +2936,27 @@ MIM.set_caret = function (target, ic)
   if (target.setSelectionRange)        // Mozilla
     {
       var scrollTop = target.scrollTop;
-      target.setSelectionRange (ic.spot, ic.spot + ic.preedit.length);
+      target.setSelectionRange (ic.range[0], ic.range[1]);
       target.scrollTop = scrollTop;
     }
   else                         // IE
     {
       var range = target.createTextRange ();
-      range.moveStart ('character', ic.spot);
-      range.moveEnd ('character', ic.spot + ic.preedit.length);
+      range.moveStart ('character', ic.range[0]);
+      range.moveEnd ('character', ic.range[1]);
       range.select ();
     }
 };
 
-(function () {
-  var range = new Array ();
-
-  MIM.check_range = function (target, ic)
-  {
-    MIM.get_range (target, range);
-    if (range[0] != ic.spot || range[1] - range[0] != ic.preedit.length
-       || target.value.substring (range[0], range[1]) != ic.preedit)
-      {
-       Xex.Log ('reset:' + ic.spot + '-' + (ic.spot + ic.preedit.length)
-                + '/' + range[0] + '-' + range[1]);
-       ic.reset ();
-      }
-    target.value = (target.value.substring (0, range[0])
-                   + target.value.substring (range[1]));
-    ic.spot = range[0];
-  }
-}) ();
-
 MIM.update = function (target, ic)
 {
   var text = target.value;
-  target.value = (text.substring (0, ic.spot)
+  target.value = (text.substring (0, ic.range[0])
                  + ic.produced
                  + ic.preedit
-                 + text.substring (ic.spot));
-  ic.spot += ic.produced.length;
+                 + text.substring (ic.range[1]));
+  ic.range[0] += ic.produced.length;
+  ic.range[1] = ic.range[0] + ic.preedit.length;
   MIM.set_caret (target, ic);
 };
 
@@ -2904,11 +2964,11 @@ MIM.reset_ic = function (event)
 {
   if (event.target.mim_ic)
     {
-      var ic = event.target.mim_ic;
-      var pos = ic.spot + ic.preedit.length;
+      var target = event.target;
+      var ic = target.mim_ic;
+      if (ic.preedit.length > 0)
+       event.target.setSelectionRange (ic.range[1], ic.range[1]);
       ic.reset ();
-      if (pos > ic.spot)
-       event.target.setSelectionRange (pos, pos);
     }
 };
 
@@ -2923,14 +2983,20 @@ MIM.keydown = function (event)
   var ic = target.mim_ic;
   if (! ic || ic.im != MIM.current)
     {
+      target.mim_ic = null;
       Xex.Log ('creating IC');
       ic = new MIM.IC (MIM.current, target);
+      if (ic.im.load_status != MIM.LoadStatus.Loaded)
+       return;
       target.mim_ic = ic;
       MIM.add_event_listener (target, 'blur', MIM.reset_ic);
+      MIM.get_range (target, ic)
+    }
+  else
+    {
+      if (! MIM.get_range (target, ic))
+       ic.reset ();
     }
-  if (ic.im.load_status != MIM.LoadStatus.Loaded)
-    return;
-  MIM.check_range (target, ic);
   MIM.debug_print (event, ic);
   ic.key = MIM.decode_key_event (event);
 };