1 /** @file scim_compose_key.cpp
2 * @brief Implementation of class ComposeKeyFactory and ComposeKeyInstance.
3 */
4
5 /*
6 * Smart Common Input Method
7 *
8 * Copyright (c) 2002-2005 James Su <suzhe@tsinghua.org.cn>
9 *
10 *
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
14 * version 2 of the License, or (at your option) any later version.
15 *
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License for more details.
20 *
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this program; if not, write to the
23 * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
24 * Boston, MA 02111-1307 USA
25 *
26 * $Id: scim_compose_key.cpp,v 1.7 2005/08/16 07:26:54 suzhe Exp $
27 *
28 */
29
30 #define Uses_SCIM_COMPOSE_KEY
31 #define Uses_C_CTYPE
32
33 #include "scim_private.h"
34 #include "scim.h"
35
36 #define SCIM_KEYBOARD_ICON_FILE (SCIM_ICONDIR "/keyboard.png")
37
38 namespace scim {
39
40 #define SCIM_MAX_COMPOSE_LEN 5
41
42 struct ComposeSequence
43 {
44 uint32 keys [SCIM_MAX_COMPOSE_LEN];
45 ucs4_t unicode;
46 };
47
48 class ComposeSequenceLessByKeys
49 {
50 public:
operator ()(const ComposeSequence & lhs,const ComposeSequence & rhs) const51 bool operator () (const ComposeSequence &lhs, const ComposeSequence &rhs) const {
52 for (size_t i = 0; i < SCIM_MAX_COMPOSE_LEN; ++i) {
53 if (lhs.keys [i] < rhs.keys [i]) return true;
54 else if (lhs.keys [i] > rhs.keys [i]) return false;
55 }
56 return false;
57 }
58
operator ()(const ComposeSequence & lhs,const uint32 * rhs) const59 bool operator () (const ComposeSequence &lhs, const uint32 *rhs) const {
60 for (size_t i = 0; i < SCIM_MAX_COMPOSE_LEN; ++i) {
61 if (lhs.keys [i] < rhs [i]) return true;
62 else if (lhs.keys [i] > rhs [i]) return false;
63 }
64 return false;
65 }
66
operator ()(const uint32 * lhs,const ComposeSequence & rhs) const67 bool operator () (const uint32 *lhs, const ComposeSequence &rhs) const {
68 for (size_t i = 0; i < SCIM_MAX_COMPOSE_LEN; ++i) {
69 if (lhs [i] < rhs.keys [i]) return true;
70 else if (lhs [i] > rhs.keys [i]) return false;
71 }
72 return false;
73 }
74
operator ()(const uint32 * lhs,const uint32 * rhs) const75 bool operator () (const uint32 *lhs, const uint32 *rhs) const {
76 for (size_t i = 0; i < SCIM_MAX_COMPOSE_LEN; ++i) {
77 if (lhs [i] < rhs [i]) return true;
78 else if (lhs [i] > rhs [i]) return false;
79 }
80 return false;
81 }
82
83 };
84
85 // Generated from /usr/X11R6/lib/X11/locale/en_US.UTF-8/Compose
86 // Get rid off all keys with unicode value.
87 // Merged with the table in gtk+2.x
88 static const ComposeSequence __scim_compose_seqs[] = {
89 #include "scim_compose_key_data.h"
90 };
91
92 #define SCIM_NUM_COMPOSE_SEQS (sizeof (__scim_compose_seqs) / sizeof (__scim_compose_seqs [0]))
93
94 static uint16 __scim_compose_ignores [] = {
95 SCIM_KEY_ISO_Level3_Shift,
96 SCIM_KEY_ISO_Group_Shift,
97 SCIM_KEY_Mode_switch,
98 SCIM_KEY_Shift_L,
99 SCIM_KEY_Shift_R,
100 SCIM_KEY_Control_L,
101 SCIM_KEY_Control_R,
102 SCIM_KEY_Caps_Lock,
103 SCIM_KEY_Shift_Lock,
104 SCIM_KEY_Meta_L,
105 SCIM_KEY_Meta_R,
106 SCIM_KEY_Alt_L,
107 SCIM_KEY_Alt_R,
108 SCIM_KEY_Super_L,
109 SCIM_KEY_Super_R,
110 SCIM_KEY_Hyper_L,
111 SCIM_KEY_Hyper_R
112 };
113
114 #define SCIM_NUM_COMPOSE_IGNORES (sizeof (__scim_compose_ignores) / sizeof (__scim_compose_ignores [0]))
115
ComposeKeyFactory()116 ComposeKeyFactory::ComposeKeyFactory ()
117 {
118 set_locales ("C");
119 }
120
~ComposeKeyFactory()121 ComposeKeyFactory::~ComposeKeyFactory ()
122 {
123 }
124
125 WideString
get_name() const126 ComposeKeyFactory::get_name () const
127 {
128 return utf8_mbstowcs (_("English/European"));
129 }
130
131 WideString
get_authors() const132 ComposeKeyFactory::get_authors () const
133 {
134 return utf8_mbstowcs ("James Su <suzhe@tsinghua.org.cn>");
135 }
136
137 WideString
get_credits() const138 ComposeKeyFactory::get_credits () const
139 {
140 return WideString ();
141 }
142
143 WideString
get_help() const144 ComposeKeyFactory::get_help () const
145 {
146 return WideString ();
147 }
148
149 String
get_uuid() const150 ComposeKeyFactory::get_uuid () const
151 {
152 return String (SCIM_COMPOSE_KEY_FACTORY_UUID);
153 }
154
155 String
get_icon_file() const156 ComposeKeyFactory::get_icon_file () const
157 {
158 return String (SCIM_KEYBOARD_ICON_FILE);
159 }
160
161 bool
validate_encoding(const String & encoding) const162 ComposeKeyFactory::validate_encoding (const String& encoding) const
163 {
164 return true;
165 }
166
167 bool
validate_locale(const String & locale) const168 ComposeKeyFactory::validate_locale (const String& locale) const
169 {
170 return true;
171 }
172
173 IMEngineInstancePointer
create_instance(const String & encoding,int id)174 ComposeKeyFactory::create_instance (const String& encoding, int id)
175 {
176 return new ComposeKeyInstance (this, encoding, id);
177 }
178
ComposeKeyInstance(ComposeKeyFactory * factory,const String & encoding,int id)179 ComposeKeyInstance::ComposeKeyInstance (ComposeKeyFactory *factory,
180 const String& encoding,
181 int id)
182 : IMEngineInstanceBase (factory, encoding, id)
183 {
184 m_compose_buffer [0] = m_compose_buffer [1] = m_compose_buffer [2] = m_compose_buffer [3] = 0;
185 m_compose_buffer [4] = m_compose_buffer [5] = m_compose_buffer [6] = m_compose_buffer [7] = 0;
186 }
187
~ComposeKeyInstance()188 ComposeKeyInstance::~ComposeKeyInstance ()
189 {
190 }
191
192 bool
process_key_event(const KeyEvent & key)193 ComposeKeyInstance::process_key_event (const KeyEvent& key)
194 {
195 if (key.is_key_release ()) return false;
196
197 // Ignore modifier key presses.
198 if (std::binary_search (__scim_compose_ignores, __scim_compose_ignores + SCIM_NUM_COMPOSE_IGNORES, (uint16) key.code))
199 return false;
200
201 // Ignore the key if ctrl or alt is down.
202 if (key.is_control_down () || key.is_alt_down ())
203 return false;
204
205 int n_compose = 0;
206
207 while (m_compose_buffer [n_compose] != 0 && n_compose < SCIM_MAX_COMPOSE_LEN)
208 ++ n_compose;
209
210 // The buffer is full, then reset the buffer first.
211 if (n_compose == SCIM_MAX_COMPOSE_LEN) {
212 reset ();
213 n_compose = 0;
214 }
215
216 m_compose_buffer [n_compose] = (uint32) key.code;
217
218 const ComposeSequence *it = std::lower_bound (__scim_compose_seqs,
219 __scim_compose_seqs + SCIM_NUM_COMPOSE_SEQS,
220 m_compose_buffer,
221 ComposeSequenceLessByKeys ());
222
223 // Not result found, reset the buffer and return false.
224 if (it == __scim_compose_seqs + SCIM_NUM_COMPOSE_SEQS) {
225 reset ();
226 return false;
227 }
228
229 // Check if the compose sequence is match.
230 for (n_compose = 0; n_compose < SCIM_MAX_COMPOSE_LEN; ++ n_compose) {
231 if (m_compose_buffer [n_compose] == 0)
232 break;
233
234 // Not match, reset the buffer and return.
235 // If it's the first key press, then return false to forward it.
236 // Otherwise return true to ignore it.
237 if (m_compose_buffer [n_compose] != it->keys [n_compose]) {
238 reset ();
239 return n_compose != 0;
240 }
241 }
242
243 // Match exactly, commit the result.
244 if (n_compose == SCIM_MAX_COMPOSE_LEN || it->keys [n_compose] == 0) {
245 WideString wstr;
246 wstr.push_back (it->unicode);
247 commit_string (wstr);
248 reset ();
249 }
250
251 return true;
252 }
253
254 void
move_preedit_caret(unsigned int)255 ComposeKeyInstance::move_preedit_caret (unsigned int /*pos*/)
256 {
257 }
258
259 void
select_candidate(unsigned int)260 ComposeKeyInstance::select_candidate (unsigned int /*item*/)
261 {
262 }
263
264 void
update_lookup_table_page_size(unsigned int)265 ComposeKeyInstance::update_lookup_table_page_size (unsigned int /*page_size*/)
266 {
267 }
268
269 void
lookup_table_page_up()270 ComposeKeyInstance::lookup_table_page_up ()
271 {
272 }
273
274 void
lookup_table_page_down()275 ComposeKeyInstance::lookup_table_page_down ()
276 {
277 }
278
279 void
reset()280 ComposeKeyInstance::reset ()
281 {
282 m_compose_buffer [0] = m_compose_buffer [1] = m_compose_buffer [2] = m_compose_buffer [3] = 0;
283 m_compose_buffer [4] = m_compose_buffer [5] = m_compose_buffer [6] = m_compose_buffer [7] = 0;
284 }
285
286 void
focus_in()287 ComposeKeyInstance::focus_in ()
288 {
289 register_properties (PropertyList ());
290 reset ();
291 }
292
293 void
focus_out()294 ComposeKeyInstance::focus_out ()
295 {
296 }
297
298 void
trigger_property(const String &)299 ComposeKeyInstance::trigger_property (const String & /*property*/)
300 {
301 }
302
303 } // namespace scim
304
305 /*
306 vi:ts=4:nowrap:ai:expandtab
307 */
308