1# -*- coding: utf-8 -*-
2# Copyright 2010-2018, Google Inc.
3# All rights reserved.
4#
5# Redistribution and use in source and binary forms, with or without
6# modification, are permitted provided that the following conditions are
7# met:
8#
9#     * Redistributions of source code must retain the above copyright
10# notice, this list of conditions and the following disclaimer.
11#     * Redistributions in binary form must reproduce the above
12# copyright notice, this list of conditions and the following disclaimer
13# in the documentation and/or other materials provided with the
14# distribution.
15#     * Neither the name of Google Inc. nor the names of its
16# contributors may be used to endorse or promote products derived from
17# this software without specific prior written permission.
18#
19# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31"""Pre-generate XML data of ibus-mozc engines.
32
33We don't support --xml command line option in the ibus-engines-mozc command
34since it could make start-up time of ibus-daemon slow when XML cache of the
35daemon in ~/.cache/ibus/bus/ is not ready or is expired.
36"""
37
38__author__ = "yusukes"
39
40import optparse
41import os
42import subprocess
43import sys
44
45# Information to generate <component> part of mozc.xml. %s will be replaced with
46# a product name, 'Mozc' or 'Google Japanese Input'.
47IBUS_COMPONENT_PROPS = {
48    'name': 'com.google.IBus.Mozc',
49    'description': '%(product_name)s Component',
50    'exec': '%(ibus_mozc_path)s --ibus',
51    # TODO(mazda): Generate the version number.
52    'version': '0.0.0.0',
53    'author': 'Google Inc.',
54    'license': 'New BSD',
55    'homepage': 'https://github.com/google/mozc',
56    'textdomain': 'ibus-mozc',
57}
58
59# A dictionary from --branding to a product name which is embedded into the
60# properties above.
61PRODUCT_NAMES = {
62    'Mozc': 'Mozc',
63    'GoogleJapaneseInput': 'Google Japanese Input',
64}
65
66CPP_HEADER = """// Copyright 2010 Google Inc. All Rights Reserved.
67
68#ifndef %s
69#define %s
70namespace {"""
71
72CPP_FOOTER = """}  // namespace
73#endif  // %s"""
74
75
76def OutputXmlElement(param_dict, element_name, value):
77  print('  <%s>%s</%s>' % (element_name, (value % param_dict), element_name))
78
79
80def OutputXml(param_dict, component, engine_common, engines, setup_arg):
81  """Outputs a XML data for ibus-daemon.
82
83  Args:
84    param_dict: A dictionary to embed options into output string.
85        For example, {'product_name': 'Mozc'}.
86    component: A dictionary from a property name to a property value of the
87        ibus-mozc component. For example, {'name': 'com.google.IBus.Mozc'}.
88    engine_common: A dictionary from a property name to a property value that
89        are commonly used in all engines. For example, {'language': 'ja'}.
90    engines: A dictionary from a property name to a list of property values of
91        engines. For example, {'name': ['mozc-jp', 'mozc', 'mozc-dv']}.
92  """
93  print('<?xml version="1.0" encoding="utf-8"?>')
94  print('<component>')
95  for key in sorted(component):
96    OutputXmlElement(param_dict, key, component[key])
97  print('<engines>')
98  for i in range(len(engines['name'])):
99    print('<engine>')
100    for key in sorted(engine_common):
101      OutputXmlElement(param_dict, key, engine_common[key])
102    if setup_arg:
103      OutputXmlElement(param_dict, 'setup', ' '.join(setup_arg))
104    for key in sorted(engines):
105      OutputXmlElement(param_dict, key, engines[key][i])
106    print('</engine>')
107  print('</engines>')
108  print('</component>')
109
110
111def OutputCppVariable(param_dict, prefix, variable_name, value):
112  print('const char k%s%s[] = "%s";' % (prefix, variable_name.capitalize(),
113                                        (value % param_dict)))
114
115
116def OutputCpp(param_dict, component, engine_common, engines):
117  """Outputs a C++ header file for mozc/unix/ibus/main.cc.
118
119  Args:
120    param_dict: see OutputXml.
121    component: ditto.
122    engine_common: ditto.
123    engines: ditto.
124  """
125  guard_name = 'MOZC_UNIX_IBUS_MAIN_H_'
126  print(CPP_HEADER % (guard_name, guard_name))
127  for key in sorted(component):
128    OutputCppVariable(param_dict, 'Component', key, component[key])
129  for key in sorted(engine_common):
130    OutputCppVariable(param_dict, 'Engine', key, engine_common[key])
131  for key in sorted(engines):
132    print('const char* kEngine%sArray[] = {' % key.capitalize())
133    for i in range(len(engines[key])):
134      print('"%s",' % (engines[key][i] % param_dict))
135    print('};')
136  print('const size_t kEngineArrayLen = %s;' % len(engines['name']))
137  print(CPP_FOOTER % guard_name)
138
139
140def CheckIBusVersion(options, minimum_version):
141  """Tests if ibus version is equal to or greater than the given value."""
142  command_line = ['pkg-config', '--exists', 'ibus-1.0 >= %s' % minimum_version]
143  return_code = subprocess.call(command_line)
144  if return_code == 0:
145    return True
146  else:
147    return False
148
149
150def main():
151  """The main function."""
152  parser = optparse.OptionParser(usage='Usage: %prog [options]')
153  parser.add_option('--output_cpp', action='store_true',
154                    dest='output_cpp', default=False,
155                    help='If specified, output a C++ header. Otherwise, output '
156                    'XML.')
157  parser.add_option('--branding', dest='branding', default=None,
158                    help='GoogleJapaneseInput for the official build. '
159                    'Otherwise, Mozc.')
160  parser.add_option('--ibus_mozc_path', dest='ibus_mozc_path', default='',
161                    help='The absolute path of ibus_mozc executable.')
162  parser.add_option('--ibus_mozc_icon_path', dest='ibus_mozc_icon_path',
163                    default='', help='The absolute path of ibus_mozc icon.')
164  parser.add_option('--server_dir', dest='server_dir', default='',
165                    help='The absolute directory path to be installed the '
166                    'server executable.')
167  parser.add_option('--renderer_dir', dest='renderer_dir', default='',
168                    help='The absolute directory path to be installed the '
169                    'renderer executable.')
170  parser.add_option('--tool_dir', dest='tool_dir', default='',
171                    help='The absolute directory path to be installed the '
172                    'tool executable.')
173  (options, unused_args) = parser.parse_args()
174
175  setup_arg = []
176  setup_arg.append(os.path.join(options.tool_dir, 'mozc_tool'))
177  setup_arg.append('--mode=config_dialog')
178
179  param_dict = {
180      'product_name': PRODUCT_NAMES[options.branding],
181      'ibus_mozc_path': options.ibus_mozc_path,
182      'ibus_mozc_icon_path': options.ibus_mozc_icon_path,
183  }
184
185  engine_common_props = {
186      'description': '%(product_name)s (Japanese Input Method)',
187      'language': 'jpn',
188      'icon': '%(ibus_mozc_icon_path)s',
189      'rank': '80',
190  }
191
192  # DO NOT change the engine name 'mozc-jp'. The names is referenced by
193  # unix/ibus/mozc_engine.cc.
194  engines_props = {
195      'name': ['mozc-jp'],
196      'longname': ['%(product_name)s'],
197  }
198
199  # IBus 1.5.11 and greater supports 'icon_prop_key'.
200  # See ibus/ibus@23c45b970b195008a54884a1a9d810e7f8b22c5c
201  if CheckIBusVersion(options, '1.5.11'):
202    # Make sure that the property key 'InputMode' matches to the property name
203    # specified to |ibus_property_new| in unix/ibus/property_handler.cc
204    engine_common_props['icon_prop_key'] = 'InputMode'
205
206  if CheckIBusVersion(options, '1.5.0'):
207    engine_common_props['symbol'] = '&#x3042;'
208    engines_props['layout'] = ['default']
209  else:
210    engines_props['layout'] = ['jp']
211
212  if options.output_cpp:
213    OutputCpp(param_dict, IBUS_COMPONENT_PROPS, engine_common_props,
214              engines_props)
215  else:
216    OutputXml(param_dict, IBUS_COMPONENT_PROPS, engine_common_props,
217              engines_props, setup_arg)
218  return 0
219
220if __name__ == '__main__':
221  sys.exit(main())
222