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