summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am38
-rw-r--r--src/PYConfig.cc4
-rw-r--r--src/PYConfig.h11
-rw-r--r--src/PYEnglishDatabase.cc7
-rw-r--r--src/PYEnglishDatabase.h2
-rw-r--r--src/PYEnglishEditor.cc19
-rw-r--r--src/PYEnglishEditor.h2
-rw-r--r--src/PYExtEditor.cc15
-rw-r--r--src/PYLibPinyin.cc59
-rw-r--r--src/PYLibPinyin.h4
-rw-r--r--src/PYMain.cc86
-rw-r--r--src/PYPBopomofoEditor.cc2
-rw-r--r--src/PYPCloudCandidates.cc43
-rw-r--r--src/PYPConfig.cc46
-rw-r--r--src/PYPConfig.h1
-rw-r--r--src/PYPDoublePinyinEditor.cc2
-rw-r--r--src/PYPEnhancedCandidates.h3
-rw-r--r--src/PYPFullPinyinEditor.cc1
-rw-r--r--src/PYPLibPinyinCandidates.cc7
-rw-r--r--src/PYPPhoneticEditor.cc31
-rw-r--r--src/PYPPhoneticEditor.h1
-rw-r--r--src/PYPPinyinEditor.cc12
-rw-r--r--src/PYPPinyinEngine.cc12
-rw-r--r--src/PYPSuggestionCandidates.cc6
-rw-r--r--src/PYPSuggestionEditor.cc15
-rw-r--r--src/PYPinyinProperties.cc124
-rw-r--r--src/PYPinyinProperties.h24
-rw-r--r--src/PYProperty.h15
-rw-r--r--src/PYTableDatabase.cc30
-rw-r--r--src/PYTableEditor.cc12
-rw-r--r--src/PYXMLUtil.cc188
-rw-r--r--src/PYXMLUtil.h43
-rw-r--r--src/default.inputmethod.xml.in.in44
-rw-r--r--src/libpinyin.inputmethod.xml.in.in19
-rw-r--r--src/libpinyin.xml.in.in53
35 files changed, 874 insertions, 107 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 8098b2a..a241bea 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -80,6 +80,7 @@ ibus_engine_libpinyin_h_sources = \
PYPSuggestionCandidates.h \
PYPEmojiTable.h \
PYPEmojiCandidates.h \
+ PYXMLUtil.h \
$(NULL)
ibus_engine_libpinyin_c_sources += \
@@ -97,6 +98,7 @@ ibus_engine_libpinyin_c_sources += \
PYPSuggestionEditor.cc \
PYPSuggestionCandidates.cc \
PYPEmojiCandidates.cc \
+ PYXMLUtil.cc \
$(NULL)
@@ -204,17 +206,28 @@ ibus_engine_libpinyin_LDADD += \
endif
if IBUS_BUILD_ENGLISH_INPUT_MODE
- ibus_engine_libpinyin_CXXFLAGS += \
+ibus_engine_libpinyin_CXXFLAGS += \
-DIBUS_BUILD_ENGLISH_INPUT_MODE \
$(NULL)
endif
if IBUS_BUILD_TABLE_INPUT_MODE
- ibus_engine_libpinyin_CXXFLAGS += \
+ibus_engine_libpinyin_CXXFLAGS += \
-DIBUS_BUILD_TABLE_INPUT_MODE \
$(NULL)
endif
+if ENABLE_LIBNOTIFY
+ibus_engine_libpinyin_CXXFLAGS += \
+ @LIBNOTIFY_CFLAGS@ \
+ -DENABLE_LIBNOTIFY \
+ $(NULL)
+
+ibus_engine_libpinyin_LDADD += \
+ @LIBNOTIFY_LIBS@ \
+ $(NULL)
+endif
+
BUILT_SOURCES = \
$(ibus_engine_built_c_sources) \
$(ibus_engine_built_h_sources) \
@@ -225,12 +238,19 @@ component_DATA = \
$(NULL)
componentdir = @datadir@/ibus/component
+engine_DATA = \
+ default.xml \
+ $(NULL)
+enginedir = ${pkgdatadir}
+
EXTRA_DIST = \
- libpinyin.xml.in \
+ libpinyin.inputmethod.xml.in \
+ default.inputmethod.xml.in \
$(NULL)
CLEANFILES = \
libpinyin.xml \
+ default.xml \
$(NULL)
PYPunctTable.h:
@@ -248,14 +268,10 @@ update-simptrad-table:
$(MAKE) -C $(top_srcdir)/scripts ZhConversion.py
$(MAKE) PYSimpTradConverterTable.h
-libpinyin.xml: libpinyin.xml.in
- $(AM_V_GEN) \
- ( \
- libexecdir=${libexecdir}; \
- pkgdatadir=${pkgdatadir}; \
- s=`cat $<`; \
- eval "echo \"$${s}\""; \
- ) > $@
+%.xml: %.inputmethod.xml.in
+ sed -e "s|\@LIBEXECDIR\@|$(libexecdir)|g" \
+ -e "s|\@PKGDATADIR\@|$(pkgdatadir)|g" \
+ $< > $@
test: ibus-engine-libpinyin
$(ENV) \
diff --git a/src/PYConfig.cc b/src/PYConfig.cc
index 1ba6704..e5f93b1 100644
--- a/src/PYConfig.cc
+++ b/src/PYConfig.cc
@@ -48,6 +48,7 @@ Config::initDefaultValues (void)
m_shift_select_candidate = FALSE;
m_minus_equal_page = TRUE;
m_comma_period_page = FALSE;
+ m_square_bracket_page = FALSE;
m_auto_commit = FALSE;
m_double_pinyin = FALSE;
@@ -79,6 +80,9 @@ Config::initDefaultValues (void)
m_english_candidate = TRUE;
m_suggestion_candidate = FALSE;
+ m_export_user_phrase = TRUE;
+ m_export_bigram_phrase = TRUE;
+
m_network_dictionary_start_timestamp = 0;
m_network_dictionary_end_timestamp = 0;
diff --git a/src/PYConfig.h b/src/PYConfig.h
index 4929e7a..e04fd2d 100644
--- a/src/PYConfig.h
+++ b/src/PYConfig.h
@@ -62,6 +62,7 @@ public:
gboolean shiftSelectCandidate (void) const { return m_shift_select_candidate; }
gboolean minusEqualPage (void) const { return m_minus_equal_page; }
gboolean commaPeriodPage (void) const { return m_comma_period_page; }
+ gboolean squareBracketPage (void) const { return m_square_bracket_page; }
gboolean autoCommit (void) const { return m_auto_commit; }
gboolean doublePinyin (void) const { return m_double_pinyin; }
DoublePinyinScheme doublePinyinSchema (void) const { return m_double_pinyin_schema; }
@@ -84,6 +85,9 @@ public:
gboolean englishCandidate (void) const { return m_english_candidate; }
gboolean suggestionCandidate (void) const { return m_suggestion_candidate; }
+ gboolean exportUserPhrase (void) const { return m_export_user_phrase; }
+ gboolean exportBigramPhrase (void) const { return m_export_bigram_phrase; }
+
std::string mainSwitch (void) const { return m_main_switch; }
std::string letterSwitch (void) const { return m_letter_switch; }
std::string punctSwitch (void) const { return m_punct_switch; }
@@ -98,6 +102,9 @@ public:
public:
/* write option */
+ virtual gboolean luaConverter (std::string converter)
+ { return FALSE; }
+
virtual gboolean networkDictionaryStartTimestamp (gint64 timestamp)
{ return FALSE; }
virtual gboolean networkDictionaryEndTimestamp (gint64 timestamp)
@@ -149,6 +156,7 @@ protected:
gboolean m_shift_select_candidate;
gboolean m_minus_equal_page;
gboolean m_comma_period_page;
+ gboolean m_square_bracket_page;
gboolean m_auto_commit;
gboolean m_double_pinyin;
@@ -176,6 +184,9 @@ protected:
gboolean m_english_candidate;
gboolean m_suggestion_candidate;
+ gboolean m_export_user_phrase;
+ gboolean m_export_bigram_phrase;
+
std::string m_main_switch;
std::string m_letter_switch;
std::string m_punct_switch;
diff --git a/src/PYEnglishDatabase.cc b/src/PYEnglishDatabase.cc
index c027a51..b68b407 100644
--- a/src/PYEnglishDatabase.cc
+++ b/src/PYEnglishDatabase.cc
@@ -45,6 +45,8 @@ EnglishDatabase::init ()
(PKGDATADIR G_DIR_SEPARATOR_S "db" G_DIR_SEPARATOR_S "english.db", path);
if (!result)
g_warning ("can't open English word list database.\n");
+
+ g_free (path);
}
@@ -52,7 +54,7 @@ EnglishDatabase::init ()
EnglishDatabase::EnglishDatabase(){
m_sqlite = NULL;
m_sql = "";
- m_user_db = "";
+ m_user_db = NULL;
m_timeout_id = 0;
m_timer = g_timer_new ();
}
@@ -69,6 +71,7 @@ EnglishDatabase::~EnglishDatabase(){
m_sqlite = NULL;
}
m_sql = "";
+ g_free (m_user_db);
m_user_db = NULL;
}
@@ -164,7 +167,7 @@ EnglishDatabase::openDatabase(const char *system_db, const char *user_db){
return FALSE;
}
/* cache the user db name. */
- m_user_db = user_db;
+ m_user_db = g_strdup (user_db);
/* do database attach here. :) */
if (sqlite3_open_v2 (system_db, &m_sqlite,
diff --git a/src/PYEnglishDatabase.h b/src/PYEnglishDatabase.h
index 002a474..ca1407c 100644
--- a/src/PYEnglishDatabase.h
+++ b/src/PYEnglishDatabase.h
@@ -59,7 +59,7 @@ private:
private:
sqlite3 *m_sqlite;
String m_sql;
- const char *m_user_db;
+ gchar *m_user_db;
guint m_timeout_id;
GTimer *m_timer;
diff --git a/src/PYEnglishEditor.cc b/src/PYEnglishEditor.cc
index 7e6e52b..9b9aaac 100644
--- a/src/PYEnglishEditor.cc
+++ b/src/PYEnglishEditor.cc
@@ -97,6 +97,12 @@ EnglishEditor::processKeyEvent (guint keyval, guint keycode, guint modifiers)
m_text.insert (m_cursor, keyval);
m_cursor ++;
}
+
+ if (!m_config.squareBracketPage () &&
+ (IBUS_bracketleft == keyval || IBUS_bracketright == keyval)) {
+ m_text.insert (m_cursor, keyval);
+ m_cursor ++;
+ }
}
/* Deal other staff with updateStateFromInput (). */
@@ -140,6 +146,12 @@ EnglishEditor::processPageKey (guint keyval)
return TRUE;
}
break;
+ case IBUS_bracketleft:
+ if (m_config.squareBracketPage ()) {
+ pageUp ();
+ return TRUE;
+ }
+ break;
case IBUS_period:
if (m_config.commaPeriodPage ()) {
pageDown ();
@@ -152,6 +164,13 @@ EnglishEditor::processPageKey (guint keyval)
return TRUE;
}
break;
+ case IBUS_bracketright:
+ if (m_config.squareBracketPage ()) {
+ pageDown ();
+ return TRUE;
+ }
+ break;
+
case IBUS_Up:
case IBUS_KP_Up:
cursorUp ();
diff --git a/src/PYEnglishEditor.h b/src/PYEnglishEditor.h
index 780c8c7..8f00ed2 100644
--- a/src/PYEnglishEditor.h
+++ b/src/PYEnglishEditor.h
@@ -29,7 +29,7 @@ namespace PY {
class EnglishDatabase;
-static const std::string EnglishSymbols = "`~!@*()+[]{}\\|:\"/<>?";
+static const std::string EnglishSymbols = "`~!@*()+{}\\|:\"/<>?";
class EnglishEditor : public Editor {
private:
diff --git a/src/PYExtEditor.cc b/src/PYExtEditor.cc
index 44aecf0..6630b2c 100644
--- a/src/PYExtEditor.cc
+++ b/src/PYExtEditor.cc
@@ -271,6 +271,14 @@ ExtEditor::processPageKey (guint keyval)
return TRUE;
}
break;
+#endif
+ case IBUS_bracketleft:
+ if (m_config.squareBracketPage ()) {
+ pageUp ();
+ return TRUE;
+ }
+ break;
+#if 0
//For "2.5" input.
case IBUS_period:
if (m_config.commaPeriodPage ()) {
@@ -285,6 +293,13 @@ ExtEditor::processPageKey (guint keyval)
return TRUE;
}
break;
+ case IBUS_bracketright:
+ if (m_config.squareBracketPage ()) {
+ pageDown ();
+ return TRUE;
+ }
+ break;
+
case IBUS_Up:
case IBUS_KP_Up:
cursorUp ();
diff --git a/src/PYLibPinyin.cc b/src/PYLibPinyin.cc
index 0a60612..d4f47c0 100644
--- a/src/PYLibPinyin.cc
+++ b/src/PYLibPinyin.cc
@@ -277,20 +277,13 @@ LibPinyinBackEnd::importPinyinDictionary (const char *filename)
}
gboolean
-LibPinyinBackEnd::exportPinyinDictionary (const char *filename)
+LibPinyinBackEnd::exportUserPhrase (FILE *dictfile)
{
- /* user phrase library should be already loaded here. */
- FILE * dictfile = fopen (filename, "w");
- if (NULL == dictfile)
- return FALSE;
-
export_iterator_t * iter = pinyin_begin_get_phrases
(m_pinyin_context, USER_DICTIONARY);
- if (NULL == iter) {
- fclose(dictfile);
+ if (NULL == iter)
return FALSE;
- }
/* use " " as the separator. */
while (pinyin_iterator_has_next_phrase (iter)) {
@@ -308,6 +301,54 @@ LibPinyinBackEnd::exportPinyinDictionary (const char *filename)
}
pinyin_end_get_phrases(iter);
+ return TRUE;
+}
+
+gboolean
+LibPinyinBackEnd::exportBigramPhrase (FILE *dictfile)
+{
+ bigram_export_iterator_t * iter = pinyin_begin_get_bigram_phrases
+ (m_pinyin_context);
+
+ if (NULL == iter)
+ return FALSE;
+
+ /* use " " as the separator. */
+ while (pinyin_bigram_iterator_has_next_phrase (iter)) {
+ gchar * phrase = NULL; gchar * pinyin = NULL;
+ gint count = -1;
+
+ check_result (pinyin_bigram_iterator_get_next_phrase (iter, &phrase, &pinyin, &count));
+
+ if (-1 == count) /* skip output the default count. */
+ fprintf (dictfile, "%s %s\n", phrase, pinyin);
+ else /* output the count. */
+ fprintf (dictfile, "%s %s %d\n", phrase, pinyin, count);
+
+ g_free (phrase); g_free (pinyin);
+ }
+
+ pinyin_end_get_bigram_phrases(iter);
+ return TRUE;
+}
+
+gboolean
+LibPinyinBackEnd::exportPinyinDictionary (const char *filename)
+{
+ if (NULL == m_pinyin_context)
+ return FALSE;
+
+ /* user phrase library should be already loaded here. */
+ FILE * dictfile = fopen (filename, "w");
+ if (NULL == dictfile)
+ return FALSE;
+
+ if (PinyinConfig::instance ().exportUserPhrase ())
+ exportUserPhrase (dictfile);
+
+ if (PinyinConfig::instance ().exportBigramPhrase ())
+ exportBigramPhrase (dictfile);
+
fclose (dictfile);
return TRUE;
}
diff --git a/src/PYLibPinyin.h b/src/PYLibPinyin.h
index e623f27..f8e0866 100644
--- a/src/PYLibPinyin.h
+++ b/src/PYLibPinyin.h
@@ -24,6 +24,7 @@
#include <memory>
#include <time.h>
#include <glib.h>
+#include <stdio.h>
typedef struct _pinyin_context_t pinyin_context_t;
typedef struct _pinyin_instance_t pinyin_instance_t;
@@ -50,6 +51,9 @@ public:
void freeChewingInstance (pinyin_instance_t *instance);
void modified (void);
+ gboolean exportUserPhrase (FILE *dictfile);
+ gboolean exportBigramPhrase (FILE *dictfile);
+
gboolean importPinyinDictionary (const char *filename);
gboolean exportPinyinDictionary (const char *filename);
gboolean clearPinyinUserData (const char *target);
diff --git a/src/PYMain.cc b/src/PYMain.cc
index a1c3040..7568e53 100644
--- a/src/PYMain.cc
+++ b/src/PYMain.cc
@@ -37,6 +37,10 @@
#ifdef IBUS_BUILD_TABLE_INPUT_MODE
#include "PYTableDatabase.h"
#endif
+#include "PYXMLUtil.h"
+#ifdef ENABLE_LIBNOTIFY
+#include <libnotify/notify.h>
+#endif
using namespace PY;
@@ -46,6 +50,7 @@ static Pointer<IBusFactory> factory;
/* options */
static gboolean ibus = FALSE;
+static gboolean xml = FALSE;
static gboolean verbose = FALSE;
static void
@@ -60,6 +65,7 @@ static const GOptionEntry entries[] =
{ "version", 'V', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK,
(gpointer) show_version_and_quit, "Show the application's version.", NULL },
{ "ibus", 'i', 0, G_OPTION_ARG_NONE, &ibus, "component is executed by ibus", NULL },
+ { "xml", 'x', 0, G_OPTION_ARG_NONE, &xml, "list engines", NULL },
{ "verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose, "verbose", NULL },
{ NULL },
};
@@ -162,6 +168,10 @@ sigterm_cb (int sig)
{
LibPinyinBackEnd::finalize ();
+#ifdef ENABLE_LIBNOTIFY
+ notify_uninit();
+#endif
+
::exit (EXIT_FAILURE);
}
@@ -169,6 +179,69 @@ static void
atexit_cb (void)
{
LibPinyinBackEnd::finalize ();
+
+#ifdef ENABLE_LIBNOTIFY
+ notify_uninit();
+#endif
+}
+
+static void
+print_engine_xml (void)
+{
+ gboolean success = FALSE;
+ gchar * content = NULL;
+
+ /* check the user engines.xml first. */
+ gchar * user_config = g_build_filename (g_get_user_config_dir (),
+ "ibus", "libpinyin", "engines.xml", NULL);
+ gchar * system_config = g_build_filename (PKGDATADIR, "default.xml", NULL);
+
+ /* if not, print the default.xml and exit. */
+ if (!g_file_test (user_config, G_FILE_TEST_IS_REGULAR)) {
+ if (!g_file_test (system_config, G_FILE_TEST_IS_REGULAR)) {
+ g_free (system_config);
+ g_free (user_config);
+ return;
+ }
+ content = load_file_content (system_config);
+ printf ("%s", content);
+ g_free (content);
+ g_free (system_config);
+ g_free (user_config);
+
+ return;
+ }
+
+ /* if the engines.xml exists, compare the version of two xml files. */
+ gchar * system_version = NULL;
+ success = parse_engine_version (system_config, &system_version);
+ gchar * user_version = NULL;
+ success = success && parse_engine_version (user_config, &user_version);
+ success = success && 0 == g_strcmp0 (system_version, user_version);
+ g_free (system_version);
+ g_free (user_version);
+ if (success) {
+ content = load_file_content (user_config);
+ printf ("%s", content);
+ g_free (content);
+ g_free (system_config);
+ g_free (user_config);
+ return;
+ }
+
+ /* if the version mis-match, create the new engines.xml by ibus-setup-libpinyin. */
+ g_spawn_command_line_sync (LIBEXECDIR"/ibus-setup-libpinyin resync-engine",
+ NULL, NULL, NULL, NULL);
+
+ /* print the user engines.xml. */
+ if (g_file_test (user_config, G_FILE_TEST_IS_REGULAR)) {
+ content = load_file_content (user_config);
+ printf ("%s", content);
+ g_free (content);
+ g_free (system_config);
+ g_free (user_config);
+ return;
+ }
}
int
@@ -192,10 +265,23 @@ main (gint argc, gchar **argv)
exit (-1);
}
+ if (xml) {
+ print_engine_xml ();
+ return 0;
+ }
+
::signal (SIGTERM, sigterm_cb);
::signal (SIGINT, sigterm_cb);
atexit (atexit_cb);
+#ifdef ENABLE_LIBNOTIFY
+ if (!notify_init("ibus-libpinyin")) {
+ g_error("notify_init failed");
+ exit(1);
+ }
+#endif
+
start_component ();
+
return 0;
}
diff --git a/src/PYPBopomofoEditor.cc b/src/PYPBopomofoEditor.cc
index 1e03b12..b91b594 100644
--- a/src/PYPBopomofoEditor.cc
+++ b/src/PYPBopomofoEditor.cc
@@ -73,6 +73,8 @@ BopomofoEditor::insert (gint ch)
return TRUE;
m_text.insert (m_cursor++, ch);
+ m_lookup_cursor = 0;
+
updatePinyin ();
update ();
diff --git a/src/PYPCloudCandidates.cc b/src/PYPCloudCandidates.cc
index f553ff9..3e2ef4c 100644
--- a/src/PYPCloudCandidates.cc
+++ b/src/PYPCloudCandidates.cc
@@ -496,6 +496,15 @@ CloudCandidates::selectCandidate (EnhancedCandidate & enhanced)
}
void
+releaseUserData (gpointer user_data)
+{
+ CloudAsyncRequestUserData *data = static_cast<CloudAsyncRequestUserData *> (user_data);
+ if (data->event_id != 0) {
+ g_free (user_data);
+ }
+}
+
+void
CloudCandidates::delayedCloudAsyncRequest (const gchar* pinyin)
{
gpointer user_data;
@@ -514,9 +523,11 @@ CloudCandidates::delayedCloudAsyncRequest (const gchar* pinyin)
data->cloud_candidates = this;
/* record the latest timer */
- m_source_event_id = g_timeout_add (m_editor->m_config.cloudRequestDelayTime (),
- delayedCloudAsyncRequestCallBack,
- user_data);
+ m_source_event_id = g_timeout_add_full (G_PRIORITY_DEFAULT,
+ m_editor->m_config.cloudRequestDelayTime (),
+ delayedCloudAsyncRequestCallBack,
+ user_data,
+ releaseUserData);
data->event_id = m_source_event_id;
data->message = NULL;
data->cancel_message = NULL;
@@ -537,6 +548,7 @@ CloudCandidates::delayedCloudAsyncRequestCallBack (gpointer user_data)
/* only send with a latest timer */
if (data->event_id == cloud_candidates->m_source_event_id) {
+ data->event_id = 0;
cloud_candidates->m_source_event_id = 0;
cloud_candidates->cloudAsyncRequest (user_data);
}
@@ -564,7 +576,7 @@ CloudCandidates::cloudAsyncRequest (gpointer user_data)
m_cancel_message = g_cancellable_new ();
data->cancel_message = m_cancel_message;
- SoupMessage *m_message = soup_message_new ("GET", query_request);
+ m_message = soup_message_new ("GET", query_request);
soup_session_send_async (m_session, m_message, SOUP_MESSAGE_PRIORITY_NORMAL, m_cancel_message, cloudResponseCallBack, user_data);
data->message = m_message;
@@ -576,23 +588,34 @@ CloudCandidates::cloudAsyncRequest (gpointer user_data)
void
CloudCandidates::cloudResponseCallBack (GObject *source_object, GAsyncResult *result, gpointer user_data)
{
- GInputStream *stream = soup_session_send_finish (SOUP_SESSION (source_object), result, NULL);
+ GError *error = NULL;
+ GInputStream *stream = soup_session_send_finish (SOUP_SESSION (source_object), result, &error);
CloudAsyncRequestUserData *data = static_cast<CloudAsyncRequestUserData *> (user_data);
CloudCandidates *cloud_candidates = data->cloud_candidates;
- /* process results */
- cloud_candidates->processCloudResponse (stream, cloud_candidates->m_editor->m_candidates, data->requested_pinyin);
+ if (!g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
+ /* process results */
+ cloud_candidates->processCloudResponse (stream, cloud_candidates->m_editor->m_candidates, data->requested_pinyin);
+
+ cloud_candidates->updateLookupTable ();
- cloud_candidates->updateLookupTable ();
+ /* reset m_message pointer only when it is not replaced with a new m_message */
+ cloud_candidates->m_message = NULL;
+ cloud_candidates->m_cancel_message = NULL;
+ }
+
+ if (error) {
+ g_error_free (error);
+ } else {
+ g_object_unref (stream);
+ }
/* clean up message */
g_object_unref (data->message);
- cloud_candidates->m_message = NULL;
/* clean up cancellable */
g_object_unref (data->cancel_message);
- cloud_candidates->m_cancel_message = NULL;
g_free (user_data);
}
diff --git a/src/PYPConfig.cc b/src/PYPConfig.cc
index 06b3ff8..f472ea9 100644
--- a/src/PYPConfig.cc
+++ b/src/PYPConfig.cc
@@ -20,8 +20,10 @@
#include "PYPConfig.h"
#include <string.h>
+#include <libintl.h>
#include <pinyin.h>
#include "PYBus.h"
+#include "PYXMLUtil.h"
#include "PYLibPinyin.h"
#include "PYTableDatabase.h"
@@ -29,6 +31,9 @@
namespace PY {
+#define _(text) (dgettext (GETTEXT_PACKAGE, text))
+#define N_(text) text
+
const gchar * const CONFIG_CORRECT_PINYIN = "correct-pinyin";
const gchar * const CONFIG_FUZZY_PINYIN = "fuzzy-pinyin";
const gchar * const CONFIG_ORIENTATION = "lookup-table-orientation";
@@ -39,6 +44,7 @@ const gchar * const CONFIG_SORT_OPTION = "sort-candidate-option";
const gchar * const CONFIG_SHIFT_SELECT_CANDIDATE = "shift-select-candidate";
const gchar * const CONFIG_MINUS_EQUAL_PAGE = "minus-equal-page";
const gchar * const CONFIG_COMMA_PERIOD_PAGE = "comma-period-page";
+const gchar * const CONFIG_SQUARE_BRACKET_PAGE = "square-bracket-page";
const gchar * const CONFIG_AUTO_COMMIT = "auto-commit";
const gchar * const CONFIG_DOUBLE_PINYIN = "double-pinyin";
const gchar * const CONFIG_DOUBLE_PINYIN_SCHEMA = "double-pinyin-schema";
@@ -63,6 +69,8 @@ const gchar * const CONFIG_USE_CUSTOM_TABLE = "use-custom-table";
const gchar * const CONFIG_EMOJI_CANDIDATE = "emoji-candidate";
const gchar * const CONFIG_ENGLISH_CANDIDATE = "english-candidate";
const gchar * const CONFIG_SUGGESTION_CANDIDATE = "suggestion-candidate";
+const gchar * const CONFIG_EXPORT_USER_PHRASE = "export-user-phrase";
+const gchar * const CONFIG_EXPORT_BIGRAM_PHRASE = "export-bigram-phrase";
const gchar * const CONFIG_IMPORT_CUSTOM_TABLE = "import-custom-table";
const gchar * const CONFIG_EXPORT_CUSTOM_TABLE = "export-custom-table";
const gchar * const CONFIG_CLEAR_CUSTOM_TABLE = "clear-custom-table";
@@ -109,6 +117,14 @@ LibPinyinConfig::~LibPinyinConfig (void)
}
gboolean
+LibPinyinConfig::luaConverter (std::string converter)
+{
+ m_lua_converter = converter;
+ return write (CONFIG_LUA_CONVERTER, converter.c_str ());
+}
+
+
+gboolean
LibPinyinConfig::networkDictionaryStartTimestamp (gint64 timestamp)
{
m_network_dictionary_start_timestamp = timestamp;
@@ -138,6 +154,9 @@ LibPinyinConfig::initDefaultValues (void)
m_english_candidate = TRUE;
m_suggestion_candidate = FALSE;
+ m_export_user_phrase = TRUE;
+ m_export_bigram_phrase = TRUE;
+
m_shift_select_candidate = FALSE;
m_minus_equal_page = TRUE;
m_comma_period_page = FALSE;
@@ -576,6 +595,7 @@ PinyinConfig::readDefaultValues (void)
m_shift_select_candidate = read (CONFIG_SHIFT_SELECT_CANDIDATE, false);
m_minus_equal_page = read (CONFIG_MINUS_EQUAL_PAGE, true);
m_comma_period_page = read (CONFIG_COMMA_PERIOD_PAGE, false);
+ m_square_bracket_page = read (CONFIG_SQUARE_BRACKET_PAGE, false);
m_auto_commit = read (CONFIG_AUTO_COMMIT, false);
m_lua_extension = read (CONFIG_LUA_EXTENSION, true);
@@ -583,6 +603,10 @@ PinyinConfig::readDefaultValues (void)
m_table_input_mode = read (CONFIG_TABLE_INPUT_MODE, true);
m_use_custom_table = read (CONFIG_USE_CUSTOM_TABLE, false);
+ /* export phrases */
+ m_export_user_phrase = read (CONFIG_EXPORT_USER_PHRASE, true);
+ m_export_bigram_phrase = read (CONFIG_EXPORT_BIGRAM_PHRASE, true);
+
/* lua */
m_lua_converter = read (CONFIG_LUA_CONVERTER, "");
@@ -646,6 +670,8 @@ PinyinConfig::valueChanged (const std::string &schema_id,
m_minus_equal_page = normalizeGVariant (value, true);
else if (CONFIG_COMMA_PERIOD_PAGE == name)
m_comma_period_page = normalizeGVariant (value, false);
+ else if (CONFIG_SQUARE_BRACKET_PAGE == name)
+ m_square_bracket_page = normalizeGVariant (value, false);
else if (CONFIG_LUA_CONVERTER == name)
m_lua_converter = normalizeGVariant (value, std::string (""));
else if (CONFIG_AUTO_COMMIT == name)
@@ -658,15 +684,23 @@ PinyinConfig::valueChanged (const std::string &schema_id,
m_table_input_mode = normalizeGVariant (value, true);
else if (CONFIG_USE_CUSTOM_TABLE == name)
m_use_custom_table = normalizeGVariant (value, false);
+ else if (CONFIG_EXPORT_USER_PHRASE == name)
+ m_export_user_phrase = normalizeGVariant (value, true);
+ else if (CONFIG_EXPORT_BIGRAM_PHRASE == name)
+ m_export_bigram_phrase = normalizeGVariant (value, true);
else if (CONFIG_IMPORT_CUSTOM_TABLE == name) {
std::string filename = normalizeGVariant (value, std::string(""));
- if (!filename.empty ())
+ if (!filename.empty ()) {
TableDatabase::userInstance ().importTable (filename.c_str ());
+ show_message (_("The table file is imported."), NULL);
+ }
}
else if (CONFIG_EXPORT_CUSTOM_TABLE == name) {
std::string filename = normalizeGVariant (value, std::string(""));
- if (!filename.empty ())
+ if (!filename.empty ()) {
TableDatabase::userInstance ().exportTable (filename.c_str ());
+ show_message (_("The table file is exported."), NULL);
+ }
}
else if (CONFIG_CLEAR_CUSTOM_TABLE == name) {
std::string target = normalizeGVariant (value, std::string(""));
@@ -675,13 +709,17 @@ PinyinConfig::valueChanged (const std::string &schema_id,
}
else if (CONFIG_IMPORT_DICTIONARY == name) {
std::string filename = normalizeGVariant (value, std::string(""));
- if (!filename.empty ())
+ if (!filename.empty ()) {
LibPinyinBackEnd::instance ().importPinyinDictionary (filename.c_str ());
+ show_message (_("The pinyin dictionary file is imported."), NULL);
+ }
}
else if (CONFIG_EXPORT_DICTIONARY == name) {
std::string filename = normalizeGVariant (value, std::string(""));
- if (!filename.empty ())
+ if (!filename.empty ()) {
LibPinyinBackEnd::instance ().exportPinyinDictionary (filename.c_str ());
+ show_message (_("The pinyin dictionary file is exported."), NULL);
+ }
}
else if (CONFIG_CLEAR_USER_DATA == name) {
std::string target = normalizeGVariant (value, std::string(""));
diff --git a/src/PYPConfig.h b/src/PYPConfig.h
index b08fd5a..b1a2dfd 100644
--- a/src/PYPConfig.h
+++ b/src/PYPConfig.h
@@ -39,6 +39,7 @@ protected:
virtual ~LibPinyinConfig (void);
public:
+ virtual gboolean luaConverter (std::string converter);
virtual gboolean networkDictionaryStartTimestamp (gint64 timestamp);
virtual gboolean networkDictionaryEndTimestamp (gint64 timestamp);
diff --git a/src/PYPDoublePinyinEditor.cc b/src/PYPDoublePinyinEditor.cc
index 22aa401..fe53ab1 100644
--- a/src/PYPDoublePinyinEditor.cc
+++ b/src/PYPDoublePinyinEditor.cc
@@ -73,6 +73,8 @@ DoublePinyinEditor::insert (gint ch)
#endif
m_text.insert (m_cursor++, ch);
+ m_lookup_cursor = 0;
+
updatePinyin ();
update ();
diff --git a/src/PYPEnhancedCandidates.h b/src/PYPEnhancedCandidates.h
index e5bc62f..bffdac9 100644
--- a/src/PYPEnhancedCandidates.h
+++ b/src/PYPEnhancedCandidates.h
@@ -42,7 +42,8 @@ enum CandidateType {
CANDIDATE_LUA_CONVERTER,
CANDIDATE_CLOUD_INPUT,
CANDIDATE_EMOJI,
- CANDIDATE_ENGLISH
+ CANDIDATE_ENGLISH,
+ CANDIDATE_PREDICTED_PUNCTUATION
};
enum SelectCandidateAction {
diff --git a/src/PYPFullPinyinEditor.cc b/src/PYPFullPinyinEditor.cc
index bd41572..b20a47c 100644
--- a/src/PYPFullPinyinEditor.cc
+++ b/src/PYPFullPinyinEditor.cc
@@ -58,6 +58,7 @@ FullPinyinEditor::insert (gint ch)
#endif
m_text.insert (m_cursor++, ch);
+ m_lookup_cursor = 0;
updatePinyin ();
update ();
diff --git a/src/PYPLibPinyinCandidates.cc b/src/PYPLibPinyinCandidates.cc
index dd3d409..6726739 100644
--- a/src/PYPLibPinyinCandidates.cc
+++ b/src/PYPLibPinyinCandidates.cc
@@ -167,7 +167,12 @@ LibPinyinCandidates::selectCandidate (EnhancedCandidate & enhanced)
guint16 begin = 0;
pinyin_get_pinyin_key_rest_positions (instance, pos, &begin, NULL);
- m_editor->m_cursor = begin;
+
+ /* The cursor is at the end of the text input. */
+ if (m_editor->m_cursor == m_editor->m_text.length ())
+ m_editor->m_lookup_cursor = begin;
+ else
+ m_editor->m_cursor = begin;
return SELECT_CANDIDATE_UPDATE;
}
diff --git a/src/PYPPhoneticEditor.cc b/src/PYPPhoneticEditor.cc
index 00fa610..42d759c 100644
--- a/src/PYPPhoneticEditor.cc
+++ b/src/PYPPhoneticEditor.cc
@@ -31,6 +31,7 @@ PhoneticEditor::PhoneticEditor (PinyinProperties &props,
: Editor (props, config),
m_pinyin_len (0),
m_lookup_table (m_config.pageSize ()),
+ m_lookup_cursor (0),
m_libpinyin_candidates (this),
#ifdef IBUS_BUILD_LUA_EXTENSION
m_lua_trigger_candidates (this),
@@ -379,12 +380,13 @@ PhoneticEditor::getPinyinCursor ()
guint
PhoneticEditor::getLookupCursor (void)
{
- guint lookup_cursor = getPinyinCursor ();
+ guint pinyin_cursor = getPinyinCursor ();
- /* show candidates when pinyin cursor is at end. */
- if (lookup_cursor == m_text.length ())
- lookup_cursor = 0;
- return lookup_cursor;
+ /* show candidates when pinyin cursor is at the end. */
+ if (m_cursor == m_text.length ())
+ return m_lookup_cursor;
+
+ return pinyin_cursor;
}
int
@@ -564,6 +566,8 @@ PhoneticEditor::removeCharBefore (void)
return FALSE;
m_cursor --;
+ m_lookup_cursor = 0;
+
m_text.erase (m_cursor, 1);
updatePinyin ();
@@ -579,6 +583,7 @@ PhoneticEditor::removeCharAfter (void)
return FALSE;
m_text.erase (m_cursor, 1);
+ m_lookup_cursor = 0;
updatePinyin ();
update ();
@@ -593,6 +598,8 @@ PhoneticEditor::moveCursorLeft (void)
return FALSE;
m_cursor --;
+ m_lookup_cursor = 0;
+
update ();
return TRUE;
}
@@ -604,6 +611,8 @@ PhoneticEditor::moveCursorRight (void)
return FALSE;
m_cursor ++;
+ m_lookup_cursor = 0;
+
update ();
return TRUE;
}
@@ -615,6 +624,8 @@ PhoneticEditor::moveCursorToBegin (void)
return FALSE;
m_cursor = 0;
+ m_lookup_cursor = 0;
+
update ();
return TRUE;
}
@@ -626,6 +637,8 @@ PhoneticEditor::moveCursorToEnd (void)
return FALSE;
m_cursor = m_text.length ();
+ m_lookup_cursor = 0;
+
update ();
return TRUE;
}
@@ -670,6 +683,8 @@ PhoneticEditor::removeWordBefore (void)
guint cursor = getCursorLeftByWord ();
m_text.erase (cursor, m_cursor - cursor);
m_cursor = cursor;
+ m_lookup_cursor = 0;
+
updatePinyin ();
update ();
return TRUE;
@@ -683,6 +698,8 @@ PhoneticEditor::removeWordAfter (void)
guint cursor = getCursorRightByWord ();
m_text.erase (m_cursor, cursor - m_cursor);
+ m_lookup_cursor = 0;
+
updatePinyin ();
update ();
return TRUE;
@@ -697,6 +714,8 @@ PhoneticEditor::moveCursorLeftByWord (void)
guint cursor = getCursorLeftByWord ();
m_cursor = cursor;
+ m_lookup_cursor = 0;
+
update ();
return TRUE;
}
@@ -710,6 +729,8 @@ PhoneticEditor::moveCursorRightByWord (void)
guint cursor = getCursorRightByWord ();
m_cursor = cursor;
+ m_lookup_cursor = 0;
+
update ();
return TRUE;
}
diff --git a/src/PYPPhoneticEditor.h b/src/PYPPhoneticEditor.h
index 03e61aa..2032cf1 100644
--- a/src/PYPPhoneticEditor.h
+++ b/src/PYPPhoneticEditor.h
@@ -117,6 +117,7 @@ protected:
/* varibles */
guint m_pinyin_len;
LookupTable m_lookup_table;
+ guint m_lookup_cursor;
String m_buffer;
/* use LibPinyinBackEnd here. */
diff --git a/src/PYPPinyinEditor.cc b/src/PYPPinyinEditor.cc
index 99efbe3..f2b2d7e 100644
--- a/src/PYPPinyinEditor.cc
+++ b/src/PYPPinyinEditor.cc
@@ -109,6 +109,12 @@ PinyinEditor::processPunct (guint keyval, guint keycode,
return TRUE;
}
break;
+ case IBUS_bracketleft:
+ if (m_config.squareBracketPage ()) {
+ pageUp ();
+ return TRUE;
+ }
+ break;
case IBUS_period:
if (m_config.commaPeriodPage ()) {
pageDown ();
@@ -121,6 +127,12 @@ PinyinEditor::processPunct (guint keyval, guint keycode,
return TRUE;
}
break;
+ case IBUS_bracketright:
+ if (m_config.squareBracketPage ()) {
+ pageDown ();
+ return TRUE;
+ }
+ break;
}
if (m_config.autoCommit ()) {
diff --git a/src/PYPPinyinEngine.cc b/src/PYPPinyinEngine.cc
index 2e06d13..16366f2 100644
--- a/src/PYPPinyinEngine.cc
+++ b/src/PYPPinyinEngine.cc
@@ -75,6 +75,12 @@ PinyinEngine::PinyinEngine (IBusEngine *engine)
#endif
}
+#ifdef IBUS_BUILD_LUA_EXTENSION
+ m_props.setLuaPlugin (m_lua_plugin);
+ if (PinyinConfig::instance ().luaExtension ())
+ m_props.appendLuaConverter ();
+#endif
+
m_editors[MODE_PUNCT].reset
(new PunctEditor (m_props, PinyinConfig::instance ()));
m_editors[MODE_RAW].reset
@@ -377,6 +383,9 @@ PinyinEngine::processKeyEvent (guint keyval, guint keycode, guint modifiers)
/* For full pinyin, "'" is used. */
(PinyinConfig::instance ().doublePinyin () &&
IBUS_apostrophe == keyval) ||
+ /* Use square brackets to flip page */
+ (!PinyinConfig::instance ().squareBracketPage () &&
+ (IBUS_bracketleft == keyval || IBUS_bracketright == keyval)) ||
/* For double pinyin, ";" is used. */
(!PinyinConfig::instance ().doublePinyin () &&
IBUS_semicolon == keyval)) &&
@@ -430,6 +439,9 @@ PinyinEngine::processKeyEvent (guint keyval, guint keycode, guint modifiers)
m_input_mode != MODE_INIT &&
m_editors[m_input_mode]->text ().empty ()))
m_input_mode = MODE_INIT;
+
+ if (G_UNLIKELY (!retval && m_input_mode == MODE_SUGGESTION))
+ m_input_mode = MODE_INIT;
}
if (G_UNLIKELY (!retval))
diff --git a/src/PYPSuggestionCandidates.cc b/src/PYPSuggestionCandidates.cc
index 7f8aa1c..84b3f0a 100644
--- a/src/PYPSuggestionCandidates.cc
+++ b/src/PYPSuggestionCandidates.cc
@@ -47,6 +47,9 @@ SuggestionCandidates::processCandidates (std::vector<EnhancedCandidate> & candid
case PREDICTED_PREFIX_CANDIDATE:
candidate_type = CANDIDATE_PREDICTED_PREFIX;
break;
+ case PREDICTED_PUNCTUATION_CANDIDATE:
+ candidate_type = CANDIDATE_PREDICTED_PUNCTUATION;
+ break;
default:
assert(FALSE);
}
@@ -70,7 +73,8 @@ SuggestionCandidates::selectCandidate (EnhancedCandidate & enhanced)
{
pinyin_instance_t * instance = m_editor->m_instance;
assert (CANDIDATE_PREDICTED_BIGRAM == enhanced.m_candidate_type ||
- CANDIDATE_PREDICTED_PREFIX == enhanced.m_candidate_type);
+ CANDIDATE_PREDICTED_PREFIX == enhanced.m_candidate_type ||
+ CANDIDATE_PREDICTED_PUNCTUATION == enhanced.m_candidate_type);
guint len = 0;
pinyin_get_n_candidate (instance, &len);
diff --git a/src/PYPSuggestionEditor.cc b/src/PYPSuggestionEditor.cc
index 85c35ec..129c093 100644
--- a/src/PYPSuggestionEditor.cc
+++ b/src/PYPSuggestionEditor.cc
@@ -113,6 +113,12 @@ SuggestionEditor::processPageKey (guint keyval)
return TRUE;
}
break;
+ case IBUS_bracketleft:
+ if (m_config.squareBracketPage ()) {
+ pageUp ();
+ return TRUE;
+ }
+ break;
case IBUS_period:
if (m_config.commaPeriodPage ()) {
pageDown ();
@@ -125,6 +131,12 @@ SuggestionEditor::processPageKey (guint keyval)
return TRUE;
}
break;
+ case IBUS_bracketright:
+ if (m_config.squareBracketPage ()) {
+ pageDown ();
+ return TRUE;
+ }
+ break;
case IBUS_Up:
case IBUS_KP_Up:
@@ -262,7 +274,7 @@ SuggestionEditor::cursorDown (void)
void
SuggestionEditor::update (void)
{
- pinyin_guess_predicted_candidates (m_instance, m_text);
+ pinyin_guess_predicted_candidates_with_punctuations (m_instance, m_text);
updateLookupTable ();
updatePreeditText ();
@@ -347,6 +359,7 @@ SuggestionEditor::selectCandidateInternal (EnhancedCandidate & candidate)
switch (candidate.m_candidate_type) {
case CANDIDATE_PREDICTED_BIGRAM:
case CANDIDATE_PREDICTED_PREFIX:
+ case CANDIDATE_PREDICTED_PUNCTUATION:
return m_suggestion_candidates.selectCandidate (candidate);
case CANDIDATE_TRADITIONAL_CHINESE:
diff --git a/src/PYPinyinProperties.cc b/src/PYPinyinProperties.cc
index fe0a7a0..edc2b88 100644
--- a/src/PYPinyinProperties.cc
+++ b/src/PYPinyinProperties.cc
@@ -21,6 +21,9 @@
#include <libintl.h>
#include "PYText.h"
#include "PYConfig.h"
+#ifdef IBUS_BUILD_LUA_EXTENSION
+#include "lua-plugin.h"
+#endif
namespace PY {
@@ -94,6 +97,29 @@ PinyinProperties::PinyinProperties (Config & config)
m_props.append (m_prop_simp);
m_props.append (m_prop_setup);
+#ifdef IBUS_BUILD_LUA_EXTENSION
+ m_prop_lua_converter = NULL;
+#endif
+}
+
+PinyinProperties::~PinyinProperties (void)
+{
+#ifdef IBUS_BUILD_LUA_EXTENSION
+ if (m_prop_lua_converter) {
+ delete m_prop_lua_converter;
+ m_prop_lua_converter = NULL;
+ }
+
+ for (auto iter = m_props_lua_converter_vec.begin ();
+ iter != m_props_lua_converter_vec.end (); ++iter) {
+ delete *iter;
+ }
+
+ for (auto iter = m_lua_converter_names.begin ();
+ iter != m_lua_converter_names.end (); ++iter) {
+ delete *iter;
+ }
+#endif
}
void
@@ -119,6 +145,9 @@ PinyinProperties::toggleModeChinese (void)
m_prop_full_punct.setSensitive (m_mode_chinese);
updateProperty (m_prop_full_punct);
+
+ m_prop_simp.setSensitive (m_mode_chinese);
+ updateProperty (m_prop_simp);
}
void
@@ -209,8 +238,103 @@ PinyinProperties::propertyActivate (const gchar *prop_name, guint prop_state) {
toggleModeSimp ();
return TRUE;
}
+
+#ifdef IBUS_BUILD_LUA_EXTENSION
+ const int len = strlen("LuaConverter.");
+ if (0 == strncmp (prop_name, "LuaConverter.", len)) {
+ toggleLuaConverter (len, prop_name, prop_state);
+ return TRUE;
+ }
+#endif
+
return FALSE;
}
+#ifdef IBUS_BUILD_LUA_EXTENSION
+gboolean
+PinyinProperties::setLuaPlugin (IBusEnginePlugin *plugin) {
+ m_lua_plugin = plugin;
+ return TRUE;
+}
+
+void
+PinyinProperties::toggleLuaConverter (const int prefix_len,
+ const gchar *prop_name,
+ guint prop_state) {
+ if (prop_state == PROP_STATE_CHECKED) {
+ std::string name = prop_name + prefix_len;
+ if (name == "None")
+ m_config.luaConverter ("");
+ else
+ m_config.luaConverter (name);
+ }
+
+ for (auto iter = m_props_lua_converter_vec.begin ();
+ iter != m_props_lua_converter_vec.end (); ++iter) {
+ Property *prop = *iter;
+ if (0 == g_strcmp0 (prop->getKey (), prop_name)) {
+ prop->setState ((IBusPropState) prop_state);
+ updateProperty (*prop);
+ }
+ }
+}
+
+gboolean
+PinyinProperties::appendLuaConverter (void) {
+ if (!m_lua_plugin)
+ return FALSE;
+
+ const GArray * converters =
+ ibus_engine_plugin_get_available_converters (m_lua_plugin);
+ if (converters->len == 0)
+ return FALSE;
+
+ m_prop_lua_converter = new Property ("LuaConverter",
+ PROP_TYPE_MENU,
+ StaticText (_("Lua Converter")),
+ PKGDATADIR"/icons/lua-converter.svg",
+ StaticText (_("Use the Lua Convertor")));
+
+ Property * prop = NULL;
+
+ /* Add the None converter. */
+ prop = new Property ("LuaConverter.None",
+ PROP_TYPE_RADIO,
+ StaticText (_("None")));
+
+ if (m_config.luaConverter ().empty ())
+ prop->setState (PROP_STATE_CHECKED);
+
+ m_props_lua_converter_vec.push_back (prop);
+ m_props_lua_converter_list.append (*prop);
+
+ /* Add the User Lua Converters. */
+ for (int i = 0; i < converters->len; i++) {
+ lua_converter_t *converter = &g_array_index
+ (converters, lua_converter_t, i);
+
+ const gchar *name = converter->lua_function_name;
+ gchar *key = g_strdup_printf ("LuaConverter.%s", name);
+ m_lua_converter_names.push_back (key);
+
+ prop = new Property (key,
+ PROP_TYPE_RADIO,
+ Text (converter->description));
+
+ if (!m_config.luaConverter ().empty () &&
+ m_config.luaConverter () == name)
+ prop->setState (PROP_STATE_CHECKED);
+
+ m_props_lua_converter_vec.push_back (prop);
+ m_props_lua_converter_list.append (*prop);
+ }
+
+ m_prop_lua_converter->setSubProps (m_props_lua_converter_list);
+ m_props.append (*m_prop_lua_converter);
+
+ return TRUE;
+}
+
+#endif
};
diff --git a/src/PYPinyinProperties.h b/src/PYPinyinProperties.h
index 58f39bd..6706032 100644
--- a/src/PYPinyinProperties.h
+++ b/src/PYPinyinProperties.h
@@ -22,6 +22,12 @@
#include "PYSignal.h"
#include "PYProperty.h"
+#include <vector>
+#include <glib.h>
+
+G_BEGIN_DECLS
+typedef struct _IBusEnginePlugin IBusEnginePlugin;
+G_END_DECLS
namespace PY {
@@ -30,6 +36,7 @@ class Config;
class PinyinProperties {
public:
PinyinProperties (Config & config);
+ virtual ~PinyinProperties (void);
void toggleModeChinese (void);
void toggleModeFull (void);
@@ -74,6 +81,23 @@ private:
Property m_prop_simp;
Property m_prop_setup;
PropList m_props;
+
+#ifdef IBUS_BUILD_LUA_EXTENSION
+ Pointer<IBusEnginePlugin> m_lua_plugin;
+ Property *m_prop_lua_converter;
+ std::vector<Property *> m_props_lua_converter_vec;
+ std::vector<gchar *> m_lua_converter_names;
+ PropList m_props_lua_converter_list;
+
+public:
+ gboolean setLuaPlugin (IBusEnginePlugin *plugin);
+
+ void toggleLuaConverter (const int prefix_len,
+ const gchar *prop_name,
+ guint prop_state);
+
+ gboolean appendLuaConverter (void);
+#endif
};
};
diff --git a/src/PYProperty.h b/src/PYProperty.h
index c30d3c2..24923e4 100644
--- a/src/PYProperty.h
+++ b/src/PYProperty.h
@@ -39,6 +39,11 @@ public:
IBusPropList *props = NULL)
: Object (ibus_property_new (key, type, label, icon, tooltip, sensitive, visible, state, props)) { }
+ const gchar * getKey (void)
+ {
+ return ibus_property_get_key (get<IBusProperty> ());
+ }
+
void setLabel (IBusText *text)
{
ibus_property_set_label (get<IBusProperty> (), text);
@@ -79,6 +84,16 @@ public:
setTooltip (Text (text));
}
+ void setState (IBusPropState state)
+ {
+ ibus_property_set_state (get<IBusProperty> (), state);
+ }
+
+ void setSubProps (IBusPropList *props)
+ {
+ ibus_property_set_sub_props (get<IBusProperty> (), props);
+ }
+
operator IBusProperty * (void) const
{
return get<IBusProperty> ();
diff --git a/src/PYTableDatabase.cc b/src/PYTableDatabase.cc
index a6f8209..0e55b6e 100644
--- a/src/PYTableDatabase.cc
+++ b/src/PYTableDatabase.cc
@@ -57,6 +57,8 @@ TableDatabase::init ()
if (!result)
g_warning ("can't open user table database.\n");
+
+ g_free (path);
}
TableDatabase::TableDatabase(){
@@ -269,12 +271,16 @@ TableDatabase::importTable (const char *filename){
"SELECT MAX(id) FROM phrases;";
m_sql = SQL_DB_SELECT;
int result = sqlite3_prepare_v2 (m_sqlite, m_sql.c_str (), -1, &stmt, &tail);
- if (result != SQLITE_OK)
+ if (result != SQLITE_OK) {
+ fclose (input);
return FALSE;
+ }
result = sqlite3_step (stmt);
- if (result != SQLITE_ROW)
+ if (result != SQLITE_ROW) {
+ fclose (input);
return FALSE;
+ }
int id = 0;
result = sqlite3_column_type (stmt, 0);
@@ -286,8 +292,10 @@ TableDatabase::importTable (const char *filename){
g_warning ("Can't find id for user table database.");
m_sql = "BEGIN TRANSACTION;";
- if (!executeSQL (m_sqlite))
+ if (!executeSQL (m_sqlite)) {
+ fclose (input);
return FALSE;
+ }
/* Open the table file with format:
"tabkeys phrase freq". */
@@ -311,8 +319,10 @@ TableDatabase::importTable (const char *filename){
}
m_sql = "COMMIT;";
- if (!executeSQL (m_sqlite))
+ if (!executeSQL (m_sqlite)) {
+ fclose (input);
return FALSE;
+ }
fclose (input);
return TRUE;
@@ -343,18 +353,24 @@ TableDatabase::exportTable (const char *filename){
while (result == SQLITE_ROW){
/* write one line. */
result = sqlite3_column_type (stmt, 0);
- if (result != SQLITE_TEXT)
+ if (result != SQLITE_TEXT) {
+ fclose (output);
return FALSE;
+ }
const char *tabkeys = (const char *)sqlite3_column_text (stmt, 0);
result = sqlite3_column_type (stmt, 1);
- if (result != SQLITE_TEXT)
+ if (result != SQLITE_TEXT) {
+ fclose (output);
return FALSE;
+ }
const char *phrase = (const char *)sqlite3_column_text (stmt, 1);
result = sqlite3_column_type (stmt, 2);
- if (result != SQLITE_INTEGER)
+ if (result != SQLITE_INTEGER) {
+ fclose (output);
return FALSE;
+ }
const int freq = sqlite3_column_int (stmt, 2);
fprintf (output, "%s\t%s\t%d\n", tabkeys, phrase, freq);
diff --git a/src/PYTableEditor.cc b/src/PYTableEditor.cc
index ddaab57..4c79983 100644
--- a/src/PYTableEditor.cc
+++ b/src/PYTableEditor.cc
@@ -135,6 +135,12 @@ TableEditor::processPageKey (guint keyval)
return TRUE;
}
break;
+ case IBUS_bracketleft:
+ if (m_config.squareBracketPage ()) {
+ pageUp ();
+ return TRUE;
+ }
+ break;
case IBUS_period:
if (m_config.commaPeriodPage ()) {
pageDown ();
@@ -147,6 +153,12 @@ TableEditor::processPageKey (guint keyval)
return TRUE;
}
break;
+ case IBUS_bracketright:
+ if (m_config.squareBracketPage ()) {
+ pageDown ();
+ return TRUE;
+ }
+ break;
case IBUS_Up:
case IBUS_KP_Up:
diff --git a/src/PYXMLUtil.cc b/src/PYXMLUtil.cc
new file mode 100644
index 0000000..dcefc14
--- /dev/null
+++ b/src/PYXMLUtil.cc
@@ -0,0 +1,188 @@
+/* vim:set et ts=4 sts=4:
+ *
+ * ibus-libpinyin - Intelligent Pinyin engine based on libpinyin for IBus
+ *
+ * Copyright (c) 2024 Peng Wu <alexepico@gmail.com>
+ *
+ * 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 3 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 program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "PYXMLUtil.h"
+#include <glib.h>
+#include <gio/gio.h>
+#ifdef ENABLE_LIBNOTIFY
+#include <libnotify/notify.h>
+#endif
+
+namespace PY {
+
+struct EngineXMLVersion{
+ gboolean in_version_tag;
+ /* There are two versions in the XML file, only keep the first version here. */
+ gchar * first_version;
+};
+
+static void engine_parser_start_element (GMarkupParseContext *context,
+ const gchar *element_name,
+ const gchar **attribute_names,
+ const gchar **attribute_values,
+ gpointer user_data,
+ GError **error);
+static void engine_parser_end_element (GMarkupParseContext *context,
+ const gchar *element_name,
+ gpointer user_data,
+ GError **error);
+static void engine_parser_characters (GMarkupParseContext *context,
+ const gchar *text,
+ gsize text_len,
+ gpointer user_data,
+ GError **error);
+static void engine_parser_passthrough (GMarkupParseContext *context,
+ const gchar *passthrough_text,
+ gsize text_len,
+ gpointer user_data,
+ GError **error);
+static void engine_parser_error (GMarkupParseContext *context,
+ GError *error,
+ gpointer user_data);
+
+
+/*
+ * Parser
+ */
+static const GMarkupParser engine_xml_parser = {
+ engine_parser_start_element,
+ engine_parser_end_element,
+ engine_parser_characters,
+ engine_parser_passthrough,
+ engine_parser_error
+};
+
+struct EngineXMLFile{
+ gboolean in_version_tag;
+ gchar * first_version;
+};
+
+static void
+engine_parser_start_element (GMarkupParseContext *context,
+ const gchar *element_name,
+ const gchar **attribute_names,
+ const gchar **attribute_values,
+ gpointer user_data,
+ GError **error)
+{
+ EngineXMLFile * xmlfile = (EngineXMLFile *) user_data;
+ if (0 == strcmp(element_name, "version"))
+ xmlfile->in_version_tag = TRUE;
+}
+
+static void
+engine_parser_end_element (GMarkupParseContext *context,
+ const gchar *element_name,
+ gpointer user_data,
+ GError **error)
+{
+ EngineXMLFile * xmlfile = (EngineXMLFile *) user_data;
+ if (0 == strcmp(element_name, "version"))
+ xmlfile->in_version_tag = FALSE;
+}
+
+static void
+engine_parser_characters (GMarkupParseContext *context,
+ const gchar *text,
+ gsize text_len,
+ gpointer user_data,
+ GError **error)
+{
+ EngineXMLFile * xmlfile = (EngineXMLFile *) user_data;
+ if (xmlfile->in_version_tag && xmlfile->first_version == NULL)
+ xmlfile->first_version = g_strdup(text);
+}
+
+static void
+engine_parser_passthrough (GMarkupParseContext *context,
+ const gchar *passthrough_text,
+ gsize text_len,
+ gpointer user_data,
+ GError **error)
+{
+}
+
+static void
+engine_parser_error (GMarkupParseContext *context,
+ GError *error,
+ gpointer user_data)
+{
+ g_printerr ("ERROR: %s\n", error->message);
+}
+
+gchar *
+load_file_content(const gchar * filename)
+{
+ gboolean success = FALSE;
+ GError *error = NULL;
+
+ GFile *file = NULL;
+ char *data = NULL;
+ gsize len = 0;
+
+ file = g_file_new_for_path (filename);
+ success = g_file_load_contents (file, NULL, &data, &len, NULL, &error);
+ g_object_unref (file);
+
+ return data;
+}
+
+gboolean
+parse_engine_version(const char * filename, gchar ** version)
+{
+ GMarkupParseContext *context = NULL;
+ gboolean success = FALSE;
+ GError *error = NULL;
+
+ GFile *file = NULL;
+ char *data = NULL;
+ gsize len = 0;
+
+ EngineXMLFile xmlfile;
+ memset(&xmlfile, 0, sizeof(EngineXMLFile));
+
+ file = g_file_new_for_path (filename);
+ success = g_file_load_contents (file, NULL, &data, &len, NULL, &error);
+ g_object_unref (file);
+ context = g_markup_parse_context_new (&engine_xml_parser, G_MARKUP_DEFAULT_FLAGS, &xmlfile, NULL);
+ success = g_markup_parse_context_parse (context, data, len, NULL);
+ g_markup_parse_context_free (context);
+ g_free (data);
+
+ *version = xmlfile.first_version;
+ return TRUE;
+}
+
+void
+show_message(const char* summary, const char* details)
+{
+#ifdef ENABLE_LIBNOTIFY
+ NotifyNotification* notice = notify_notification_new (summary, details, NULL);
+ notify_notification_show (notice, NULL);
+ g_object_unref (notice);
+#else
+ if (details == NULL)
+ g_message ("%s\n", summary);
+ else
+ g_message ("%s\n%s\n", summary, details);
+#endif
+}
+
+};
diff --git a/src/PYXMLUtil.h b/src/PYXMLUtil.h
new file mode 100644
index 0000000..10fe4f6
--- /dev/null
+++ b/src/PYXMLUtil.h
@@ -0,0 +1,43 @@
+/* vim:set et ts=4 sts=4:
+ *
+ * ibus-libpinyin - Intelligent Pinyin engine based on libpinyin for IBus
+ *
+ * Copyright (c) 2024 Peng Wu <alexepico@gmail.com>
+ *
+ * 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 3 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 program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __PY_XML_UTIL_H_
+#define __PY_XML_UTIL_H_
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <glib.h>
+
+namespace PY {
+
+gchar *
+load_file_content(const gchar * filename);
+
+gboolean
+parse_engine_version(const char * filename, gchar ** version);
+
+void
+show_message(const char* summary, const char* details);
+
+};
+
+#endif
diff --git a/src/default.inputmethod.xml.in.in b/src/default.inputmethod.xml.in.in
new file mode 100644
index 0000000..c68a61d
--- /dev/null
+++ b/src/default.inputmethod.xml.in.in
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- filename: default.xml -->
+<engines>
+ <engine>
+ <name>libpinyin</name>
+ <language>zh_CN</language>
+ <license>GPL</license>
+ <author>
+ Peng Wu &lt;alexepico@gmail.com&gt;
+ Peng Huang &lt;shawn.p.huang@gmail.com&gt;
+ BYVoid &lt;byvoid1@gmail.com&gt;
+ </author>
+ <icon>@PKGDATADIR@/icons/ibus-pinyin.svg</icon>
+ <layout>default</layout>
+ <longname>Intelligent Pinyin</longname>
+ <description>Intelligent Pinyin input method</description>
+ <rank>99</rank>
+ <symbol>&#x62FC;</symbol>
+ @ICON_PROP_KEY_XML@
+ <setup>@LIBEXECDIR@/ibus-setup-libpinyin libpinyin</setup>
+ <version>@VERSION@</version>
+ <textdomain>ibus-libpinyin</textdomain>
+ </engine>
+ <engine>
+ <name>libbopomofo</name>
+ <language>zh_TW</language>
+ <license>GPL</license>
+ <author>
+ Peng Wu &lt;alexepico@gmail.com&gt;
+ Peng Huang &lt;shawn.p.huang@gmail.com&gt;
+ BYVoid &lt;byvoid1@gmail.com&gt;
+ </author>
+ <icon>@PKGDATADIR@/icons/ibus-bopomofo.svg</icon>
+ <layout>default</layout>
+ <longname>Bopomofo</longname>
+ <description>Bopomofo input method</description>
+ <rank>98</rank>
+ <symbol>&#x3109;</symbol>
+ @ICON_PROP_KEY_XML@
+ <setup>@LIBEXECDIR@/ibus-setup-libpinyin libbopomofo</setup>
+ <version>@VERSION@</version>
+ <textdomain>ibus-libpinyin</textdomain>
+ </engine>
+</engines>
diff --git a/src/libpinyin.inputmethod.xml.in.in b/src/libpinyin.inputmethod.xml.in.in
new file mode 100644
index 0000000..b7c4c3e
--- /dev/null
+++ b/src/libpinyin.inputmethod.xml.in.in
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- filename: pinyin.xml -->
+<component>
+ <name>org.freedesktop.IBus.Libpinyin</name>
+ <description>Libpinyin Component</description>
+ <exec>@LIBEXECDIR@/ibus-engine-libpinyin --ibus</exec>
+ <version>@VERSION@</version>
+ <author>Peng Wu &lt;alexepico@gmail.com&gt;</author>
+ <license>GPL</license>
+ <homepage>https://github.com/libpinyin/ibus-libpinyin</homepage>
+ <textdomain>ibus-libpinyin</textdomain>
+
+ <!-- for engines -->
+ <observed-paths>
+ <path>~/.config/ibus/libpinyin/engines.xml</path>
+ <path>@PKGDATADIR@/default.xml</path>
+ </observed-paths>
+ <engines exec="@LIBEXECDIR@/ibus-engine-libpinyin --xml" />
+</component>
diff --git a/src/libpinyin.xml.in.in b/src/libpinyin.xml.in.in
deleted file mode 100644
index d548375..0000000
--- a/src/libpinyin.xml.in.in
+++ /dev/null
@@ -1,53 +0,0 @@
-<?xml version=\"1.0\" encoding=\"utf-8\"?>
-<!-- filename: pinyin.xml -->
-<component>
- <name>org.freedesktop.IBus.Libpinyin</name>
- <description>Libpinyin Component</description>
- <exec>${libexecdir}/ibus-engine-libpinyin --ibus</exec>
- <version>@VERSION@</version>
- <author>Peng Wu &lt;alexepico@gmail.com&gt;</author>
- <license>GPL</license>
- <homepage>https://github.com/libpinyin/ibus-libpinyin</homepage>
- <textdomain>ibus-libpinyin</textdomain>
-
- <engines>
- <engine>
- <name>libpinyin</name>
- <language>zh_CN</language>
- <license>GPL</license>
- <author>
- Peng Wu &lt;alexepico@gmail.com&gt;
- Peng Huang &lt;shawn.p.huang@gmail.com&gt;
- BYVoid &lt;byvoid1@gmail.com&gt;
- </author>
- <icon>${pkgdatadir}/icons/ibus-pinyin.svg</icon>
- <layout>default</layout>
- <longname>Intelligent Pinyin</longname>
- <description>Intelligent Pinyin input method</description>
- <rank>99</rank>
- <symbol>&#x62FC;</symbol>
- @ICON_PROP_KEY_XML@
- <setup>${libexecdir}/ibus-setup-libpinyin libpinyin</setup>
- <textdomain>ibus-libpinyin</textdomain>
- </engine>
- <engine>
- <name>libbopomofo</name>
- <language>zh_TW</language>
- <license>GPL</license>
- <author>
- Peng Wu &lt;alexepico@gmail.com&gt;
- Peng Huang &lt;shawn.p.huang@gmail.com&gt;
- BYVoid &lt;byvoid1@gmail.com&gt;
- </author>
- <icon>${pkgdatadir}/icons/ibus-bopomofo.svg</icon>
- <layout>default</layout>
- <longname>Bopomofo</longname>
- <description>Bopomofo input method</description>
- <rank>98</rank>
- <symbol>&#x3109;</symbol>
- @ICON_PROP_KEY_XML@
- <setup>${libexecdir}/ibus-setup-libpinyin libbopomofo</setup>
- <textdomain>ibus-libpinyin</textdomain>
- </engine>
- </engines>
-</component>