Fixed defect detected by static analysis tool
[platform/core/uifw/libscl-ui.git] / xmlresource / layout_parser.cpp
1 /*
2  * Copyright (c) 2012 - 2014 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the License);
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an AS IS BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 #include <algorithm>
19 #include <vector>
20 #include <malloc.h>
21 #include <string.h>
22 #include <libxml/parser.h>
23 #include <glib.h>
24
25 #include "layout_parser.h"
26 #include "default_configure_parser.h" /* use data in default_configure.xml */
27 #include "xml_parser_utils.h"
28 #include "layout_parser_helper.h"
29 #include "put_record.h"
30 #include "simple_debug.h"
31 #include <dlog.h>
32
33 using namespace std;
34
35 #define LAYOUT_TAG "layout"
36 #define LAYOUT_NAME_ATTRIBUTE "name"
37 #define LAYOUT_DIRECTION_ATTRIBUTE "direction"
38 #define LAYOUT_DIRECTION_ATTRIBUTE_PORTRAIT_VALUE "portrait"
39 #define LAYOUT_DIRECTION_ATTRIBUTE_LANDSCAPE_VALUE "landscape"
40 #define LAYOUT_STYLE_ATTRIBUTE "style"
41 #define LAYOUT_STYLE_ATTRIBUTE_BASE_VALUE "base"
42 #define LAYOUT_STYLE_ATTRIBUTE_POPUP_VALUE "popup"
43 #define LAYOUT_STYLE_ATTRIBUTE_POPUP_GRAB_VALUE "popup_grab"
44 #define LAYOUT_WIDTH_ATTRIBUTE "width"
45 #define LAYOUT_HEIGHT_ATTRIBUTE "height"
46 #define LAYOUT_MAGNIFIER_ATTRIBUTE "magnifier"
47 #define LAYOUT_PART_BACKGROUND_ATTRIBUTE "part_background"
48 #define LAYOUT_SW_BUTTON_ATTRIBUTE "sw_button"
49 #define LAYOUT_SW_BACKGROUND_ATTRIBUTE "sw_background"
50 #define LAYOUT_KEY_WIDTH_ATTRIBUTE "key_width"
51 #define LAYOUT_KEY_HEIGHT_ATTRIBUTE "key_height"
52 #define LAYOUT_KEY_SPACING_ATTRIBUTE "key_spacing"
53 #define LAYOUT_ROW_SPACING_ATTRIBUTE "row_spacing"
54 #define LAYOUT_KEY_ADD_HIT_LEFT_ATTRIBUTE "hit_left"
55 #define LAYOUT_KEY_ADD_HIT_RIGHT_ATTRIBUTE "hit_right"
56 #define LAYOUT_KEY_ADD_HIT_TOP_ATTRIBUTE "hit_top"
57 #define LAYOUT_KEY_ADD_HIT_BOTTOM_ATTRIBUTE "hit_bottom"
58 #define LAYOUT_VIBE_STYLE_ATTRIBUTE "vibe_style"
59 #define LAYOUT_SOUND_STYLE_ATTRIBUTE "sound_style"
60 #define LAYOUT_LABEL_TYPE_ATTRIBUTE "label_type"
61 #define LAYOUT_MODIFIER_DECORATION_ATTRIBUTE "modifier_decoration"
62
63 #define LAYOUT_ADD_GRAB_TAG "grab_area"
64 #define LAYOUT_ADD_GRAB_LEFT_TAG "left"
65 #define LAYOUT_ADD_GRAB_RIGHT_TAG "right"
66 #define LAYOUT_ADD_GRAB_TOP_TAG "top"
67 #define LAYOUT_ADD_GRAB_BOTTOM_TAG "bottom"
68
69 #define LAYOUT_KEY_BACKGROUND_REC_TAG "rec"
70 #define LAYOUT_KEY_BACKGROUND_REC_BUTTON_ATTRIBUTE "button"
71 #define LAYOUT_KEY_BACKGROUND_REC_BUTTON_ATTRIBUTE_NORMAL_VALUE "normal"
72 #define LAYOUT_KEY_BACKGROUND_REC_BUTTON_ATTRIBUTE_PRESSED_VALUE "pressed"
73 #define LAYOUT_KEY_BACKGROUND_REC_BUTTON_ATTRIBUTE_DISABLED_VALUE "disabled"
74
75 #define LAYOUT_KEY_BACKGROUND_TAG "background_image"
76 #define LAYOUT_KEY_BACKGROUND_REC_TAG "rec"
77 #define LAYOUT_KEY_BACKGROUND_REC_BUTTON_ATTRIBUTE "button"
78 #define LAYOUT_KEY_BACKGROUND_REC_BUTTON_ATTRIBUTE_NORMAL_VALUE "normal"
79 #define LAYOUT_KEY_BACKGROUND_REC_BUTTON_ATTRIBUTE_PRESSED_VALUE "pressed"
80 #define LAYOUT_KEY_BACKGROUND_REC_BUTTON_ATTRIBUTE_DISABLED_VALUE "disabled"
81
82 #define LAYOUT_BACKGROUND_TAG "image_path"
83 #define LAYOUT_BACKGROUND_NORMAL_TAG "button_normal"
84 #define LAYOUT_BACKGROUND_PRESSED_TAG "button_pressed"
85 #define LAYOUT_BACKGROUND_DISABLED_TAG "button_disabled"
86 #define LAYOUT_BACKGROUND_TOGGLED_TAG "button_toggled"
87
88 #define LAYOUT_SW_BACKGROUND_TAG "background_color"
89
90 #define LAYOUT_ROW_TAG "row"
91 #define LAYOUT_ROW_SUBLAYOUT_ID_ATTRIBUTE "sub_layout"
92 #define LAYOUT_ROW_X_ATTRIBUTE "x"
93 #define LAYOUT_ROW_Y_ATTRIBUTE "y"
94 #define LAYOUT_ROW_KEY_WIDTH_ATTRIBUTE LAYOUT_KEY_WIDTH_ATTRIBUTE
95 #define LAYOUT_ROW_KEY_HEIGHT_ATTRIBUTE LAYOUT_KEY_HEIGHT_ATTRIBUTE
96 #define LAYOUT_ROW_KEY_SPACING_ATTRIBUTE LAYOUT_KEY_SPACING_ATTRIBUTE
97
98 #define LAYOUT_ROW_KEY_TAG "key"
99 #define LAYOUT_ROW_KEY_CUSTOMID_ATTRIBUTE "custom_id"
100 #define LAYOUT_ROW_KEY_BUTTON_TYPE_ATTRIBUTE "button_type"
101 #define LAYOUT_ROW_KEY_KEY_TYPE_ATTRIBUTE "key_type"
102 #define LAYOUT_ROW_KEY_POPUP_TYPE_ATTRIBUTE "popup_type"
103 #define LAYOUT_ROW_KEY_MAGNIFIER_ATTRIBUTE "use_magnifier"
104 #define LAYOUT_ROW_KEY_LONGKEY_MAGNIFIER_ATTRIBUTE "longkey_magnifier"
105 #define LAYOUT_ROW_KEY_VIBE_STYLE_ATTRIBUTE LAYOUT_VIBE_STYLE_ATTRIBUTE
106 #define LAYOUT_ROW_KEY_SOUND_STYLE_ATTRIBUTE LAYOUT_SOUND_STYLE_ATTRIBUTE
107 #define LAYOUT_ROW_KEY_SIDE_BUTTON_ATTRIBUTE "is_side_button"
108
109 #define LAYOUT_ROW_KEY_X_ATTRIBUTE "x"
110 #define LAYOUT_ROW_KEY_Y_ATTRIBUTE "y"
111 #define LAYOUT_ROW_KEY_KEY_WIDTH_ATTRIBUTE "width"
112 #define LAYOUT_ROW_KEY_KEY_HEIGHT_ATTRIBUTE "height"
113 #define LAYOUT_ROW_KEY_ADD_HIT_LEFT_ATTRIBUTE "hit_left"
114 #define LAYOUT_ROW_KEY_ADD_HIT_RIGHT_ATTRIBUTE "hit_right"
115 #define LAYOUT_ROW_KEY_ADD_HIT_TOP_ATTRIBUTE "hit_top"
116 #define LAYOUT_ROW_KEY_ADD_HIT_BOTTOM_ATTRIBUTE "hit_bottom"
117 #define LAYOUT_ROW_KEY_POPUP_POS_X_ATTRIBUTE "popup_offset_x"
118 #define LAYOUT_ROW_KEY_POPUP_POS_Y_ATTRIBUTE "popup_offset_y"
119 #define LAYOUT_ROW_KEY_POPUP_IMAGE_X_ATTRIBUTE "popup_image_x"
120 #define LAYOUT_ROW_KEY_POPUP_IMAGE_Y_ATTRIBUTE "popup_image_y"
121 #define LAYOUT_ROW_KEY_SUBLAYOUT_ID_ATTRIBUTE "sub_layout"
122
123 #define LAYOUT_ROW_KEY_LABEL_TYPE_ATTRIBUTE "label_type"
124 #define LAYOUT_ROW_KEY_IMAGE_LABEL_TYPE_ATTRIBUTE "image_label_type"
125 #define LAYOUT_ROW_KEY_LONGKEY_TYPE_ATTRIBUTE "long_key_type"
126 #define LAYOUT_ROW_KEY_LONGKEY_VALUE_ATTRIBUTE "long_key_value"
127 #define LAYOUT_ROW_KEY_LONGKEY_EVENT_ATTRIBUTE "long_key_event"
128 #define LAYOUT_ROW_KEY_USE_REPEAT_KEY_ATTRIBUTE "use_repeat_key"
129 #define LAYOUT_ROW_KEY_DONOT_CLOSE_POPUP_ATTRIBUTE "donot_close_popup"
130 #define LAYOUT_ROW_KEY_EXTRA_OPTION_ATTRIBUTE "extra_option"
131 #define LAYOUT_ROW_KEY_MULTITOUCH_TYPE_ATTRIBUTE "multitouch_type"
132 #define LAYOUT_ROW_KEY_MODIFIER_DECORATION_ID_ATTRIBUTE "modifier_decoration_id"
133
134 #define LAYOUT_ROW_KEY_KEY_SPACING_ATTRIBUTE "key_spacing"
135
136 #define LAYOUT_ROW_KEY_LABEL_TAG "label"
137 #define LAYOUT_ROW_KEY_IMAGE_LABEL_TAG "image_label"
138 #define LAYOUT_ROW_KEY_BACKGROUND_IMAGE_TAG "background_image"
139 #define LAYOUT_ROW_KEY_KEY_VALUE_TAG "key_value"
140 #define LAYOUT_ROW_KEY_KEY_EVENT_TAG "key_event"
141
142 #define LAYOUT_ROW_KEY_POPUP_INPUTMODE_RECORD_TAG "popup_input_mode_record"
143 #define LAYOUT_ROW_KEY_POPUP_INPUTMODE_RECORD_INPUTMODE_TAG "popup_input_mode"
144
145 #define LAYOUT_ROW_KEY_AUTOPOPUP_KEYS_TAG "auto_popup_keys"
146 #define LAYOUT_ROW_KEY_AUTOPOPUP_KEYS_SHIFTMODE_ATTRIBUTE "shift_state"
147 #define LAYOUT_ROW_KEY_MAGNIFIER_LABEL_TAG "magnifier_label"
148
149 #define LAYOUT_ROW_KEY_HINT_STRING_TAG "hint_string"
150
151 #define LAYOUT_SUB_LAYOUT_DEFAULT_STRING "DEFAULT"
152
153 #ifndef LOG_TAG
154 #define LOG_TAG "LIBSCL_UI"
155 #endif
156
157 class LayoutParserImpl {
158     public:
159         typedef struct {
160             int row_x;
161             int row_y;
162
163             sclshort key_width;
164             sclshort key_height;
165             sclshort key_spacing;
166             sclshort row_spacing;
167
168             sclshort add_hit_left;
169             sclshort add_hit_right;
170             sclshort add_hit_top;
171             sclshort add_hit_bottom;
172
173             sclchar *sub_layout;
174             sclchar *vibe_style;
175             sclchar *sound_style;
176             sclchar *label_type;
177             sclchar *bg_image_path[SCL_SHIFT_STATE_MAX][SCL_BUTTON_STATE_MAX];
178         } Row;
179         LayoutParserImpl();
180         ~LayoutParserImpl();
181
182         void load(int layout_id);
183         void unload();
184         bool loaded(int layout_id);
185         void set_directory(const string &dir);
186         int get_layout_index(const char *name);
187         int get_layout_size();
188         PSclLayout get_layout_table();
189         PSclLayoutKeyCoordinatePointerTable get_key_coordinate_pointer_frame();
190         int get_drag_state_prop(const xmlNodePtr cur_node);
191         int get_shift_state_prop(const xmlNodePtr cur_node);
192         int get_button_state_prop(const xmlNodePtr cur_node);
193         int get_multitouch_type_prop(const xmlNodePtr cur_node);
194         int get_extra_option_prop(const xmlNodePtr cur_node);
195
196         int parsing_layout_table(const vector<string> &layout_file_name);
197         void parsing_layout_node(const xmlNodePtr cur_node, const PSclLayout cur_rec_layout, int layout_no);
198         void loading_coordinate_resources(const xmlNodePtr cur_node, const PSclLayout cur_rec_layout, int layout_no);
199         void parsing_background(const xmlNodePtr cur_node, const PSclLayout);
200         void parsing_key_background(const xmlNodePtr cur_node, const PSclLayout);
201         void parsing_grab_area(const xmlNodePtr cur_node, const PSclLayout cur_rec_layout);
202         void parsing_sw_background_color(const xmlNodePtr cur_node, const PSclLayout);
203
204         void set_default_layout_value(const PSclLayout);
205         void set_default_row_value(Row*, const PSclLayout cur_rec_layout, const int row_y);
206         void set_default_key_coordinate_value(const PSclLayoutKeyCoordinate cur_rec_coordinate, const Row*);
207
208         void free_key_coordinate_table(const PSclLayoutKeyCoordinateTable curTable);
209
210         void parsing_layout_row_node(const xmlNodePtr cur_node, const PSclLayout cur_rec_layout,
211             int *row_y, int *sub_layout_height, SclLayoutKeyCoordinatePointer **cur_key);
212         void parsing_key_coordinate_record_node(const xmlNodePtr cur_node, Row* row, SclLayoutKeyCoordinatePointer *cur_key);
213
214         void parsing_label_record_node(const xmlNodePtr cur_node, const PSclLayoutKeyCoordinate cur_rec);
215         void parsing_label_image_record_node(const xmlNodePtr cur_node, const PSclLayoutKeyCoordinate cur_rec);
216         void parsing_background_image_record_node(const xmlNodePtr cur_node, const PSclLayoutKeyCoordinate cur_rec);
217         void parsing_popup_input_mode_record_node(const xmlNodePtr cur_node, const PSclLayoutKeyCoordinate cur_rec);
218         void parsing_key_value_record_node(const xmlNodePtr cur_node, const PSclLayoutKeyCoordinate cur_rec);
219         void parsing_key_event_record_node(const xmlNodePtr cur_node, const PSclLayoutKeyCoordinate cur_rec);
220         void parsing_auto_popup_keys_record_node(const xmlNodePtr cur_node, const PSclLayoutKeyCoordinate cur_rec);
221         void parsing_magnifier_label_record_node(const xmlNodePtr cur_node, const PSclLayoutKeyCoordinate cur_rec);
222         void parsing_hint_string_record_node(const xmlNodePtr cur_node, const PSclLayoutKeyCoordinate cur_rec);
223
224         void add_layout_string(xmlChar*);
225         void release_layout_strings();
226
227         void add_key_string(xmlChar*);
228         void release_key_strings();
229
230         void add_upper_string(gchar*);
231         void release_upper_strings();
232
233     private:
234         int m_layout_size;
235         SclLayout m_layout_table[MAX_SCL_LAYOUT];
236         vector<string> m_file_names;
237         SclLayoutKeyCoordinate* m_key_coordinate_pointer_frame[MAX_SCL_LAYOUT][MAX_KEY];
238
239         std::vector<xmlChar*> m_vec_layout_strings;
240         std::vector<xmlChar*> m_vec_key_strings;
241         std::vector<gchar*> m_vec_upper_strings;
242         std::string m_dir;
243 };
244
245
246 LayoutParserImpl::LayoutParserImpl() {
247     m_layout_size = 0;
248     memset(m_layout_table, 0x00, sizeof(SclLayout) * MAX_SCL_LAYOUT);
249     memset(m_key_coordinate_pointer_frame, 0x00, sizeof(SclLayoutKeyCoordinatePointer) * MAX_SCL_LAYOUT * MAX_KEY);
250 }
251
252 LayoutParserImpl::~LayoutParserImpl() {
253     for (int i = 0; i < MAX_SCL_LAYOUT; ++i) {
254         for (int j = 0; j < MAX_KEY; ++j) {
255             free(m_key_coordinate_pointer_frame[i][j]);
256             m_key_coordinate_pointer_frame[i][j] = NULL;
257         }
258     }
259
260     release_layout_strings();
261     release_key_strings();
262     release_upper_strings();
263 }
264
265 void
266 LayoutParserImpl::load(int layout_id) {
267     if (layout_id >= 0 && layout_id < MAX_SCL_LAYOUT) {
268         xmlDocPtr doc;
269         xmlNodePtr cur_node;
270
271         string input_file = m_dir + "/" + m_file_names[layout_id];
272         doc = xmlReadFile(input_file.c_str(), NULL, 0);
273         if (doc == NULL) {
274             SCLLOG(SclLog::ERROR, "Could not load file: %s.", input_file.c_str());
275             LOGE("Could not load file: %s.", input_file.c_str());
276             return;
277         }
278
279         cur_node = xmlDocGetRootElement(doc);
280         if (cur_node == NULL) {
281             SCLLOG(SclLog::ERROR, "LayoutParserImpl: empty document.\n");
282             LOGE("LayoutParserImpl: empty document.");
283             xmlFreeDoc(doc);
284             return;
285         }
286         if (0 != xmlStrcmp(cur_node->name, (const xmlChar*)LAYOUT_TAG))
287         {
288             SCLLOG(SclLog::ERROR, "LayoutParserImpl: root name error: %s\n!", (char *)cur_node->name);
289             LOGE("LayoutParserImpl: root name error: %s!", (char *)cur_node->name);
290             xmlFreeDoc(doc);
291             return;
292         }
293
294         PSclLayout cur_rec_layout = m_layout_table + layout_id;
295         loading_coordinate_resources(cur_node, cur_rec_layout, layout_id);
296
297         xmlFreeDoc(doc);
298     }
299 }
300
301 void LayoutParserImpl::unload() {
302     for (int i = 0; i < MAX_SCL_LAYOUT; ++i) {
303         for (int j = 0; j < MAX_KEY; ++j) {
304             free(m_key_coordinate_pointer_frame[i][j]);
305             m_key_coordinate_pointer_frame[i][j] = NULL;
306         }
307     }
308
309     release_key_strings();
310     release_upper_strings();
311 }
312
313 bool
314 LayoutParserImpl::loaded(int layout_id) {
315     bool ret = TRUE;
316
317     if (layout_id >= 0 && layout_id < MAX_SCL_LAYOUT) {
318         if (m_key_coordinate_pointer_frame[layout_id][0] == NULL) {
319             ret = FALSE;
320         }
321     }
322
323     return ret;
324 }
325
326 void
327 LayoutParserImpl::set_directory(const string& dir) {
328     m_dir = dir;
329 }
330
331 void
332 LayoutParserImpl::add_layout_string(xmlChar* newstr) {
333     if (newstr) {
334         m_vec_layout_strings.push_back(newstr);
335     }
336 }
337
338 void
339 LayoutParserImpl::release_layout_strings() {
340     for (size_t loop = 0; loop < m_vec_layout_strings.size(); loop++) {
341         if (m_vec_layout_strings[loop]) {
342             xmlFree(m_vec_layout_strings[loop]);
343         }
344     }
345     m_vec_layout_strings.clear();
346 }
347
348 void
349 LayoutParserImpl::add_key_string(xmlChar* newstr) {
350     if (newstr) {
351         m_vec_key_strings.push_back(newstr);
352     }
353 }
354
355 void
356 LayoutParserImpl::release_key_strings() {
357     for (size_t loop = 0; loop < m_vec_key_strings.size(); loop++) {
358         if (m_vec_key_strings[loop]) {
359             xmlFree(m_vec_key_strings[loop]);
360         }
361     }
362     m_vec_key_strings.clear();
363 }
364
365 void
366 LayoutParserImpl::add_upper_string(gchar* newstr) {
367     if (newstr) {
368         m_vec_upper_strings.push_back(newstr);
369     }
370 }
371
372 void
373 LayoutParserImpl::release_upper_strings() {
374     for (size_t loop = 0; loop < m_vec_upper_strings.size(); loop++) {
375         if (m_vec_upper_strings[loop]) {
376             g_free(m_vec_upper_strings[loop]);
377         }
378     }
379     m_vec_upper_strings.clear();
380 }
381
382 int
383 LayoutParserImpl::get_layout_index(const char *name) {
384     if (name) {
385         string strName = (string)name;
386         vector<string>::iterator it;
387         // make sure that the m_file_names are sorted.
388         it = lower_bound(m_file_names.begin(), m_file_names.end(), strName);
389         if (it != m_file_names.end() && *it == strName) {
390             return it - m_file_names.begin();
391         }
392     }
393     return NOT_USED;
394 }
395
396 PSclLayout
397 LayoutParserImpl::get_layout_table() {
398     return m_layout_table;
399 }
400
401 int
402 LayoutParserImpl::get_layout_size() {
403     return m_layout_size;
404 }
405
406 PSclLayoutKeyCoordinatePointerTable
407 LayoutParserImpl::get_key_coordinate_pointer_frame() {
408     return m_key_coordinate_pointer_frame;
409 }
410
411 int
412 LayoutParserImpl::parsing_layout_table(const vector<string> &vec_file) {
413     m_file_names = vec_file;
414     m_layout_size = vec_file.size();
415     vector<string>::const_iterator it;
416     for (it = vec_file.begin(); it != vec_file.end(); it++) {
417         xmlDocPtr doc;
418         xmlNodePtr cur_node;
419
420         string input_file = m_dir + "/" + *it;
421         doc = xmlReadFile(input_file.c_str(), NULL, 0);
422         if (doc == NULL) {
423             SCLLOG(SclLog::DEBUG, "Could not load file: %s.", input_file.c_str());
424             return -1;
425         }
426
427         cur_node = xmlDocGetRootElement(doc);
428         if (cur_node == NULL) {
429             SCLLOG(SclLog::DEBUG, "LayoutParserImpl: empty document.\n");
430             xmlFreeDoc(doc);
431             return -1;
432         }
433         if (0 != xmlStrcmp(cur_node->name, (const xmlChar*)LAYOUT_TAG))
434         {
435             SCLLOG(SclLog::DEBUG, "LayoutParserImpl: root name error: %s\n!", (char *)cur_node->name);
436             xmlFreeDoc(doc);
437             return -1;
438         }
439
440         int layout_id = it - vec_file.begin();
441         PSclLayout cur_rec_layout = &(m_layout_table[layout_id]);
442         parsing_layout_node(cur_node, cur_rec_layout, layout_id);
443         cur_rec_layout->name = (sclchar*)strdup(it->c_str());
444
445         xmlFreeDoc(doc);
446     }
447     return 0;
448 }
449
450 void
451 LayoutParserImpl::parsing_background(
452         const xmlNodePtr cur_node,
453         PSclLayout cur_layout) {
454     assert(cur_node != NULL);
455     assert(cur_layout != NULL);
456
457     xmlNodePtr child_node = cur_node->xmlChildrenNode;
458     while (child_node != NULL) {
459         if (0 == xmlStrcmp(child_node->name, (const xmlChar*)LAYOUT_BACKGROUND_NORMAL_TAG)) {
460             xmlChar *key = xmlNodeGetContent(child_node);
461             cur_layout->image_path[BUTTON_STATE_NORMAL] = (char *)key;
462             add_layout_string(key);
463         } else if (0 == xmlStrcmp(child_node->name, (const xmlChar*)LAYOUT_BACKGROUND_PRESSED_TAG)) {
464             xmlChar *key = xmlNodeGetContent(child_node);
465             cur_layout->image_path[BUTTON_STATE_PRESSED] = (char *)key;
466             add_layout_string(key);
467         } else if (0 == xmlStrcmp(child_node->name, (const xmlChar*)LAYOUT_BACKGROUND_DISABLED_TAG )) {
468             xmlChar *key = xmlNodeGetContent(child_node);
469             cur_layout->image_path[BUTTON_STATE_DISABLED] = (char *)key;
470             add_layout_string(key);
471         } else if (0 == xmlStrcmp(child_node->name, (const xmlChar*)LAYOUT_BACKGROUND_TOGGLED_TAG )) {
472             xmlChar *key = xmlNodeGetContent(child_node);
473             cur_layout->image_path[BUTTON_STATE_TOGGLED] = (char *)key;
474             add_layout_string(key);
475         }
476
477         child_node = child_node->next;
478     }
479 }
480
481 void
482 LayoutParserImpl::parsing_sw_background_color(
483     const xmlNodePtr cur_node,
484     PSclLayout cur_layout) {
485     assert(cur_node != NULL);
486     assert(cur_layout != NULL);
487
488     xmlNodePtr child_node = cur_node->xmlChildrenNode;
489     while (child_node != NULL) {
490         if (0 == xmlStrcmp(child_node->name, (const xmlChar *)"r")) {
491             cur_layout->bg_color.r = get_content_int(child_node);
492         } else if (0 == xmlStrcmp(child_node->name, (const xmlChar *)"g")) {
493             cur_layout->bg_color.g = get_content_int(child_node);
494         } else if (0 == xmlStrcmp(child_node->name, (const xmlChar *)"b")) {
495             cur_layout->bg_color.b = get_content_int(child_node);
496         } else if (0 == xmlStrcmp(child_node->name, (const xmlChar *)"a")) {
497             cur_layout->bg_color.a = get_content_int(child_node);
498         }
499
500         child_node = child_node->next;
501     }
502 }
503
504 void
505 LayoutParserImpl::parsing_key_background(
506         const xmlNodePtr cur_node,
507         PSclLayout cur_layout) {
508     assert(cur_node != NULL);
509     assert(cur_layout != NULL);
510
511     xmlNodePtr child_node = cur_node->xmlChildrenNode;
512     while (child_node != NULL) {
513         if (0 == xmlStrcmp(child_node->name, (const xmlChar*)"rec")) {
514             int shift_state = get_shift_state_prop(child_node);
515             int button_state = get_button_state_prop(child_node);
516             for (int shift_loop = 0;shift_loop < SCL_SHIFT_STATE_MAX;shift_loop++) {
517                 for (int button_loop = 0;button_loop < SCL_BUTTON_STATE_MAX;button_loop++) {
518                     if ((shift_state == shift_loop || shift_state == -1) &&
519                         (button_state == button_loop || button_state == -1)) {
520                             xmlChar* key = xmlNodeGetContent(child_node);
521                             cur_layout->key_background_image[shift_loop][button_loop] = (sclchar*)key;
522                             add_layout_string(key);
523                     }
524                 }
525             }
526         }
527
528         child_node = child_node->next;
529     }
530 }
531
532
533 void
534 LayoutParserImpl::set_default_layout_value(const PSclLayout cur_layout) {
535     DefaultConfigParser *default_configure_parser = DefaultConfigParser::get_instance();
536     assert(default_configure_parser);
537     const PSclDefaultConfigure sclres_default_configure = default_configure_parser->get_default_configure();
538
539     assert(cur_layout != NULL);
540     cur_layout->valid = 1;
541     cur_layout->style = LAYOUT_STYLE_BASE;
542     cur_layout->name = NULL;
543
544     if (sclres_default_configure) {
545         cur_layout->width = sclres_default_configure->target_screen_width;
546         cur_layout->height = sclres_default_configure->target_screen_height;
547     }
548
549     cur_layout->key_width = 0;
550     cur_layout->key_height = 0;
551     cur_layout->key_spacing = 0;
552     cur_layout->row_spacing = 0;
553
554     cur_layout->image_path[BUTTON_STATE_NORMAL]      = NULL;
555     cur_layout->image_path[BUTTON_STATE_PRESSED]     = NULL;
556     cur_layout->image_path[BUTTON_STATE_DISABLED]    = NULL;
557     cur_layout->image_path[BUTTON_STATE_TOGGLED]     = NULL;
558
559     cur_layout->use_sw_button = false;
560     cur_layout->use_magnifier_window = false;
561
562     cur_layout->display_mode = DISPLAYMODE_PORTRAIT;
563     cur_layout->use_sw_background = false;
564     memset (&(cur_layout->bg_color), 0, sizeof(SclColor));
565     cur_layout->bg_line_width = 0.0;
566     memset (&(cur_layout->bg_line_color), 0, sizeof(SclColor));
567
568     memset (cur_layout->key_background_image, 0, sizeof(cur_layout->key_background_image));
569     cur_layout->sound_style = NULL;
570     cur_layout->vibe_style = NULL;
571     cur_layout->label_type = NULL;
572     cur_layout->modifier_decorator = NULL;
573
574     cur_layout->add_grab_left = NOT_USED;
575     cur_layout->add_grab_right = NOT_USED;
576     cur_layout->add_grab_top = NOT_USED;
577     cur_layout->add_grab_bottom = NOT_USED;
578 }
579
580 void
581 LayoutParserImpl::set_default_row_value(
582         Row* row,
583         const PSclLayout cur_rec_layout,
584         int row_y) {
585     if (row) {
586         row->row_x = 0;
587         row->row_y = row_y;
588         row->key_width = cur_rec_layout->key_width;
589         row->key_height = cur_rec_layout->key_height;
590         row->key_spacing = cur_rec_layout->key_spacing;
591         row->row_spacing = cur_rec_layout->row_spacing;
592         row->add_hit_left = cur_rec_layout->add_hit_left;
593         row->add_hit_right = cur_rec_layout->add_hit_right;
594         row->add_hit_top = cur_rec_layout->add_hit_top;
595         row->add_hit_bottom = cur_rec_layout->add_hit_bottom;
596         row->sub_layout = NULL;
597         row->label_type = cur_rec_layout->label_type;
598         row->vibe_style = cur_rec_layout->vibe_style;
599         row->sound_style = cur_rec_layout->sound_style;
600         for (int shift_state = 0; shift_state < SCL_SHIFT_STATE_MAX; shift_state++) {
601             for (int button_state = 0; button_state < SCL_BUTTON_STATE_MAX; ++button_state) {
602                 row->bg_image_path[shift_state][button_state] = cur_rec_layout->key_background_image[shift_state][button_state];
603             }
604         }
605     }
606 }
607
608 void
609 LayoutParserImpl::set_default_key_coordinate_value(
610         const PSclLayoutKeyCoordinate cur_rec_coordinate,
611         const Row* row) {
612     assert(row != NULL);
613     assert(cur_rec_coordinate != NULL);
614
615     int loop;
616
617     if (row && cur_rec_coordinate) {
618         cur_rec_coordinate->valid = FALSE;
619         cur_rec_coordinate->custom_id = NULL;
620         cur_rec_coordinate->button_type = BUTTON_TYPE_NORMAL;
621         cur_rec_coordinate->key_type = KEY_TYPE_CHAR;
622         cur_rec_coordinate->popup_type = POPUP_TYPE_NONE;
623         cur_rec_coordinate->use_magnifier = (sclboolean)true;
624         cur_rec_coordinate->use_long_key_magnifier = (sclboolean)false;
625         //cur_rec_coordinate->enabled =(sclboolean) TRUE;
626         for (loop = 0;loop < SCL_DRAG_STATE_MAX;loop++) {
627             cur_rec_coordinate->popup_input_mode[loop] = NULL;
628         }
629         cur_rec_coordinate->sound_style = row->sound_style;
630         cur_rec_coordinate->vibe_style = row->vibe_style;
631         cur_rec_coordinate->is_side_button = false;
632
633         cur_rec_coordinate->x = row->row_x;
634         cur_rec_coordinate->y = row->row_y;
635         cur_rec_coordinate->width = row->key_width;
636         cur_rec_coordinate->height = row->key_height;
637
638         cur_rec_coordinate->add_hit_left = row->add_hit_left;
639         cur_rec_coordinate->add_hit_right = row->add_hit_right;
640         cur_rec_coordinate->add_hit_top = row->add_hit_top;
641         cur_rec_coordinate->add_hit_bottom = row->add_hit_bottom;
642
643         cur_rec_coordinate->label_type = row->label_type;
644         cur_rec_coordinate->image_label_type = NULL;
645
646         cur_rec_coordinate->label_count = 0;
647         for (int shift_state = 0; shift_state < SCL_SHIFT_STATE_MAX; shift_state++) {
648             for (int label_for_one = 0; label_for_one < MAX_SIZE_OF_LABEL_FOR_ONE; ++label_for_one) {
649                 cur_rec_coordinate->label[shift_state][label_for_one] = NULL;
650             }
651         }
652         for (int shift_state = 0; shift_state < SCL_SHIFT_STATE_MAX; shift_state++) {
653             for (int button_state = 0; button_state < SCL_BUTTON_STATE_MAX; ++button_state) {
654                 cur_rec_coordinate->image_label_path[shift_state][button_state] = NULL;
655             }
656         }
657         for (int shift_state = 0; shift_state < SCL_SHIFT_STATE_MAX; shift_state++) {
658             for (int button_state = 0; button_state < SCL_BUTTON_STATE_MAX; ++button_state) {
659                 //cur_rec_coordinate->bg_image_path[shift_state]![button_state] = NULL;
660                 cur_rec_coordinate->bg_image_path[shift_state][button_state] = row->bg_image_path[shift_state][button_state];
661             }
662         }
663         cur_rec_coordinate->key_value_count = 0;
664         for (int shift_state = 0; shift_state < SCL_SHIFT_STATE_MAX; shift_state++) {
665             for (int multitap_state = 0; multitap_state < MAX_SIZE_OF_MULTITAP_CHAR; ++multitap_state) {
666                 cur_rec_coordinate->key_value[shift_state][multitap_state] = NULL;
667             }
668         }
669         for (int shift_state = 0; shift_state < SCL_SHIFT_STATE_MAX; shift_state++) {
670             for (int multitap_state = 0; multitap_state < MAX_SIZE_OF_MULTITAP_CHAR; ++multitap_state) {
671                 cur_rec_coordinate->key_event[shift_state][multitap_state] = 0;
672             }
673         }
674         /* assume the long_key_type is the same with key_type, by default */
675         cur_rec_coordinate->long_key_type = cur_rec_coordinate->key_type;
676         cur_rec_coordinate->long_key_value = NULL;
677         cur_rec_coordinate->long_key_event = 0;
678
679         cur_rec_coordinate->use_repeat_key = false;
680         for (int shift_state = 0; shift_state < SCL_SHIFT_STATE_MAX; shift_state++) {
681             for (int autopopup_state = 0; autopopup_state < MAX_SIZE_OF_AUTOPOPUP_STRING; ++autopopup_state) {
682                 cur_rec_coordinate->autopopup_key_labels[shift_state][autopopup_state] = NULL;
683                 cur_rec_coordinate->autopopup_key_events[shift_state][autopopup_state] = 0;
684                 cur_rec_coordinate->autopopup_key_values[shift_state][autopopup_state] = NULL;
685             }
686         }
687         cur_rec_coordinate->dont_close_popup = false;
688         cur_rec_coordinate->extra_option = NOT_USED;
689         cur_rec_coordinate->multitouch_type = SCL_MULTI_TOUCH_TYPE_EXCLUSIVE;
690         cur_rec_coordinate->modifier_decorator = NULL;
691         for (int shift_state = 0; shift_state < SCL_SHIFT_STATE_MAX; shift_state++) {
692             for (int multitap_state = 0; multitap_state < MAX_SIZE_OF_MULTITAP_CHAR; ++multitap_state) {
693                 cur_rec_coordinate->hint_string[shift_state][multitap_state] = NULL;
694             }
695         }
696         cur_rec_coordinate->sub_layout = row->sub_layout;
697     }
698 }
699
700 void
701 LayoutParserImpl::parsing_grab_area(
702         const xmlNodePtr cur_node,
703         const PSclLayout cur_rec_layout) {
704     assert(cur_node != NULL);
705
706     xmlNodePtr child_node = cur_node->xmlChildrenNode;
707     while (child_node != NULL) {
708         if (0 == xmlStrcmp(child_node->name, (const xmlChar*)LAYOUT_ADD_GRAB_LEFT_TAG)) {
709             cur_rec_layout->add_grab_left = get_content_int(child_node);
710         } else if (0 == xmlStrcmp(child_node->name, (const xmlChar*)LAYOUT_ADD_GRAB_RIGHT_TAG)) {
711             cur_rec_layout->add_grab_right = get_content_int(child_node);
712         } else if (0 == xmlStrcmp(child_node->name, (const xmlChar*)LAYOUT_ADD_GRAB_TOP_TAG)) {
713             cur_rec_layout->add_grab_top = get_content_int(child_node);
714         } else if (0 == xmlStrcmp(child_node->name, (const xmlChar*)LAYOUT_ADD_GRAB_BOTTOM_TAG)) {
715             cur_rec_layout->add_grab_bottom = get_content_int(child_node);
716         }
717         child_node = child_node->next;
718     }
719 }
720
721 void
722 LayoutParserImpl::parsing_layout_node(
723         const xmlNodePtr cur_node,
724         const PSclLayout cur_rec_layout,
725         int layout_no) {
726     assert(cur_node != NULL);
727     assert(cur_rec_layout != NULL);
728
729     set_default_layout_value(cur_rec_layout);
730
731     xmlChar* key;
732
733     if (equal_prop(cur_node, LAYOUT_DIRECTION_ATTRIBUTE,
734         LAYOUT_DIRECTION_ATTRIBUTE_LANDSCAPE_VALUE)) {
735         cur_rec_layout->display_mode = DISPLAYMODE_LANDSCAPE;
736     }
737
738     if (equal_prop(cur_node, LAYOUT_STYLE_ATTRIBUTE,
739         LAYOUT_STYLE_ATTRIBUTE_POPUP_VALUE)) {
740             cur_rec_layout->style = LAYOUT_STYLE_POPUP;
741     } else if (equal_prop(cur_node, LAYOUT_STYLE_ATTRIBUTE,
742         LAYOUT_STYLE_ATTRIBUTE_POPUP_GRAB_VALUE)) {
743             cur_rec_layout->style = LAYOUT_STYLE_POPUP_GRAB;
744     }
745
746     get_prop_number(cur_node, LAYOUT_WIDTH_ATTRIBUTE, &(cur_rec_layout->width));
747     get_prop_number(cur_node, LAYOUT_HEIGHT_ATTRIBUTE, &(cur_rec_layout->height));
748     get_prop_bool(cur_node, LAYOUT_MAGNIFIER_ATTRIBUTE, &(cur_rec_layout->use_magnifier_window));
749
750     get_prop_bool(cur_node, LAYOUT_PART_BACKGROUND_ATTRIBUTE, &(cur_rec_layout->extract_background));
751     get_prop_bool(cur_node, LAYOUT_SW_BUTTON_ATTRIBUTE, &(cur_rec_layout->use_sw_button));
752     get_prop_bool(cur_node, LAYOUT_SW_BACKGROUND_ATTRIBUTE, &(cur_rec_layout->use_sw_background));
753
754     get_prop_number(cur_node, LAYOUT_KEY_WIDTH_ATTRIBUTE, &(cur_rec_layout->key_width));
755     get_prop_number(cur_node, LAYOUT_KEY_HEIGHT_ATTRIBUTE, &(cur_rec_layout->key_height));
756     get_prop_number(cur_node, LAYOUT_KEY_SPACING_ATTRIBUTE, &(cur_rec_layout->key_spacing));
757     get_prop_number(cur_node, LAYOUT_ROW_SPACING_ATTRIBUTE, &(cur_rec_layout->row_spacing));
758
759     get_prop_number(cur_node, LAYOUT_KEY_ADD_HIT_LEFT_ATTRIBUTE, &(cur_rec_layout->add_hit_left));
760     get_prop_number(cur_node, LAYOUT_KEY_ADD_HIT_RIGHT_ATTRIBUTE, &(cur_rec_layout->add_hit_right));
761     get_prop_number(cur_node, LAYOUT_KEY_ADD_HIT_TOP_ATTRIBUTE, &(cur_rec_layout->add_hit_top));
762     get_prop_number(cur_node, LAYOUT_KEY_ADD_HIT_BOTTOM_ATTRIBUTE, &(cur_rec_layout->add_hit_bottom));
763
764     key = xmlGetProp(cur_node, (const xmlChar*)LAYOUT_VIBE_STYLE_ATTRIBUTE);
765     if (key) {
766         cur_rec_layout->vibe_style = (sclchar*)key;
767         add_layout_string(key);
768     }
769     key = xmlGetProp(cur_node, (const xmlChar*)LAYOUT_SOUND_STYLE_ATTRIBUTE);
770     if (key) {
771         cur_rec_layout->sound_style = (sclchar*)key;
772         add_layout_string(key);
773     }
774     key = xmlGetProp(cur_node, (const xmlChar*)LAYOUT_LABEL_TYPE_ATTRIBUTE);
775     if (key) {
776         cur_rec_layout->label_type = (sclchar*)key;
777         add_layout_string(key);
778     }
779     key = xmlGetProp(cur_node, (const xmlChar*)LAYOUT_MODIFIER_DECORATION_ATTRIBUTE);
780     if (key) {
781         cur_rec_layout->modifier_decorator = (sclchar*)key;
782         add_layout_string(key);
783     }
784
785     xmlNodePtr child_node = cur_node->xmlChildrenNode;
786     while (child_node != NULL) {
787         /* row node: layout coordinate resources is no need to parsing at this time */
788         if (0 == xmlStrcmp(child_node->name, (const xmlChar*)LAYOUT_BACKGROUND_TAG)) {
789             parsing_background(child_node, cur_rec_layout);
790         } else if (0 == xmlStrcmp(child_node->name, (const xmlChar*)LAYOUT_SW_BACKGROUND_TAG)) {
791             parsing_sw_background_color(child_node, cur_rec_layout);
792         } else if (0 == xmlStrcmp(child_node->name, (const xmlChar*)LAYOUT_KEY_BACKGROUND_TAG)) {
793             parsing_key_background(child_node, cur_rec_layout);
794         } else if (0 == xmlStrcmp(cur_node->name, (const xmlChar *)LAYOUT_ADD_GRAB_TAG)) {
795             parsing_grab_area(child_node, cur_rec_layout);
796         }
797
798         child_node = child_node->next;
799     }
800 }
801
802 void
803 LayoutParserImpl::loading_coordinate_resources(
804         const xmlNodePtr cur_node,
805         const PSclLayout cur_rec_layout,
806         int layout_no) {
807     assert(cur_node != NULL);
808
809     int row_y = 0;
810     int sub_layout_height = 0;
811
812     SclLayoutKeyCoordinatePointer *cur_key = &m_key_coordinate_pointer_frame[layout_no][0];
813
814     if (*cur_key == NULL) {
815         xmlNodePtr child_node = cur_node->xmlChildrenNode;
816         while (child_node != NULL) {
817             if (0 == xmlStrcmp(child_node->name, (const xmlChar*)LAYOUT_ROW_TAG)) {
818                 parsing_layout_row_node(child_node, cur_rec_layout, &row_y, &sub_layout_height, &cur_key);
819             }
820
821             child_node = child_node->next;
822         }
823     }
824 }
825
826 void
827 LayoutParserImpl::parsing_layout_row_node(
828         const xmlNodePtr cur_node,
829         const PSclLayout cur_rec_layout,
830         int *row_y, int *sub_layout_height,
831         SclLayoutKeyCoordinatePointer **cur_key) {
832     assert(cur_node != NULL);
833
834     Row row = {0};
835     if (row_y) {
836         set_default_row_value(&row, cur_rec_layout, *row_y);
837     }
838
839     get_prop_number(cur_node, LAYOUT_ROW_X_ATTRIBUTE, &(row.row_x));
840     get_prop_number(cur_node, LAYOUT_ROW_Y_ATTRIBUTE, &(row.row_y));
841     get_prop_number(cur_node, LAYOUT_ROW_KEY_WIDTH_ATTRIBUTE, &(row.key_width));
842     get_prop_number(cur_node, LAYOUT_ROW_KEY_HEIGHT_ATTRIBUTE, &(row.key_height));
843     get_prop_number(cur_node, LAYOUT_ROW_KEY_SPACING_ATTRIBUTE, &(row.key_spacing));
844
845     xmlChar *key = xmlGetProp(cur_node, (const xmlChar*)LAYOUT_ROW_SUBLAYOUT_ID_ATTRIBUTE);
846     if (key) {
847         row.sub_layout = (sclchar*)key;
848         add_key_string(key);
849     }
850
851     if (row.sub_layout == NULL) {
852         if (row_y) {
853             /* If there's a stored sub_layout_height value, add it to current row's y position */
854             if (sub_layout_height) {
855                 row.row_y += *sub_layout_height;
856                 *sub_layout_height = 0;
857             }
858             *row_y = row.row_y + row.key_height + row.row_spacing;
859         }
860     }
861     /* Store the current row's height for later use when this sublayout is "DEFAULT" */
862     static const char default_sub_layout_string[] = LAYOUT_SUB_LAYOUT_DEFAULT_STRING;
863     if (row.sub_layout && strncmp(row.sub_layout, default_sub_layout_string, sizeof(default_sub_layout_string)) == 0) {
864         if (sub_layout_height) {
865             *sub_layout_height = row.key_height + row.row_spacing;
866         }
867     }
868
869     xmlNodePtr child_node = cur_node->xmlChildrenNode;
870     while (child_node != NULL) {
871         if (0 == xmlStrcmp(child_node->name, (const xmlChar*)LAYOUT_ROW_KEY_TAG)) {
872             parsing_key_coordinate_record_node(child_node, &row, *cur_key);
873             (*cur_key)++;
874         }
875         child_node = child_node->next;
876     }
877 }
878
879 int
880 LayoutParserImpl::get_drag_state_prop(const xmlNodePtr cur_node) {
881     assert(cur_node != NULL);
882     typedef struct _Match_Struct {
883         int value;
884         const char* key;
885     }Match_Struct;
886     static Match_Struct table[] = {
887         {SCL_DRAG_STATE_NONE,       "drag_state_none"       },
888         {SCL_DRAG_STATE_LEFT,       "drag_state_left"       },
889         {SCL_DRAG_STATE_RIGHT,      "drag_state_right"      },
890         {SCL_DRAG_STATE_UP,         "drag_state_up"         },
891         {SCL_DRAG_STATE_DOWN,       "drag_state_down"       },
892         {SCL_DRAG_STATE_INVALID,    "drag_state_invalid"    },
893         {SCL_DRAG_STATE_RETURN,     "drag_state_return"     }
894     };
895
896     xmlChar* key = xmlGetProp(cur_node, (const xmlChar*)"drag_state");
897     if (key == NULL) return SCL_DRAG_STATE_NONE;
898
899     int drag_state = SCL_DRAG_STATE_NONE;
900
901     for (size_t i = 0; i < sizeof(table)/sizeof(Match_Struct); ++i) {
902         if (0 == strcmp((const char*)key, table[i].key))
903         {
904             drag_state = table[i].value;
905             break;
906         }
907     }
908
909     xmlFree(key);
910     return drag_state;
911 }
912
913 int
914 LayoutParserImpl::get_shift_state_prop(const xmlNodePtr cur_node) {
915     assert(cur_node != NULL);
916
917     int shift_state = -1;
918
919     if (equal_prop(cur_node, "shift", "on")) {
920         shift_state = SCL_SHIFT_STATE_ON;
921     } else if (equal_prop(cur_node, "shift", "off")) {
922         shift_state = SCL_SHIFT_STATE_OFF;
923     } else if (equal_prop(cur_node, "shift", "loc")) {
924         shift_state = SCL_SHIFT_STATE_LOCK;
925     }
926     return shift_state;
927 }
928 int
929 LayoutParserImpl::get_button_state_prop(const xmlNodePtr cur_node) {
930     assert(cur_node != NULL);
931     int button_state = -1;
932
933     if (equal_prop(cur_node, "button", "pressed")) {
934         button_state = BUTTON_STATE_PRESSED;
935     } else if (equal_prop(cur_node, "button", "normal")) {
936         button_state = BUTTON_STATE_NORMAL;
937     } else if (equal_prop(cur_node, "button", "disabled")) {
938         button_state = BUTTON_STATE_DISABLED;
939     } else if (equal_prop(cur_node, "button", "toggled")) {
940         button_state = BUTTON_STATE_TOGGLED;
941     }
942     return button_state;
943 }
944
945 int
946 LayoutParserImpl::get_multitouch_type_prop(const xmlNodePtr cur_node) {
947     assert(cur_node != NULL);
948     typedef struct _Match_Struct {
949         int value;
950         const char* key;
951     }Match_Struct;
952     static Match_Struct table[] = {
953         {SCL_MULTI_TOUCH_TYPE_EXCLUSIVE,        "exclusive"         },
954         {SCL_MULTI_TOUCH_TYPE_SETTLE_PREVIOUS,  "settle_previous"   },
955         {SCL_MULTI_TOUCH_TYPE_COOPERATIVE,      "cooperative"       },
956         {SCL_MULTI_TOUCH_TYPE_GRAB_SUB_EVENTS,  "grab_sub_events"   },
957     };
958
959     xmlChar* key = xmlGetProp(cur_node, (const xmlChar*)LAYOUT_ROW_KEY_MULTITOUCH_TYPE_ATTRIBUTE);
960     if (key == NULL) return SCL_MULTI_TOUCH_TYPE_EXCLUSIVE;
961
962     int type = SCL_MULTI_TOUCH_TYPE_EXCLUSIVE;
963
964     for (size_t i = 0; i < sizeof(table)/sizeof(Match_Struct); ++i) {
965         if (0 == strcmp((const char*)key, table[i].key))
966         {
967             type = table[i].value;
968             break;
969         }
970     }
971
972     xmlFree(key);
973     return type;
974 }
975
976 int
977 LayoutParserImpl::get_extra_option_prop(
978         const xmlNodePtr cur_node) {
979     assert(cur_node != NULL);
980     typedef struct _Match_Struct {
981         int value;
982         const char* key;
983     }Match_Struct;
984     static Match_Struct table[] = {
985         {DIRECTION_EXTRA_OPTION_4_DIRECTIONS,                        "4-directions"                 },
986         {DIRECTION_EXTRA_OPTION_8_DIRECTIONS,                        "8-directions"                 },
987         {DIRECTION_EXTRA_OPTION_4_DIRECTIONS_WITH_LONG,              "4-directions-long"            },
988         {DIRECTION_EXTRA_OPTION_8_DIRECTIONS_WITH_LONG,              "8-directions-long"            },
989         {DIRECTION_EXTRA_OPTION_4_DIRECTIONS_WITH_RETURN,            "4-directions-return"          },
990         {DIRECTION_EXTRA_OPTION_8_DIRECTIONS_WITH_RETURN,            "8-directions-return"          },
991         {DIRECTION_EXTRA_OPTION_4_DIRECTIONS_WITH_RETURN_AND_CURVE,  "4-directions-return-curve"    },
992     };
993
994     xmlChar* key = xmlGetProp(cur_node, (const xmlChar*)LAYOUT_ROW_KEY_EXTRA_OPTION_ATTRIBUTE);
995     if (key == NULL) return 0;
996
997     int type = DIRECTION_EXTRA_OPTION_4_DIRECTIONS;
998
999     for (size_t i = 0; i < sizeof(table)/sizeof(Match_Struct); ++i) {
1000         if (0 == strcmp((const char*)key, table[i].key))
1001         {
1002             type = table[i].value;
1003             break;
1004         }
1005     }
1006
1007     xmlFree(key);
1008     return type;
1009 }
1010
1011
1012 void
1013 LayoutParserImpl::parsing_label_record_node(
1014         const xmlNodePtr cur_node,
1015         const PSclLayoutKeyCoordinate cur_rec) {
1016     assert(cur_node != NULL);
1017     assert(cur_rec != NULL);
1018     assert(0 == xmlStrcmp(cur_node->name, (const xmlChar*)"label"));
1019     xmlNodePtr child_node = cur_node->xmlChildrenNode;
1020
1021     while (child_node != NULL) {
1022         if (0 == xmlStrcmp(child_node->name, (const xmlChar*)"rec")) {
1023             int shift_state = get_shift_state_prop(child_node);
1024
1025             int label_for_one_state = 0;
1026             get_prop_number(child_node, "multi", &label_for_one_state);
1027             if (cur_rec->label_count < (label_for_one_state + 1)) {
1028                 cur_rec->label_count = (label_for_one_state + 1);
1029             }
1030
1031             sclboolean auto_upper = FALSE;
1032             get_prop_bool(child_node, "auto_upper", &auto_upper);
1033
1034             if (label_for_one_state >= 0 && label_for_one_state < MAX_SIZE_OF_LABEL_FOR_ONE) {
1035                 for (int shift_loop = 0;shift_loop < SCL_SHIFT_STATE_MAX;shift_loop++) {
1036                     if ((shift_state == shift_loop || shift_state == -1)) {
1037                         xmlChar* key = xmlNodeGetContent(child_node);
1038                         if (key) {
1039                             sclboolean upper_created = FALSE;
1040                             if (auto_upper) {
1041                                 if (shift_loop != SCL_SHIFT_STATE_OFF) {
1042                                     gchar *upper = g_utf8_strup(reinterpret_cast<gchar*>(key), -1);
1043                                     xmlFree(key);
1044                                     add_upper_string(upper);
1045                                     upper_created = TRUE;
1046                                     key = reinterpret_cast<xmlChar*>(upper);
1047                                 }
1048                             }
1049                             if (!upper_created) {
1050                                 add_key_string(key);
1051                             }
1052                             cur_rec->label[shift_loop][label_for_one_state] = (sclchar*)key;
1053                             /* If current key_value is NULL, let's just consider this label is the default key_value */
1054                             if (label_for_one_state == 0) {
1055                                 if (cur_rec->key_value[shift_loop][label_for_one_state] == NULL) {
1056                                     cur_rec->key_value[shift_loop][label_for_one_state] = (sclchar*)key;
1057                                 }
1058                             }
1059                         }
1060                     }
1061                 }
1062             }
1063         }
1064         child_node = child_node->next;
1065     }
1066 }
1067
1068 void
1069 LayoutParserImpl::parsing_magnifier_label_record_node(
1070         const xmlNodePtr cur_node,
1071         const PSclLayoutKeyCoordinate cur_rec) {
1072     assert(cur_node != NULL);
1073     assert(cur_rec != NULL);
1074     assert(0 == xmlStrcmp(cur_node->name, (const xmlChar*)"magnifier_label"));
1075     xmlNodePtr child_node = cur_node->xmlChildrenNode;
1076
1077     while (child_node != NULL) {
1078         if (0 == xmlStrcmp(child_node->name, (const xmlChar*)"rec")) {
1079             int shift_state = get_shift_state_prop(child_node);
1080
1081             int label_for_one_state = 0;
1082             get_prop_number(child_node, "multi", &label_for_one_state);
1083
1084             if (label_for_one_state >= 0 && label_for_one_state < MAX_SIZE_OF_LABEL_FOR_ONE) {
1085                 for (int shift_loop = 0;shift_loop < SCL_SHIFT_STATE_MAX;shift_loop++) {
1086                     if ((shift_state == shift_loop || shift_state == -1)) {
1087                         xmlChar* key = xmlNodeGetContent(child_node);
1088                         if (key) {
1089                             cur_rec->magnifier_label[shift_loop][label_for_one_state] = (sclchar*)key;
1090                             add_key_string(key);
1091                         }
1092                     }
1093                 }
1094             }
1095         }
1096         child_node = child_node->next;
1097     }
1098 }
1099
1100 void
1101 LayoutParserImpl::parsing_hint_string_record_node(
1102     const xmlNodePtr cur_node,
1103     const PSclLayoutKeyCoordinate cur_rec) {
1104         assert(cur_node != NULL);
1105         assert(cur_rec != NULL);
1106         assert(0 == xmlStrcmp(cur_node->name, (const xmlChar*)"hint_string"));
1107         xmlNodePtr child_node = cur_node->xmlChildrenNode;
1108
1109         while (child_node != NULL) {
1110             if (0 == xmlStrcmp(child_node->name, (const xmlChar*)"rec")) {
1111                 int shift_state = get_shift_state_prop(child_node);
1112                 int multichar_state = 0;
1113                 get_prop_number(child_node, "multichar_state", &multichar_state);
1114
1115                 if (multichar_state >= 0 && multichar_state < MAX_SIZE_OF_MULTITAP_CHAR) {
1116                     for (int shift_loop = 0;shift_loop < SCL_SHIFT_STATE_MAX;shift_loop++) {
1117                         if ((shift_state == shift_loop || shift_state == -1)) {
1118                             xmlChar* key = xmlNodeGetContent(child_node);
1119                             if (key) {
1120                                 cur_rec->hint_string[shift_loop][multichar_state] = (sclchar*)key;
1121                                 add_key_string(key);
1122                             }
1123                         }
1124                     }
1125                 }
1126             }
1127             child_node = child_node->next;
1128         }
1129 }
1130
1131 void
1132 LayoutParserImpl::parsing_label_image_record_node(
1133         const xmlNodePtr cur_node,
1134         const PSclLayoutKeyCoordinate cur_rec) {
1135     assert(cur_node != NULL);
1136     assert(cur_rec != NULL);
1137     assert(0 == xmlStrcmp(cur_node->name, (const xmlChar*)"image_label"));
1138     xmlNodePtr child_node = cur_node->xmlChildrenNode;
1139
1140     while (child_node != NULL) {
1141         if (0 == xmlStrcmp(child_node->name, (const xmlChar*)"rec")) {
1142             int shift_state = get_shift_state_prop(child_node);
1143             int button_state = get_button_state_prop(child_node);
1144             for (int shift_loop = 0;shift_loop < SCL_SHIFT_STATE_MAX;shift_loop++) {
1145                 for (int button_loop = 0;button_loop < SCL_BUTTON_STATE_MAX;button_loop++) {
1146                     if ((shift_state == shift_loop || shift_state == -1) &&
1147                         (button_state == button_loop || button_state == -1)) {
1148                             xmlChar* key = xmlNodeGetContent(child_node);
1149                             if (key) {
1150                                 cur_rec->image_label_path[shift_loop][button_loop] = (sclchar*)key;
1151                                 add_key_string(key);
1152                             }
1153                     }
1154                 }
1155             }
1156         }
1157         child_node = child_node->next;
1158     }
1159 }
1160
1161 void
1162 LayoutParserImpl::parsing_background_image_record_node(
1163         const xmlNodePtr cur_node,
1164         const PSclLayoutKeyCoordinate cur_rec) {
1165     assert(cur_node != NULL);
1166     assert(cur_rec != NULL);
1167     assert(0 == xmlStrcmp(cur_node->name, (const xmlChar*)"background_image"));
1168     xmlNodePtr child_node = cur_node->xmlChildrenNode;
1169
1170     while (child_node != NULL) {
1171         if (0 == xmlStrcmp(child_node->name, (const xmlChar*)"rec")) {
1172             int shift_state = get_shift_state_prop(child_node);
1173             int button_state = get_button_state_prop(child_node);
1174             for (int shift_loop = 0;shift_loop < SCL_SHIFT_STATE_MAX;shift_loop++) {
1175                 for (int button_loop = 0;button_loop < SCL_BUTTON_STATE_MAX;button_loop++) {
1176                     if ((shift_state == shift_loop || shift_state == -1) &&
1177                         (button_state == button_loop || button_state == -1)) {
1178                             xmlChar* key = xmlNodeGetContent(child_node);
1179                             if (key) {
1180                                 cur_rec->bg_image_path[shift_loop][button_loop] = (sclchar*)key;
1181                                 add_key_string(key);
1182                             }
1183                     }
1184                 }
1185             }
1186         }
1187         child_node = child_node->next;
1188     }
1189 }
1190
1191 void
1192 LayoutParserImpl::parsing_key_value_record_node(
1193         const xmlNodePtr cur_node,
1194         const PSclLayoutKeyCoordinate cur_rec) {
1195     assert(cur_node != NULL);
1196     assert(cur_rec != NULL);
1197     assert(0 == xmlStrcmp(cur_node->name, (const xmlChar*)"key_value"));
1198     xmlNodePtr child_node = cur_node->xmlChildrenNode;
1199
1200     while (child_node != NULL) {
1201         if (0 == xmlStrcmp(child_node->name, (const xmlChar*)"rec")) {
1202             int shift_state = get_shift_state_prop(child_node);
1203             int multichar_state = 0;
1204             get_prop_number(child_node, "multichar_state", &multichar_state);
1205
1206             sclboolean auto_upper = FALSE;
1207             get_prop_bool(child_node, "auto_upper", &auto_upper);
1208
1209             if (multichar_state >= 0 && multichar_state < MAX_SIZE_OF_MULTITAP_CHAR) {
1210                 for (int shift_loop = 0;shift_loop < SCL_SHIFT_STATE_MAX;shift_loop++) {
1211                     if ((shift_state == shift_loop || shift_state == -1)) {
1212                         xmlChar* key = xmlNodeGetContent(child_node);
1213                         if (key) {
1214                             sclboolean upper_created = FALSE;
1215                             if (auto_upper) {
1216                                 if (shift_loop != SCL_SHIFT_STATE_OFF) {
1217                                     gchar *upper = g_utf8_strup(reinterpret_cast<gchar*>(key), -1);
1218                                     xmlFree(key);
1219                                     add_upper_string(upper);
1220                                     upper_created = TRUE;
1221                                     key = reinterpret_cast<xmlChar*>(upper);
1222                                 }
1223                             }
1224                             if (!upper_created) {
1225                                 add_key_string(key);
1226                             }
1227                             cur_rec->key_value[shift_loop][multichar_state] = (sclchar*)key;
1228                         }
1229                     }
1230                 }
1231             }
1232         }
1233         child_node = child_node->next;
1234     }
1235 }
1236
1237 void
1238 LayoutParserImpl::parsing_key_event_record_node(
1239         const xmlNodePtr cur_node,
1240         const PSclLayoutKeyCoordinate cur_rec) {
1241     assert(cur_node != NULL);
1242     assert(cur_rec != NULL);
1243     assert(0 == xmlStrcmp(cur_node->name, (const xmlChar*)"key_event"));
1244     xmlNodePtr child_node = cur_node->xmlChildrenNode;
1245
1246     while (child_node != NULL) {
1247         if (0 == xmlStrcmp(child_node->name, (const xmlChar*)"rec")) {
1248             int shift_state = get_shift_state_prop(child_node);
1249             int multichar_state = 0;
1250             get_prop_number(child_node, "multichar_state", &multichar_state);
1251
1252             if (multichar_state >= 0 && multichar_state < MAX_SIZE_OF_MULTITAP_CHAR) {
1253                 for (int shift_loop = 0;shift_loop < SCL_SHIFT_STATE_MAX;shift_loop++) {
1254                     if ((shift_state == shift_loop || shift_state == -1)) {
1255                         cur_rec->key_event[shift_loop][multichar_state] = (sclulong)get_content_dex_string_int(child_node);
1256                     }
1257                 }
1258             }
1259         }
1260         child_node = child_node->next;
1261     }
1262 }
1263
1264 void
1265 LayoutParserImpl::parsing_auto_popup_keys_record_node(
1266         const xmlNodePtr cur_node,
1267         const PSclLayoutKeyCoordinate cur_rec) {
1268     assert(cur_node != NULL);
1269     assert(cur_rec != NULL);
1270     assert(0 == xmlStrcmp(cur_node->name, (const xmlChar*)"auto_popup_keys"));
1271     xmlNodePtr child_node = cur_node->xmlChildrenNode;
1272
1273     while (child_node != NULL) {
1274         int shift_state = get_shift_state_prop(child_node);
1275         int autopopup_state = 0;
1276         get_prop_number(child_node, "autopopup", &autopopup_state);
1277
1278         sclboolean auto_upper = FALSE;
1279         get_prop_bool(child_node, "auto_upper", &auto_upper);
1280
1281         if (autopopup_state >= 0 && autopopup_state < MAX_SIZE_OF_AUTOPOPUP_STRING) {
1282             for (int shift_loop = 0;shift_loop < SCL_SHIFT_STATE_MAX;shift_loop++) {
1283                 if ((shift_state == shift_loop || shift_state == -1)) {
1284                     xmlChar* key = xmlNodeGetContent(child_node);
1285                     if (key) {
1286                         if (0 == xmlStrcmp(child_node->name, (const xmlChar*)"label")) {
1287                             sclboolean upper_created = FALSE;
1288                             if (auto_upper) {
1289                                 if (shift_loop != SCL_SHIFT_STATE_OFF) {
1290                                     gchar *upper = g_utf8_strup(reinterpret_cast<gchar*>(key), -1);
1291                                     xmlFree(key);
1292                                     add_upper_string(upper);
1293                                     upper_created = TRUE;
1294                                     key = reinterpret_cast<xmlChar*>(upper);
1295                                 }
1296                             }
1297                             if (!upper_created) {
1298                                 add_key_string(key);
1299                             }
1300                             cur_rec->autopopup_key_labels[shift_loop][autopopup_state] = (sclchar*)key;
1301                             /* If current key_value is NULL, let's just consider this label is the default key_value */
1302                             if (cur_rec->autopopup_key_values[shift_loop][autopopup_state] == NULL) {
1303                                 cur_rec->autopopup_key_values[shift_loop][autopopup_state] = (sclchar*)key;
1304                             }
1305                         } else if (0 == xmlStrcmp(child_node->name, (const xmlChar*)"value")) {
1306                             cur_rec->autopopup_key_values[shift_loop][autopopup_state] = (sclchar*)key;
1307                             add_key_string(key);
1308                         } else if (0 == xmlStrcmp(child_node->name, (const xmlChar*)"event")) {
1309                             cur_rec->autopopup_key_events[shift_loop][autopopup_state] = (sclulong)atoi((sclchar*)key);
1310                             add_key_string(key);
1311                         }
1312                     }
1313                 }
1314             }
1315         }
1316         child_node = child_node->next;
1317     }
1318 }
1319
1320 void
1321 LayoutParserImpl::parsing_key_coordinate_record_node(
1322         const xmlNodePtr cur_node, Row *row,
1323         SclLayoutKeyCoordinatePointer *cur_rec_coordinate) {
1324     assert(cur_node != NULL);
1325     assert(cur_rec_coordinate != NULL);
1326
1327     *cur_rec_coordinate = (SclLayoutKeyCoordinatePointer)malloc(sizeof(SclLayoutKeyCoordinate));
1328     if (*cur_rec_coordinate == NULL) {
1329         SCLLOG(SclLog::ERROR, "LayoutParserImpl: memory malloc eror.\n");
1330         return;
1331     }
1332     memset(*cur_rec_coordinate, 0x00, sizeof(SclLayoutKeyCoordinate));
1333
1334     set_default_key_coordinate_value(*cur_rec_coordinate, row);
1335
1336     xmlChar *key;
1337
1338     int key_spacing = 0;
1339
1340     if (row) {
1341         key_spacing = row->key_spacing;
1342     }
1343
1344     (*cur_rec_coordinate)->valid = TRUE;
1345
1346     key = xmlGetProp(cur_node, (const xmlChar*)LAYOUT_ROW_KEY_CUSTOMID_ATTRIBUTE);
1347     if (key) {
1348         (*cur_rec_coordinate)->custom_id = (sclchar*)key;
1349         add_key_string(key);
1350     }
1351
1352     key = xmlGetProp(cur_node, (const xmlChar*)LAYOUT_ROW_KEY_BUTTON_TYPE_ATTRIBUTE);
1353     if (key) {
1354         (*cur_rec_coordinate)->button_type = (SCLButtonType)ButtonTypeHelper::Int((const char*)key);
1355         xmlFree(key);
1356     }
1357
1358     key = xmlGetProp(cur_node, (const xmlChar*)LAYOUT_ROW_KEY_KEY_TYPE_ATTRIBUTE);
1359     if (key) {
1360         (*cur_rec_coordinate)->key_type = (SCLKeyType)KeyTypeHelper::Int((const char*)key);
1361         xmlFree(key);
1362     }
1363     key = xmlGetProp(cur_node, (const xmlChar*)LAYOUT_ROW_KEY_POPUP_TYPE_ATTRIBUTE);
1364     if (key) {
1365         (*cur_rec_coordinate)->popup_type = (SCLPopupType)PopupTypeHelper::Int((const char*)key);
1366         xmlFree(key);
1367     }
1368
1369     get_prop_bool(cur_node, LAYOUT_ROW_KEY_MAGNIFIER_ATTRIBUTE, &((*cur_rec_coordinate)->use_magnifier));
1370     get_prop_bool(cur_node, LAYOUT_ROW_KEY_LONGKEY_MAGNIFIER_ATTRIBUTE,
1371         &((*cur_rec_coordinate)->use_long_key_magnifier));
1372
1373     key = xmlGetProp(cur_node, (const xmlChar*)LAYOUT_VIBE_STYLE_ATTRIBUTE);
1374     if (key) {
1375         (*cur_rec_coordinate)->vibe_style = (sclchar*)key;
1376         add_key_string(key);
1377     }
1378     key = xmlGetProp(cur_node, (const xmlChar*)LAYOUT_SOUND_STYLE_ATTRIBUTE);
1379     if (key) {
1380         (*cur_rec_coordinate)->sound_style = (sclchar*)key;
1381         add_key_string(key);
1382     }
1383
1384     get_prop_bool(cur_node, LAYOUT_ROW_KEY_SIDE_BUTTON_ATTRIBUTE, &((*cur_rec_coordinate)->is_side_button));
1385
1386     get_prop_number(cur_node, LAYOUT_ROW_KEY_X_ATTRIBUTE, &((*cur_rec_coordinate)->x));
1387     get_prop_number(cur_node, LAYOUT_ROW_KEY_Y_ATTRIBUTE, &((*cur_rec_coordinate)->y));
1388     get_prop_number(cur_node, LAYOUT_ROW_KEY_KEY_WIDTH_ATTRIBUTE, &((*cur_rec_coordinate)->width));
1389     get_prop_number(cur_node, LAYOUT_ROW_KEY_KEY_HEIGHT_ATTRIBUTE, &((*cur_rec_coordinate)->height));
1390
1391     get_prop_number(cur_node, LAYOUT_ROW_KEY_ADD_HIT_LEFT_ATTRIBUTE, &((*cur_rec_coordinate)->add_hit_left));
1392     get_prop_number(cur_node, LAYOUT_ROW_KEY_ADD_HIT_RIGHT_ATTRIBUTE, &((*cur_rec_coordinate)->add_hit_right));
1393     get_prop_number(cur_node, LAYOUT_ROW_KEY_ADD_HIT_TOP_ATTRIBUTE, &((*cur_rec_coordinate)->add_hit_top));
1394     get_prop_number(cur_node, LAYOUT_ROW_KEY_ADD_HIT_BOTTOM_ATTRIBUTE, &((*cur_rec_coordinate)->add_hit_bottom));
1395
1396     get_prop_number(cur_node, LAYOUT_ROW_KEY_POPUP_POS_X_ATTRIBUTE, &((*cur_rec_coordinate)->popup_relative_x));
1397     get_prop_number(cur_node, LAYOUT_ROW_KEY_POPUP_POS_Y_ATTRIBUTE, &((*cur_rec_coordinate)->popup_relative_y));
1398
1399     get_prop_number(cur_node, LAYOUT_ROW_KEY_POPUP_IMAGE_X_ATTRIBUTE, &((*cur_rec_coordinate)->extract_offset_x));
1400     get_prop_number(cur_node, LAYOUT_ROW_KEY_POPUP_IMAGE_Y_ATTRIBUTE, &((*cur_rec_coordinate)->extract_offset_y));
1401
1402     key = xmlGetProp(cur_node, (const xmlChar*)LAYOUT_ROW_KEY_LONGKEY_TYPE_ATTRIBUTE);
1403     if (key) {
1404         (*cur_rec_coordinate)->long_key_type = (SCLKeyType)KeyTypeHelper::Int((const char*)key);
1405         xmlFree(key);
1406     } else {
1407         /* assume the long_key_type is the same with key_type, by default */
1408         (*cur_rec_coordinate)->long_key_type = (*cur_rec_coordinate)->key_type;
1409     }
1410
1411     key = xmlGetProp(cur_node, (const xmlChar*)LAYOUT_ROW_KEY_LONGKEY_VALUE_ATTRIBUTE);
1412     if (key) {
1413         (*cur_rec_coordinate)->long_key_value = (sclchar*)key;
1414         add_key_string(key);
1415     }
1416
1417     get_prop_number(cur_node, LAYOUT_ROW_KEY_LONGKEY_EVENT_ATTRIBUTE, &((*cur_rec_coordinate)->long_key_event));
1418
1419     get_prop_bool(cur_node, LAYOUT_ROW_KEY_USE_REPEAT_KEY_ATTRIBUTE, &((*cur_rec_coordinate)->use_repeat_key));
1420     get_prop_bool(cur_node, LAYOUT_ROW_KEY_DONOT_CLOSE_POPUP_ATTRIBUTE, &((*cur_rec_coordinate)->dont_close_popup));
1421
1422     (*cur_rec_coordinate)->extra_option = get_extra_option_prop(cur_node);
1423     (*cur_rec_coordinate)->multitouch_type = get_multitouch_type_prop(cur_node);
1424
1425     key = xmlGetProp(cur_node, (const xmlChar*)LAYOUT_ROW_KEY_SUBLAYOUT_ID_ATTRIBUTE);
1426     if (key) {
1427         (*cur_rec_coordinate)->sub_layout = (sclchar*)key;
1428         add_key_string(key);
1429     }
1430
1431     key = xmlGetProp(cur_node, (const xmlChar*)LAYOUT_ROW_KEY_LABEL_TYPE_ATTRIBUTE);
1432     if (key) {
1433         (*cur_rec_coordinate)->label_type = (sclchar*)key;
1434         add_key_string(key);
1435     }
1436
1437     key = xmlGetProp(cur_node, (const xmlChar*)LAYOUT_ROW_KEY_IMAGE_LABEL_TYPE_ATTRIBUTE);
1438     if (key) {
1439         (*cur_rec_coordinate)->image_label_type = (sclchar*)key;
1440         add_key_string(key);
1441     }
1442
1443     key = xmlGetProp(cur_node, (const xmlChar*)LAYOUT_ROW_KEY_MODIFIER_DECORATION_ID_ATTRIBUTE);
1444     if (key) {
1445         (*cur_rec_coordinate)->modifier_decorator = (sclchar*)key;
1446         add_key_string(key);
1447     }
1448
1449     get_prop_number(cur_node, LAYOUT_ROW_KEY_KEY_SPACING_ATTRIBUTE, &key_spacing);
1450
1451     xmlNodePtr child_node = cur_node->xmlChildrenNode;
1452     while (child_node != NULL) {
1453         if (0 == xmlStrcmp(child_node->name, (const xmlChar*)LAYOUT_ROW_KEY_LABEL_TAG)) {
1454             parsing_label_record_node(child_node, (*cur_rec_coordinate));
1455             (*cur_rec_coordinate)->valid = TRUE;
1456         } else if (0 == xmlStrcmp(child_node->name, (const xmlChar*)LAYOUT_ROW_KEY_IMAGE_LABEL_TAG)) {
1457             parsing_label_image_record_node(child_node, (*cur_rec_coordinate));
1458             (*cur_rec_coordinate)->valid = TRUE;
1459         } else if (0 == xmlStrcmp(child_node->name, (const xmlChar*)LAYOUT_ROW_KEY_BACKGROUND_IMAGE_TAG)) {
1460             parsing_background_image_record_node(child_node, (*cur_rec_coordinate));
1461             (*cur_rec_coordinate)->valid = TRUE;
1462         } else if (0 == xmlStrcmp(child_node->name, (const xmlChar*)LAYOUT_ROW_KEY_KEY_VALUE_TAG)) {
1463             parsing_key_value_record_node(child_node, (*cur_rec_coordinate));
1464             (*cur_rec_coordinate)->valid = TRUE;
1465         } else if (0 == xmlStrcmp(child_node->name, (const xmlChar*)LAYOUT_ROW_KEY_KEY_EVENT_TAG)) {
1466             parsing_key_event_record_node(child_node, (*cur_rec_coordinate));
1467             (*cur_rec_coordinate)->valid = TRUE;
1468         } else if (0 == xmlStrcmp(child_node->name, (const xmlChar*)LAYOUT_ROW_KEY_AUTOPOPUP_KEYS_TAG)) {
1469             parsing_auto_popup_keys_record_node(child_node, (*cur_rec_coordinate));
1470             (*cur_rec_coordinate)->valid = TRUE;
1471         } else if (0 == xmlStrcmp(child_node->name, (const xmlChar*)LAYOUT_ROW_KEY_POPUP_INPUTMODE_RECORD_TAG)) {
1472             parsing_popup_input_mode_record_node(child_node, (*cur_rec_coordinate));
1473             (*cur_rec_coordinate)->valid = TRUE;
1474         } else if (0 == xmlStrcmp(child_node->name, (const xmlChar*)LAYOUT_ROW_KEY_MAGNIFIER_LABEL_TAG)) {
1475             parsing_magnifier_label_record_node(child_node, (*cur_rec_coordinate));
1476             (*cur_rec_coordinate)->valid = TRUE;
1477         } else if (0 == xmlStrcmp(child_node->name, (const xmlChar*)LAYOUT_ROW_KEY_HINT_STRING_TAG)) {
1478             parsing_hint_string_record_node(child_node, (*cur_rec_coordinate));
1479             (*cur_rec_coordinate)->valid = TRUE;
1480         }
1481
1482         child_node = child_node->next;
1483     }
1484
1485     if (row) {
1486         row->row_x = (*cur_rec_coordinate)->x + (*cur_rec_coordinate)->width + key_spacing;
1487     }
1488 }
1489
1490 void
1491 LayoutParserImpl::parsing_popup_input_mode_record_node(
1492         const xmlNodePtr cur_node,
1493         const PSclLayoutKeyCoordinate cur_rec) {
1494     assert(cur_node != NULL);
1495     assert(cur_rec != NULL);
1496     assert(0 == xmlStrcmp(cur_node->name, (const xmlChar*)LAYOUT_ROW_KEY_POPUP_INPUTMODE_RECORD_TAG));
1497     xmlNodePtr child_node = cur_node->xmlChildrenNode;
1498
1499     while (child_node != NULL) {
1500         if (0 == xmlStrcmp(child_node->name, (const xmlChar*)LAYOUT_ROW_KEY_POPUP_INPUTMODE_RECORD_INPUTMODE_TAG)) {
1501             int drag_state = get_drag_state_prop(child_node);
1502             assert(drag_state >=0);
1503             assert(drag_state < SCL_DRAG_STATE_MAX);
1504             xmlChar* key = xmlNodeGetContent(child_node);
1505
1506             if (key) {
1507                 cur_rec->popup_input_mode[drag_state] = (sclchar*)key;
1508                 add_key_string(key);
1509             }
1510         }
1511         child_node = child_node->next;
1512     }
1513 }
1514
1515 LayoutParser::LayoutParser() {
1516     m_impl = new LayoutParserImpl;
1517 }
1518 LayoutParser::~LayoutParser() {
1519     SCLLOG(SclLog::MESSAGE, "~LayoutParser() has called");
1520     delete m_impl;
1521     m_impl = NULL;
1522 }
1523
1524 LayoutParser*
1525 LayoutParser::get_instance() {
1526     static LayoutParser instance;
1527     return &instance;
1528 }
1529
1530 int
1531 LayoutParser::init(const char* dir, const vector<string> &vec_file) {
1532     int ret = -1;
1533     if (dir) {
1534         m_impl->set_directory(dir);
1535         ret = m_impl->parsing_layout_table(vec_file);
1536     }
1537
1538     return ret;
1539 }
1540
1541 void
1542 LayoutParser::load(int layout_id) {
1543     m_impl->load(layout_id);
1544 }
1545
1546 bool
1547 LayoutParser::loaded(int layout_id) {
1548     return m_impl->loaded(layout_id);
1549 }
1550
1551 void
1552 LayoutParser::unload() {
1553     m_impl->unload();
1554 }
1555
1556 int
1557 LayoutParser::get_layout_index(const char *name) {
1558     return m_impl->get_layout_index(name);
1559 }
1560
1561 int
1562 LayoutParser::get_layout_size() {
1563     return m_impl->get_layout_size();
1564 }
1565
1566 PSclLayout
1567 LayoutParser::get_layout_table() {
1568     return m_impl->get_layout_table();
1569 }
1570
1571 PSclLayoutKeyCoordinatePointerTable
1572 LayoutParser::get_key_coordinate_pointer_frame() {
1573     return m_impl->get_key_coordinate_pointer_frame();
1574 }