Tizen 2.1 base
[platform/core/uifw/ise-engine-sunpinyin.git] / wrapper / scim / src / sunpinyin_lookup_table.cpp
1 /*
2  * Copyright (c) 2007 Kov Chai <tchaikov@gmail.com>
3  *
4  * The contents of this file are subject to the terms of either the GNU Lesser
5  * General Public License Version 2.1 only ("LGPL") or the Common Development and
6  * Distribution License ("CDDL")(collectively, the "License"). You may not use this
7  * file except in compliance with the License. You can obtain a copy of the CDDL at
8  * http://www.opensource.org/licenses/cddl1.php and a copy of the LGPLv2.1 at
9  * http://www.opensource.org/licenses/lgpl-license.php. See the License for the 
10  * specific language governing permissions and limitations under the License. When
11  * distributing the software, include this License Header Notice in each file and
12  * include the full text of the License in the License file as well as the
13  * following notice:
14  * 
15  * NOTICE PURSUANT TO SECTION 9 OF THE COMMON DEVELOPMENT AND DISTRIBUTION LICENSE
16  * (CDDL)
17  * For Covered Software in this distribution, this License shall be governed by the
18  * laws of the State of California (excluding conflict-of-law provisions).
19  * Any litigation relating to this License shall be subject to the jurisdiction of
20  * the Federal Courts of the Northern District of California and the state courts
21  * of the State of California, with venue lying in Santa Clara County, California.
22  * 
23  * Contributor(s):
24  * 
25  * If you wish your version of this file to be governed by only the CDDL or only
26  * the LGPL Version 2.1, indicate your decision by adding "[Contributor]" elects to
27  * include this software in this distribution under the [CDDL or LGPL Version 2.1]
28  * license." If you don't indicate a single choice of license, a recipient has the
29  * option to distribute your version of this file under either the CDDL or the LGPL
30  * Version 2.1, or to extend the choice of license to its licensees as provided
31  * above. However, if you add LGPL Version 2.1 code and therefore, elected the LGPL
32  * Version 2 license, then the option applies only if the new code is made subject
33  * to such option by the copyright holder. 
34  */
35
36 #include <cassert>
37 #include <vector>
38
39 #include "portability.h"
40
41 #include "sunpinyin_lookup_table.h"
42 #include "sunpinyin_utils.h"
43
44 #include <imi_uiobjects.h>
45
46 using namespace scim;
47
48 template <class Seg>
49 class SegVector
50 {
51     typedef typename Seg::value_type T;
52     std::vector<T>      m_buffer;
53     std::vector<uint32> m_index;
54 public:
55     uint32 length() const {
56         return m_index.size();
57     }
58     
59     void push_back(const Seg& s) {
60         m_index.push_back(m_buffer.size());
61         m_buffer.insert(m_buffer.end(), s.begin(), s.end());
62     }
63     
64     void push_back(const T& t) {
65         m_index.push_back(m_buffer.size());
66         m_buffer.push_back(t);
67     }
68     
69     Seg operator [] (uint32 index) const {
70         const uint32 len = length();
71         if (index >= len)
72             return Seg();
73         typename std::vector<T>::const_iterator begin, end;
74         begin = m_buffer.begin() + m_index[index];
75         if (index < len - 1)
76             end = m_buffer.begin() + m_index[index+1];
77         else
78             end = m_buffer.end();
79         return Seg(begin, end);
80     }
81     
82     void clear() {
83         std::vector<T>     ().swap(m_buffer);
84         std::vector<uint32>().swap(m_index);
85     }
86 };
87
88 class SunLookupTable::SunLookupTableImpl
89 {
90 public:
91     SegVector<WideString>     m_candidates;
92     SegVector<AttributeList>  m_attributes;
93 };
94
95 SunLookupTable::SunLookupTable(int page_size)
96     : LookupTable(page_size),
97       m_impl( new SunLookupTableImpl ())
98 {
99     std::vector <WideString> labels;
100     char buf [2] = { 0, 0 };
101     for (int i = 0; i < 9; ++i) {
102         buf [0] = '1' + i;
103         labels.push_back (utf8_mbstowcs (buf));
104     }
105
106     labels.push_back (utf8_mbstowcs ("0"));
107     fix_page_size(false);
108     set_candidate_labels (labels);
109 }
110
111 SunLookupTable::~SunLookupTable()
112 {
113     delete m_impl;
114 }
115
116 WideString
117 SunLookupTable::get_candidate (int index) const
118 {
119     // the start point should be synced
120     SCIM_DEBUG_IMENGINE  (3) <<  "get_candidate(" << index << ")\n";
121     
122     index = translate_index(index);
123     
124     if (index < 0) {
125         SCIM_DEBUG_IMENGINE (2) << "index out of bound: " << index << "!\n";
126         return WideString();
127     }
128     else
129         return m_impl->m_candidates[index];
130 }
131
132 AttributeList
133 SunLookupTable::get_attributes (int index) const
134 {
135     index = translate_index(index);
136     
137     if (index < 0) {
138         SCIM_DEBUG_IMENGINE (2) << "index out of bound: " << index << "!\n";
139         return AttributeList();
140     }
141     else
142         return m_impl->m_attributes[index];
143 }
144
145 uint32
146 SunLookupTable::number_of_candidates () const
147 {
148     return m_total;
149 }
150
151 void
152 SunLookupTable::clear()
153 {
154     LookupTable::clear();
155     m_impl->m_candidates.clear();
156     m_impl->m_attributes.clear();
157 }
158
159 void
160 SunLookupTable::update(const ICandidateList& cl)
161 {
162     clear();
163
164     const int sz = cl.size();
165     m_total = cl.total();
166     
167     for (int i = 0, begin = 0; i < sz; ++i) {
168         const int len = append_candidate(cl, i, begin);
169         if (len)
170             begin += len;
171         else
172             break;
173     }
174     LookupTable::set_page_size(sz);
175     SCIM_DEBUG_IMENGINE (3) << "update() " << sz << "/" << m_total << " candidates updated\n";
176 }
177
178 int
179 SunLookupTable::translate_index(int index) const
180 {
181     // SunLookupTable *only* provides access to candidates in current page
182     assert(index >= get_current_page_start());
183     assert(index < (get_current_page_start() + get_current_page_size()));
184     return index - get_current_page_start();
185 }
186
187 int
188 SunLookupTable::append_candidate(const ICandidateList& cl, int i, int begin)
189 {
190     const TWCHAR* cand = 0;
191     int len = 0;
192     
193     if ( (cand = cl.candiString(i)) ) {
194         len = cl.candiSize(i);
195         m_impl->m_candidates.push_back( wstr_to_widestr(cand, len) );
196         // XXX, a better looking decoration should be used
197         // to disable this, simply s/push_back(attr)/push_back(AttributeList())/
198         Attribute attr(begin, len, SCIM_ATTR_DECORATE);
199         switch (cl.candiType(i)) {
200         case ICandidateList::BEST_TAIL:
201             attr.set_value(SCIM_ATTR_DECORATE_REVERSE);
202             break;
203         case ICandidateList::BEST_WORD:
204             attr.set_value(SCIM_ATTR_DECORATE_UNDERLINE);
205             break;
206         default:
207             // NORMAL_WORD, USER_SELECTED_WORD, ...
208             break;
209         }
210         m_impl->m_attributes.push_back(attr);
211     }
212     return len;
213 }