mirror of
https://github.com/keymanapp/keyman.git
synced 2026-08-23 00:37:41 +00:00
487 lines
16 KiB
C
487 lines
16 KiB
C
/* vim:set et sts=4: */
|
|
|
|
/*
|
|
* Keyman Input Method for IBUS (The Input Bus)
|
|
*
|
|
* Copyright (C) 2018 SIL Global
|
|
*
|
|
* kmpdetails is dual licensed under the MIT or GPL licenses as described below.
|
|
*
|
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
*
|
|
* MIT license
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
* of this software and associated documentation files (the "Software"), to deal
|
|
* in the Software without restriction, including without limitation the rights
|
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
* copies of the Software, and to permit persons to whom the Software is
|
|
* furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be included in all
|
|
* copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
* SOFTWARE.
|
|
*
|
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
* OR
|
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2 of the License, or (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
|
*
|
|
*/
|
|
|
|
|
|
|
|
// APIs to get info that ibus-keyman will want from
|
|
// the kmp.json from each kmp
|
|
//
|
|
// get list of keyboards from this
|
|
// associated languages
|
|
|
|
#include <locale.h>
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <glib.h>
|
|
#include <json-glib/json-glib.h>
|
|
#include "kmpdetails.h"
|
|
|
|
|
|
void get_detail_description_from_object(JsonObject *object, const gchar *member_name, gchar **description, gchar **url)
|
|
{
|
|
const gchar *value;
|
|
JsonNode *member_node;
|
|
JsonObject *member_object;
|
|
|
|
member_node = json_object_get_member(object, member_name);
|
|
if (member_node != NULL && JSON_NODE_HOLDS_VALUE (member_node)) {
|
|
value = json_object_get_string_member (object, member_name);
|
|
*description = g_strdup(value);
|
|
if (url != NULL) {
|
|
*url = NULL;
|
|
}
|
|
}
|
|
else if (member_node != NULL && JSON_NODE_HOLDS_OBJECT (member_node)) {
|
|
member_object = json_node_get_object(member_node);
|
|
|
|
member_node = json_object_get_member(member_object, "description");
|
|
if (member_node != NULL && JSON_NODE_HOLDS_VALUE (member_node)) {
|
|
value = json_object_get_string_member (member_object, "description");
|
|
*description = g_strdup(value);
|
|
}
|
|
else {
|
|
g_warning("could not find description in %s\n", member_name);
|
|
*description = NULL;
|
|
if (url != NULL) {
|
|
*url = NULL;
|
|
}
|
|
}
|
|
if (url != NULL) {
|
|
member_node = json_object_get_member(member_object, "url");
|
|
if (member_node != NULL && JSON_NODE_HOLDS_VALUE (member_node)) {
|
|
value = json_object_get_string_member (member_object, "url");
|
|
*url = g_strdup(value);
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
g_message("could not find %s in json\n", member_name);
|
|
*description = NULL;
|
|
if (url != NULL) {
|
|
*url = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void get_detail_from_object(JsonObject *object, const gchar *member_name, gchar **detail)
|
|
{
|
|
const gchar *value;
|
|
JsonNode *member_node;
|
|
|
|
member_node = json_object_get_member(object, member_name);
|
|
if (member_node != NULL && JSON_NODE_HOLDS_VALUE (member_node)) {
|
|
value = json_object_get_string_member (object, member_name);
|
|
*detail = g_strdup(value);
|
|
}
|
|
else {
|
|
*detail = NULL;
|
|
}
|
|
}
|
|
|
|
void kmp_languages_foreach (JsonArray *array,
|
|
guint index_,
|
|
JsonNode *element_node,
|
|
gpointer user_data)
|
|
{
|
|
JsonObject *lang_object;
|
|
kmp_keyboard *keyboard;
|
|
kmp_language *language;
|
|
|
|
if (JSON_NODE_HOLDS_OBJECT(element_node)){
|
|
lang_object = json_node_get_object(element_node);
|
|
keyboard = (kmp_keyboard *) user_data;
|
|
language = g_new0(kmp_language, 1);
|
|
|
|
get_detail_from_object(lang_object, "name",
|
|
&(language->name));
|
|
get_detail_from_object(lang_object, "id",
|
|
&(language->id));
|
|
keyboard->languages = g_list_append(keyboard->languages, language);
|
|
}
|
|
}
|
|
|
|
|
|
void kmp_keyboards_foreach (JsonArray *array,
|
|
guint index_,
|
|
JsonNode *element_node,
|
|
gpointer user_data)
|
|
{
|
|
JsonObject *keyboard_object;
|
|
JsonNode *languages_node;
|
|
GList *l;
|
|
g_autofree gchar *l_kmx_file = NULL;
|
|
g_autofree gchar *l_kvk_file = NULL;
|
|
kmp_fileinfo *fileinfo;
|
|
kmp_details *details;
|
|
kmp_keyboard *keyboard;
|
|
|
|
if (JSON_NODE_HOLDS_OBJECT(element_node)){
|
|
keyboard_object = json_node_get_object(element_node);
|
|
details = (kmp_details *) user_data;
|
|
keyboard = g_new0(kmp_keyboard, 1);
|
|
|
|
get_detail_from_object(keyboard_object, "name",
|
|
&(keyboard->name));
|
|
get_detail_from_object(keyboard_object, "id",
|
|
&(keyboard->id));
|
|
get_detail_from_object(keyboard_object, "version",
|
|
&(keyboard->version));
|
|
// languages is another array
|
|
languages_node = json_object_get_member(keyboard_object, "languages");
|
|
if (languages_node != NULL && JSON_NODE_HOLDS_ARRAY (languages_node)) {
|
|
array = json_node_get_array (languages_node);
|
|
if (array)
|
|
{
|
|
json_array_foreach_element (array,
|
|
kmp_languages_foreach,
|
|
keyboard);
|
|
}
|
|
}
|
|
|
|
if (keyboard->id)
|
|
{
|
|
l_kmx_file = g_strdup_printf("%s.kmx", keyboard->id);
|
|
l_kvk_file = g_strdup_printf("%s.kvk", keyboard->id);
|
|
if (details->files != NULL) {
|
|
for (l = details->files; l != NULL; l = l->next) {
|
|
fileinfo = (kmp_fileinfo *) l->data;
|
|
if (g_strcmp0(fileinfo->name, l_kmx_file)) {
|
|
keyboard->kmx_file = g_strdup(l_kmx_file);
|
|
}
|
|
else if (g_strcmp0(fileinfo->name, l_kvk_file)) {
|
|
keyboard->kvk_file = g_strdup(l_kvk_file);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
details->keyboards = g_list_append(details->keyboards, keyboard);
|
|
}
|
|
}
|
|
|
|
void kmp_files_foreach (JsonArray *array,
|
|
guint index_,
|
|
JsonNode *element_node,
|
|
gpointer user_data)
|
|
{
|
|
JsonObject *file_object;
|
|
kmp_details *details;
|
|
kmp_fileinfo *fileinfo;
|
|
|
|
if (JSON_NODE_HOLDS_OBJECT(element_node)){
|
|
file_object = json_node_get_object(element_node);
|
|
details = (kmp_details *) user_data;
|
|
fileinfo = g_new0(kmp_fileinfo, 1);
|
|
|
|
get_detail_from_object(file_object, "name",
|
|
&(fileinfo->name));
|
|
get_detail_from_object(file_object, "description",
|
|
&(fileinfo->description));
|
|
details->files = g_list_append(details->files, fileinfo);
|
|
}
|
|
}
|
|
|
|
// Get kmp_details from `<kbd>.json`
|
|
kmp_json_status get_keyboard_details(const char *kmp_dir, const char *id, keyboard_details *keyboard)
|
|
{
|
|
g_autoptr(JsonParser) parser;
|
|
JsonObject *object;
|
|
JsonNode *root;
|
|
g_autofree gchar *json_file;
|
|
g_autoptr(GError) error = NULL;
|
|
|
|
parser = json_parser_new ();
|
|
json_file = g_strjoin("/", kmp_dir, id, NULL);
|
|
|
|
if (!g_file_test(json_file, G_FILE_TEST_EXISTS)) {
|
|
return JSON_FILE_NOT_EXISTS;
|
|
}
|
|
|
|
json_parser_load_from_file (parser,
|
|
json_file,
|
|
&error);
|
|
if (error)
|
|
{
|
|
g_warning ("Unable to parse `%s': %s\n", json_file, error->message);
|
|
return JSON_PARSE_ERROR;
|
|
}
|
|
|
|
root = json_parser_get_root (parser);
|
|
|
|
if (JSON_NODE_HOLDS_OBJECT(root)){
|
|
object = json_node_get_object(root);
|
|
get_detail_from_object(object, "id",
|
|
&(keyboard->id));
|
|
get_detail_from_object(object, "description",
|
|
&(keyboard->description));
|
|
get_detail_from_object(object, "license",
|
|
&(keyboard->license));
|
|
}
|
|
return JSON_OK;
|
|
}
|
|
|
|
// Get kmp_details from `kmp.json` file
|
|
kmp_json_status get_kmp_details(const char *kmp_dir, kmp_details *details)
|
|
{
|
|
g_autoptr(JsonParser) parser;
|
|
JsonNode *root;
|
|
JsonObject *root_object, *object;
|
|
JsonArray *array;
|
|
JsonNode *kmp_system, *kmp_info, *kmp_options, *kmp_files, *kmp_keyboards;
|
|
g_autofree gchar *kmp_json;
|
|
g_autoptr(GError) error = NULL;
|
|
|
|
parser = json_parser_new ();
|
|
kmp_json = g_strdup_printf("%s/kmp.json", kmp_dir);
|
|
|
|
if (!g_file_test(kmp_json, G_FILE_TEST_EXISTS)) {
|
|
return JSON_FILE_NOT_EXISTS;
|
|
}
|
|
|
|
json_parser_load_from_file (parser,
|
|
kmp_json,
|
|
&error);
|
|
if (error)
|
|
{
|
|
g_warning ("Unable to parse `%s': %s\n", kmp_json, error->message);
|
|
return JSON_PARSE_ERROR;
|
|
}
|
|
|
|
root = json_parser_get_root (parser);
|
|
|
|
if (JSON_NODE_HOLDS_OBJECT(root)){
|
|
root_object = json_node_get_object(root);
|
|
kmp_system = json_object_get_member(root_object, "system");
|
|
if (kmp_system)
|
|
{
|
|
object = json_node_get_object(kmp_system);
|
|
get_detail_from_object(object, "keymanDeveloperVersion",
|
|
&(details->system.keymanDeveloperVersion));
|
|
get_detail_from_object(object, "fileVersion",
|
|
&(details->system.fileVersion));
|
|
}
|
|
|
|
kmp_info = json_object_get_member(root_object, "info");
|
|
if (kmp_info)
|
|
{
|
|
object = json_node_get_object(kmp_info);
|
|
get_detail_description_from_object(object, "name",
|
|
&(details->info.name), NULL);
|
|
get_detail_description_from_object(object, "version",
|
|
&(details->info.version), NULL);
|
|
get_detail_description_from_object(object, "copyright",
|
|
&(details->info.copyright), NULL);
|
|
get_detail_description_from_object(object, "author",
|
|
&(details->info.author_desc), &(details->info.author_url));
|
|
get_detail_description_from_object(object, "website",
|
|
&(details->info.website_desc), &(details->info.website_url));
|
|
}
|
|
|
|
kmp_options = json_object_get_member(root_object, "options");
|
|
if (kmp_options)
|
|
{
|
|
object = json_node_get_object(kmp_options);
|
|
get_detail_from_object(object, "readmeFile",
|
|
&(details->options.readmeFile));
|
|
get_detail_from_object(object, "graphicFile",
|
|
&(details->options.graphicFile));
|
|
}
|
|
|
|
kmp_files = json_object_get_member(root_object, "files");
|
|
details->files = NULL;
|
|
if (kmp_files) {
|
|
array = json_node_get_array (kmp_files);
|
|
if (array)
|
|
{
|
|
json_array_foreach_element (array,
|
|
kmp_files_foreach,
|
|
details);
|
|
}
|
|
}
|
|
|
|
kmp_keyboards = json_object_get_member(root_object, "keyboards");
|
|
details->keyboards = NULL;
|
|
if (kmp_keyboards) {
|
|
array = json_node_get_array (kmp_keyboards);
|
|
if (array)
|
|
{
|
|
json_array_foreach_element (array,
|
|
kmp_keyboards_foreach,
|
|
details);
|
|
}
|
|
}
|
|
}
|
|
return JSON_OK;
|
|
}
|
|
|
|
kmp_json_status print_kmp_details(kmp_details *details)
|
|
{
|
|
GList *l, *p;
|
|
kmp_keyboard *keyboard;
|
|
kmp_language *language;
|
|
kmp_fileinfo *fileinfo;
|
|
int i, j;
|
|
|
|
g_assert(details != NULL);
|
|
g_print("system.fileVersion: %s\n", details->system.fileVersion);
|
|
g_print("system.keymanDeveloperVersion: %s\n", details->system.keymanDeveloperVersion);
|
|
g_print("options.readmeFile: %s\n", details->options.readmeFile);
|
|
g_print("options.graphicFile: %s\n", details->options.graphicFile);
|
|
g_print("info.name: %s\n", details->info.name);
|
|
g_print("info.version: %s\n", details->info.version);
|
|
g_print("info.copyright: %s\n", details->info.copyright);
|
|
g_print("info.author_desc: %s\n", details->info.author_desc);
|
|
g_print("info.author_url: %s\n", details->info.author_url);
|
|
g_print("info.website_desc: %s\n", details->info.website_desc);
|
|
g_print("info.website_url: %s\n", details->info.website_url);
|
|
if (details->keyboards != NULL) {
|
|
for (l = details->keyboards, i=0; l != NULL; l = l->next, i++) {
|
|
keyboard = (kmp_keyboard *) l->data;
|
|
g_print("keyboard.%d.name %s\n", i, keyboard->name);
|
|
g_print("keyboard.%d.id %s\n", i, keyboard->id);
|
|
g_print("keyboard.%d.version %s\n", i, keyboard->version);
|
|
g_print("keyboard.%d.kmx_file %s\n", i, keyboard->kmx_file);
|
|
g_print("keyboard.%d.kvk_file %s\n", i, keyboard->kvk_file);
|
|
if (keyboard->languages != NULL) {
|
|
for (p = keyboard->languages, j=0; p != NULL; p = p->next, j++) {
|
|
language = (kmp_language *) p->data;
|
|
g_print("keyboard.%d.lang%d.name %s\n", i, j, language->name);
|
|
g_print("keyboard.%d.lang%d.id %s\n", i, j, language->id);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (details->files != NULL) {
|
|
for (l = details->files, i=0; l != NULL; l = l->next, i++) {
|
|
fileinfo = (kmp_fileinfo *) l->data;
|
|
g_print("file.%d.name %s\n", i, fileinfo->name);
|
|
g_print("file.%d.description %s\n", i, fileinfo->description);
|
|
}
|
|
}
|
|
return JSON_OK;
|
|
}
|
|
|
|
void free_language(gpointer data)
|
|
{
|
|
kmp_language *language = (kmp_language *) data;
|
|
g_free(language->name);
|
|
g_free(language->id);
|
|
g_free(language);
|
|
}
|
|
|
|
void free_keyboard(gpointer data)
|
|
{
|
|
kmp_keyboard *keyboard = (kmp_keyboard *) data;
|
|
g_free(keyboard->name);
|
|
g_free(keyboard->id);
|
|
g_free(keyboard->version);
|
|
g_free(keyboard->kmx_file);
|
|
g_free(keyboard->kvk_file);
|
|
if (keyboard->languages != NULL) {
|
|
g_list_free_full(keyboard->languages, (GDestroyNotify)free_language);
|
|
}
|
|
g_free(keyboard);
|
|
}
|
|
|
|
void free_fileinfo(gpointer data)
|
|
{
|
|
kmp_fileinfo *fileinfo = (kmp_fileinfo *) data;
|
|
g_free(fileinfo->name);
|
|
g_free(fileinfo->description);
|
|
g_free(fileinfo);
|
|
}
|
|
|
|
kmp_json_status free_keyboard_details(keyboard_details *kbd_details)
|
|
{
|
|
g_free(kbd_details->id);
|
|
g_free(kbd_details->description);
|
|
g_free(kbd_details->license);
|
|
g_free(kbd_details);
|
|
return JSON_OK;
|
|
}
|
|
|
|
void free_info(gpointer data) {
|
|
kmp_info *info = (kmp_info *)data;
|
|
if (info->name)
|
|
g_free(info->name);
|
|
if (info->version)
|
|
g_free(info->version);
|
|
if (info->copyright)
|
|
g_free(info->copyright);
|
|
if (info->author_desc)
|
|
g_free(info->author_desc);
|
|
if (info->author_url)
|
|
g_free(info->author_url);
|
|
if (info->website_desc)
|
|
g_free(info->website_desc);
|
|
if (info->website_url)
|
|
g_free(info->website_url);
|
|
}
|
|
|
|
kmp_json_status free_kmp_details(kmp_details * details)
|
|
{
|
|
if (details == NULL)
|
|
return JSON_OK;
|
|
|
|
g_free(details->system.fileVersion);
|
|
g_free(details->system.keymanDeveloperVersion);
|
|
g_free(details->options.readmeFile);
|
|
g_free(details->options.graphicFile);
|
|
free_info(&details->info);
|
|
if (details->keyboards != NULL) {
|
|
g_list_free_full(details->keyboards, (GDestroyNotify)free_keyboard);
|
|
}
|
|
if (details->files != NULL) {
|
|
g_list_free_full(details->files, (GDestroyNotify)free_fileinfo);
|
|
}
|
|
g_free(details);
|
|
return JSON_OK;
|
|
}
|