1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of the utils of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:GPL-EXCEPT$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/contact-us.
16 **
17 ** GNU General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU
19 ** General Public License version 3 as published by the Free Software
20 ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
21 ** included in the packaging of this file. Please review the following
22 ** information to ensure the GNU General Public License requirements will
23 ** be met: https://www.gnu.org/licenses/gpl-3.0.html.
24 **
25 ** $QT_END_LICENSE$
26 **
27 ****************************************************************************/
28 #include <QtCore>
29 #include <QtXml>
30
31 class XKBLayout
32 {
33 public:
34 QString name;
35 QString description;
36 QStringList variants;
37 };
38
find(const QString & tagName,const QDomElement & e)39 QDomElement find(const QString &tagName, const QDomElement &e)
40 {
41 QDomNodeList children = e.childNodes();
42 for (int i = 0; i < children.size(); ++i) {
43 const QDomNode &n = children.at(i);
44 if (n.isElement()) {
45 QDomElement c = n.toElement();
46 if (c.tagName() == tagName)
47 return c;
48 }
49 }
50 return QDomElement();
51 }
52
parseVariant(const QDomElement & e)53 QString parseVariant(const QDomElement &e)
54 {
55 QDomElement configItem = find("configItem", e);
56 return find("name", configItem).text();
57 }
58
findVariants(const QDomElement & e)59 QStringList findVariants(const QDomElement &e)
60 {
61 QStringList variants;
62
63 QDomNodeList children = e.childNodes();
64 for (int i = 0; i < children.size(); ++i) {
65 const QDomNode &n = children.at(i);
66 if (n.isElement())
67 variants += parseVariant(n.toElement());
68 }
69
70 return variants;
71 }
72
parseLayout(const QDomElement & e)73 XKBLayout parseLayout(const QDomElement &e)
74 {
75 QDomElement configItem = find("configItem", e);
76
77 XKBLayout layout;
78 layout.name = find("name", configItem).text();
79 layout.description = find("description", configItem).text();
80
81 QDomElement variantList = find("variantList", e);
82 if (!variantList.isNull())
83 layout.variants = findVariants(variantList);
84
85 return layout;
86 }
87
findLayouts(const QDomElement & layoutList)88 QList<XKBLayout> findLayouts(const QDomElement &layoutList)
89 {
90 QList<XKBLayout> layouts;
91
92 QDomNodeList children = layoutList.childNodes();
93 for (int i = 0; i < children.size(); ++i) {
94 const QDomNode &n = children.at(i);
95 if (n.isElement())
96 layouts += parseLayout(n.toElement());
97 }
98
99 return layouts;
100 }
101
mapCountry(const QString & v)102 QString mapCountry(const QString &v)
103 {
104 static QMap<QString, QString> map;
105 static bool initialized = false;
106 if (!initialized) {
107 map["U.S. English"] = "UnitedStates";
108 map["PC-98xx Series"] = "Japan";
109 map["Bosnia and Herzegovina"] = "BosniaAndHerzegowina";
110 map["Czechia"] = "CzechRepublic";
111 map["Faroe Islands"] = "FaroeIslands";
112 map["Laos"] = "Laos";
113 map["Latin American"] = "Mexico";
114 map["Russia"] = "Russia";
115 map["Syria"] = "Syria";
116 map["Sri Lanka"] = "SriLanka";
117 map["United Kingdom"] = "UnitedKingdom";
118 map["Vietnam"] = "Vietnam";
119 map["Macedonian"] = "Macedonia";
120 map["Serbian"] = "Serbia";
121 map["Turkish "] = "Turkey";
122 map["Maori"] = "NewZealand";
123 map["Arabic"] = "UnitedArabEmirates";
124 initialized = true;
125 }
126 return map.value(v, v);
127 }
128
mapLanguage(const QString & v)129 QString mapLanguage(const QString &v)
130 {
131 static QMap<QString, QString> map;
132 static bool initialized = false;
133 if (!initialized) {
134 map["us"] = "English";
135 map["us:intl"] = "English";
136 map["us:alt-intl"] = "English";
137 map["us:dvorak"] = "English";
138 map["us:rus"] = "Russian";
139 map["ara"] = "Arabic";
140 map["ara:azerty"] = "Arabic";
141 map["ara:azerty_digits"] = "Arabic";
142 map["ara:digits"] = "Arabic";
143 map["ara:qwerty"] = "Arabic";
144 map["ara:qwerty_digits"] = "Arabic";
145 map["al"] = "Albanian";
146 map["am"] = "Armenian";
147 map["am:phonetic"] = "Armenian";
148 map["az"] = "Azerbaijani";
149 map["az:cyrillic"] = "Azerbaijani";
150 map["by"] = "Belarusian";
151 map["by:winkeys"] = "Belarusian";
152 map["be"] = "Dutch";
153 map["be:iso-alternate"] = "Dutch";
154 map["be:nodeadkeys"] = "Dutch";
155 map["be:sundeadkeys"] = "Dutch";
156 map["bd"] = "Bengali";
157 map["bd:probhat"] = "Bengali";
158 map["in"] = "Hindi";
159 map["in:ben"] = "Bengali";
160 map["in:ben_probhat"] = "Bengali";
161 map["in:guj"] = "Gujarati";
162 map["in:guru"] = "Punjabi";
163 map["in:kan"] = "Kannada";
164 map["in:mal"] = "Malayalam";
165 map["in:ori"] = "Oriya";
166 map["in:tam_unicode"] = "Tamil";
167 map["in:tam_TAB"] = "Tamil";
168 map["in:tam_TSCII"] = "Tamil";
169 map["in:tam"] = "Tamil";
170 map["in:tel"] = "Telugu";
171 map["in:urd"] = "Urdu";
172 map["ba"] = "Bosnian";
173 map["br"] = "Portuguese";
174 map["br:nodeadkeys"] = "Portuguese";
175 map["bg"] = "Bulgarian";
176 map["bg:phonetic"] = "Bulgarian";
177 map["mm"] = "Burmese";
178 map["ca"] = "English";
179 map["ca:fr-dvorak"] = "French";
180 map["ca:fr-legacy"] = "French";
181 map["ca:multi"] = "English";
182 map["ca:multi-2gr"] = "English";
183 map["ca:ike"] = "Inuktitut";
184 map["hr"] = "Croatian";
185 map["hr:us"] = "Croatian";
186 map["cz"] = "Czech";
187 map["cz:bksl"] = "Czech";
188 map["cz:qwerty"] = "Czech";
189 map["cz:qwerty_bksl"] = "Czech";
190 map["dk"] = "Danish";
191 map["dk:nodeadkeys"] = "Danish";
192 map["nl"] = "Dutch";
193 map["bt"] = "Bhutani";
194 map["ee"] = "Estonian";
195 map["ee:nodeadkeys"] = "Estonian";
196 map["ir"] = "Persian";
197 map["fo"] = "Faroese";
198 map["fo:nodeadkeys"] = "Faroese";
199 map["fi"] = "Finnish";
200 map["fi:nodeadkeys"] = "Finnish";
201 map["fi:smi"] = "Finnish";
202 map["fr"] = "French";
203 map["fr:nodeadkeys"] = "French";
204 map["fr:sundeadkeys"] = "French";
205 map["fr:latin9"] = "French";
206 map["fr:latin9_nodeadkeys"] = "French";
207 map["fr:latin9_sundeadkeys"] = "French";
208 map["fr:dvorak"] = "French";
209 map["ge"] = "Georgian";
210 map["ge:ru"] = "Russian";
211 map["de"] = "German";
212 map["de:deadacute"] = "German";
213 map["de:deadgraveacute"] = "German";
214 map["de:nodeadkeys"] = "German";
215 map["de:ro"] = "Romanian";
216 map["de:ro_nodeadkeys"] = "Romanian";
217 map["de:dvorak"] = "German";
218 map["gr"] = "Greek";
219 map["gr:extended"] = "Greek";
220 map["gr:nodeadkeys"] = "Greek";
221 map["gr:polytonic"] = "Greek";
222 map["hu"] = "Hungarian";
223 map["hu:standard"] = "Hungarian";
224 map["hu:nodeadkeys"] = "Hungarian";
225 map["hu:qwerty"] = "Hungarian";
226 map["hu:101_qwertz_comma_dead"] = "Hungarian";
227 map["hu:101_qwertz_comma_nodead"] = "Hungarian";
228 map["hu:101_qwertz_dot_dead"] = "Hungarian";
229 map["hu:101_qwertz_dot_nodead"] = "Hungarian";
230 map["hu:101_qwerty_comma_dead"] = "Hungarian";
231 map["hu:101_qwerty_comma_nodead"] = "Hungarian";
232 map["hu:101_qwerty_dot_dead"] = "Hungarian";
233 map["hu:101_qwerty_dot_nodead"] = "Hungarian";
234 map["hu:102_qwertz_comma_dead"] = "Hungarian";
235 map["hu:102_qwertz_comma_nodead"] = "Hungarian";
236 map["hu:102_qwertz_dot_dead"] = "Hungarian";
237 map["hu:102_qwertz_dot_nodead"] = "Hungarian";
238 map["hu:102_qwerty_comma_dead"] = "Hungarian";
239 map["hu:102_qwerty_comma_nodead"] = "Hungarian";
240 map["hu:102_qwerty_dot_dead"] = "Hungarian";
241 map["hu:102_qwerty_dot_nodead"] = "Hungarian";
242 map["is"] = "Icelandic";
243 map["is:Sundeadkeys"] = "Icelandic";
244 map["is:nodeadkeys"] = "Icelandic";
245 map["il"] = "Hebrew";
246 map["il:lyx"] = "Hebrew";
247 map["il:si1452"] = "Hebrew";
248 map["il:phonetic"] = "Hebrew";
249 map["it"] = "Italian";
250 map["it:nodeadkeys"] = "Italian";
251 map["jp"] = "Japanese";
252 map["kg"] = "Kirghiz";
253 map["la"] = "Laothian";
254 map["latam"] = "Spanish";
255 map["latam:nodeadkeys"] = "Spanish";
256 map["latam:sundeadkeys"] = "Spanish";
257 map["lt"] = "Lithuanian";
258 map["lt:std"] = "Lithuanian";
259 map["lt:us"] = "Lithuanian";
260 map["lv"] = "Latvian";
261 map["lv:apostrophe"] = "Latvian";
262 map["lv:tilde"] = "Latvian";
263 map["lv:fkey"] = "Latvian";
264 map["mao"] = "Maori";
265 map["mkd"] = "Macedonian";
266 map["mkd:nodeadkeys"] = "Macedonian";
267 map["mt"] = "Maltese";
268 map["mt:us"] = "Maltese";
269 map["mn"] = "Mongolian";
270 map["no"] = "Norwegian";
271 map["no:nodeadkeys"] = "Norwegian";
272 map["no:dvorak"] = "Norwegian";
273 map["no:smi"] = "Norwegian";
274 map["no:smi_nodeadkeys"] = "Norwegian";
275 map["pl"] = "Polish";
276 map["pl:qwertz"] = "Polish";
277 map["pl:dvorak"] = "Polish";
278 map["pl:dvorak_quotes"] = "Polish";
279 map["pl:dvorak_altquotes"] = "Polish";
280 map["pt"] = "Portuguese";
281 map["pt:nodeadkeys"] = "Portuguese";
282 map["pt:sundeadkeys"] = "Portuguese";
283 map["ro"] = "Romanian";
284 map["ro:us"] = "English";
285 map["ro:de"] = "German";
286 map["ru"] = "Russian";
287 map["ru:phonetic"] = "Russian";
288 map["ru:typewriter"] = "Russian";
289 map["ru:winkeys"] = "Russian";
290 map["srp"] = "Serbian";
291 map["srp:yz"] = "Serbian";
292 map["srp:latin"] = "Serbian";
293 map["srp:latinunicode"] = "Serbian";
294 map["srp:latinyz"] = "Serbian";
295 map["srp:latinunicodeyz"] = "Serbian";
296 map["srp:alternatequotes"] = "Serbian";
297 map["srp:latinalternatequotes"] = "Serbian";
298 map["si"] = "Slovenian";
299 map["sk"] = "Slovak";
300 map["sk:bksl"] = "Slovak";
301 map["sk:qwerty"] = "Slovak";
302 map["sk:qwerty_bksl"] = "Slovak";
303 map["es"] = "Spanish";
304 map["es:nodeadkeys"] = "Spanish";
305 map["es:sundeadkeys"] = "Spanish";
306 map["es:dvorak"] = "Spanish";
307 map["se"] = "Swedish";
308 map["se:nodeadkeys"] = "Swedish";
309 map["se:dvorak"] = "Swedish";
310 map["se:rus"] = "Russian";
311 map["se:rus_nodeadkeys"] = "Russian";
312 map["se:smi"] = "Swedish";
313 map["ch"] = "German";
314 map["ch:de_nodeadkeys"] = "German";
315 map["ch:de_sundeadkeys"] = "German";
316 map["ch:fr"] = "French";
317 map["ch:fr_nodeadkeys"] = "French";
318 map["ch:fr_sundeadkeys"] = "French";
319 map["sy"] = "Arabic";
320 map["sy:syc"] = "Arabic";
321 map["sy:syc_phonetic"] = "Arabic";
322 map["tj"] = "Tajik";
323 map["lk"] = "Sinhala";
324 map["lk:tam_unicode"] = "Tamil";
325 map["lk:tam_TAB"] = "Tamil";
326 map["lk:tam_TSCII"] = "Tamil";
327 map["lk:sin_phonetic"] = "Sinhala";
328 map["th"] = "Thai";
329 map["th:tis"] = "Thai";
330 map["th:pat"] = "Thai";
331 map["tr"] = "Turkish";
332 map["tr:f"] = "Turkish";
333 map["tr:alt"] = "Turkish";
334 map["ua"] = "Ukrainian";
335 map["ua:phonetic"] = "Ukrainian";
336 map["ua:typewriter"] = "Ukrainian";
337 map["ua:winkeys"] = "Ukrainian";
338 map["ua:rstu"] = "Ukrainian";
339 map["ua:rstu_ru"] = "Ukrainian";
340 map["gb"] = "English";
341 map["gb:intl"] = "English";
342 map["gb:dvorak"] = "English";
343 map["uz"] = "Uzbek";
344 map["vn"] = "Vietnamese";
345 map["nec_vndr/jp"] = "Japanese";
346 map["ie"] = "Irish";
347 map["ie:CloGaelach"] = "Gaelic";
348 map["ie:UnicodeExpert"] = "Irish";
349 map["ie:ogam"] = "Gaelic";
350 map["ie:ogam_is434"] = "Gaelic";
351 map["pk"] = "Urdu";
352 initialized = true;
353 }
354 return map.value(v, v);
355 }
356
mapDirection(const QString & v)357 QString mapDirection(const QString &v)
358 {
359 static QMap<QString, QString> map;
360 static bool initialized = false;
361 if (!initialized) {
362 // 1. xkbdata-X11R7.0-1.0.1/symbols% grep -l '\([Hh]ebrew\|[Aa]rabic\)' **/*
363 map["Arabic"] = "Qt::RightToLeft";
364 map["Persian"] = "Qt::RightToLeft";
365 map["Urdu"] = "Qt::RightToLeft";
366 initialized = true;
367 }
368 return map.value(v, "Qt::LeftToRight");
369 }
370
main(int argc,char ** argv)371 int main(int argc, char **argv)
372 {
373 if (argc != 2) {
374 fprintf(stderr, "usage: %s <xml input file>\n", argv[0]);
375 return 1;
376 }
377
378 QCoreApplication app(argc, argv);
379
380 QFile file;
381 file.setFileName(argv[1]);
382 if (!file.open(QIODevice::ReadOnly)) {
383 fprintf(stderr, "cannot open %s: %s\n", qPrintable(file.fileName()), qPrintable(file.errorString()));
384 return 1;
385 }
386
387 QDomDocument dom;
388 dom.setContent(&file);
389
390 if (dom.documentElement().tagName() != QLatin1String("xkbConfigRegistry")) {
391 fprintf(stderr, "cannot parse %s, this is not an XKB config file\n", qPrintable(file.fileName()));
392 return 1;
393 }
394
395 QDomElement layoutList = find("layoutList", dom.documentElement());
396 if (layoutList.isNull()) {
397 fprintf(stderr, "cannot parse %s, this is not an XKB config file\n", qPrintable(file.fileName()));
398 return 1;
399 }
400
401 QList<XKBLayout> layouts = findLayouts(layoutList);
402
403 // copyright and stuff
404 printf("/****************************************************************************\n"
405 "**\n"
406 "** Copyright (C) 2016 The Qt Company Ltd.\n"
407 "** Contact: https://www.qt.io/licensing/\n"
408 "**\n"
409 "** This file is part of the QtGui module of the Qt Toolkit.\n"
410 "**\n"
411 "** $QT_BEGIN_LICENSE:LGPL$\n"
412 "** Commercial License Usage\n"
413 "** Licensees holding valid commercial Qt licenses may use this file in\n"
414 "** accordance with the commercial license agreement provided with the\n"
415 "** Software or, alternatively, in accordance with the terms contained in\n"
416 "** a written agreement between you and The Qt Company. For licensing terms\n"
417 "** and conditions see https://www.qt.io/terms-conditions. For further\n"
418 "** information use the contact form at https://www.qt.io/contact-us.\n"
419 "**\n"
420 "** GNU Lesser General Public License Usage\n"
421 "** Alternatively, this file may be used under the terms of the GNU Lesser\n"
422 "** General Public License version 3 as published by the Free Software\n"
423 "** Foundation and appearing in the file LICENSE.LGPL3 included in the\n"
424 "** packaging of this file. Please review the following information to\n"
425 "** ensure the GNU Lesser General Public License version 3 requirements\n"
426 "** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.\n"
427 "**\n"
428 "** GNU General Public License Usage\n"
429 "** Alternatively, this file may be used under the terms of the GNU\n"
430 "** General Public License version 2.0 or (at your option) the GNU General\n"
431 "** Public license version 3 or any later version approved by the KDE Free\n"
432 "** Qt Foundation. The licenses are as published by the Free Software\n"
433 "** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3\n"
434 "** included in the packaging of this file. Please review the following\n"
435 "** information to ensure the GNU General Public License requirements will\n"
436 "** be met: https://www.gnu.org/licenses/gpl-2.0.html and\n"
437 "** https://www.gnu.org/licenses/gpl-3.0.html.\n"
438 "**\n"
439 "** $QT_END_LICENSE$\n"
440 "**\n"
441 "****************************************************************************/\n"
442 "\n"
443 "// This file is auto-generated, do not edit!\n"
444 "// (Generated using util/xkbdatagen)\n"
445 "\n");
446
447 // data structure
448 printf("static struct {\n"
449 " const char *layout;\n"
450 " const char *variant; // 0 means any variant\n"
451 " Qt::LayoutDirection direction;\n"
452 " QLocale::Language language;\n"
453 " QLocale::Country country;\n"
454 "} xkbLayoutData[] = {\n");
455
456 // contents
457 foreach (const XKBLayout &l, layouts) {
458 const QString country = mapCountry(l.description);
459 QString lang = mapLanguage(l.name);
460 if (lang.isEmpty())
461 lang = "C";
462 printf(" // name = %s, description = %s\n"
463 " { \"%s\", \"\", %s, QLocale::%s, QLocale::%s },\n",
464 l.name.toLatin1().constData(),
465 l.description.toLatin1().constData(),
466 l.name.toLatin1().constData(),
467 mapDirection(lang).toLatin1().constData(),
468 lang.toLatin1().constData(),
469 country.toLatin1().constData());
470 foreach (const QString &v, l.variants) {
471 QString vlang = mapLanguage(l.name + ":" + v);
472 if (vlang.isEmpty())
473 vlang = "C";
474 printf(" // name = %s:%s, description = %s\n"
475 " { \"%s\", \"%s\", %s, QLocale::%s, QLocale::%s },\n",
476 l.name.toLatin1().constData(),
477 v.toLatin1().constData(),
478 l.description.toLatin1().constData(),
479 l.name.toLatin1().constData(),
480 v.toLatin1().constData(),
481 mapDirection(vlang).toLatin1().constData(),
482 vlang.toLatin1().constData(),
483 country.toLatin1().constData());
484 }
485 }
486
487 // wrapping up
488 printf(" { 0, 0, Qt::LeftToRight, QLocale::C, QLocale::AnyCountry }\n"
489 "};\n");
490
491 return 0;
492 }
493