Newer
Older
scim-wnn / honoka / src / honoka_imengine_setup.cpp
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 *  Copyright (C) 2004 TAM (Teppei Tamra)
 *  Copyright (C) 2004 Hiroyuki Ikezoe
 *  Copyright (C) 2004 Takuro Ashie
 *
 *  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, 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, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

/*
 * Based on scim-hangul.
 * Copyright (c) 2004 James Su <suzhe@turbolinux.com.cn>
 */

#define Uses_SCIM_CONFIG_BASE

#include <gtk/gtk.h>
#include <sys/types.h>
#include <dirent.h>
#include <dlfcn.h>

#ifdef HAVE_CONFIG_H
  #include <config.h>
#endif

#include <scim.h>
#include <gtk/scimkeyselection.h>
#include "honoka_def.h"

#ifdef HAVE_GETTEXT
  #include <libintl.h>
  #define _(String) dgettext(GETTEXT_PACKAGE,String)
  #define N_(String) (String)
#else
  #define _(String) (String)
  #define N_(String) (String)
  #define bindtextdomain(Package,Directory)
  #define textdomain(domain)
  #define bind_textdomain_codeset(domain,codeset)
#endif

using namespace scim;

#define scim_module_init honoka_imengine_setup_LTX_scim_module_init
#define scim_module_exit honoka_imengine_setup_LTX_scim_module_exit

#define scim_setup_module_create_ui       honoka_imengine_setup_LTX_scim_setup_module_create_ui
#define scim_setup_module_get_category    honoka_imengine_setup_LTX_scim_setup_module_get_category
#define scim_setup_module_get_name        honoka_imengine_setup_LTX_scim_setup_module_get_name
#define scim_setup_module_get_description honoka_imengine_setup_LTX_scim_setup_module_get_description
#define scim_setup_module_load_config     honoka_imengine_setup_LTX_scim_setup_module_load_config
#define scim_setup_module_save_config     honoka_imengine_setup_LTX_scim_setup_module_save_config
#define scim_setup_module_query_changed   honoka_imengine_setup_LTX_scim_setup_module_query_changed


#include <honokasetupgtk.h>
#include <honokapluginbase.h>

typedef HonokaSetupCorePage *pluginSetupFunc();
typedef int getPluginVersionFunc();

static GtkWidget * create_setup_window ();
static void        load_config (const ConfigPointer &config);
static void        save_config (const ConfigPointer &config);
static bool        query_changed ();

static HonokaSetupGtk * setup;

// Module Interface.

extern "C" {
    void scim_module_init (void)
    {
        bindtextdomain (GETTEXT_PACKAGE, HONOKA_LOCALEDIR);
        bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
    }

    void scim_module_exit (void)
    {
    }

    GtkWidget * scim_setup_module_create_ui (void)
    {
        return create_setup_window ();
    }

    String scim_setup_module_get_category (void)
    {
        return String ("IMEngine");
    }

    String scim_setup_module_get_name (void)
    {
        return String (_("Honoka"));
    }

    String scim_setup_module_get_description (void)
    {
        return String (_("A Honoka IMEngine Module."));
    }

    void scim_setup_module_load_config (const ConfigPointer &config)
    {
        load_config (config);
    }

    void scim_setup_module_save_config (const ConfigPointer &config)
    {
        save_config (config);
    }

    bool scim_setup_module_query_changed ()
    {
        return query_changed ();
    }
} // extern "C"


