1 /* ***** BEGIN LICENSE BLOCK *****
  2  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  3  *
  4  * The contents of this file are subject to the Mozilla Public License Version
  5  * 1.1 (the "License"); you may not use this file except in compliance with
  6  * the License. You may obtain a copy of the License at
  7  * http://www.mozilla.org/MPL/
  8  *
  9  * Software distributed under the License is distributed on an "AS IS" basis,
 10  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 11  * for the specific language governing rights and limitations under the
 12  * License.
 13  *
 14  * The Initial Developer of the Original Code is Fireinput Inc.
 15  *
 16  * Portions created by the Initial Developer are Copyright (C) 2007
 17  * the Initial Developer. All Rights Reserved.
 18  *
 19  * Contributor(s):
 20  *     Olly Ja <ollyja@gmail.com>
 21  *
 22  * Alternatively, the contents of this file may be used under the terms of
 23  * either the GNU General Public License Version 2 or later (the "GPL"), or
 24  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 25  * in which case the provisions of the GPL or the LGPL are applicable instead
 26  * of those above. If you wish to allow use of your version of this file only
 27  * under the terms of either the GPL or the LGPL, and not to allow others to
 28  * use your version of this file under the terms of the MPL, indicate your
 29  * decision by deleting the provisions above and replace them with the notice
 30  * and other provisions required by the GPL or the LGPL. If you do not delete
 31  * the provisions above, a recipient may use your version of this file under
 32  * the terms of any one of the MPL, the GPL or the LGPL.
 33  *
 34  * ***** END LICENSE BLOCK ***** 
 35  */
 36 
 37 const PinyinInitials = [ "b", "c", "ch", "d", "f", "g", "h", "j", "k", "l", "m",
 38                           "n", "p","q", "r", "s", "sh", "t", "w", "x", "y", "z", "zh"];
 39 
 40 const PinyinFinals = ["a","ai", "an", "ang", "ao", "e", "ei", "en", "eng", "er",
 41                        "i", "ia", "ian", "iang", "iao", "ie", "in", "ing", "io", "ion", "iong",
 42                        "iou", "iu", "o", "on", "ong", "ou", "u", "ua", "uai", "uan",
 43                        "uang", "ue", "uei", "uen", "ueng", "ui", "un", "uo", "v", "van",
 44                        "ve", "vn"];  
 45 
 46 const PinyinAMBInitials  = ["zh z","ch c","sh s"];
 47 const PinyinAMBFinals  = ["an ang", "en eng","in ing"];
 48 
 49 const ZiGuangShuangPinInitials = [
 50        { key: "a", initials: "ch"      },
 51        { key: "b", initials: "b"       },
 52        { key: "c", initials: "c"       },
 53        { key: "d", initials: "d"       },
 54        { key: "f", initials: "f"       },
 55        { key: "g", initials: "g"       },
 56        { key: "h", initials: "h"       },
 57        { key: "i", initials: "sh"      },
 58        { key: "j", initials: "j"       },
 59        { key: "k", initials: "k"       },
 60        { key: "l", initials: "l"       },
 61        { key: "m", initials: "m"       },
 62        { key: "n", initials: "n"       },
 63        { key: "p", initials: "p"       },
 64        { key: "q", initials: "q"       },
 65        { key: "r", initials: "r"       },
 66        { key: "s", initials: "s"       },
 67        { key: "t", initials: "t"       },
 68        { key: "u", initials: "zh"      },
 69        { key: "w", initials: "w"       },
 70        { key: "x", initials: "x"       },
 71        { key: "y", initials: "y"       },
 72        { key: "z", initials: "z"       }
 73     ]; 
 74 
 75 const ZiGuangShuangPinFinals = [
 76        { key: "a", finals: "a"         },
 77        { key: "b", finals: "iao"       },
 78        { key: "c", finals: "ing"       },
 79        { key: "d", finals: "ie"        },
 80        { key: "e", finals: "e"         },
 81        { key: "f", finals: "ian"       },
 82        { key: "g", finals: "uang,iang" },
 83        { key: "h", finals: "ong,iong"  },
 84        { key: "i", finals: "i"         },
 85        { key: "j", finals: "iu,er"     },
 86        { key: "k", finals: "ei"        },
 87        { key: "l", finals: "uan"       },
 88        { key: "m", finals: "un"        },
 89        { key: "n", finals: "ui,ue"     },
 90        { key: "o", finals: "uo,o"      },
 91        { key: "p", finals: "ai"        },
 92        { key: "q", finals: "ao"        },
 93        { key: "r", finals: "an"        },
 94        { key: "s", finals: "ang"       },
 95        { key: "t", finals: "ng,eng"    },
 96        { key: "u", finals: "u"         },
 97        { key: "v", finals: "v"         },
 98        { key: "w", finals: "en"        },
 99        { key: "x", finals: "ia,ua"     },
100        { key: "y", finals: "in,uai"    },
101        { key: "z", finals: "ou"        }
102     ]; 
103    
104 const MSShuangPinInitials = [
105        { key: "b", initials: "b"       },
106        { key: "c", initials: "c"       },
107        { key: "d", initials: "d"       },
108        { key: "f", initials: "f"       },
109        { key: "g", initials: "g"       },
110        { key: "h", initials: "h"       },
111        { key: "i", initials: "ch"      },
112        { key: "j", initials: "j"       },
113        { key: "k", initials: "k"       },
114        { key: "l", initials: "l"       },
115        { key: "m", initials: "m"       },
116        { key: "n", initials: "n"       },
117        { key: "p", initials: "p"       },
118        { key: "q", initials: "q"       },
119        { key: "r", initials: "r"       },
120        { key: "s", initials: "s"       },
121        { key: "t", initials: "t"       },
122        { key: "u", initials: "sh"      },
123        { key: "v", initials: "zh"      },
124        { key: "w", initials: "w"       },
125        { key: "x", initials: "x"       },
126        { key: "y", initials: "y"       },
127        { key: "z", initials: "z"       }
128     ];
129  
130 const MSShuangPinFinals = [
131        { key: "a", finals: "a"         },
132        { key: "b", finals: "ou"        },
133        { key: "c", finals: "iao"       },
134        { key: "d", finals: "uang,iang" },  
135        { key: "e", finals: "e"         },
136        { key: "f", finals: "en"        },
137        { key: "g", finals: "ng,eng"    },
138        { key: "h", finals: "ang"       },
139        { key: "i", finals: "i"         },
140        { key: "j", finals: "an"        },
141        { key: "k", finals: "ao"        },
142        { key: "l", finals: "ai"        },
143        { key: "m", finals: "ian"       },
144        { key: "n", finals: "in"        },
145        { key: "o", finals: "o,uo"      },
146        { key: "p", finals: "un"        },
147        { key: "q", finals: "iu"        },
148        { key: "r", finals: "uan,er"    },
149        { key: "s", finals: "ong,iong"  },
150        { key: "t", finals: "ue"        },
151        { key: "u", finals: "u"         },
152        { key: "v", finals: "v,ui"      },
153        { key: "w", finals: "ia,ua"     },
154        { key: "x", finals: "ie"        },
155        { key: "y", finals: "uai"       },
156        { key: "z", finals: "ei"        },
157        { key: ";", finals: "ing"       }
158     ]; 
159 
160 const ChineseStarShuangPinInitials = [
161        { key: "b", initials: "b"       },
162        { key: "c", initials: "c"       },
163        { key: "d", initials: "d"       },
164        { key: "f", initials: "f"       },
165        { key: "g", initials: "g"       },
166        { key: "h", initials: "h"       },
167        { key: "i", initials: "sh"      },
168        { key: "j", initials: "j"       },
169        { key: "k", initials: "k"       },
170        { key: "l", initials: "l"       },
171        { key: "m", initials: "m"       },
172        { key: "n", initials: "n"       },
173        { key: "p", initials: "p"       },
174        { key: "q", initials: "q"       },
175        { key: "r", initials: "r"       },
176        { key: "s", initials: "s"       },
177        { key: "t", initials: "t"       },
178        { key: "u", initials: "ch"      },
179        { key: "v", initials: "zh"      },
180        { key: "w", initials: "w"       },
181        { key: "x", initials: "x"       },
182        { key: "y", initials: "y"       },
183        { key: "z", initials: "z"       }
184     ];
185   
186 const ChineseStarShuangPinFinals = [
187        { key: "a", finals: "a"         },
188        { key: "b", finals: "ia,ua"     },
189        { key: "c", finals: "uan"       },
190        { key: "d", finals: "ao"        },
191        { key: "e", finals: "e"         },
192        { key: "f", finals: "an"        },
193        { key: "g", finals: "ang"       },
194        { key: "h", finals: "uang,iang" },
195        { key: "i", finals: "i"         },
196        { key: "j", finals: "ian"       },
197        { key: "k", finals: "iao"       },
198        { key: "l", finals: "in"        },
199        { key: "m", finals: "ie"        },
200        { key: "n", finals: "iu"        },
201        { key: "o", finals: "uo,o"      },
202        { key: "p", finals: "ou"        },
203        { key: "q", finals: "ing,er"    },
204        { key: "r", finals: "en"        },
205        { key: "s", finals: "ai"        },
206        { key: "t", finals: "ng,eng"    },
207        { key: "u", finals: "u"         },
208        { key: "v", finals: "v,ui"      },
209        { key: "w", finals: "ei"        },
210        { key: "x", finals: "uai,ue"    },
211        { key: "y", finals: "ong,iong"  },
212        { key: "z", finals: "un"        }
213     ];
214 
215 const SmartABCShuangPinInitials = [
216        { key: "a", initials: "zh"      },
217        { key: "b", initials: "b"       },
218        { key: "c", initials: "c"       },
219        { key: "d", initials: "d"       },
220        { key: "e", initials: "ch"      },
221        { key: "f", initials: "f"       },
222        { key: "g", initials: "g"       },
223        { key: "h", initials: "h"       },
224        { key: "j", initials: "j"       },
225        { key: "k", initials: "k"       },
226        { key: "l", initials: "l"       },
227        { key: "m", initials: "m"       },
228        { key: "n", initials: "n"       },
229        { key: "p", initials: "p"       },
230        { key: "q", initials: "q"       },
231        { key: "r", initials: "r"       },
232        { key: "s", initials: "s"       },
233        { key: "t", initials: "t"       },
234        { key: "v", initials: "sh"      },
235        { key: "w", initials: "w"       },
236        { key: "x", initials: "x"       },
237        { key: "y", initials: "y"       },
238        { key: "z", initials: "z"       }
239     ];
240 
241 const SmartABCShuangPinFinals = [
242        { key: "a", finals: "a"         },
243        { key: "b", finals: "ou"        },
244        { key: "c", finals: "in,uai"    },
245        { key: "d", finals: "ia,ua"     },
246        { key: "e", finals: "e"         },
247        { key: "f", finals: "en"        },
248        { key: "g", finals: "ng,eng"    },
249        { key: "h", finals: "ang"       },
250        { key: "i", finals: "i"         },
251        { key: "j", finals: "an"        },
252        { key: "k", finals: "ao"        },
253        { key: "l", finals: "ai"        },
254        { key: "m", finals: "ui,ue"     },
255        { key: "n", finals: "un"        },
256        { key: "o", finals: "uo,o"      },
257        { key: "p", finals: "uan"       },
258        { key: "q", finals: "ei"        },
259        { key: "r", finals: "iu,er"     },
260        { key: "s", finals: "ong,iong"  },
261        { key: "t", finals: "uang,iang" },
262        { key: "u", finals: "u"         },
263        { key: "v", finals: "v"         },
264        { key: "w", finals: "ian"       },
265        { key: "x", finals: "ie"        },
266        { key: "y", finals: "ing"       },
267        { key: "z", finals: "iao"       }
268     ];
269 
270  
271 var PinyinSchema = function() {}; 
272 
273 PinyinSchema.prototype = 
274 {
275     debug: 0, 
276     pinyinInitials: null,
277     pinyinFinals: null,
278     pinyinAMBInitialHash: null, 
279     pinyinAMBFinalHash: null, 
280     pinyinSchema: SMART_PINYIN, 
281     enableAMBZh: false, 
282     enableAMBSh: false, 
283     enableAMBCh: false, 
284     enableAMBAng: false, 
285     enableAMBEng: false, 
286     enableAMBIng: false, 
287 
288     getSchema: function()
289     {
290        return this.pinyinSchema;
291     }, 
292 
293     setSchema: function(schema)
294     {
295        this.pinyinInitials = new FireinputHash(); 
296        this.pinyinFinals = new FireinputHash(); 
297        this.pinyinSchema = schema; 
298 
299        switch(schema)
300        {
301           case ZIGUANG_SHUANGPIN: 
302              for(var i=ZiGuangShuangPinInitials.length-1; i>=0; i--)
303              {
304                 this.pinyinInitials.setItem(ZiGuangShuangPinInitials[i].key, 
305                                        ZiGuangShuangPinInitials[i].initials); 
306              }
307              for(var i=ZiGuangShuangPinFinals.length-1; i>=0; i--)
308              {
309                 this.pinyinFinals.setItem(ZiGuangShuangPinFinals[i].key, 
310                                        ZiGuangShuangPinFinals[i].finals); 
311              }
312           break; 
313 
314           case MS_SHUANGPIN: 
315              for(var i=MSShuangPinInitials.length-1; i>=0; i--)
316              {
317                 this.pinyinInitials.setItem(MSShuangPinInitials[i].key, 
318                                        MSShuangPinInitials[i].initials);
319              }
320              for(var i=MSShuangPinFinals.length-1; i>=0; i--)
321              {
322                 this.pinyinFinals.setItem(MSShuangPinFinals[i].key, 
323                                        MSShuangPinFinals[i].finals);
324              }
325           break;
326 
327           case CHINESESTAR_SHUANGPIN: 
328              for(var i=ChineseStarShuangPinInitials.length-1; i>=0; i--)
329              {
330                 this.pinyinInitials.setItem(ChineseStarShuangPinInitials[i].key, 
331                                        ChineseStarShuangPinInitials[i].initials);
332              }
333              for(var i=ChineseStarShuangPinFinals.length-1; i>=0; i--)
334              {
335                 this.pinyinFinals.setItem(ChineseStarShuangPinFinals[i].key, 
336                                        ChineseStarShuangPinFinals[i].finals);
337              }
338           break;
339 
340           case SMARTABC_SHUANGPIN: 
341              for(var i=SmartABCShuangPinInitials.length-1; i>=0; i--)
342              {
343                 this.pinyinInitials.setItem(SmartABCShuangPinInitials[i].key, 
344                                        SmartABCShuangPinInitials[i].initials);
345              }
346              for(var i=SmartABCShuangPinFinals.length-1; i>=0; i--)
347              {
348                 this.pinyinFinals.setItem(SmartABCShuangPinFinals[i].key, 
349                                        SmartABCShuangPinFinals[i].finals);
350              }
351           break;
352 
353           default: 
354              this.pinyinSchema = SMART_PINYIN; 
355           break;
356        }
357 
358        this.initAMB(); 
359     },
360 
361     initAMB: function()
362     {
363        if(this.pinyinAMBInitialHash != null)
364           return; 
365 
366        this.setAMBOption();
367        FireinputPref.addObserver(this, false);	
368        this.pinyinAMBInitialHash = new FireinputHash(); 
369        this.pinyinAMBFinalHash = new FireinputHash(); 
370 
371        //FIXME: should be based on configuration 
372        for(var i=0; i<PinyinAMBInitials.length; i++)
373        {
374           var strArray = PinyinAMBInitials[i].split(' ');
375           if(strArray.length < 2) 
376              continue; 
377           for(var j=0; j<PinyinFinals.length; j++)
378           {
379                this.pinyinAMBInitialHash.setItem(strArray[0]+PinyinFinals[j], strArray[1]+PinyinFinals[j]); 
380           }
381        }
382 
383        for(var i=0; i<PinyinAMBFinals.length; i++)
384        {
385           var strArray = PinyinAMBFinals[i].split(' ');
386           if(strArray.length < 2) 
387              continue; 
388           for(var j=0; j<PinyinInitials.length; j++)
389           {
390                this.pinyinAMBFinalHash.setItem(PinyinInitials[j]+strArray[0], PinyinInitials[j]+strArray[1]); 
391           }
392           // put final in as well 
393           this.pinyinAMBFinalHash.setItem(strArray[0], strArray[1]); 
394        }
395     }, 
396 
397     getAllowedKeys: function()
398     {
399        var allowedKeys = ""; 
400        var self  =  this; 
401        this.pinyinInitials.foreach ( function(k, v) { allowedKeys += k; }); 
402        this.pinyinFinals.foreach ( function(k, v) { if(!self.pinyinInitials.hasItem(k)) {allowedKeys += k; }}); 
403 
404        // smart pinyin by default 
405        if(allowedKeys.length <= 0)
406           allowedKeys = "abcdefghijklmnopqrstuvwxyz"; 
407 
408        return allowedKeys; 
409 
410     }, 
411 
412     observe: function(subject, topic, data)
413     {
414         var name = data.substr(prefDomain.length+1);
415         this.setAMBOption(name);
416     },
417      
418     setAMBOption: function(option)
419     {
420 
421        if(!option || option == "fireinputAMBZh")
422          this.enableAMBZh = FireinputPrefDefault.getAMBOption("fireinputAMBZh");
423 
424        if(!option || option == "fireinputAMBSh")
425          this.enableAMBSh = FireinputPrefDefault.getAMBOption("fireinputAMBSh");
426 
427        if(!option || option == "fireinputAMBCh")
428          this.enableAMBCh = FireinputPrefDefault.getAMBOption("fireinputAMBCh");
429 
430        if(!option || option == "fireinputAMBAng")
431          this.enableAMBAng = FireinputPrefDefault.getAMBOption("fireinputAMBAng");
432 
433        if(!option || option == "fireinputAMBEng")
434          this.enableAMBEng = FireinputPrefDefault.getAMBOption("fireinputAMBEng");
435 
436        if(!option || option == "fireinputAMBIng")
437          this.enableAMBIng = FireinputPrefDefault.getAMBOption("fireinputAMBIng");
438     },
439 
440     getAMBKeys: function (ikey)
441     {
442        if(this.getSchema() != SMART_PINYIN)
443           return null; 
444 
445        var ambKeys = [];
446 
447        if((this.enableAMBZh && /^z/.test(ikey)) || 
448           (this.enableAMBSh && /^s/.test(ikey)) ||
449           (this.enableAMBCh && /^c/.test(ikey)))
450        {
451           if(this.pinyinAMBInitialHash.hasItem(ikey))
452           {
453              ambKeys[ambKeys.length] = this.pinyinAMBInitialHash.getItem(ikey); 
454 
455              if((this.enableAMBAng && (/an$/.test(ikey) || /ang$/.test(ikey))) || 
456                 (this.enableAMBEng && (/en$/.test(ikey) || /eng$/.test(ikey))) || 
457                 (this.enableAMBIng && (/in$/.test(ikey) || /ing$/.test(ikey))))
458              {
459                 if(this.pinyinAMBFinalHash.hasItem(ikey))
460                    ambKeys[ambKeys.length] = this.pinyinAMBFinalHash.getItem(ikey); 
461              }
462           }
463         }
464  
465         return ambKeys; 
466     }, 
467 
468     // ikey/mkey should be: 
469     //    zan => zhang: final hash
470     //    zan =>zhan: initial hash 
471     //
472     compareAMB: function(ikey, mkey)
473     {
474        if(this.getSchema() != SMART_PINYIN)
475           return false; 
476 
477        return this.compareAMBInitial(ikey, mkey) || this.compareAMBFinal(ikey, mkey);  
478     },
479  
480     compareAMBInitial: function(ikey, mkey)
481     {
482        if(ikey == mkey)
483           return true; 
484 
485        if((this.enableAMBZh && /^z/.test(ikey)) || 
486           (this.enableAMBSh && /^s/.test(ikey)) ||
487           (this.enableAMBCh && /^c/.test(ikey)))
488        {
489           if(this.pinyinAMBInitialHash.hasItem(ikey))
490           {
491              if (this.pinyinAMBInitialHash.getItem(ikey) == mkey) 
492                 return true; 
493              // mapping such as zen -> zheng 
494              if(this.compareAMBFinal(this.pinyinAMBInitialHash.getItem(ikey), mkey))
495                 return true; 
496 
497              return false; 
498           }
499           else if(this.pinyinAMBInitialHash.hasItem(mkey))
500           {
501              if (this.pinyinAMBInitialHash.getItem(mkey) == ikey)
502                 return true; 
503 
504              // mapping such as zen -> zheng 
505              if(this.compareAMBFinal(this.pinyinAMBInitialHash.getItem(mkey), ikey))
506                 return true; 
507 
508              return false; 
509           }
510        }
511 
512        return false; 
513     }, 
514 
515     compareAMBFinal: function(ikey, mkey)
516     {
517        if((this.enableAMBAng && (/an$/.test(ikey) || /ang$/.test(ikey))) || 
518           (this.enableAMBEng && (/en$/.test(ikey) || /eng$/.test(ikey))) || 
519           (this.enableAMBIng && (/in$/.test(ikey) || /ing$/.test(ikey))))
520        {
521           if(this.pinyinAMBFinalHash.hasItem(ikey))
522           {
523              return (this.pinyinAMBFinalHash.getItem(ikey) == mkey); 
524           }
525           else if(this.pinyinAMBFinalHash.hasItem(mkey))
526           {
527              return (this.pinyinAMBFinalHash.getItem(mkey) == ikey); 
528           }
529        }
530 
531        return false; 
532     }, 
533 
534     getKeyByFormat: function(keys, format)
535     {
536        var keyArray = new Array(); 
537        var keySet = new Array();
538        var k;
539        var useFormat = ""; 
540 
541        for(var i=0; i<format.length;)
542        {
543           var fkey = format.substr(i, 1); 
544           var ykey = format.substr(i+1, 1); 
545           if(fkey == "s")
546           {
547              // it's initial 
548              var c1 = keys.substr(i,1);
549              if(this.pinyinInitials.hasItem(c1) || c1 == "o")
550              {
551                 var firstKey = ""; 
552                 if(c1 != "o")
553                 {
554                    firstKey = this.pinyinInitials.getItem(c1);
555                 }
556                 else 
557                 {
558                    if(ykey == 's') 
559                       ykey = "y"; 
560                    firstKey = "o"; 
561                 }
562  
563                 // if keyArray has saved a list of keys, append the new key to each of them
564                 // otherwise just add to keySet only 
565                 
566                 // check second key whether it's y or s 
567                 var c2 = keys.substr(i+1,1);
568                 if(ykey == 's' && !this.pinyinInitials.hasItem(c2))
569                     ykey = 'y'; 
570                 if(ykey == 'y' && !this.pinyinFinals.hasItem(c2))
571                     ykey = 's'; 
572                 
573                 if(ykey != "y")
574                 {
575                    if(keyArray.length > 0)
576                    {
577                       for (var ii=0; ii<keyArray.length; ii++)
578                       {
579                          keyArray[ii].push({key: firstKey, type: KEY_INITIAL}); 
580                       }
581                    }
582                    else
583                       keySet.push({key: firstKey, type: KEY_INITIAL}); 
584                 }
585                 else if(ykey == "y")
586                 {
587                   
588                    if(firstKey == "o")
589                       firstKey = ""; 
590 
591                    var keyType = firstKey.length>0 ? KEY_FULL : KEY_FINAL; 
592                    if(this.pinyinFinals.hasItem(c2))
593                    {
594                       var finalArray = this.pinyinFinals.getItem(c2).split(",");
595                       if(keyArray.length > 0)
596                       {
597                           for(var ii=0; ii<keyArray.length; ii++)  
598                           {
599                            keyArray[ii].push({key: firstKey+finalArray[0], type: keyType}); 
600                           }
601                       }
602                       else 
603                           keySet.push({key: firstKey+finalArray[0], type: keyType}); 
604 
605                       // multiple finals. We have save the previous keyset and create a matrix table here 
606                       // to list all possibilities 
607                       if(finalArray.length > 1)
608                       {
609                          if(keyArray.length > 0)
610                          {
611                             var keyArrayCloned = cloneArray(keyArray); 
612                             for(var jj=0; jj<keyArrayCloned.length; jj++)
613                             {
614                                keyArrayCloned[jj].pop(); 
615                                keyArrayCloned[jj].push({key: firstKey+finalArray[1], type: keyType}); 
616                                keyArray.push(keyArrayCloned[jj]); 
617                             }
618                          }   
619                          else
620                          {
621                             keyArray.push(keySet); 
622                             var keySetCloned = cloneArray(keySet); 
623                             keySetCloned.pop(); 
624                             keySetCloned.push({key: firstKey+finalArray[1], type: keyType}); 
625                             keyArray.push(keySetCloned); 
626                          }
627                       }
628                    } /* if in finals */   
629                 } /* else */
630              }
631           } /* first has to be s */
632 
633           // save format 
634           useFormat += fkey; 
635 
636           if(ykey == "y")
637           {
638              useFormat += ykey; 
639              i += 2; 
640           }
641           else
642              i++; 
643 
644             
645        }
646 
647        // FireinputLog.debug(this, "format: " + format + ", Return format: " + useFormat); 
648        // mkey: a flag to show if the return has multiple set 
649        return {format: useFormat, keyset: keyArray.length > 0 ? keyArray: keySet, mkey: keyArray.length > 0 ? 1:0}; 
650     }, 
651 
652 
653     getComposeKey: function(keys, useDefaultSchema)
654     {
655        var keyArray = new Array(); 
656        // 两字词:输入两字的双拼码 (SY);
657        // 三字词:输入前两个字的声码和第三个字的双拼码,共4码 (SSSY);
658        // 四字词:输入每个字的声码,共4码 (SSSS);
659        // 五字词:输入前三个字和第五个字的声码,共4码 (SSSSS)。 FIXME: how ? 
660        
661        // upper level asks to use default schema: pingyin 
662        if(useDefaultSchema)
663           return keys; 
664 
665        switch(this.pinyinSchema)
666        {
667           case ZIGUANG_SHUANGPIN: 
668           case MS_SHUANGPIN: 
669           case CHINESESTAR_SHUANGPIN: 
670           case SMARTABC_SHUANGPIN: 
671              if(keys.length == 1)
672              {
673                 var keySet = new Array(); 
674                 if(this.pinyinInitials.hasItem(keys))
675                    keySet.push({key: this.pinyinInitials.getItem(keys), type: KEY_INITIAL}); 
676                 else
677                    keySet.push({key: keys, type: KEY_INITIAL}); 
678                 keyArray.push(keySet); 
679                 return keyArray; 
680              }
681              else if (keys.length == 2)
682              {
683                 var keySet = this.getKeyByFormat(keys, "sy"); 
684                 if(keySet.mkey)
685                    keyArray = keySet.keyset; 
686                 else
687                    keyArray.push(keySet.keyset); 
688 
689                 return keyArray; 
690              }
691              else if(keys.length == 3)
692              {
693                 // s -sy
694                 var keySet = this.getKeyByFormat(keys, "sss"); 
695                 if(keySet.mkey)
696                    keyArray = keySet.keyset; 
697                 else
698                    keyArray.push(keySet.keyset); 
699 
700                 var useFormat = keySet.format; 
701                 if(useFormat != "ssy")
702                 {
703                    keySet = this.getKeyByFormat(keys, "ssy"); 
704                    // ignore the keys if the returned format is not same as we expected: such as syy or sys 
705                    if(keySet.format == 'ssy')
706                    {
707                       if(keySet.mkey)
708                          arrayInsert(keyArray, keyArray.length, keySet.keyset); 
709                       else
710                          keyArray.push(keySet.keyset); 
711                    }
712                 }
713 
714                 if(useFormat != "sys")
715                 {
716                    keySet = this.getKeyByFormat(keys, "sys"); 
717                    // ignore the keys if the returned format is not same as we expected: such as syy  
718                    if(keySet.format == 'sys')
719                    {
720                       if(keySet.mkey)
721                          arrayInsert(keyArray, keyArray.length, keySet.keyset); 
722                       else
723                          keyArray.push(keySet.keyset); 
724                    }
725                 }
726 
727                 return keyArray; 
728              } 
729              else if(keys.length == 4)
730              {
731                 // s s s s 
732                 var keySet = this.getKeyByFormat(keys, "ssss"); 
733                 if(keySet.mkey)
734                    keyArray = keySet.keyset; 
735                 else
736                    keyArray.push(keySet.keyset); 
737 
738                 var useFormat = keySet.format; 
739 		// if ssss -> sysy, the keys will be in format as sysy, and cannot be in other formats 
740 		// if ssss -> sssy, then syss will be same as sysy
741 		// if ssss -> syss, then sssy will be same as sysy
742                 if(useFormat == "sysy")
743                    return keyArray; 
744 
745                 // if format changed, in any case only sysy will be valid format 
746                 if(useFormat != "ssss")
747                 {
748                    keySet = this.getKeyByFormat(keys, "sysy"); 
749                    if(keySet.mkey)
750                       arrayInsert(keyArray, keyArray.length, keySet.keyset); 
751                    else
752                       keyArray.push(keySet.keyset); 
753                    return keyArray; 
754                    
755                 }
756                 else 
757                 {
758                    keySet = this.getKeyByFormat(keys, "sssy"); 
759                    if(keySet.mkey)
760                       arrayInsert(keyArray, keyArray.length, keySet.keyset); 
761                    else
762                       keyArray.push(keySet.keyset); 
763 
764                    keySet = this.getKeyByFormat(keys, "sysy"); 
765                    if(keySet.mkey)
766                       arrayInsert(keyArray, keyArray.length, keySet.keyset); 
767                    else
768                       keyArray.push(keySet.keyset); 
769 
770                    keySet = this.getKeyByFormat(keys, "syss"); 
771                    if(keySet.mkey)
772                       arrayInsert(keyArray, keyArray.length, keySet.keyset); 
773                    else
774                       keyArray.push(keySet.keyset); 
775 
776                    return keyArray; 
777                 }
778              }
779              else
780              {
781                 // s s s s s
782                 var fs = ""; 
783                 for(var i=0; i<keys.length; i++)
784                    fs = fs + "s"; 
785 
786                 var keySet = this.getKeyByFormat(keys, fs); 
787                 if(keySet.mkey)
788                    keyArray = keySet.keyset; 
789                 else
790                    keyArray.push(keySet.keyset); 
791 
792                 return keyArray; 
793              }
794           break; 
795 
796           case SMART_PINYIN: 
797           default: 
798              return keys; 
799           break; 
800        }
801 
802        return keyArray; 
803     } 
804 
805     
806 }; 


syntax highlighted by Code2HTML, v. 0.9.1