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