Home | History | Annotate | Download | only in ime-core
      1 /*
      2  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
      3  *
      4  * Copyright (c) 2007 Sun Microsystems, Inc. All Rights Reserved.
      5  *
      6  * The contents of this file are subject to the terms of either the GNU Lesser
      7  * General Public License Version 2.1 only ("LGPL") or the Common Development and
      8  * Distribution License ("CDDL")(collectively, the "License"). You may not use this
      9  * file except in compliance with the License. You can obtain a copy of the CDDL at
     10  * http://www.opensource.org/licenses/cddl1.php and a copy of the LGPLv2.1 at
     11  * http://www.opensource.org/licenses/lgpl-license.php. See the License for the
     12  * specific language governing permissions and limitations under the License. When
     13  * distributing the software, include this License Header Notice in each file and
     14  * include the full text of the License in the License file as well as the
     15  * following notice:
     16  *
     17  * NOTICE PURSUANT TO SECTION 9 OF THE COMMON DEVELOPMENT AND DISTRIBUTION LICENSE
     18  * (CDDL)
     19  * For Covered Software in this distribution, this License shall be governed by the
     20  * laws of the State of California (excluding conflict-of-law provisions).
     21  * Any litigation relating to this License shall be subject to the jurisdiction of
     22  * the Federal Courts of the Northern District of California and the state courts
     23  * of the State of California, with venue lying in Santa Clara County, California.
     24  *
     25  * Contributor(s):
     26  *
     27  * If you wish your version of this file to be governed by only the CDDL or only
     28  * the LGPL Version 2.1, indicate your decision by adding "[Contributor]" elects to
     29  * include this software in this distribution under the [CDDL or LGPL Version 2.1]
     30  * license." If you don't indicate a single choice of license, a recipient has the
     31  * option to distribute your version of this file under either the CDDL or the LGPL
     32  * Version 2.1, or to extend the choice of license to its licensees as provided
     33  * above. However, if you add LGPL Version 2.1 code and therefore, elected the LGPL
     34  * Version 2 license, then the option applies only if the new code is made subject
     35  * to such option by the copyright holder.
     36  */
     37 
     38 #ifndef _IMI_OPTIONS_H
     39 #define _IMI_OPTIONS_H
     40 
     41 #include "utils.h"
     42 #include "portability.h"
     43 #include "imi_view.h"
     44 #include "imi_view_classic.h"
     45 #include "imi_funcobjs.h"
     46 #include "imi_data.h"
     47 #include "imi_option_event.h"
     48 #include "userdict.h"
     49 #include "ic_history.h"
     50 #include "shuangpin_seg.h"
     51 
     52 #ifndef SUNPINYIN_USERDATA_DIR_PREFIX
     53 #define SUNPINYIN_USERDATA_DIR_PREFIX ".sunpinyin"
     54 #endif
     55 
     56 struct CSimplifiedChinesePolicy : public IConfigurable
     57 {
     58     CSimplifiedChinesePolicy ();
     59 
     60     bool loadResources ();
     61 
     62     CIMIContext* createContext ();
     63     void destroyContext (CIMIContext *context);
     64 
     65     /**
     66      * set a customizable punctuation mapping
     67      * @param punc_map an interleaved array of <key,value> pairs, which looks
     68      *                 like ["key_1", "val_1", "key_2", "val_2", ...],
     69      *                 where ispunct(key_n). system defined mapping for a
     70      *                 given punct will be overriden by user specified one.
     71      */
     72     void setPunctMapping (const char *const* map)
     73         {m_getFullPunctOp.initPunctMap (map);}
     74 
     75     void enableFullSymbol (bool v=true) {m_bEnableFullSymbol = v;}
     76     void enableFullPunct (bool v=true) {m_bEnableFullPunct = v;}
     77 
     78     virtual bool onConfigChanged (const COptionEvent& event);
     79 
     80     template<class> friend class SingletonHolder;
     81 
     82 protected:
     83     ~CSimplifiedChinesePolicy () {}
     84 
     85     bool createDirectory (char *path);
     86     bool saveUserHistory ();
     87 
     88     CIMIData             m_coreData;
     89     CBigramHistory       m_historyCache;
     90     CUserDict            m_userDict;
     91     bool                 m_bLoaded;
     92     bool                 m_bTried;
     93     unsigned             m_csLevel;
     94     bool                 m_bEnableFullSymbol;
     95     CGetFullSymbolOp     m_getFullSymbolOp;
     96     bool                 m_bEnableFullPunct;
     97     CGetFullPunctOp      m_getFullPunctOp;
     98     const char          *m_userDataDirPrefix;
     99 };
    100 
    101 typedef SingletonHolder<CSimplifiedChinesePolicy> ASimplifiedChinesePolicy;
    102 
    103 struct CQuanpinSchemePolicy : IConfigurable
    104 {
    105 public:
    106 
    107     IPySegmentor* createPySegmentor ()
    108     {
    109         CQuanpinSegmentor *pseg = new CQuanpinSegmentor ();
    110         if (pseg->load(SUNPINYIN_DATA_DIR"/quanpin.dat")) {
    111             pseg->setGetFuzzySyllablesOp (&m_getFuzzySyllablesOp);
    112             pseg->setGetCorrectionPairOp (&m_getCorrectionPairOp);
    113         } else {
    114             delete pseg;
    115             pseg = NULL;
    116         }
    117         return pseg;
    118     }
    119 
    120     void setFuzzyForwarding (bool v=true)
    121         {m_getFuzzySyllablesOp.setEnable (v);}
    122 
    123     enum {
    124         MAX_FUZZY_PINYINS = 32,
    125         MAX_AUTOCORRECTION_PINYINS = 32
    126     };
    127 
    128     void setFuzzyPinyinPairs (const char* const* pairs, unsigned num)
    129         {m_getFuzzySyllablesOp.initFuzzyMap (pairs, num);}
    130 
    131     void setAutoCorrecting (bool v=true)
    132         {m_getCorrectionPairOp.setEnable (v);}
    133 
    134     void setAutoCorrectionPairs (const char* const* pairs, unsigned num)
    135         {m_getCorrectionPairOp.setCorrectionPairs (pairs, num);}
    136 
    137     virtual bool onConfigChanged(const COptionEvent& event);
    138 
    139     template<class> friend class SingletonHolder;
    140 
    141 protected:
    142     ~CQuanpinSchemePolicy () {}
    143 
    144     CGetFuzzySyllablesOp m_getFuzzySyllablesOp;
    145     CGetCorrectionPairOp m_getCorrectionPairOp;
    146 };
    147 
    148 typedef SingletonHolder<CQuanpinSchemePolicy> AQuanpinSchemePolicy;
    149 
    150 struct CShuangpinSchemePolicy : public IConfigurable
    151 {
    152 public:
    153     CShuangpinSchemePolicy();
    154 
    155     IPySegmentor* createPySegmentor ()
    156     {
    157         CShuangpinSegmentor *pseg = new CShuangpinSegmentor (m_shuangpinType);
    158         return pseg;
    159     }
    160 
    161     void setShuangpinType (EShuangpinType t) {m_shuangpinType = t;}
    162     virtual bool onConfigChanged(const COptionEvent& event);
    163 
    164     template<class> friend class SingletonHolder;
    165 protected:
    166     ~CShuangpinSchemePolicy () {}
    167     EShuangpinType m_shuangpinType;
    168 };
    169 
    170 typedef SingletonHolder<CShuangpinSchemePolicy> AShuangpinSchemePolicy;
    171 
    172 struct CClassicStylePolicy : public IConfigurable
    173 {
    174     CIMIView* createView () {return new CIMIClassicView ();}
    175 
    176     template<class> friend class SingletonHolder;
    177 protected:
    178     ~CClassicStylePolicy () {}
    179 };
    180 
    181 typedef SingletonHolder<CClassicStylePolicy> AClassicStylePolicy;
    182 
    183 struct ISunpinyinProfile
    184 {
    185     virtual CIMIView* createProfile () = 0;
    186     virtual void destroyProfile (CIMIView *) = 0;
    187     virtual ~ISunpinyinProfile () {};
    188 };
    189 
    190 template <class LanguagePolicy, class PinyinSchemePolicy, class InputStylePolicy>
    191 class CSunpinyinProfile : public ISunpinyinProfile
    192 {
    193 public:
    194     CSunpinyinProfile () {};
    195 
    196     /* profile by itself is a profile, so we are creating a session here? */
    197     virtual CIMIView* createProfile ()
    198     {
    199         typename LanguagePolicy::Type& langPolicy =
    200             LanguagePolicy::instance();
    201         typename PinyinSchemePolicy::Type& pySchemePolicy =
    202             PinyinSchemePolicy::instance();
    203         typename InputStylePolicy::Type& inputStylePolicy =
    204             InputStylePolicy::instance();
    205 
    206 
    207         if (!langPolicy.loadResources ())
    208             return NULL;
    209 
    210         IPySegmentor* pseg = pySchemePolicy.createPySegmentor ();
    211         if (pseg == NULL)
    212             return NULL;
    213 
    214         CIMIContext *pic = langPolicy.createContext ();
    215         CIMIView* pview = inputStylePolicy.createView ();
    216         pview->attachIC (pic);
    217         pview->setPySegmentor (pseg);
    218 
    219         langPolicy.addRef();
    220         pySchemePolicy.addRef();
    221         inputStylePolicy.addRef();
    222 
    223         return pview;
    224     }
    225 
    226     virtual void destroyProfile(CIMIView* pview)
    227     {
    228         LanguagePolicy::instance().release();
    229         PinyinSchemePolicy::instance().release();
    230         InputStylePolicy::instance().release();
    231         if (pview) {
    232             LanguagePolicy::instance().destroyContext(pview->getIC());
    233             delete pview->getPySegmentor();
    234             delete pview;
    235         }
    236     }
    237 };
    238 
    239 class CSunpinyinSessionFactory : private CNonCopyable
    240 {
    241 public:
    242     typedef enum {
    243         QUANPIN,
    244         SHUANGPIN,
    245         YUEPIN,
    246         ZHUYIN,
    247     } EPyScheme;
    248 
    249     typedef enum {
    250         MSPY_STYLE,
    251         CLASSIC_STYLE,
    252     } EInputStyle;
    253 
    254     typedef enum {
    255         SIMPLIFIED_CHINESE,
    256         TRADITIONAL_CHINESE,
    257     } ELanguage;
    258 
    259 public:
    260     static CSunpinyinSessionFactory& getFactory ()
    261     {
    262         static CSunpinyinSessionFactory inst;
    263         return inst;
    264     }
    265 
    266     void setLanguage (ELanguage lang) {m_lang = lang;}
    267     void setInputStyle (EInputStyle inputStyle) {m_inputStyle = inputStyle;}
    268     void setPinyinScheme (EPyScheme pyScheme) {m_pyScheme = pyScheme;}
    269     void setCandiWindowSize (unsigned size) {m_candiWindowSize = size;}
    270 
    271     CIMIView* createSession ()
    272     {
    273         unsigned key = _policiesToKey (m_lang, m_pyScheme, m_inputStyle);
    274         ISunpinyinProfile *profile = _getProfile(key);
    275         if (!profile)
    276             return NULL;
    277 
    278         CIMIView *pview = profile->createProfile ();
    279         if (!pview)
    280             return NULL;
    281 
    282         pview->setHotkeyProfile (&m_hotkeyProfile);
    283         pview->setCandiWindowSize (m_candiWindowSize);
    284         return pview;
    285     }
    286 
    287     void destroySession (CIMIView* pview)
    288     {
    289         unsigned key = _policiesToKey (m_lang, m_pyScheme, m_inputStyle);
    290         ISunpinyinProfile *profile = _getProfile(key);
    291         if (!profile)
    292             return;
    293         profile->destroyProfile(pview);
    294     }
    295 
    296     void updateToken () {++m_tokenNum;}
    297     unsigned getToken () const {return m_tokenNum;}
    298 
    299 private:
    300     CSunpinyinSessionFactory ()
    301         : m_pyScheme (QUANPIN), m_inputStyle(CLASSIC_STYLE), m_lang(SIMPLIFIED_CHINESE),
    302           m_candiWindowSize(10), m_tokenNum(0)
    303     {
    304         m_profiles [_policiesToKey (SIMPLIFIED_CHINESE, QUANPIN, CLASSIC_STYLE)] =
    305                 new CSunpinyinProfile <ASimplifiedChinesePolicy, AQuanpinSchemePolicy, AClassicStylePolicy> ();
    306 
    307         m_profiles [_policiesToKey (SIMPLIFIED_CHINESE, SHUANGPIN, CLASSIC_STYLE)] =
    308                 new CSunpinyinProfile <ASimplifiedChinesePolicy, AShuangpinSchemePolicy, AClassicStylePolicy> ();
    309     }
    310 
    311     ~CSunpinyinSessionFactory ()
    312     {
    313         std::map <unsigned, ISunpinyinProfile*>::iterator it  = m_profiles.begin ();
    314         std::map <unsigned, ISunpinyinProfile*>::iterator ite = m_profiles.end ();
    315 
    316         for (; it != ite; ++it)
    317             delete it->second;
    318     }
    319 
    320     ISunpinyinProfile* _getProfile(unsigned key)
    321     {
    322         std::map <unsigned, ISunpinyinProfile*>::iterator it = m_profiles.find (key);
    323         if (it != m_profiles.end()) {
    324             return it->second;
    325         } else {
    326             return NULL;
    327         }
    328     }
    329 
    330     unsigned _policiesToKey (ELanguage lang, EPyScheme pyScheme, EInputStyle inputStyle)
    331         {return (lang<<16) + (pyScheme<<8) + inputStyle;}
    332 
    333     std::map <unsigned, ISunpinyinProfile*> m_profiles;
    334 
    335     EPyScheme           m_pyScheme;
    336     EInputStyle         m_inputStyle;
    337     ELanguage           m_lang;
    338     unsigned            m_candiWindowSize;
    339     CHotkeyProfile      m_hotkeyProfile;
    340 
    341     unsigned            m_tokenNum;
    342 };
    343 
    344 /**
    345  * helper function to transform string vector to array of char*
    346  */
    347 class CPairParser
    348 {
    349 public:
    350     CPairParser()
    351         : m_free(m_buf), m_end(m_buf+256)
    352     {}
    353 
    354     /**
    355      * transform a string vector to interleaved <key,value> array of (char*)
    356      * @param event a list of string, each element should be in the form of "key:value".
    357      * @returns the number of pairs transformed
    358      * @note this function uses a local buffer for the returned array
    359      */
    360     size_t parse(const std::vector<std::string> pairs);
    361     size_t parse(const COptionEvent& event);
    362     const char* const* get_pairs() const;
    363 
    364 private:
    365     char* strdup(const std::string& s);
    366     char* alloc(size_t size);
    367 
    368     char* m_pairs[32];
    369     char  m_buf[256];
    370     char* m_free;
    371     const char* m_end;
    372 };
    373 
    374 #endif
    375