1 /** @file scim_sctc_filter.cpp
2  */
3 
4 /*
5  * Smart Common Input Method
6  *
7  * Copyright (c) 2005 James Su <suzhe@tsinghua.org.cn>
8  *
9  *
10  * This library is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Lesser General Public
12  * License as published by the Free Software Foundation; either
13  * version 2 of the License, or (at your option) any later version.
14  *
15  * This library is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public
21  * License along with this program; if not, write to the
22  * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
23  * Boston, MA  02111-1307  USA
24  *
25  * $Id: scim_sctc_filter.cpp,v 1.7.2.1 2006/01/09 13:37:25 suzhe Exp $
26  *
27  */
28 
29 #define Uses_SCIM_FILTER
30 #define Uses_SCIM_FILTER_MODULE
31 #define Uses_SCIM_CONFIG_BASE
32 #include "scim_private.h"
33 #include "scim.h"
34 #include "scim_stl_map.h"
35 #include "scim_sctc_filter.h"
36 #include "scim_sctc_filter_data.h"
37 
38 #define scim_module_init sctc_LTX_scim_module_init
39 #define scim_module_exit sctc_LTX_scim_module_exit
40 #define scim_filter_module_init sctc_LTX_scim_filter_module_init
41 #define scim_filter_module_create_filter sctc_LTX_scim_filter_module_create_filter
42 #define scim_filter_module_get_filter_info sctc_LTX_scim_filter_module_get_filter_info
43 
44 using namespace scim;
45 
46 // Private datatype definition.
47 #if SCIM_USE_STL_EXT_HASH_MAP
48 typedef __gnu_cxx::hash_map <unsigned short, unsigned short, __gnu_cxx::hash <unsigned short> > UUMap;
49 #elif SCIM_USE_STL_HASH_MAP
50 typedef std::hash_map <unsigned short, unsigned short, std::hash <unsigned short> >             UUMap;
51 #else
52 typedef std::map <unsigned short, unsigned short>                                               UUMap;
53 #endif
54 
55 // Private data definition.
56 static FilterInfo   __filter_info (String ("adb861a9-76da-454c-941b-1957e644a94e"),
57                                    String (_("Simplified-Traditional Chinese Conversion")),
58                                    String ("zh_CN,zh_TW,zh_SG,zh_HK"),
59                                    String (SCIM_ICONDIR "/sctc.png"),
60                                    String (_("Convert between Simplified Chinese and Traditional Chinese")));
61 
62 static std::vector <String> __sc_encodings;
63 static std::vector <String> __tc_encodings;
64 
65 static UUMap        __sc_to_tc_map;
66 static UUMap        __tc_to_sc_map;
67 static bool         __sc_to_tc_initialized = false;
68 static bool         __tc_to_sc_initialized = false;
69 
70 static Property     __prop_root     (String ("/Filter/SCTC"),
71                                      String (_("SC-TC")),
72                                      String (SCIM_ICONDIR "/sctc.png"),
73                                      String (_("Simplified-Traditional Chinese conversion")));
74 
75 static Property     __prop_off      (String ("/Filter/SCTC/Off"),
76                                      String (_("No Conversion")),
77                                      String (SCIM_ICONDIR "/sctc.png"),
78                                      String (_("Simplified-Traditional Chinese conversion")));
79 
80 static Property     __prop_sc_to_tc (String ("/Filter/SCTC/SC-TC"),
81                                      String (_("Simplified to Traditional")),
82                                      String (SCIM_ICONDIR "/sctc-sc-to-tc.png"),
83                                      String (_("Convert Simplified Chinese to Traditional Chinese")));
84 
85 static Property     __prop_tc_to_sc (String ("/Filter/SCTC/TC-SC"),
86                                      String (_("Traditional to Simplified")),
87                                      String (SCIM_ICONDIR "/sctc-tc-to-sc.png"),
88                                      String (_("Convert Traditional Chinese to Simplified Chinese")));
89 
90 //Private functions definition.
91 static void       __init_sc_to_tc ();
92 static void       __init_tc_to_sc ();
93 
94 static bool       __is_sc_encoding (const String &encoding);
95 static bool       __is_tc_encoding (const String &encoding);
96 
97 static WideString __sc_to_tc (const WideString &sc);
98 static WideString __tc_to_sc (const WideString &tc);
99 
100 
101 //Module Interface
102 extern "C" {
scim_module_init(void)103     void scim_module_init (void)
104     {
105         //Initialize encoding information.
106         __sc_encodings.push_back ("GB2312");
107         __sc_encodings.push_back ("GBK");
108         __sc_encodings.push_back ("GB18030");
109         __sc_encodings.push_back ("EUC-CN");
110         __tc_encodings.push_back ("BIG5");
111         __tc_encodings.push_back ("BIG5-HKSCS");
112         __tc_encodings.push_back ("EUC-TW");
113     }
114 
scim_module_exit(void)115     void scim_module_exit (void)
116     {
117     }
118 
scim_filter_module_init(const ConfigPointer & config)119     unsigned int scim_filter_module_init (const ConfigPointer &config)
120     {
121         return 1;
122     }
123 
scim_filter_module_create_filter(unsigned int index)124     FilterFactoryPointer scim_filter_module_create_filter (unsigned int index)
125     {
126         if (index == 0)
127             return new SCTCFilterFactory ();
128 
129         return FilterFactoryPointer (0);
130     }
131 
scim_filter_module_get_filter_info(unsigned int index,FilterInfo & info)132     bool scim_filter_module_get_filter_info (unsigned int index, FilterInfo &info)
133     {
134         if (index == 0) {
135             info = __filter_info;
136             return true;
137         }
138         return false;
139     }
140 }
141 
142 //Implementation of private functions
143 static void
__init_sc_to_tc()144 __init_sc_to_tc ()
145 {
146     if (__sc_to_tc_initialized) return;
147 
148     __sc_to_tc_map.clear ();
149 
150     for (size_t i = 0; __sc_to_tc_table [i].first; ++i)
151         __sc_to_tc_map [__sc_to_tc_table [i].first] = __sc_to_tc_table [i].second;
152 
153     __sc_to_tc_initialized = true;
154 }
155 
156 static void
__init_tc_to_sc()157 __init_tc_to_sc ()
158 {
159     if (__tc_to_sc_initialized) return;
160 
161     __tc_to_sc_map.clear ();
162 
163     for (size_t i = 0; __tc_to_sc_table [i].first; ++i)
164         __tc_to_sc_map [__tc_to_sc_table [i].first] = __tc_to_sc_table [i].second;
165 
166     __tc_to_sc_initialized = true;
167 }
168 
__sc_to_tc(const WideString & sc)169 static WideString __sc_to_tc (const WideString &sc)
170 {
171     WideString tc;
172     if (!__sc_to_tc_initialized) __init_sc_to_tc ();
173 
174     UUMap::const_iterator mapit;
175     WideString::const_iterator sit;
176 
177     for (sit = sc.begin (); sit != sc.end (); ++sit) {
178         if (*sit <= 0xFFFF) {
179             mapit = __sc_to_tc_map.find ((unsigned short) (*sit));
180             if (mapit != __sc_to_tc_map.end ()) {
181                 tc.push_back (static_cast<ucs4_t> (mapit->second));
182             } else {
183                 tc.push_back (*sit);
184             }
185         } else {
186             tc.push_back (*sit);
187         }
188     }
189     return tc;
190 }
191 
__tc_to_sc(const WideString & tc)192 static WideString __tc_to_sc (const WideString &tc)
193 {
194     WideString sc;
195     if (!__tc_to_sc_initialized) __init_tc_to_sc ();
196 
197     UUMap::const_iterator mapit;
198     WideString::const_iterator sit;
199 
200     for (sit = tc.begin (); sit != tc.end (); ++sit) {
201         if (*sit <= 0xFFFF) {
202             mapit = __tc_to_sc_map.find ((unsigned short) (*sit));
203             if (mapit != __tc_to_sc_map.end ()) {
204                 sc.push_back (static_cast<ucs4_t> (mapit->second));
205             } else {
206                 sc.push_back (*sit);
207             }
208         } else {
209             sc.push_back (*sit);
210         }
211     }
212     return sc;
213 }
214 
215 static bool
__is_sc_encoding(const String & encoding)216 __is_sc_encoding (const String &encoding)
217 {
218     return std::find (__sc_encodings.begin (), __sc_encodings.end (), encoding) != __sc_encodings.end ();
219 }
220 
221 static bool
__is_tc_encoding(const String & encoding)222 __is_tc_encoding (const String &encoding)
223 {
224     return std::find (__tc_encodings.begin (), __tc_encodings.end (), encoding) != __tc_encodings.end ();
225 }
226 
227 //Implementation of SCTCFilterFactory.
SCTCFilterFactory()228 SCTCFilterFactory::SCTCFilterFactory ()
229     : m_sc_ok(false),
230       m_tc_ok(false)
231 {
232 }
233 
234 void
attach_imengine_factory(const IMEngineFactoryPointer & orig)235 SCTCFilterFactory::attach_imengine_factory (const IMEngineFactoryPointer &orig)
236 {
237     size_t i;
238 
239     FilterFactoryBase::attach_imengine_factory (orig);
240 
241     for (i = 0; i < __sc_encodings.size (); ++i) {
242         if (orig->validate_encoding (__sc_encodings [i])) {
243             m_sc_ok = true;
244             if (orig->validate_encoding ("GB18030"))
245                 m_sc_encoding = "GB18030";
246             else
247                 m_sc_encoding = __sc_encodings [i];
248 
249             break;
250         }
251     }
252 
253     for (i = 0; i < __tc_encodings.size (); ++i) {
254         if (orig->validate_encoding (__tc_encodings [i])) {
255             m_tc_ok = true;
256             if (orig->validate_encoding ("BIG5"))
257                 m_tc_encoding = "BIG5";
258             else
259                 m_tc_encoding = __tc_encodings [i];
260 
261             break;
262         }
263     }
264 
265     if (m_sc_ok || m_tc_ok) {
266         String locales = orig->get_locales ();
267         locales = locales + String (",") + scim_get_language_locales ("zh_CN");
268         locales = locales + String (",") + scim_get_language_locales ("zh_TW");
269         locales = locales + String (",") + scim_get_language_locales ("zh_SG");
270         locales = locales + String (",") + scim_get_language_locales ("zh_HK");
271         set_locales (locales);
272     }
273 }
274 
275 WideString
get_name() const276 SCTCFilterFactory::get_name () const
277 {
278      WideString name = FilterFactoryBase::get_name ();
279      return name.length () ? name : utf8_mbstowcs (__filter_info.name);
280 }
281 
282 String
get_uuid() const283 SCTCFilterFactory::get_uuid () const
284 {
285     String uuid = FilterFactoryBase::get_uuid ();
286     return uuid.length () ? uuid : __filter_info.uuid;
287 }
288 
289 String
get_icon_file() const290 SCTCFilterFactory::get_icon_file () const
291 {
292     String icon = FilterFactoryBase::get_icon_file ();
293     return icon.length () ? icon : __filter_info.icon;
294 }
295 
296 WideString
get_authors() const297 SCTCFilterFactory::get_authors () const
298 {
299     WideString authors = FilterFactoryBase::get_authors ();
300     return authors.length () ? authors : utf8_mbstowcs (_("James Su <suzhe@tsinghua.org.cn>"));
301 }
302 
303 WideString
get_help() const304 SCTCFilterFactory::get_help () const
305 {
306     // No help yet.
307     WideString help = FilterFactoryBase::get_help ();
308     return help;
309 }
310 
311 bool
validate_encoding(const String & encoding) const312 SCTCFilterFactory::validate_encoding (const String& encoding) const
313 {
314     // Bypass the original IMEngineFactory.
315     return IMEngineFactoryBase::validate_encoding (encoding);
316 }
317 
318 bool
validate_locale(const String & locale) const319 SCTCFilterFactory::validate_locale (const String& locale) const
320 {
321     // Bypass the original IMEngineFactory.
322     return IMEngineFactoryBase::validate_locale (locale);
323 }
324 
325 IMEngineInstancePointer
create_instance(const String & encoding,int id)326 SCTCFilterFactory::create_instance (const String& encoding, int id)
327 {
328     if (m_sc_ok || m_tc_ok) {
329         SCTCWorkMode mode = SCTC_MODE_OFF;
330 
331         String orig_encoding = encoding;
332 
333         // If the original IMEngineFactory doesn't support this encoding,
334         // then we must use another encoding to create the original IMEngineInstance.
335         // It means we must use a conversion mode.
336         if (!FilterFactoryBase::validate_encoding (encoding)) {
337             // The client encoding is Simplified Chinese encoding, but is not supported by the IMEngine.
338             // So use Traditional Chinese encoding instead.
339             if (__is_sc_encoding (encoding)) {
340                 if (FilterFactoryBase::validate_encoding (m_sc_encoding)) {
341                     orig_encoding = m_sc_encoding;
342                 } else {
343                     orig_encoding = m_tc_encoding;
344                     mode = SCTC_MODE_FORCE_TC_TO_SC;
345                 }
346             } else if (__is_tc_encoding (encoding)) {
347                 if (FilterFactoryBase::validate_encoding (m_tc_encoding)) {
348                     orig_encoding = m_tc_encoding;
349                 } else {
350                     orig_encoding = m_sc_encoding;
351                     mode = SCTC_MODE_FORCE_SC_TO_TC;
352                 }
353             }
354         } else if ((__is_sc_encoding (encoding) && !FilterFactoryBase::validate_encoding (m_tc_encoding)) ||
355                    (__is_tc_encoding (encoding) && !FilterFactoryBase::validate_encoding (m_sc_encoding))) {
356             mode = SCTC_MODE_FORCE_OFF;
357         }
358 
359         return new SCTCFilterInstance (this, mode, encoding, FilterFactoryBase::create_instance (orig_encoding, id));
360     }
361 
362     return FilterFactoryBase::create_instance (encoding, id);
363 }
364 
365 //Implementation of SCTCFilterInstance
SCTCFilterInstance(SCTCFilterFactory * factory,const SCTCWorkMode & mode,const String & client_encoding,const IMEngineInstancePointer & orig_inst)366 SCTCFilterInstance::SCTCFilterInstance (SCTCFilterFactory *factory, const SCTCWorkMode &mode, const String &client_encoding, const IMEngineInstancePointer &orig_inst)
367     : FilterInstanceBase (factory, orig_inst),
368       m_factory (factory),
369       m_props_registered (false),
370       m_work_mode (mode)
371 {
372     IMEngineInstanceBase::set_encoding (client_encoding);
373 }
374 
375 bool
set_encoding(const String & encoding)376 SCTCFilterInstance::set_encoding (const String &encoding)
377 {
378     if (m_work_mode == SCTC_MODE_SC_TO_TC || m_work_mode == SCTC_MODE_FORCE_SC_TO_TC) {
379         if (__is_tc_encoding (encoding))
380             FilterInstanceBase::set_encoding (m_factory->m_sc_encoding);
381     } else if (m_work_mode == SCTC_MODE_TC_TO_SC || m_work_mode == SCTC_MODE_FORCE_TC_TO_SC) {
382         if (__is_sc_encoding (encoding))
383             FilterInstanceBase::set_encoding (m_factory->m_tc_encoding);
384     } else {
385         FilterInstanceBase::set_encoding (encoding);
386     }
387     reset ();
388     return IMEngineInstanceBase::set_encoding (encoding);
389 }
390 
391 void
focus_in()392 SCTCFilterInstance::focus_in ()
393 {
394     m_props_registered = false;
395 
396     FilterInstanceBase::focus_in ();
397 
398     if (!m_props_registered) {
399         PropertyList props;
400         filter_register_properties (props);
401     }
402 }
403 
404 void
trigger_property(const String & property)405 SCTCFilterInstance::trigger_property (const String &property)
406 {
407     if (property != __prop_off.get_key () && property != __prop_sc_to_tc.get_key () && property != __prop_tc_to_sc.get_key ()) {
408         FilterInstanceBase::trigger_property (property);
409         return;
410     }
411 
412     if (m_work_mode == SCTC_MODE_FORCE_SC_TO_TC || m_work_mode == SCTC_MODE_FORCE_TC_TO_SC || m_work_mode == SCTC_MODE_FORCE_OFF)
413         return;
414 
415     Property prop = __prop_root;
416     bool changed = false;
417 
418     if (property == __prop_off.get_key () && (m_work_mode == SCTC_MODE_SC_TO_TC || m_work_mode == SCTC_MODE_TC_TO_SC)) {
419         m_work_mode = SCTC_MODE_OFF;
420         changed = true;
421     } else if (property == __prop_sc_to_tc.get_key () && m_factory->m_sc_ok && !__is_sc_encoding (get_encoding ()) &&
422                (m_work_mode == SCTC_MODE_OFF || m_work_mode == SCTC_MODE_TC_TO_SC)) {
423         m_work_mode = SCTC_MODE_SC_TO_TC;
424         prop.set_icon (__prop_sc_to_tc.get_icon ());
425         prop.set_label (_("SC->TC"));
426         changed = true;
427     } else if (property == __prop_tc_to_sc.get_key () && m_factory->m_tc_ok && !__is_tc_encoding (get_encoding ()) &&
428                (m_work_mode == SCTC_MODE_OFF || m_work_mode == SCTC_MODE_SC_TO_TC)) {
429         m_work_mode = SCTC_MODE_TC_TO_SC;
430         prop.set_icon (__prop_tc_to_sc.get_icon ());
431         prop.set_label (_("TC->SC"));
432         changed = true;
433     }
434 
435     if (changed) {
436         set_encoding (get_encoding ());
437         update_property (prop);
438     }
439 }
440 
441 void
filter_update_preedit_string(const WideString & str,const AttributeList & attrs)442 SCTCFilterInstance::filter_update_preedit_string (const WideString    &str,
443                                                   const AttributeList &attrs)
444 {
445     WideString nstr = str;
446 
447     if (m_work_mode == SCTC_MODE_SC_TO_TC || m_work_mode == SCTC_MODE_FORCE_SC_TO_TC)
448         nstr = __sc_to_tc (str);
449     if (m_work_mode == SCTC_MODE_TC_TO_SC || m_work_mode == SCTC_MODE_FORCE_TC_TO_SC)
450         nstr = __tc_to_sc (str);
451 
452     update_preedit_string (nstr, attrs);
453 }
454 
455 void
filter_update_aux_string(const WideString & str,const AttributeList & attrs)456 SCTCFilterInstance::filter_update_aux_string (const WideString    &str,
457                                               const AttributeList &attrs)
458 {
459     WideString nstr = str;
460 
461     if (m_work_mode == SCTC_MODE_SC_TO_TC || m_work_mode == SCTC_MODE_FORCE_SC_TO_TC)
462         nstr = __sc_to_tc (str);
463     if (m_work_mode == SCTC_MODE_TC_TO_SC || m_work_mode == SCTC_MODE_FORCE_TC_TO_SC)
464         nstr = __tc_to_sc (str);
465 
466     update_aux_string (nstr, attrs);
467 }
468 
469 void
filter_update_lookup_table(const LookupTable & table)470 SCTCFilterInstance::filter_update_lookup_table (const LookupTable &table)
471 {
472     if (m_work_mode == SCTC_MODE_OFF) {
473         update_lookup_table (table);
474     } else {
475         CommonLookupTable ntable;
476         std::vector<WideString> labels;
477         size_t i;
478 
479         // Can be paged up.
480         if (table.get_current_page_start ())
481             ntable.append_candidate (0x3400);
482 
483         if (m_work_mode == SCTC_MODE_SC_TO_TC || m_work_mode == SCTC_MODE_FORCE_SC_TO_TC) {
484             for (i = 0; i < table.get_current_page_size (); ++i) {
485                 ntable.append_candidate (__sc_to_tc (table.get_candidate_in_current_page (i)), table.get_attributes_in_current_page (i));
486                 labels.push_back (__sc_to_tc (table.get_candidate_label (i)));
487             }
488         } else {
489             for (i = 0; i < table.get_current_page_size (); ++i) {
490                 ntable.append_candidate (__tc_to_sc (table.get_candidate_in_current_page (i)), table.get_attributes_in_current_page (i));
491                 labels.push_back (__tc_to_sc (table.get_candidate_label (i)));
492             }
493         }
494 
495         if (table.get_current_page_start () + table.get_current_page_size () < table.number_of_candidates ())
496             ntable.append_candidate (0x3400);
497 
498         if (table.get_current_page_start ()) {
499             ntable.set_page_size (1);
500             ntable.page_down ();
501         }
502 
503         ntable.set_page_size (table.get_current_page_size ());
504         ntable.set_cursor_pos_in_current_page (table.get_cursor_pos_in_current_page ());
505         ntable.show_cursor (table.is_cursor_visible ());
506         ntable.fix_page_size (table.is_page_size_fixed ());
507         ntable.set_candidate_labels (labels);
508 
509         update_lookup_table (ntable);
510     }
511 }
512 
513 void
filter_commit_string(const WideString & str)514 SCTCFilterInstance::filter_commit_string (const WideString &str)
515 {
516     WideString nstr = str;
517 
518     if (m_work_mode == SCTC_MODE_SC_TO_TC || m_work_mode == SCTC_MODE_FORCE_SC_TO_TC)
519         nstr = __sc_to_tc (str);
520     if (m_work_mode == SCTC_MODE_TC_TO_SC || m_work_mode == SCTC_MODE_FORCE_TC_TO_SC)
521         nstr = __tc_to_sc (str);
522 
523     commit_string (nstr);
524 }
525 
526 void
filter_register_properties(const PropertyList & properties)527 SCTCFilterInstance::filter_register_properties (const PropertyList &properties)
528 {
529     PropertyList props;
530 
531     if (m_work_mode == SCTC_MODE_SC_TO_TC || m_work_mode == SCTC_MODE_FORCE_SC_TO_TC) {
532         for (size_t i = 0; i < properties.size (); ++i) {
533             Property prop = properties [i];
534             prop.set_label (utf8_wcstombs (__sc_to_tc (utf8_mbstowcs (prop.get_label ()))));
535             prop.set_tip   (utf8_wcstombs (__sc_to_tc (utf8_mbstowcs (prop.get_tip ()))));
536             props.push_back (prop);
537         }
538     } else if (m_work_mode == SCTC_MODE_TC_TO_SC || m_work_mode == SCTC_MODE_FORCE_TC_TO_SC) {
539         for (size_t i = 0; i < properties.size (); ++i) {
540             Property prop = properties [i];
541             prop.set_label (utf8_wcstombs (__tc_to_sc (utf8_mbstowcs (prop.get_label ()))));
542             prop.set_tip   (utf8_wcstombs (__tc_to_sc (utf8_mbstowcs (prop.get_tip ()))));
543             props.push_back (prop);
544         }
545     } else {
546         props = properties;
547     }
548 
549     if (m_work_mode == SCTC_MODE_OFF || m_work_mode == SCTC_MODE_SC_TO_TC || m_work_mode == SCTC_MODE_TC_TO_SC) {
550         Property root = __prop_root;
551 
552         if (m_work_mode == SCTC_MODE_SC_TO_TC) {
553             root.set_icon (__prop_sc_to_tc.get_icon ());
554             root.set_tip  (__prop_sc_to_tc.get_tip ());
555             root.set_label (_("SC->TC"));
556         } else if (m_work_mode == SCTC_MODE_TC_TO_SC) {
557             root.set_icon (__prop_tc_to_sc.get_icon ());
558             root.set_tip  (__prop_tc_to_sc.get_tip ());
559             root.set_label (_("TC->SC"));
560         }
561 
562         props.push_back (root);
563         props.push_back (__prop_off);
564 
565         if (!__is_sc_encoding (get_encoding ()) && m_factory->m_sc_ok)
566             props.push_back (__prop_sc_to_tc);
567         if (!__is_tc_encoding (get_encoding ()) && m_factory->m_tc_ok)
568             props.push_back (__prop_tc_to_sc);
569     } else if (m_work_mode == SCTC_MODE_FORCE_SC_TO_TC) {
570         Property root = __prop_sc_to_tc;
571         root.set_label (_("SC->TC"));
572         props.push_back (root);
573     } else if (m_work_mode == SCTC_MODE_FORCE_TC_TO_SC) {
574         Property root = __prop_tc_to_sc;
575         root.set_label (_("TC->SC"));
576         props.push_back (root);
577     }
578 
579     register_properties (props);
580 
581     m_props_registered = true;
582 }
583 
584 void
filter_update_property(const Property & property)585 SCTCFilterInstance::filter_update_property (const Property &property)
586 {
587     Property prop = property;
588 
589     if (m_work_mode == SCTC_MODE_SC_TO_TC || m_work_mode == SCTC_MODE_FORCE_SC_TO_TC) {
590         prop.set_label (utf8_wcstombs (__sc_to_tc (utf8_mbstowcs (prop.get_label ()))));
591         prop.set_tip   (utf8_wcstombs (__sc_to_tc (utf8_mbstowcs (prop.get_tip ()))));
592     } else if (m_work_mode == SCTC_MODE_TC_TO_SC || m_work_mode == SCTC_MODE_FORCE_TC_TO_SC) {
593         prop.set_label (utf8_wcstombs (__tc_to_sc (utf8_mbstowcs (prop.get_label ()))));
594         prop.set_tip   (utf8_wcstombs (__tc_to_sc (utf8_mbstowcs (prop.get_tip ()))));
595     }
596 
597     update_property (prop);
598 }
599 
600 /*
601 vi:ts=4:nowrap:ai:expandtab
602 */
603