// jmode (XIM Server) currently for Japanese
// initialize many modules
//
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif

#include <stdio.h>
#include <string.h>
#include <locale.h>
#include <ctype.h>
#include <stdlib.h>
#include <pwd.h>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <gtk/gtk.h>
#include "jmode.h"
#include "keyatom.h"

//設定
int g_option_mask;
int uid;
char *homedir;
int scr_width,scr_height;
int host_byte_order;

//文字列
#ifdef __FreeBSD__
#define LANG "ja_JP.EUC"
#else
#define LANG "ja_JP"
#endif
#define VERSION_NAME "jmode out of the way! Version "VERSION"\n"
char *version_name=VERSION_NAME;
char *usage=
"--help , --version :Show usage or version\n"
"--popup :use popup window\n"
"--trace :trace-connection\n"
"--trace-xim :trace-xim-message\n"
#ifdef USE_GNOME_APPLET
"--toolbar :not as a gnome panel applet\n"
#endif
#ifdef USE_WITHDRAWN
"--withdrawn :as WindowMaker DockApp / Blackbox slit\n"
#endif
"--issue :Show the current issue\n";



static char *issue=
VERSION_NAME
"jmodeの起動以降に環境変数XMODIFIERSに@im=jmode を\n"
"セットして起動したアプリケーションに対して入力が可能です。\n"
"(ktermや,gtkを使ったものなどの対応アプリケーションに限る)\n";

static void
print_version()
{
    printf(version_name);
}

static void
print_usage()
{
    print_version();
    printf(usage);
    exit(0);
}

static void
parse_args(int argc, char **argv)
{
    int i;
    for (i = 1; i < argc; i++) {
	if (!strncmp(argv[i], "--", 2)) {
	    char *opt;
	    opt = &argv[i][2];
	    if (!strcmp(opt, "version")) {
		print_version();
		exit(0);
	    } else if (!strcmp(opt, "help")) {
		print_usage();
	    } else if(!strcmp(opt, "trace")) {
		g_option_mask |= OPT_TRACE;
	    } else if(!strcmp(opt, "trace-xim")) {
		g_option_mask |= OPT_TRACE_XIM;
	    } else if (!strcmp(opt, "popup")) {
		g_option_mask |= OPT_POPUP;
            } else if (!strcmp(opt, "issue")) {
		g_option_mask |= OPT_ISSUE;
#ifdef USE_GNOME_APPLET
	    } else if (!strcmp(opt, "toolbar")) {
		g_option_mask |= OPT_TOOLBAR;
#endif
#ifdef USE_WITHDRAWN
	    } else if (!strcmp(opt, "withdrawn")) {
		g_option_mask |= OPT_WITHDRAWN;
#endif
	    }
	}
    }
}

static void
get_runtime_env()
{
    uid = getuid();
    homedir = strdup(getenv("HOME"));
    if (!homedir) {
	struct passwd *pw;
	pw = getpwuid(uid);
	if (!pw) {
	    printf("failed to getpwuid\n");
	    exit(0);
	}
	homedir = strdup(pw->pw_dir);
    }
    int i = 1;
    char *v = (char *)&i;
    if (*v == 1) {
	host_byte_order = LSB_FIRST;
    } else {
	host_byte_order = MSB_FIRST;
    }
}

void
global_finalize(int none)
{
    free_kkconv();
    exit(0);
}

static void
init_finalize_handlers()
{
    signal(SIGQUIT,(void (*)(int))global_finalize);
    gtk_quit_add(0, (GtkFunction)global_finalize, 0);
}

int
main(int argc, char **argv)
{
    int fd;
    KKConv *conv;

    init_default_atoms();
#ifndef USE_GNOME_APPLET
    g_option_mask |= OPT_TOOLBAR;
#endif
    putenv("LANG=" LANG);
    setlocale(LC_ALL, LANG);
    get_runtime_env();
    parse_args(argc, argv);
	
    // gtkの初期化後にやるとgtkが混乱する。
    if (!pretrans_register()) {
	return 1;
    }

    if (strncmp(gtk_set_locale(), "ja", 2)) {
	printf("failed to set Japanese locale.\n");
	return 1;
    }

    init_preconf_kkconv();
    read_conf_file();
    conv = init_kkconv();
    init_toolkit(&argc, &argv);
    init_finalize_handlers();
    //ユーザインターフェースはkkconvの後に初期化されないといけない
    init_ui(conv);

    connection_setup();
    fd = pretrans_setup();
    if (fd == -1) {
	return 0;
    }
    init_convdisp();
    if (g_option_mask & OPT_ISSUE) {
	show_issue(issue);
    }

    Dispatcher *dpt = get_dispatcher();
    dpt->mainLoop();

    global_finalize(0);
    return 0;
}

int
pad4(int x)
{
    return (4-(x%4))%4;
}

void
hex_dump(unsigned char *buf, int len)
{
    int i, j;
    unsigned char c[16];
    for (i = 0 ; i < len ; i += 16) {
	printf("%8.8x ", i);
	for (j = 0 ; j < 16 ; j++) {
	    if (i + j < len) {
		c[j] = buf[i+j];
		if (j == 7) {
		    printf("%2.2x-", c[j]);
		} else {
		    printf("%2.2x ", c[j]);
		}
	    } else {
		c[j] = 0;
		printf("-- ");
	    }
	}
	printf(" ");
	for (j = 0; j < 16; j++) {
	    if (isprint(c[j])) {
		printf("%c", c[j]);
	    } else {
		printf(".");
	    }
	}
	printf("\n");
    }
}

char *
my_getenv(char *s)
{
    atom_t a = get_atom_by_name(s);
    if (is_bind_to(a, A_env)) {
	char *c;
	c = getenv(s);
	if (c) {
	    return c;
	}
    }
    atom_t b;
    b = get_bound_atoms(a, 0);
    return get_atom_name(b);
}
/*
 * Local variables:
 *  c-indent-level: 4
 *  c-basic-offset: 4
 * End:
 */
