Skip to content

Commit

Permalink
refactor(linux): Add more tests for keymanutil.c 🏘️
Browse files Browse the repository at this point in the history
  • Loading branch information
ermshiperete committed Sep 19, 2023
1 parent afdafcf commit c9cac51
Show file tree
Hide file tree
Showing 3 changed files with 654 additions and 100 deletions.
230 changes: 132 additions & 98 deletions linux/ibus-keyman/src/keymanutil.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,10 @@
#include <keyman/keyboardprocessor.h>

#include "bcp47util.h"
#include "keymanutil.h"
#include "kmpdetails.h"
#include "keyman-version.h"
#include "keymanutil.h"
#include "keymanutil_internal.h"

#define N_(text) text

Expand Down Expand Up @@ -115,7 +116,7 @@ gchar * keyman_get_icon_file(const gchar *kmx_file)
return full_path_to_icon_file;
}

static IBusEngineDesc *
IBusEngineDesc *
ibus_keyman_engine_desc_new (gchar * file_name,
gchar *name,
gchar *description,
Expand Down Expand Up @@ -152,114 +153,147 @@ ibus_keyman_engine_desc_new (gchar * file_name,
return engine_desc;
}

IBusEngineDesc *
get_engine_for_language(
kmp_keyboard *keyboard,
kmp_info *info,
keyboard_details *kbd_details,
gchar *kmp_dir,
gchar *lang_id,
gchar *lang_name) {
IBusEngineDesc* engine_desc = NULL;
if (!lang_id || !strlen(lang_id))
return engine_desc;

int capacity = 255;
gchar *name_with_lang = NULL;
gchar *minimized_tag = g_new0(gchar, capacity);
int result = bcp47_minimize(lang_id, minimized_tag, capacity);
if (result < 0) {
g_strlcpy(minimized_tag, lang_id, capacity);
}

gchar *lang_code = g_new0(gchar, capacity);
if (!bcp47_get_language_code(minimized_tag, lang_code, capacity)) {
g_strlcpy(lang_code, minimized_tag, capacity);
}

// If ibus doesn't know about the language then append the
// language name to the keyboard name
if (lang_name != NULL) {
gchar *ibus_lang = ibus_get_untranslated_language_name(lang_code);
g_debug("%s: untranslated ibus language for %s: %s", __FUNCTION__, minimized_tag, ibus_lang);
if (g_strcmp0(ibus_lang, "Other") == 0) {
name_with_lang = g_strjoin(" - ", keyboard->name, lang_name, NULL);
}
g_free(ibus_lang);
}

gchar *abs_kmx = g_strjoin("/", kmp_dir, keyboard->kmx_file, NULL);
gchar *id_with_lang = g_strjoin(":", minimized_tag, abs_kmx, NULL);

g_message("adding engine %s", id_with_lang);
engine_desc = ibus_keyman_engine_desc_new(
id_with_lang, // lang:kmx full path
name_with_lang ? name_with_lang : keyboard->name, // longname
kbd_details->description, // description
info->copyright, // copyright if available
lang_code, // language, most are ignored by ibus except major languages
kbd_details->license, // license
info->author_desc, // author name only, not email
keyman_get_icon_file(abs_kmx), // icon full path
"us", // layout defaulting to us (en-US)
keyboard->version);
g_free(abs_kmx);
g_free(lang_code);
g_free(minimized_tag);
g_free(id_with_lang);
g_free(name_with_lang);
return engine_desc;
}

// Add a keyboard (ibus engine) to the list of engines
void
keyman_add_keyboard(gpointer data, gpointer user_data) {
kmp_keyboard *keyboard = (kmp_keyboard *)data;
add_keyboard_data *kb_data = (add_keyboard_data *)user_data;
gboolean alreadyexists = FALSE;

for (GList *e = kb_data->engines_list; e != NULL && alreadyexists == FALSE; e = e->next) {
IBusEngineDesc *engine_desc = (IBusEngineDesc *)e->data;
const gchar *version = ibus_engine_desc_get_version(engine_desc);
const gchar *engine_name = ibus_engine_desc_get_name(engine_desc);
gchar *kmx_file = g_path_get_basename(engine_name);
// If we already have an engine for this keyboard (in a different area), we
// don't want to add it again since we wouldn't add anything new
// if it's the same version
// TODO: fix version comparison (#9593)
if (g_strcmp0(kmx_file, keyboard->kmx_file) == 0 && g_strcmp0(version, keyboard->version) >= 0) {
alreadyexists = TRUE;
g_debug("keyboard %s already exists at version %s which is newer or same as %s", kmx_file, version, keyboard->version);
}
g_free(kmx_file);
}

if (!alreadyexists) {
gchar *json_file = g_strjoin(".", keyboard->id, "json", NULL);
keyboard_details *kbd_details = g_new0(keyboard_details, 1);
get_keyboard_details(kb_data->kmp_dir, json_file, kbd_details);
g_free(json_file);

if (keyboard->languages != NULL) {
for (GList *l = keyboard->languages; l != NULL; l = l->next) {
kmp_language *language = (kmp_language *)l->data;
IBusEngineDesc *engine_desc =
get_engine_for_language(keyboard, kb_data->info, kbd_details, kb_data->kmp_dir, language->id, language->name);
if (engine_desc) {
kb_data->engines_list = g_list_append(kb_data->engines_list, engine_desc);
}
}
} else {
gchar *abs_kmx = g_strjoin("/", kb_data->kmp_dir, keyboard->kmx_file, NULL);
g_message("adding engine %s", abs_kmx);
kb_data->engines_list = g_list_append(
kb_data->engines_list,
ibus_keyman_engine_desc_new(
abs_kmx, // kmx full path
keyboard->name, // longname
kbd_details->description, // description
kb_data->info->copyright, // copyright if available
NULL, // language, most are ignored by ibus except major languages
kbd_details->license, // license
kb_data->info->author_desc, // author name only, not email
keyman_get_icon_file(abs_kmx), // icon full path
"us", // layout defaulting to us (en-US)
keyboard->version));
g_free(abs_kmx);
}
free_keyboard_details(kbd_details);
g_free(kbd_details);
}
}

GList *
ibus_keyman_add_engines(GList * engines, GList * kmpdir_list)
ibus_keyman_add_engines(GList * engines_list, GList * kmpdir_list)
{
GList *p, *k, *l, *e;
GList *p;

for (p=kmpdir_list; p != NULL; p = p->next) {
gchar * kmp_dir = (gchar *) p->data;

kmp_details *details = g_new0(kmp_details, 1);
get_kmp_details(kmp_dir, details);

for (k=details->keyboards; k != NULL; k = k->next) {
kmp_keyboard *keyboard = (kmp_keyboard *) k->data;
gboolean alreadyexists = FALSE;

for (e=engines; e != NULL && alreadyexists == FALSE; e = e->next) {
IBusEngineDesc *engine_desc = (IBusEngineDesc *) e->data;
const gchar *version = ibus_engine_desc_get_version(engine_desc);
const gchar *engine_name = ibus_engine_desc_get_name(engine_desc);
gchar *kmx_file = g_path_get_basename(engine_name);
if (g_strcmp0(kmx_file, keyboard->kmx_file) == 0 && g_strcmp0(version, keyboard->version) >= 0) {
alreadyexists = TRUE;
g_debug("keyboard %s already exists at version %s which is newer or same as %s", kmx_file, version, keyboard->version);
}
g_free(kmx_file);
}
if (get_kmp_details(kmp_dir, details) == JSON_OK) {
add_keyboard_data kb_data;
kb_data.engines_list = engines_list;
kb_data.info = &details->info;
kb_data.kmp_dir = kmp_dir;

if (!alreadyexists) {
gchar *abs_kmx = g_strjoin("/", kmp_dir, keyboard->kmx_file, NULL);
gchar *json_file = g_strjoin(".", keyboard->id, "json", NULL);
keyboard_details *kbd_details = g_new0(keyboard_details, 1);
get_keyboard_details(kmp_dir, json_file, kbd_details);
g_free(json_file);

if (keyboard->languages != NULL) {
for (l=keyboard->languages; l != NULL; l = l->next) {
kmp_language *language = (kmp_language *) l->data;
if (language->id != NULL) {
int capacity = 255;
gchar *name_with_lang = NULL;
gchar *minimized_tag = g_new0(gchar, capacity);
int result = bcp47_minimize(language->id, minimized_tag, capacity);
if (result < 0) {
g_strlcpy(minimized_tag, language->id, capacity);
}

gchar *lang_code = g_new0(gchar, capacity);
if (!bcp47_get_language_code(minimized_tag, lang_code, capacity)) {
g_strlcpy(lang_code, minimized_tag, capacity);
}

// If ibus doesn't know about the language then append the
// language name to the keyboard name
if (language->name != NULL) {
gchar *ibus_lang = ibus_get_untranslated_language_name(lang_code);
g_debug("%s: untranslated ibus language for %s: %s", __FUNCTION__, minimized_tag, ibus_lang);
if (g_strcmp0(ibus_lang, "Other") == 0) {
name_with_lang = g_strjoin(" - ", keyboard->name, language->name, NULL);
}
g_free(ibus_lang);
}

gchar *id_with_lang = g_strjoin(":", minimized_tag, abs_kmx, NULL);

g_message("adding engine %s", id_with_lang);
engines = g_list_append(
engines,
ibus_keyman_engine_desc_new(
id_with_lang, // lang:kmx full path
name_with_lang ? name_with_lang : keyboard->name, // longname
kbd_details->description, // description
details->info.copyright, // copyright if available
lang_code, // language, most are ignored by ibus except major languages
kbd_details->license, // license
details->info.author_desc, // author name only, not email
keyman_get_icon_file(abs_kmx), // icon full path
"us", // layout defaulting to us (en-US)
keyboard->version));
g_free(lang_code);
g_free(minimized_tag);
g_free(id_with_lang);
g_free(name_with_lang);
}
}
}
else {
g_message("adding engine %s", abs_kmx);
engines = g_list_append (engines,
ibus_keyman_engine_desc_new (abs_kmx, // kmx full path
keyboard->name, // longname
kbd_details->description, // description
details->info.copyright, // copyright if available
NULL, // language, most are ignored by ibus except major languages
kbd_details->license, // license
details->info.author_desc, // author name only, not email
keyman_get_icon_file(abs_kmx), // icon full path
"us", // layout defaulting to us (en-US)
keyboard->version));
}
free_keyboard_details(kbd_details);
g_free(kbd_details);
g_free(abs_kmx);
}
g_list_foreach(details->keyboards, keyman_add_keyboard, &kb_data);
}
free_kmp_details(details);
g_free(details);
}
return engines;
return engines_list;
}

GList *
Expand Down
38 changes: 38 additions & 0 deletions linux/ibus-keyman/src/keymanutil_internal.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// Internal data structures used in the implementation of keymanutil methods
// and exposed for unit testing.

#ifndef __KEYMANUTIL_INTERNAL_H__
#define __KEYMANUTIL_INTERNAL_H__

#include <gmodule.h>
#include "kmpdetails.h"

typedef struct {
GList *engines_list;
kmp_info *info;
gchar *kmp_dir;
} add_keyboard_data;

IBusEngineDesc *ibus_keyman_engine_desc_new(
gchar *file_name,
gchar *name,
gchar *description,
gchar *copyright,
gchar *lang,
gchar *license,
gchar *author,
gchar *icon,
gchar *layout,
gchar *version);

IBusEngineDesc *get_engine_for_language(
kmp_keyboard *keyboard,
kmp_info *info,
keyboard_details *kbd_details,
gchar *kmp_dir,
gchar *lang_id,
gchar *lang_name);

void keyman_add_keyboard(gpointer data, gpointer user_data);

#endif // __KEYMANUTIL_INTERNAL_H__
Loading

0 comments on commit c9cac51

Please sign in to comment.