/* Copyright (C) 2001-2002 Kenichi Suto
*
* 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 program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#define _GLOBAL
#include <signal.h>
#include <sys/wait.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <pthread.h>
#ifdef HAVE_CONFIG_H
#include "../config.h"
#endif
#ifdef HAVE_GETOPT_LONG
#include <getopt.h>
#endif
#include "defs.h"
#include "global.h"
#include <gdk/gdkkeysyms.h>
#include <X11/Xlib.h>
#include <gdk/gdkx.h>
#include "eb.h"
#include "dictheading.h"
#include "dicttext.h"
#include "dictgroup.h"
#include "weblist.h"
#include "pixmap.h"
#include "selection.h"
#include "preference.h"
#include "dialog.h"
#define DEFAULT_WINDOW_WIDTH 670
#define DEFAULT_WINDOW_HEIGHT 440
static gboolean style_set=FALSE;
static pthread_t server_tid=(pthread_t)-1;
static guint signal_remote_command = 0;
static gint conn;
static gchar sock_name[512];
extern GtkWidget *dict_scroll;
extern GtkWidget *note_tree;
void exit_program( GtkWidget *widget,
gpointer data )
{
if(pthread_self() == server_tid)
pthread_exit(0);
ebook_end();
gdk_window_get_root_origin(window->window, &window_x, &window_y);
window_width = window->allocation.width;
window_height = window->allocation.height;
tree_width = note_tree->allocation.width;
tree_height = note_tree->allocation.height;
save_preference();
gtk_main_quit ();
if(server_tid != (pthread_t)-1)
pthread_cancel(server_tid);
close(conn);
unlink(sock_name);
// pthread_kill(server_tid, SIGKILL);
pthread_join(server_tid, NULL);
exit(0);
}
static void delete_event( GtkWidget *widget,
GdkEvent *event,
gpointer data )
{
exit_program(widget, data);
}
static void sig_handler(int sig){
gint status;
//g_print("(%d) signal %d received\n", getpid(), sig);
switch(sig){
case SIGCHLD:
wait(&status);
if(WEXITSTATUS(status) == 100){
warning(_("Failed to execute command. Please check setting."));
}
break;
case SIGTERM:
case SIGINT:
exit_program(NULL, NULL);
break;
default:
break;
}
}
static void style_set_event( GtkWidget *widget,
GdkEvent *event,
gpointer data )
{
style_set = TRUE;
}
static void draw_event( GtkWidget *widget,
GdkEvent *event,
gpointer data )
{
gint save_row;
gchar *text=NULL;
if(style_set == FALSE)
return;
save_row = current_row;
clear_tree(tree_root);
current_row = save_row;
show_result_tree();
if(current_position.page >= 0){
text = ebook_get_text(current_book_info,
current_position.page,
current_position.offset);
show_text(current_book_info, text);
free(text);
} else {
show_about();
}
style_set = FALSE;
}
gboolean perform_shortcut(GdkEventKey *event);
static gint window_key_event(GtkWidget *widget, GdkEventKey *event){
// g_print("window_key_event\n");
if(perform_shortcut(event) == TRUE){
gtk_signal_emit_stop_by_name(GTK_OBJECT(window), "key_press_event");
}
if(ebook_search_method() != SEARCH_METHOD_MULTI)
gtk_window_set_focus(GTK_WINDOW(window), word_entry);
return(FALSE);
}
gint g_argc;
gchar *g_argv[16];
static void remote_command_old( GtkWidget *widget,
gpointer data )
{
gboolean selection=FALSE;
gboolean popup=FALSE;
gboolean iconify=FALSE;
gboolean raise=FALSE;
gboolean save_popup;
gint i;
gint c;
gchar word[512];
Window xwindow;
int option_index = 0;
static struct option long_options[] = {
{"selection", 0, 0, 's'},
{"popup", 0, 0, 'p'},
{"raise", 0, 0, 'r'},
{"iconify", 0, 0, 'i'},
{0, 0, 0, 0}
};
/*
g_print("g_argc = %d\n", g_argc);
for(i=0;i<g_argc;i++){
printf("g_argv[%d] = %s\n", i, g_argv[i]);
}
*/
optarg = NULL;
optind = 0;
while(1){
#ifndef HAVE_GETOPT_LONG
c = getopt(g_argc, g_argv, "sprig:");
#else
c = getopt_long(g_argc, g_argv, "sprig:",
long_options, &option_index);
#endif
if(c == -1)
break;
switch( c ){
case 's' :
// printf("Option %c(%d).\n", c , optind);
selection = TRUE;
break;
case 'p' :
// printf("Option %c(%d).\n", c , optind);
popup = TRUE;
break;
case 'r' :
// printf("Option %c(%d).\n", c , optind);
raise = TRUE;
break;
case 'i' :
// printf("Option %c(%d).\n", c , optind);
iconify = TRUE;
break;
case 'g' :
// printf("Option %c with arg %s(%d).\n", c, optarg, optind);
break;
case '?' :
break;
default :
// printf("Unknown option '%c'\n", optopt);
break;
}
optarg = NULL;
}
word[0] = '\0';
if(optind < g_argc){
while (optind < g_argc){
strcat(word, g_argv[optind++]);
strcat(word, " ");
}
}
if(selection){
g_print("Searching selection\n");
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button_popup), popup);
bshow_popup = popup;
copy_clipboard(NULL);
// if(!bshow_popup)
gtk_window_activate_focus(GTK_WINDOW(window));
gtk_window_activate_default(GTK_WINDOW(window));
return;
} else if (iconify) {
g_print("Iconify\n");
// GTK2.0
// gdk_window_iconify(window->window);
xwindow = GDK_WINDOW_XWINDOW(window->window);
XIconifyWindow(GDK_DISPLAY (), xwindow, DefaultScreen (GDK_DISPLAY ()));
}
if (raise) {
g_print("Raise\n");
// gdk_window_hide(window->window);
gtk_widget_grab_focus(window);
gdk_window_raise(window->window);
// gdk_window_show(window->window);
// gtk_window_activate_focus(GTK_WINDOW(window));
/*
xwindow = GDK_WINDOW_XWINDOW(window->window);
XRaiseWindow(GDK_DISPLAY (), xwindow);
*/
}
if(strlen(word) != 0){
g_print("Searching %s\n", word);
gtk_entry_set_text(GTK_ENTRY(word_entry), word);
start_search();
}
}
extern GtkWidget *popup;
static void remote_command( GtkWidget *widget,
gpointer data )
{
gboolean bpopup=FALSE;
gint i;
gchar word[512];
if(strcmp(g_argv[1], "--search") == 0){
word[0] = '\0';
for(i=2; i < g_argc ; i ++){
strcat(word, g_argv[i]);
strcat(word, " ");
}
if(strlen(word) != 0){
g_print("Searching %s\n", word);
gtk_entry_set_text(GTK_ENTRY(word_entry), word);
start_search();
}
} else if((strcmp(g_argv[1], "--selection") == 0) ||
(strcmp(g_argv[1], "--popup") == 0)) {
if(strcmp(g_argv[1], "--popup") == 0)
bpopup = TRUE;
g_print("Searching selection\n");
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button_popup), bpopup);
bshow_popup = bpopup;
copy_clipboard(NULL);
return;
} else if(strcmp(g_argv[1], "--close-popup") == 0){
if(popup != NULL)
gtk_signal_emit_by_name(GTK_OBJECT (popup),
// "delete_event");
"close_popup");
gtk_signal_emit_by_name(GTK_OBJECT (popup),
"redraw");
}
}
static void *server_thread(void *arg)
{
gint count=0;
gchar buff[256];
int len, read_len;
gchar *p;
gint i;
gint state;
struct sockaddr_un address;
int sock;
size_t addrLength;
signal(SIGCHLD, SIG_DFL);
// signal(SIGINT, SIG_DFL);
signal(SIGTERM, SIG_DFL);
signal(SIGPIPE, SIG_DFL);
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &state);
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &state);
if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) {
perror("socket");
_exit(1);
}
/* Remove any preexisting socket (or other file) */
address.sun_family = AF_UNIX; /* Unix domain socket */
// strcpy(address.sun_path, "./sample-socket");
sprintf(sock_name, "%s/.remote-sock", package_dir);
strcpy(address.sun_path, sock_name);
unlink(sock_name);
/* The total length of the address includes the sun_family
element */
#ifndef HAVE_GETOPT_LONG
addrLength = sizeof(address.sun_len) + sizeof(address.sun_family) + strlen(address.sun_path) + 1;
address.sun_len = addrLength;
#else
addrLength = sizeof(address.sun_family) + strlen(address.sun_path);
#endif
if (bind(sock, (struct sockaddr *) &address, addrLength)){
perror("bind");
_exit(1);
}
if (listen(sock, 5)){
perror("listen");
_exit(1);
}
sprintf(buff, "remote command %d", count);
while ((conn = accept(sock, (struct sockaddr *) &address,
&addrLength)) >= 0) {
printf("---- getting data\n");
read_len = read(conn, buff, 1);
if(read_len != 1){
g_print("Failed to read socket\n");
close(conn);
continue;
}
len = (unsigned char)buff[0];
if(len == 0){
g_print("Data too short\n");
close(conn);
continue;
}
g_print("Receiving %d bytes of data...", len);
read_len = read(conn, buff, len);
if(read_len != len){
g_print("%d should be %d\n", read_len , len);
perror("read");
g_print("Failed to read socket\n");
close(conn);
continue;
}
g_print("done\n");
close(conn);
p = buff;
g_argc = *p;
p ++;
for(i=0; i<g_argc; i++){
g_argv[i] = p;
p = strchr(p, '\0');
p++;
}
gdk_threads_enter();
gtk_signal_emit (GTK_OBJECT (window), signal_remote_command);
gdk_threads_leave();
}
if (conn < 0) {
perror("accept");
_exit(1);
}
}
void execute_remote_command(gint argc, gchar **argv){
gchar buff[256];
gint len;
gint i;
g_print("execute_remote_command\n");
g_argc = argc;
for(i=0; i<argc ; i++)
g_argv[i] = argv[i];
gdk_threads_enter();
gtk_signal_emit (GTK_OBJECT (window), signal_remote_command);
gdk_threads_leave();
}
int main( int argc,
char *argv[] )
{
GtkWidget *dict_window;
GtkWidget *hidden_window;
GtkWidget *vbox;
gint i;
DIR *dir;
gchar *home_dir;
gchar buff[256];
gint rc;
pthread_attr_t thread_attr ;
signal(SIGCHLD, sig_handler);
signal(SIGINT, sig_handler);
signal(SIGTERM, sig_handler);
signal(SIGPIPE, sig_handler);
gtk_set_locale();
setlocale(LC_ALL,"");
bindtextdomain(PACKAGE,LOCALEDIR);
textdomain(PACKAGE);
g_thread_init(NULL);
gtk_init (&argc, &argv);
gdk_imlib_init();
// 外部変数の初期化
bauto_lookup = FALSE;
bbeep_on_nohit = TRUE;
bignore_locks = TRUE;
tree_root = NULL;
entry_focus_in = FALSE;
search_result = NULL;
current_position.page = -1;
current_position.offset = -1;
current_book_info = NULL;
line_space = 0.3;
h_space = 0;
v_space = 2;
h_border = 5;
v_border = 6;
menu_word_search = FALSE;
menu_endword_search = FALSE;
menu_exactword_search = FALSE;
menu_keyword_search = FALSE;
menu_menu = FALSE;
menu_copyright = FALSE;
menu_multi_search = FALSE;
max_search = 100;
max_remember_words = 10;
dict_label_bytes = 10;
auto_interval = 1000;
auto_minchar = 3;
auto_maxchar = 64;
bshow_menu_bar = 1;
bshow_status_bar = 1;
bshow_dict_bar = 1;
bshow_tree_tab = 1;
bending_correction = 1;
bending_only_nohit = 1;
bshow_popup = 1;
bshow_popup_title = 1;
popup_width = 300;
popup_height = 200;
window_x = 0;
window_y = 0;
window_width = DEFAULT_WINDOW_WIDTH;
window_height = DEFAULT_WINDOW_HEIGHT;
tree_width = 185;
tree_height = 344;
mpeg_template = strdup("plaympeg %f");
wave_template = strdup("playwave %f");
browser_template = strdup("gnome-moz-remote %f");
fontset_normal = strdup("-misc-fixed-medium-r-normal-*-14-*-*-*-*-*-*-*");
fontset_bold = strdup("-misc-fixed-bold-r-normal-*-14-*-*-*-*-*-*-*");
fontset_italic = strdup("-misc-fixed-medium-i-normal-*-14-*-*-*-*-*-*-*");
fontset_superscript = strdup("-misc-fixed-medium-r-normal-*-10-*-*-*-*-*-*-*");
// ディレクトリ名を外部変数にセットしておく
home_dir = getenv("HOME");
sprintf(buff, "/.%s", PACKAGE);
package_dir = calloc(strlen(home_dir)+strlen(buff)+1, 1);
sprintf(package_dir,"%s%s", home_dir, buff);
sprintf(buff, "/.%s/tmp", PACKAGE);
tmp_dir = calloc(strlen(home_dir)+strlen(buff)+1, 1);
sprintf(tmp_dir,"%s%s", home_dir, buff);
if((dir = opendir(package_dir)) == NULL){
if(mkdir(package_dir,
S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH) != 0){
fprintf(stderr, "Failed to create directory : %s\n", package_dir);
exit(1);
}
} else {
closedir(dir);
}
// テンポラリディレクトリを作成
if((dir = opendir(tmp_dir)) == NULL){
if(mkdir(tmp_dir,
S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH) != 0){
fprintf(stderr, "Failed to create directory : %s\n", tmp_dir);
exit(1);
}
} else {
closedir(dir);
sprintf(buff, "rm -fr %s/*", tmp_dir);
system(buff);
}
ebook_start();
load_preference();
load_ending();
load_ending_ja();
load_dictgroup();
load_shortcut();
alloc_colors();
tooltip = gtk_tooltips_new();
//gtk_tooltips_set_colors(tooltip, &colors[COLOR_YELLOW], &colors[COLOR_BLACK]);
#ifdef ENABLE_WEBSEARCH
load_weblist();
#endif
signal_remote_command =
gtk_object_class_user_signal_new (gtk_type_class (GTK_TYPE_WIDGET),
"remote_command",
GTK_RUN_LAST | GTK_RUN_ACTION,
gtk_marshal_NONE__POINTER,
GTK_TYPE_NONE, 0);
gtk_object_class_user_signal_new (gtk_type_class (GTK_TYPE_WIDGET),
"close_popup",
GTK_RUN_LAST | GTK_RUN_ACTION,
gtk_marshal_NONE__POINTER,
GTK_TYPE_NONE, 0);
pthread_attr_init (&thread_attr) ;
pthread_attr_setstacksize (&thread_attr, 512*1024) ;
rc = pthread_create(&server_tid, &thread_attr, server_thread, (void *)NULL);
if(rc != 0){
perror("pthread_create");
exit(1);
}
pthread_attr_destroy(&thread_attr);
// window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
window = gtk_widget_new (GTK_TYPE_WINDOW,
"type", GTK_WINDOW_TOPLEVEL,
"x", window_x,
"y", window_y,
NULL);
// style = gtk_widget_get_style(window);
sprintf(buff, "EBView %s", VERSION);
gtk_window_set_title (GTK_WINDOW (window), buff);
gtk_window_set_wmclass(GTK_WINDOW(window), "Main", "EBView");
gtk_signal_connect (GTK_OBJECT (window), "delete_event",
GTK_SIGNAL_FUNC (delete_event), NULL);
gtk_signal_connect (GTK_OBJECT (window), "style_set",
GTK_SIGNAL_FUNC (style_set_event), NULL);
gtk_signal_connect (GTK_OBJECT (window), "draw",
GTK_SIGNAL_FUNC (draw_event), NULL);
gtk_signal_connect( GTK_OBJECT(window),"key_press_event",
(GtkSignalFunc)window_key_event, NULL);
gtk_signal_connect (GTK_OBJECT (window), "remote_command",
GTK_SIGNAL_FUNC (remote_command), NULL);
// gtk_container_set_border_width (GTK_CONTAINER (window), 5);
gtk_widget_realize(window);
vbox = gtk_vbox_new(FALSE, 0);
gtk_container_add (GTK_CONTAINER (window), vbox);
load_pixmaps();
load_font();
// dictionary window
dict_window = create_dict_window();
gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(dict_window), TRUE, TRUE, 0);
gtk_widget_show(vbox);
gtk_widget_set_usize(window, window_width, window_height);
gtk_window_set_policy(GTK_WINDOW(window),
1, // allow_shrink
1, // allow_grow
1); // auto_shrink
gtk_widget_set_usize(note_tree, tree_width, tree_height);
gtk_widget_show (window);
gdk_window_set_icon (window->window, NULL, ebook_pixmap, ebook_mask);
hidden_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
hidden_entry = gtk_entry_new();
gtk_signal_connect (GTK_OBJECT(hidden_entry), "selection_received",
GTK_SIGNAL_FUNC (selection_received), NULL);
gtk_container_add (GTK_CONTAINER (hidden_window), hidden_entry);
show_about();
gtk_selection_owner_set(window, GDK_SELECTION_PRIMARY,GDK_CURRENT_TIME);
if(!bshow_menu_bar)
hide_menu_bar();
if(!bshow_dict_bar)
hide_dict_bar();
if(!bshow_status_bar)
hide_status_bar();
if(argc != 1)
execute_remote_command(argc, argv);
gdk_threads_enter();
gtk_main ();
gdk_threads_leave();
ebook_end();
_exit(0);
// return(0);
}
syntax highlighted by Code2HTML, v. 0.9.1