static GtkWidget * create_setup_window ()
{
    setup = new HonokaSetup("setup","","");
    HonokaSetupPage *page;
    vector<String> l;

    //
    // general setting 
    //
    
    page = new HonokaSetupPage(_("general setting"),"","");
    page->append(new HonokaSetupIntItem(
        _("_Auto candidates popup: "),
        HONOKA_CONFIG_ALP,
        _("set the count of conversion until displaying the list of lookup result automatically."),
        HONOKA_DEFAULT_ALP,
        -1,10
    ));
    page->append(new HonokaSetupBoolItem(
        _("Auto _conversion: "),
        HONOKA_CONFIG_AUTO_CONVERSION,
        _("If you set default to the auto conversion mode use, check this."),
        HONOKA_DEFAULT_AUTO_CONVERSION
    ));
    page->append(new HonokaSetupBoolItem(
        _("_NumKey selection: "),
        HONOKA_CONFIG_NUMKEY_SELECT,
        _("If you use the candidate selection by numkey, check this."),
        HONOKA_DEFAULT_NUMKEY_SELECT
    ));
    page->append(new HonokaSetupBoolItem(
        _("use _Prediction: "),
        HONOKA_CONFIG_PREDICTION,
        _("If you use the prediction, check this."),
        HONOKA_DEFAULT_PREDICTION
    ));
    page->append(new HonokaSetupBoolItem(
        _("_Realtime Prediction: "),
        HONOKA_CONFIG_REALTIME_PREDICTION,
        _("If you use the realtime prediction, check this."),
        HONOKA_DEFAULT_REALTIME_PREDICTION
    ));
    page->append(new HonokaSetupIntItem(
        _("_Delay Prediction search: "),
        HONOKA_CONFIG_PREDICTION_DELAY,
        _("set the time to delay prediction search. (1/10secs)"),
        HONOKA_DEFAULT_PREDICTION_DELAY,
        0,10
    ));
    page->append(new HonokaSetupBoolItem(
        _("_Select prediction direct: "),
        HONOKA_CONFIG_SELECT_PREDICTION_DIRECT,
        _("If you want select prediction direct with numkey, check this."),
        HONOKA_DEFAULT_SELECT_PREDICTION_DIRECT
    ));
    page->append(new HonokaSetupBoolItem(
        _("Restore previous setting: "),
        HONOKA_CONFIG_SAVE_SETTING,
        _("if you restore previous setting at the startup time ,check this."),
        HONOKA_DEFAULT_SAVE_SETTING
    ));
    page->append(new HonokaSetupEntryItem(
        _("Default _PreEditor: "),
        HONOKA_CONFIG_DEFAULT_PREEDITOR,
        _("select the default preeditor."),
        HONOKA_DEFAULT_DEFAULT_PREEDITOR
    ));
    page->append(new HonokaSetupEntryItem(
        _("Default _Convertor: "),
        HONOKA_CONFIG_DEFAULT_CONVERTOR,
        _("select the default Convertor."),
        HONOKA_DEFAULT_DEFAULT_CONVERTOR
    ));
    page->append(new HonokaSetupEntryItem(
        _("Default _Predictor: "),
        HONOKA_CONFIG_DEFAULT_PREDICTOR,
        _("select the default predictor."),
        HONOKA_DEFAULT_DEFAULT_PREDICTOR
    ));
    page->append(new HonokaSetupBoolItem(
        _("Enable Changeable _Splitter: "),
        HONOKA_CONFIG_CHANGEABLE_SPLITTER,
        _("If you want to select a segments splitter other than a selected converter,check this."),
        HONOKA_DEFAULT_CHANGEABLE_SPLITTER
    ));
    
    setup->append(page);
    
    
    //
    // key setting
    //
    
    HonokaSetup * keys = new HonokaSetup(_("key setting"),"","");

    page = new HonokaSetupPage(_("Common keys"),"","");
    page->append(new HonokaSetupKeyItem(
        _("Commit keys:"),
        HONOKA_CONFIG_KEY_COMMIT,
        _("The key events to commit the preedit string. "),
        HONOKA_DEFAULT_KEY_COMMIT
    ));
    page->append(new HonokaSetupKeyItem(
        _("Convert keys:"),
        HONOKA_CONFIG_KEY_CONVERSION_START,
        _("The key events to convert the preedit string to kanji. "),
        HONOKA_DEFAULT_KEY_CONVERSION_START
    ));
    page->append(new HonokaSetupKeyItem(
        _("Cancel keys:"),
        HONOKA_CONFIG_KEY_CANCEL,
        _("The key events to cancel preediting or converting. "),
        HONOKA_DEFAULT_KEY_CANCEL
    ));
    page->append(new HonokaSetupKeyItem(
        _("Backspace keys:"),
        HONOKA_CONFIG_KEY_BACKSPACE,
        _("The key events to delete a character before caret. "),
        HONOKA_DEFAULT_KEY_BACKSPACE
    ));
    page->append(new HonokaSetupKeyItem(
        _("Delete keys:"),
        HONOKA_CONFIG_KEY_DELETE,
        _("The key events to delete a character after caret. "),
        HONOKA_DEFAULT_KEY_DELETE
    ));
    keys->append(page);

    page = new HonokaSetupPage(_("Preedit keys"),"","");
    page->append(new HonokaSetupKeyItem(
        _("Move forward keys:"),
        HONOKA_CONFIG_KEY_FORWARD,
        _("The key events to move the caret to forward. "),
        HONOKA_DEFAULT_KEY_FORWARD
    ));
    page->append(new HonokaSetupKeyItem(
        _("Move backward keys:"),
        HONOKA_CONFIG_KEY_BACKWARD,
        _("The key events to move the caret to backward. "),
        HONOKA_DEFAULT_KEY_BACKWARD
    ));
    keys->append(page);

    page = new HonokaSetupPage(_("Segment keys"),"","");
    page->append(new HonokaSetupKeyItem(
        _("Next segment keys:"),
        HONOKA_CONFIG_KEY_CONVERSION_FORWARD,
        _("The key events to select next segment. "),
        HONOKA_DEFAULT_KEY_CONVERSION_FORWARD
    ));
    page->append(new HonokaSetupKeyItem(
        _("Previous segment keys:"),
        HONOKA_CONFIG_KEY_CONVERSION_BACKWARD,
        _("The key events to select previous segment. "),
        HONOKA_DEFAULT_KEY_CONVERSION_BACKWARD
    ));
    page->append(new HonokaSetupKeyItem(
        _("Shrink segment keys:"),
        HONOKA_CONFIG_KEY_CONVERSION_SHRINK,
        _("The key events to shrink the selected segment. "),
        HONOKA_DEFAULT_KEY_CONVERSION_SHRINK
    ));
    page->append(new HonokaSetupKeyItem(
        _("Expand segment keys:"),
        HONOKA_CONFIG_KEY_CONVERSION_EXPAND,
        _("The key events to expand the selected segment. "),
        HONOKA_DEFAULT_KEY_CONVERSION_EXPAND
    ));
    keys->append(page);

    page = new HonokaSetupPage(_("Candidates keys"),"","");
    page->append(new HonokaSetupKeyItem(
        _("Next keys:"),
        HONOKA_CONFIG_KEY_CONVERSION_NEXT,
        _("The key events to select next candidate. "),
        HONOKA_DEFAULT_KEY_CONVERSION_NEXT
    ));
    page->append(new HonokaSetupKeyItem(
        _("Previous keys:"),
        HONOKA_CONFIG_KEY_CONVERSION_PREV,
        _("The key events to select previous candidate. "),
        HONOKA_DEFAULT_KEY_CONVERSION_PREV
    ));
    page->append(new HonokaSetupKeyItem(
        _("candidates list keys:"),
        HONOKA_CONFIG_KEY_LOOKUPPOPUP,
        _("The key events to popup candidates list. "),
        HONOKA_DEFAULT_KEY_LOOKUPPOPUP
    ));
    page->append(new HonokaSetupKeyItem(
        _("Page up keys:"),
        HONOKA_CONFIG_KEY_LOOKUPPAGEUP,
        _("The key events to select page up candidates. "),
        HONOKA_DEFAULT_KEY_LOOKUPPAGEUP
    ));
    page->append(new HonokaSetupKeyItem(
        _("Page down keys:"),
        HONOKA_CONFIG_KEY_LOOKUPPAGEDOWN,
        _("The key events to select page down candidates. "),
        HONOKA_DEFAULT_KEY_LOOKUPPAGEDOWN
    ));
    keys->append(page);

    page = new HonokaSetupPage(_("Other function keys"),"","");
    page->append(new HonokaSetupKeyItem(
        _("auto conversion mode keys:"),
        HONOKA_CONFIG_KEY_AUTO_CONVERSION,
        _("The key events to change auto conversion mode. "),
        HONOKA_DEFAULT_KEY_AUTO_CONVERSION
    ));
    page->append(new HonokaSetupKeyItem(
        _("Prediction keys:"),
        HONOKA_CONFIG_KEY_SELECT_PREDICTION,
        _("The key events to select from prediction list. "),
        HONOKA_DEFAULT_KEY_SELECT_PREDICTION
    ));
    page->append(new HonokaSetupKeyItem(
        _("Convert to HIRAGANA keys:"),
        HONOKA_CONFIG_KEY_CONVERT_HIRAGANA,
        _("The key events to convert the selected candidate or the preedit string to HIRAGANA. "),
        HONOKA_DEFAULT_KEY_CONVERT_HIRAGANA
    ));
    page->append(new HonokaSetupKeyItem(
        _("Convert to KATAKANA keys:"),
        HONOKA_CONFIG_KEY_CONVERT_KATAKANA,
        _("The key events to convert the selected candidate or the preedit string to KATAKANA. "),
        HONOKA_DEFAULT_KEY_CONVERT_KATAKANA
    ));
    page->append(new HonokaSetupKeyItem(
        _("Convert to WIDE keys:"),
        HONOKA_CONFIG_KEY_CONVERT_WIDE,
        _("The key events to convert the selected candidate or the preedit string to WIDE-charactors. "),
        HONOKA_DEFAULT_KEY_CONVERT_WIDE
    ));
    page->append(new HonokaSetupKeyItem(
        _("Convert to HALF keys:"),
        HONOKA_CONFIG_KEY_CONVERT_HALF,
        _("The key events to convert the selected candidate or the preedit string to HALF-charactors. "),
        HONOKA_DEFAULT_KEY_CONVERT_HALF
    ));
    page->append(new HonokaSetupKeyItem(
        _("Convert to ikeiji keys:"),
        HONOKA_CONFIG_KEY_CONVERSION_SPECIAL2,
        _("The key events to convert the selected candidate to ikei-kanji. "),
        HONOKA_DEFAULT_KEY_CONVERSION_SPECIAL2
    ));
    page->append(new HonokaSetupKeyItem(
        _("Convert to rensou keys:"),
        HONOKA_CONFIG_KEY_CONVERSION_SPECIAL1,
        _("The key events to convert the selected candidate to the associated acceptation string.  "),
        HONOKA_DEFAULT_KEY_CONVERSION_SPECIAL1
    ));
    page->append(new HonokaSetupKeyItem(
        _("Character type conversion :"),
        HONOKA_CONFIG_KEY_CONVERT_CTYPETOGGLE,
        _("The key events to string to other character type."),
        HONOKA_DEFAULT_KEY_CONVERT_CTYPETOGGLE
    ));

    keys->append(page);
    
    setup->append(keys);
    
    //
    // plugins setting
    //
    
    HonokaSetup * plugins = new HonokaSetup(_("plugins setting"),"","");
    
    ////
    DIR *dir = opendir(HONOKA_PLUGINDIR);
    if (dir) {
        struct dirent *entry;
        while((entry = readdir(dir)) != NULL) {
            String d = entry->d_name;
            if ((d.substr(0,6) == "plugin") && (d.substr(d.length() - 3,3) == ".so")) {
                String pluginName = d.substr(0,d.length() - 3);
                d = String(HONOKA_PLUGINDIR) + "/" + d;
                void* plugin = dlopen(d.c_str(), RTLD_LAZY);
                if (!plugin) continue;
                pluginSetupFunc *pluginSetup = (pluginSetupFunc *)dlsym(plugin,"HonokaPluginSetup");
                getPluginVersionFunc *getPluginVersion = (getPluginVersionFunc *)dlsym(plugin,"getHonokaPluginVersion");
                if ((!pluginSetup) || (!getPluginVersion)) {
                    dlclose(plugin);
                    continue;
                }
                if (getPluginVersion() == HONOKA_PLUGIN_VERSION) {
                    HonokaSetupCorePage *p = pluginSetup();
                    // "if you use this plugin, check this." ----
                    HonokaSetupGtkPage *page = new HonokaSetupGtkPage(p->getLabel(),p->getName(),p->getTip());
                    page->append(new HonokaSetupBoolItem(
                        _("_Use this plugin: "),
                        String(HONOKA_CONFIG_PLUGINLOADER_PREFIX) + "/" + pluginName,
                        _("if you use this plugin, check this."),
                        true
                    ));
                    for(unsigned int i = 0;i < p->getChildren().size();i ++) {
                        page->append(HonokaSetup::HonokaSetupCoreToGtk(p->getChildren()[i]));
                    }
                    plugins->append(page);
                    //plugin->append(p);
                }
                dlclose(plugin);
            }
        }
        closedir(dir);
    }
    ////
    
    setup->append(plugins);


    return setup->getValueWidget();
};

static void
load_config (const ConfigPointer &config)
{
    if (!config.null()) {
        setup->readConfig(config);
        HonokaSetup::changed = false;
    }
}

static void
save_config (const ConfigPointer &config)
{
    if (!config.null()) {
        setup->saveConfig(config);
        HonokaSetup::changed = false;
    }
}

static bool
query_changed ()
{
    return HonokaSetup::changed;
}