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 #ifdef HAVE_CONFIG_H
     39 #include <config.h>
     40 #endif
     41 
     42 #include <algorithm>
     43 #include <sys/types.h>
     44 #include <sys/stat.h>
     45 #include <unistd.h>
     46 #include <cassert>
     47 
     48 #include "imi_option_keys.h"
     49 #include "imi_keys.h"
     50 #include "imi_options.h"
     51 #include "imi_view_classic.h"
     52 
     53 CSimplifiedChinesePolicy::CSimplifiedChinesePolicy()
     54     : m_bLoaded(false), m_bTried(false), m_csLevel(3),
     55       m_bEnableFullSymbol(false), m_bEnableFullPunct(true)
     56 {}
     57 
     58 bool
     59 CSimplifiedChinesePolicy::loadResources()
     60 {
     61     if (m_bLoaded || m_bTried)
     62         return m_bLoaded;
     63 
     64     bool suc = true;
     65     suc &= m_coreData.loadResource (SUNPINYIN_DATA_DIR"/lm_sc.t3g", SUNPINYIN_DATA_DIR"/pydict_sc.bin");
     66 
     67     char path[256];
     68     const char *home = getenv ("HOME");
     69     snprintf (path, sizeof(path), "%s/%s", home, SUNPINYIN_USERDATA_DIR_PREFIX);
     70     suc &= createDirectory(path);
     71 
     72     CBigramHistory::initClass();
     73     snprintf (path, sizeof(path), "%s/%s/history", home, SUNPINYIN_USERDATA_DIR_PREFIX);
     74     suc &= m_historyCache.loadFromFile (path);
     75 
     76     snprintf (path, sizeof(path), "%s/%s/userdict", home, SUNPINYIN_USERDATA_DIR_PREFIX);
     77     suc &= m_userDict.load (path);
     78 
     79     m_bTried = true;
     80     return m_bLoaded = suc;
     81 }
     82 
     83 CIMIContext *
     84 CSimplifiedChinesePolicy::createContext()
     85 {
     86     CIMIContext* pic = new CIMIContext ();
     87     pic->setCoreData (&m_coreData);
     88     pic->setHistoryMemory (&m_historyCache);
     89     pic->setUserDict (&m_userDict);
     90 
     91     pic->setFullSymbolForwarding (m_bEnableFullSymbol);
     92     pic->setGetFullSymbolOp (&m_getFullSymbolOp);
     93 
     94     pic->setFullPunctForwarding (m_bEnableFullPunct);
     95     pic->setGetFullPunctOp (&m_getFullPunctOp);
     96     return pic;
     97 }
     98 
     99 void
    100 CSimplifiedChinesePolicy::destroyContext (CIMIContext *context)
    101 {
    102     assert(context != NULL);
    103     saveUserHistory();
    104     delete context;
    105 }
    106 
    107 bool
    108 CSimplifiedChinesePolicy::onConfigChanged (const COptionEvent& event)
    109 {
    110     if (event.name == PINYIN_PUNCTMAPPING_MAPPINGS) {
    111         CPairParser parser;
    112         size_t num = parser.parse(event);
    113         setPunctMapping(parser.get_pairs());
    114         return true;
    115     }
    116     return false;
    117 }
    118 
    119 bool
    120 CSimplifiedChinesePolicy::saveUserHistory ()
    121 {
    122     char path[256];
    123     const char *home = getenv ("HOME");
    124     snprintf (path, sizeof(path), "%s/%s/history", home, SUNPINYIN_USERDATA_DIR_PREFIX);
    125     return m_historyCache.saveToFile(path);
    126 }
    127 
    128 bool
    129 CSimplifiedChinesePolicy::createDirectory(char *path) {
    130     char *p = path;
    131     while (p = strchr(p+1, '/')) {
    132         *p = 0;
    133         if (access(path, F_OK) != 0 && mkdir(path, S_IRWXU) != 0) {
    134             perror("unabled to mkdir() for user history");
    135             return false;
    136         }
    137         *p = '/';
    138     }
    139     return !(access(path, F_OK) != 0 && mkdir(path, S_IRWXU) != 0);
    140 }
    141 
    142 CShuangpinSchemePolicy::CShuangpinSchemePolicy()
    143     : m_shuangpinType(MS2003)
    144 {}
    145 
    146 bool
    147 CQuanpinSchemePolicy::onConfigChanged(const COptionEvent& event)
    148 {
    149     if (event.name == QUANPIN_FUZZY_ENABLED) {
    150         setFuzzyForwarding(event.get_bool());
    151     } else if (event.name == QUANPIN_FUZZY_PINYINS) {
    152         CPairParser parser;
    153         size_t num = parser.parse(event);
    154         setFuzzyPinyinPairs(parser.get_pairs(), num);
    155     } else if (event.name == QUANPIN_AUTOCORRECTION_ENABLED) {
    156         setAutoCorrecting(event.get_bool());
    157     } else if (event.name == QUANPIN_AUTOCORRECTION_PINYINS) {
    158         CPairParser parser;
    159         size_t num = parser.parse(event);
    160         setAutoCorrectionPairs(parser.get_pairs(), num);
    161     } else {
    162         return false;
    163     }
    164     return true;
    165 }
    166 
    167 bool
    168 CShuangpinSchemePolicy::onConfigChanged(const COptionEvent& event)
    169 {
    170     if (event.name == SHUANGPIN_TYPE) {
    171         setShuangpinType( (EShuangpinType) event.get_int());
    172         return true;
    173     }
    174     return false;
    175 }
    176 
    177 size_t
    178 CPairParser::parse(const COptionEvent& event)
    179 {
    180     return parse(event.get_string_list());
    181 }
    182 
    183 size_t
    184 CPairParser::parse(const std::vector<std::string> pairs)
    185 {
    186     assert(m_free == m_buf);
    187 
    188     size_t npairs = std::min(sizeof(m_pairs)/sizeof(m_pairs[0]),
    189                              pairs.size());
    190     memset(m_pairs, 0, sizeof(m_pairs));
    191     int i = 0;
    192     for (;i < npairs; ++i) {
    193         const std::string& pair = pairs[i];
    194         std::string::size_type found = pair.find(':');
    195         if (found == pair.npos)
    196             continue;
    197         const std::string key = pair.substr(0, found);
    198         const std::string val = pair.substr(found+1);
    199         char *skey = strdup(key);
    200         char *sval = strdup(val);
    201         if (skey && sval) {
    202             m_pairs[2*i] = skey;
    203             m_pairs[2*i+1] = sval;
    204         } else {
    205             // running out of memory
    206             break;
    207         }
    208     }
    209     // reclaim the used memory
    210     m_free = m_buf;
    211     return i;
    212 }
    213 
    214 const char* const*
    215 CPairParser::get_pairs() const
    216 {
    217     return m_pairs;
    218 }
    219 
    220 char*
    221 CPairParser::strdup(const std::string& s)
    222 {
    223     size_t len = s.length() + 1;
    224     char* str = alloc(len);
    225     if (str) {
    226         strncpy(str, s.c_str(), s.length());
    227         str[s.length()] = '\0';
    228     }
    229     return str;
    230 }
    231 
    232 char*
    233 CPairParser::alloc(size_t size)
    234 {
    235     char *result = NULL;
    236     char *new_free = m_free + size;
    237     if (m_end > new_free) {
    238         result = m_free;
    239         m_free = new_free;
    240     }
    241     return result;
    242 }
    243