1 /* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
2 /* vim:set et sts=4: */
3 /* bus - The Input Bus
4  * Copyright (C) 2008-2015 Peng Huang <shawn.p.huang@gmail.com>
5  * Copyright (C) 2008-2019 Red Hat, Inc.
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
20  * USA
21  */
22 #include <stdlib.h>
23 #include "ibusenginedesc.h"
24 #include "ibusinternal.h"
25 #include "ibusxml.h"
26 
27 enum {
28     LAST_SIGNAL,
29 };
30 
31 enum {
32     PROP_0 = 0,
33     PROP_NAME,
34     PROP_LONGNAME,
35     PROP_DESCRIPTION,
36     PROP_LANGUAGE,
37     PROP_LICENSE,
38     PROP_AUTHOR,
39     PROP_ICON,
40     PROP_LAYOUT,
41     PROP_LAYOUT_VARIANT,
42     PROP_LAYOUT_OPTION,
43     PROP_RANK,
44     PROP_HOTKEYS,
45     PROP_SYMBOL,
46     PROP_SETUP,
47     PROP_VERSION,
48     PROP_TEXTDOMAIN,
49     PROP_ICON_PROP_KEY
50 };
51 
52 
53 /* IBusEngineDescPriv */
54 struct _IBusEngineDescPrivate {
55     gchar      *name;
56     gchar      *longname;
57     gchar      *description;
58     gchar      *language;
59     gchar      *license;
60     gchar      *author;
61     gchar      *icon;
62     gchar      *layout;
63     gchar      *layout_variant;
64     gchar      *layout_option;
65     guint       rank;
66     gchar      *hotkeys;
67     gchar      *symbol;
68     gchar      *setup;
69     gchar      *version;
70     gchar      *textdomain;
71     gchar      *icon_prop_key;
72 };
73 
74 #define IBUS_ENGINE_DESC_GET_PRIVATE(o)  \
75    ((IBusEngineDescPrivate *)ibus_engine_desc_get_instance_private (o))
76 
77 // static guint            _signals[LAST_SIGNAL] = { 0 };
78 
79 /* functions prototype */
80 static void         ibus_engine_desc_set_property   (IBusEngineDesc         *desc,
81                                                      guint                   prop_id,
82                                                      const GValue           *value,
83                                                      GParamSpec             *pspec);
84 static void         ibus_engine_desc_get_property   (IBusEngineDesc         *desc,
85                                                      guint                   prop_id,
86                                                      GValue                 *value,
87                                                      GParamSpec             *pspec);
88 static void         ibus_engine_desc_destroy        (IBusEngineDesc         *desc);
89 static gboolean     ibus_engine_desc_serialize      (IBusEngineDesc         *desc,
90                                                      GVariantBuilder        *builder);
91 static gint         ibus_engine_desc_deserialize    (IBusEngineDesc         *desc,
92                                                      GVariant               *variant);
93 static gboolean     ibus_engine_desc_copy           (IBusEngineDesc         *dest,
94                                                      const IBusEngineDesc   *src);
95 static gboolean     ibus_engine_desc_parse_xml_node (IBusEngineDesc         *desc,
96                                                      XMLNode                *node);
97 
G_DEFINE_TYPE_WITH_PRIVATE(IBusEngineDesc,ibus_engine_desc,IBUS_TYPE_SERIALIZABLE)98 G_DEFINE_TYPE_WITH_PRIVATE (IBusEngineDesc,
99                             ibus_engine_desc,
100                             IBUS_TYPE_SERIALIZABLE)
101 
102 
103 static void
104 ibus_engine_desc_class_init (IBusEngineDescClass *class)
105 {
106     GObjectClass *gobject_class = G_OBJECT_CLASS (class);
107     IBusObjectClass *object_class = IBUS_OBJECT_CLASS (class);
108     IBusSerializableClass *serializable_class = IBUS_SERIALIZABLE_CLASS (class);
109 
110     gobject_class->set_property = (GObjectSetPropertyFunc) ibus_engine_desc_set_property;
111     gobject_class->get_property = (GObjectGetPropertyFunc) ibus_engine_desc_get_property;
112     object_class->destroy = (IBusObjectDestroyFunc) ibus_engine_desc_destroy;
113 
114     serializable_class->serialize   = (IBusSerializableSerializeFunc) ibus_engine_desc_serialize;
115     serializable_class->deserialize = (IBusSerializableDeserializeFunc) ibus_engine_desc_deserialize;
116     serializable_class->copy        = (IBusSerializableCopyFunc) ibus_engine_desc_copy;
117 
118     /* install properties */
119     /**
120      * IBusEngineDesc:name:
121      *
122      * The name of engine description
123      */
124     g_object_class_install_property (gobject_class,
125                     PROP_NAME,
126                     g_param_spec_string ("name",
127                         "description name",
128                         "The name of engine description",
129                         NULL,
130                         G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
131 
132     /**
133      * IBusEngineDesc:longname:
134      *
135      * The longname of engine description
136      */
137     g_object_class_install_property (gobject_class,
138                     PROP_LONGNAME,
139                     g_param_spec_string ("longname",
140                         "description longname",
141                         "The longname of engine description",
142                         "",
143                         G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
144 
145     /**
146      * IBusEngineDesc:description:
147      *
148      * The description of engine description
149      */
150     g_object_class_install_property (gobject_class,
151                     PROP_DESCRIPTION,
152                     g_param_spec_string ("description",
153                         "description description",
154                         "The description of engine description",
155                         "",
156                         G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
157 
158     /**
159      * IBusEngineDesc:language:
160      *
161      * The language of engine description
162      */
163     g_object_class_install_property (gobject_class,
164                     PROP_LANGUAGE,
165                     g_param_spec_string ("language",
166                         "description language",
167                         "The language of engine description",
168                         "",
169                         G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
170 
171     /**
172      * IBusEngineDesc:license:
173      *
174      * The license of engine description
175      */
176     g_object_class_install_property (gobject_class,
177                     PROP_LICENSE,
178                     g_param_spec_string ("license",
179                         "description license",
180                         "The license of engine description",
181                         "",
182                         G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
183 
184     /**
185      * IBusEngineDesc:author:
186      *
187      * The author of engine description
188      */
189     g_object_class_install_property (gobject_class,
190                     PROP_AUTHOR,
191                     g_param_spec_string ("author",
192                         "description author",
193                         "The author of engine description",
194                         "",
195                         G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
196 
197     /**
198      * IBusEngineDesc:icon:
199      *
200      * The icon of engine description
201      */
202     g_object_class_install_property (gobject_class,
203                     PROP_ICON,
204                     g_param_spec_string ("icon",
205                         "description icon",
206                         "The icon of engine description",
207                         "ibus-engine",
208                         G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
209 
210     /**
211      * IBusEngineDesc:layout:
212      *
213      * The layout of engine description
214      */
215     g_object_class_install_property (gobject_class,
216                     PROP_LAYOUT,
217                     g_param_spec_string ("layout",
218                         "description layout",
219                         "The layout of engine description",
220                         "us",
221                         G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
222 
223     /**
224      * IBusEngineDesc:layout-variant:
225      *
226      * The keyboard variant of engine description
227      */
228     g_object_class_install_property (gobject_class,
229                     PROP_LAYOUT_VARIANT,
230                     g_param_spec_string ("layout-variant",
231                         "description keyboard variant",
232                         "The keyboard variant of engine description",
233                         "",
234                         G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
235 
236     /**
237      * IBusEngineDesc:layout-option:
238      *
239      * The keyboard option of engine description
240      */
241     g_object_class_install_property (gobject_class,
242                     PROP_LAYOUT_OPTION,
243                     g_param_spec_string ("layout-option",
244                         "description keyboard option",
245                         "The keyboard option of engine description",
246                         "",
247                         G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
248 
249     /**
250      * IBusEngineDesc:rank:
251      *
252      * The rank of engine description
253      */
254     g_object_class_install_property (gobject_class,
255                     PROP_RANK,
256                     g_param_spec_uint ("rank",
257                         "description rank",
258                         "The rank of engine description",
259                         0,
260                         G_MAXUINT,
261                         0,
262                         G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
263 
264     /**
265      * IBusEngineDesc:hotkeys:
266      *
267      * The hotkeys of engine description
268      */
269     g_object_class_install_property (gobject_class,
270                     PROP_HOTKEYS,
271                     g_param_spec_string ("hotkeys",
272                         "description hotkeys",
273                         "The hotkeys of engine description",
274                         "",
275                         G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
276 
277     /**
278      * IBusEngineDesc:symbol:
279      *
280      * The symbol chars of engine description instead of icon image
281      */
282     g_object_class_install_property (gobject_class,
283                     PROP_SYMBOL,
284                     g_param_spec_string ("symbol",
285                         "description symbol",
286                         "The icon symbol chars of engine description",
287                         "",
288                         G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
289 
290     /**
291      * IBusEngineDesc:setup:
292      *
293      * The exec lists of the engine setup command
294      */
295     g_object_class_install_property (gobject_class,
296                     PROP_SETUP,
297                     g_param_spec_string ("setup",
298                         "setup args",
299                         "The exec lists of the engine setup command",
300                         "",
301                         G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
302 
303     /**
304      * IBusEngineDesc:version:
305      *
306      * The version number of engine description
307      */
308     g_object_class_install_property (gobject_class,
309                     PROP_VERSION,
310                     g_param_spec_string ("version",
311                         "version number",
312                         "The version number of engine description",
313                         "",
314                         G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
315 
316     /**
317      * IBusEngineDesc:textdomain:
318      *
319      * The textdomain of engine description
320      */
321     g_object_class_install_property (gobject_class,
322                     PROP_TEXTDOMAIN,
323                     g_param_spec_string ("textdomain",
324                         "textdomain",
325                         "The textdomain of engine description",
326                         "",
327                         G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
328 
329     /**
330      * IBusEngineDesc:icon-prop-key:
331      *
332      * The key of IBusProperty to change panel icon dynamically.
333      */
334     g_object_class_install_property (gobject_class,
335                     PROP_ICON_PROP_KEY,
336                     g_param_spec_string ("icon-prop-key",
337                         "icon property key",
338                         "The key of IBusProperty for the dynamic panel icon",
339                         "",
340                         G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
341 }
342 
343 static void
ibus_engine_desc_init(IBusEngineDesc * desc)344 ibus_engine_desc_init (IBusEngineDesc *desc)
345 {
346     desc->priv = IBUS_ENGINE_DESC_GET_PRIVATE (desc);
347 
348     desc->priv->name = NULL;
349     desc->priv->longname = NULL;
350     desc->priv->description = NULL;
351     desc->priv->language = NULL;
352     desc->priv->license = NULL;
353     desc->priv->author = NULL;
354     desc->priv->icon = NULL;
355     desc->priv->layout = NULL;
356     desc->priv->layout_variant = NULL;
357     desc->priv->layout_option = NULL;
358     desc->priv->rank = 0;
359     desc->priv->hotkeys = NULL;
360     desc->priv->symbol = NULL;
361     desc->priv->setup = NULL;
362     desc->priv->version = NULL;
363     desc->priv->textdomain = NULL;
364     desc->priv->icon_prop_key = NULL;
365 }
366 
367 static void
ibus_engine_desc_destroy(IBusEngineDesc * desc)368 ibus_engine_desc_destroy (IBusEngineDesc *desc)
369 {
370     g_free (desc->priv->name);
371     g_free (desc->priv->longname);
372     g_free (desc->priv->description);
373     g_free (desc->priv->language);
374     g_free (desc->priv->license);
375     g_free (desc->priv->author);
376     g_free (desc->priv->icon);
377     g_free (desc->priv->layout);
378     g_free (desc->priv->layout_variant);
379     g_free (desc->priv->layout_option);
380     g_free (desc->priv->hotkeys);
381     g_free (desc->priv->symbol);
382     g_free (desc->priv->setup);
383     g_free (desc->priv->version);
384     g_free (desc->priv->textdomain);
385     g_free (desc->priv->icon_prop_key);
386 
387     IBUS_OBJECT_CLASS (ibus_engine_desc_parent_class)->destroy (IBUS_OBJECT (desc));
388 }
389 
390 static void
ibus_engine_desc_set_property(IBusEngineDesc * desc,guint prop_id,const GValue * value,GParamSpec * pspec)391 ibus_engine_desc_set_property (IBusEngineDesc *desc,
392                                guint           prop_id,
393                                const GValue   *value,
394                                GParamSpec     *pspec)
395 {
396     switch (prop_id) {
397     case PROP_NAME:
398         g_assert (desc->priv->name == NULL);
399         desc->priv->name = g_value_dup_string (value);
400         break;
401     case PROP_LONGNAME:
402         g_assert (desc->priv->longname == NULL);
403         desc->priv->longname = g_value_dup_string (value);
404         break;
405     case PROP_DESCRIPTION:
406         g_assert (desc->priv->description == NULL);
407         desc->priv->description  = g_value_dup_string (value);
408         break;
409     case PROP_LANGUAGE:
410         g_assert (desc->priv->language == NULL);
411         desc->priv->language = g_value_dup_string (value);
412         break;
413     case PROP_LICENSE:
414         g_assert (desc->priv->license == NULL);
415         desc->priv->license = g_value_dup_string (value);
416         break;
417     case PROP_AUTHOR:
418         g_assert (desc->priv->author == NULL);
419         desc->priv->author = g_value_dup_string (value);
420         break;
421     case PROP_ICON:
422         g_assert (desc->priv->icon == NULL);
423         desc->priv->icon = g_value_dup_string (value);
424         break;
425     case PROP_LAYOUT:
426         g_assert (desc->priv->layout == NULL);
427         desc->priv->layout = g_value_dup_string (value);
428         break;
429     case PROP_LAYOUT_VARIANT:
430         g_assert (desc->priv->layout_variant == NULL);
431         desc->priv->layout_variant = g_value_dup_string (value);
432         break;
433     case PROP_LAYOUT_OPTION:
434         g_assert (desc->priv->layout_option == NULL);
435         desc->priv->layout_option = g_value_dup_string (value);
436         break;
437     case PROP_RANK:
438         desc->priv->rank = g_value_get_uint (value);
439         break;
440     case PROP_HOTKEYS:
441         g_assert (desc->priv->hotkeys == NULL);
442         desc->priv->hotkeys = g_value_dup_string (value);
443         break;
444     case PROP_SYMBOL:
445         g_assert (desc->priv->symbol == NULL);
446         desc->priv->symbol = g_value_dup_string (value);
447         break;
448     case PROP_SETUP:
449         g_assert (desc->priv->setup == NULL);
450         desc->priv->setup = g_value_dup_string (value);
451         break;
452     case PROP_VERSION:
453         g_assert (desc->priv->version == NULL);
454         desc->priv->version = g_value_dup_string (value);
455         break;
456     case PROP_TEXTDOMAIN:
457         g_assert (desc->priv->textdomain == NULL);
458         desc->priv->textdomain = g_value_dup_string (value);
459         break;
460     case PROP_ICON_PROP_KEY:
461         g_assert (desc->priv->icon_prop_key == NULL);
462         desc->priv->icon_prop_key = g_value_dup_string (value);
463         break;
464     default:
465         G_OBJECT_WARN_INVALID_PROPERTY_ID (desc, prop_id, pspec);
466     }
467 }
468 
469 static void
ibus_engine_desc_get_property(IBusEngineDesc * desc,guint prop_id,GValue * value,GParamSpec * pspec)470 ibus_engine_desc_get_property (IBusEngineDesc *desc,
471                                guint           prop_id,
472                                GValue         *value,
473                                GParamSpec     *pspec)
474 {
475     switch (prop_id) {
476     case PROP_NAME:
477         g_value_set_string (value, ibus_engine_desc_get_name (desc));
478         break;
479     case PROP_LONGNAME:
480         g_value_set_string (value, ibus_engine_desc_get_longname (desc));
481         break;
482     case PROP_DESCRIPTION:
483         g_value_set_string (value, ibus_engine_desc_get_description (desc));
484         break;
485     case PROP_LANGUAGE:
486         g_value_set_string (value, ibus_engine_desc_get_language (desc));
487         break;
488     case PROP_LICENSE:
489         g_value_set_string (value, ibus_engine_desc_get_license (desc));
490         break;
491     case PROP_AUTHOR:
492         g_value_set_string (value, ibus_engine_desc_get_author (desc));
493         break;
494     case PROP_ICON:
495         g_value_set_string (value, ibus_engine_desc_get_icon (desc));
496         break;
497     case PROP_LAYOUT:
498         g_value_set_string (value, ibus_engine_desc_get_layout (desc));
499         break;
500     case PROP_LAYOUT_VARIANT:
501         g_value_set_string (value, ibus_engine_desc_get_layout_variant (desc));
502         break;
503     case PROP_LAYOUT_OPTION:
504         g_value_set_string (value, ibus_engine_desc_get_layout_option (desc));
505         break;
506     case PROP_RANK:
507         g_value_set_uint (value, ibus_engine_desc_get_rank (desc));
508         break;
509     case PROP_HOTKEYS:
510         g_value_set_string (value, ibus_engine_desc_get_hotkeys (desc));
511         break;
512     case PROP_SYMBOL:
513         g_value_set_string (value, ibus_engine_desc_get_symbol (desc));
514         break;
515     case PROP_SETUP:
516         g_value_set_string (value, ibus_engine_desc_get_setup (desc));
517         break;
518     case PROP_VERSION:
519         g_value_set_string (value, ibus_engine_desc_get_version (desc));
520         break;
521     case PROP_TEXTDOMAIN:
522         g_value_set_string (value, ibus_engine_desc_get_textdomain (desc));
523         break;
524     case PROP_ICON_PROP_KEY:
525         g_value_set_string (value, ibus_engine_desc_get_icon_prop_key (desc));
526         break;
527     default:
528         G_OBJECT_WARN_INVALID_PROPERTY_ID (desc, prop_id, pspec);
529     }
530 }
531 
532 static gboolean
ibus_engine_desc_serialize(IBusEngineDesc * desc,GVariantBuilder * builder)533 ibus_engine_desc_serialize (IBusEngineDesc  *desc,
534                             GVariantBuilder *builder)
535 {
536     gboolean retval;
537 
538     retval = IBUS_SERIALIZABLE_CLASS (ibus_engine_desc_parent_class)->serialize ((IBusSerializable *)desc, builder);
539     g_return_val_if_fail (retval, FALSE);
540     /* End dict iter */
541 
542 #define NOTNULL(s) ((s) != NULL ? (s) : "")
543     /* If you will add a new property, you can append it at the end and
544      * you should not change the serialized order of name, longname,
545      * description, ... because the order is also used in other applications
546      * likes ibus-qt. */
547     g_variant_builder_add (builder, "s", NOTNULL (desc->priv->name));
548     g_variant_builder_add (builder, "s", NOTNULL (desc->priv->longname));
549     g_variant_builder_add (builder, "s", NOTNULL (desc->priv->description));
550     g_variant_builder_add (builder, "s", NOTNULL (desc->priv->language));
551     g_variant_builder_add (builder, "s", NOTNULL (desc->priv->license));
552     g_variant_builder_add (builder, "s", NOTNULL (desc->priv->author));
553     g_variant_builder_add (builder, "s", NOTNULL (desc->priv->icon));
554     g_variant_builder_add (builder, "s", NOTNULL (desc->priv->layout));
555     g_variant_builder_add (builder, "u", desc->priv->rank);
556     /* The serialized order should be kept. */
557     g_variant_builder_add (builder, "s", NOTNULL (desc->priv->hotkeys));
558     g_variant_builder_add (builder, "s", NOTNULL (desc->priv->symbol));
559     g_variant_builder_add (builder, "s", NOTNULL (desc->priv->setup));
560     g_variant_builder_add (builder, "s", NOTNULL (desc->priv->layout_variant));
561     g_variant_builder_add (builder, "s", NOTNULL (desc->priv->layout_option));
562     g_variant_builder_add (builder, "s", NOTNULL (desc->priv->version));
563     g_variant_builder_add (builder, "s", NOTNULL (desc->priv->textdomain));
564     g_variant_builder_add (builder, "s", NOTNULL (desc->priv->icon_prop_key));
565 #undef NOTNULL
566 
567     return TRUE;
568 }
569 
570 static gint
ibus_engine_desc_deserialize(IBusEngineDesc * desc,GVariant * variant)571 ibus_engine_desc_deserialize (IBusEngineDesc *desc,
572                               GVariant       *variant)
573 {
574     gint retval;
575 
576     retval = IBUS_SERIALIZABLE_CLASS (ibus_engine_desc_parent_class)->deserialize ((IBusSerializable *)desc, variant);
577     g_return_val_if_fail (retval, 0);
578 
579     /* If you will add a new property, you can append it at the end and
580      * you should not change the serialized order of name, longname,
581      * description, ... because the order is also used in other applications
582      * likes ibus-qt. */
583     ibus_g_variant_get_child_string (variant, retval++,
584                                      &desc->priv->name);
585     ibus_g_variant_get_child_string (variant, retval++,
586                                      &desc->priv->longname);
587     ibus_g_variant_get_child_string (variant, retval++,
588                                      &desc->priv->description);
589     ibus_g_variant_get_child_string (variant, retval++,
590                                      &desc->priv->language);
591     ibus_g_variant_get_child_string (variant, retval++,
592                                      &desc->priv->license);
593     ibus_g_variant_get_child_string (variant, retval++,
594                                      &desc->priv->author);
595     ibus_g_variant_get_child_string (variant, retval++,
596                                      &desc->priv->icon);
597     ibus_g_variant_get_child_string (variant, retval++,
598                                      &desc->priv->layout);
599     g_variant_get_child (variant, retval++, "u", &desc->priv->rank);
600     /* The serialized order should be kept. */
601     ibus_g_variant_get_child_string (variant, retval++,
602                                      &desc->priv->hotkeys);
603     ibus_g_variant_get_child_string (variant, retval++,
604                                      &desc->priv->symbol);
605     ibus_g_variant_get_child_string (variant, retval++,
606                                      &desc->priv->setup);
607     if (g_variant_n_children (variant) < retval + 2)
608         return retval;
609     ibus_g_variant_get_child_string (variant, retval++,
610                                      &desc->priv->layout_variant);
611     ibus_g_variant_get_child_string (variant, retval++,
612                                      &desc->priv->layout_option);
613     if (g_variant_n_children (variant) < retval + 1)
614         return retval;
615     ibus_g_variant_get_child_string (variant, retval++,
616                                      &desc->priv->version);
617     if (g_variant_n_children (variant) < retval + 1)
618         return retval;
619     ibus_g_variant_get_child_string (variant, retval++,
620                                      &desc->priv->textdomain);
621     if (g_variant_n_children (variant) < retval + 1)
622         return retval;
623     ibus_g_variant_get_child_string (variant, retval++,
624                                      &desc->priv->icon_prop_key);
625 
626     return retval;
627 }
628 
629 static gboolean
ibus_engine_desc_copy(IBusEngineDesc * dest,const IBusEngineDesc * src)630 ibus_engine_desc_copy (IBusEngineDesc       *dest,
631                        const IBusEngineDesc *src)
632 {
633     gboolean retval;
634 
635     retval = IBUS_SERIALIZABLE_CLASS (ibus_engine_desc_parent_class)->copy ((IBusSerializable *)dest,
636                                  (IBusSerializable *)src);
637     g_return_val_if_fail (retval, FALSE);
638 
639     dest->priv->name             = g_strdup (src->priv->name);
640     dest->priv->longname         = g_strdup (src->priv->longname);
641     dest->priv->description      = g_strdup (src->priv->description);
642     dest->priv->language         = g_strdup (src->priv->language);
643     dest->priv->license          = g_strdup (src->priv->license);
644     dest->priv->author           = g_strdup (src->priv->author);
645     dest->priv->icon             = g_strdup (src->priv->icon);
646     dest->priv->layout           = g_strdup (src->priv->layout);
647     dest->priv->layout_variant   = g_strdup (src->priv->layout_variant);
648     dest->priv->layout_option    = g_strdup (src->priv->layout_option);
649     dest->priv->rank             = src->priv->rank;
650     dest->priv->hotkeys          = g_strdup (src->priv->hotkeys);
651     dest->priv->symbol           = g_strdup (src->priv->symbol);
652     dest->priv->setup            = g_strdup (src->priv->setup);
653     dest->priv->version          = g_strdup (src->priv->version);
654     dest->priv->textdomain       = g_strdup (src->priv->textdomain);
655     dest->priv->icon_prop_key    = g_strdup (src->priv->icon_prop_key);
656     return TRUE;
657 }
658 
659 #define g_string_append_indent(string, indent)  \
660     {                                           \
661         gint i;                                 \
662         for (i = 0; i < (indent); i++) {        \
663             g_string_append (string, "    ");   \
664         }                                       \
665     }
666 
667 void
ibus_engine_desc_output(IBusEngineDesc * desc,GString * output,gint indent)668 ibus_engine_desc_output (IBusEngineDesc *desc,
669                          GString        *output,
670                          gint            indent)
671 {
672     g_string_append_indent (output, indent);
673     g_string_append (output, "<engine>\n");
674 #define OUTPUT_ENTRY(field, element)                                        \
675     {                                                                       \
676         gchar *escape_text = g_markup_escape_text (                         \
677                         desc->priv->field ? desc->priv->field : "", -1);    \
678         g_string_append_indent (output, indent + 1);                        \
679         g_string_append_printf (output, "<"element">%s</"element">\n",      \
680                                 escape_text);                               \
681         g_free (escape_text);                                               \
682     }
683 #define OUTPUT_ENTRY_1(name) OUTPUT_ENTRY(name, #name)
684     OUTPUT_ENTRY_1(name);
685     OUTPUT_ENTRY_1(longname);
686     OUTPUT_ENTRY_1(description);
687     OUTPUT_ENTRY_1(language);
688     OUTPUT_ENTRY_1(license);
689     OUTPUT_ENTRY_1(author);
690     OUTPUT_ENTRY_1(icon);
691     OUTPUT_ENTRY_1(layout);
692     OUTPUT_ENTRY_1(layout_variant);
693     OUTPUT_ENTRY_1(layout_option);
694     OUTPUT_ENTRY_1(hotkeys);
695     OUTPUT_ENTRY_1(symbol);
696     OUTPUT_ENTRY_1(setup);
697     OUTPUT_ENTRY_1(version);
698     OUTPUT_ENTRY_1(textdomain);
699     OUTPUT_ENTRY_1(icon_prop_key);
700     g_string_append_indent (output, indent + 1);
701     g_string_append_printf (output, "<rank>%u</rank>\n", desc->priv->rank);
702 #undef OUTPUT_ENTRY
703 #undef OUTPUT_ENTRY_1
704     g_string_append_indent (output, indent);
705     g_string_append (output, "</engine>\n");
706 }
707 
708 static gboolean
ibus_engine_desc_parse_xml_node(IBusEngineDesc * desc,XMLNode * node)709 ibus_engine_desc_parse_xml_node (IBusEngineDesc *desc,
710                                 XMLNode       *node)
711 {
712     GList *p;
713 
714     for (p = node->sub_nodes; p != NULL; p = p->next) {
715         XMLNode *sub_node = (XMLNode *) p->data;
716 
717 #define PARSE_ENTRY(field_name, element_name)                   \
718         if (g_strcmp0 (sub_node->name, element_name) == 0) {    \
719             g_free (desc->priv->field_name);                    \
720             desc->priv->field_name = g_strdup (sub_node->text); \
721             continue;                                           \
722         }
723 #define PARSE_ENTRY_1(name) PARSE_ENTRY(name, #name)
724         PARSE_ENTRY_1(name);
725         PARSE_ENTRY_1(longname);
726         PARSE_ENTRY_1(description);
727         PARSE_ENTRY_1(language);
728         PARSE_ENTRY_1(license);
729         PARSE_ENTRY_1(author);
730         PARSE_ENTRY_1(icon);
731         PARSE_ENTRY_1(layout);
732         PARSE_ENTRY_1(layout_variant);
733         PARSE_ENTRY_1(layout_option);
734         PARSE_ENTRY_1(hotkeys);
735         PARSE_ENTRY_1(symbol);
736         PARSE_ENTRY_1(setup);
737         PARSE_ENTRY_1(version);
738         PARSE_ENTRY_1(textdomain);
739         PARSE_ENTRY_1(icon_prop_key);
740 #undef PARSE_ENTRY
741 #undef PARSE_ENTRY_1
742         if (g_strcmp0 (sub_node->name , "rank") == 0) {
743             desc->priv->rank = atoi (sub_node->text);
744             continue;
745         }
746         g_warning ("<engines> element contains invalidate element <%s>", sub_node->name);
747     }
748     return TRUE;
749 }
750 
751 #define IBUS_ENGINE_DESC_GET_PROPERTY(property, return_type)    \
752 return_type                                                     \
753 ibus_engine_desc_get_ ## property (IBusEngineDesc *desc)        \
754 {                                                               \
755     return desc->priv->property;                                \
756 }
757 
IBUS_ENGINE_DESC_GET_PROPERTY(name,const gchar *)758 IBUS_ENGINE_DESC_GET_PROPERTY (name, const gchar *)
759 IBUS_ENGINE_DESC_GET_PROPERTY (longname, const gchar *)
760 IBUS_ENGINE_DESC_GET_PROPERTY (description, const gchar *)
761 IBUS_ENGINE_DESC_GET_PROPERTY (language, const gchar *)
762 IBUS_ENGINE_DESC_GET_PROPERTY (license, const gchar *)
763 IBUS_ENGINE_DESC_GET_PROPERTY (author, const gchar *)
764 IBUS_ENGINE_DESC_GET_PROPERTY (icon, const gchar *)
765 IBUS_ENGINE_DESC_GET_PROPERTY (layout, const gchar *)
766 IBUS_ENGINE_DESC_GET_PROPERTY (layout_variant, const gchar *)
767 IBUS_ENGINE_DESC_GET_PROPERTY (layout_option, const gchar *)
768 IBUS_ENGINE_DESC_GET_PROPERTY (rank, guint)
769 IBUS_ENGINE_DESC_GET_PROPERTY (hotkeys, const gchar *)
770 IBUS_ENGINE_DESC_GET_PROPERTY (symbol, const gchar *)
771 IBUS_ENGINE_DESC_GET_PROPERTY (setup, const gchar *)
772 IBUS_ENGINE_DESC_GET_PROPERTY (version, const gchar *)
773 IBUS_ENGINE_DESC_GET_PROPERTY (textdomain, const gchar *)
774 IBUS_ENGINE_DESC_GET_PROPERTY (icon_prop_key, const gchar *)
775 #undef IBUS_ENGINE_DESC_GET_PROPERTY
776 
777 IBusEngineDesc *
778 ibus_engine_desc_new (const gchar *name,
779                       const gchar *longname,
780                       const gchar *description,
781                       const gchar *language,
782                       const gchar *license,
783                       const gchar *author,
784                       const gchar *icon,
785                       const gchar *layout)
786 {
787     return ibus_engine_desc_new_varargs ("name", name,
788                                          "longname", longname,
789                                          "description", description,
790                                          "language", language,
791                                          "license", license,
792                                          "author", author,
793                                          "icon", icon,
794                                          "layout", layout,
795                                          NULL);
796 }
797 
798 IBusEngineDesc *
ibus_engine_desc_new_varargs(const gchar * first_property_name,...)799 ibus_engine_desc_new_varargs (const gchar *first_property_name, ...)
800 {
801     va_list var_args;
802     IBusEngineDesc *desc;
803 
804     g_assert (first_property_name);
805 
806     va_start (var_args, first_property_name);
807     desc = (IBusEngineDesc *) g_object_new_valist (IBUS_TYPE_ENGINE_DESC,
808                                                    first_property_name,
809                                                    var_args);
810     va_end (var_args);
811 
812     /* name is required. Other properties are set in class_init by default. */
813     g_assert (desc->priv->name);
814     g_assert (desc->priv->longname);
815     g_assert (desc->priv->description);
816     g_assert (desc->priv->language);
817     g_assert (desc->priv->license);
818     g_assert (desc->priv->author);
819     g_assert (desc->priv->icon);
820     g_assert (desc->priv->layout);
821     g_assert (desc->priv->layout_variant);
822     g_assert (desc->priv->layout_option);
823     g_assert (desc->priv->hotkeys);
824     g_assert (desc->priv->symbol);
825     g_assert (desc->priv->setup);
826     g_assert (desc->priv->version);
827     g_assert (desc->priv->textdomain);
828     g_assert (desc->priv->icon_prop_key);
829 
830     return desc;
831 }
832 
833 IBusEngineDesc *
ibus_engine_desc_new_from_xml_node(XMLNode * node)834 ibus_engine_desc_new_from_xml_node (XMLNode      *node)
835 {
836     g_assert (node);
837 
838     IBusEngineDesc *desc;
839 
840     if (G_UNLIKELY (g_strcmp0 (node->name, "engine") != 0)) {
841         return NULL;
842     }
843 
844     desc = (IBusEngineDesc *)g_object_new (IBUS_TYPE_ENGINE_DESC, NULL);
845 
846     if (!ibus_engine_desc_parse_xml_node (desc, node)) {
847         g_object_unref (desc);
848         desc = NULL;
849     }
850 
851     return desc;
852 }
853