/* 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.
*/
#include "defs.h"
#include "global.h"
#include "render.h"
#include "eb.h"
static gint click_event (GtkWidget *widget, GdkEventButton *event);
static gint expose_event (GtkWidget *widget, GdkEventExpose *event);
static gint release_event (GtkWidget *widget, GdkEventButton *event);
static gint configure_event(GtkWidget *widget, GdkEventConfigure *event);
static gint motion_event(GtkWidget *widget, GdkEventMotion *event);
void clear_link(CONTENT_AREA *content_area);
void clear_location(CONTENT_AREA *content_area);
void clear_history(CONTENT_AREA *content_area);
void save_history(CONTENT_AREA *content_area, BOOK_INFO *binfo, gint page, gint offset);
void dump_hex();
extern GdkAtom clipboard_atom;
extern gchar *clipboard;
#ifdef HAVE_ICONV_H
#include <iconv.h>
#endif
#define CHAR_KIND_ALPHA 0
#define CHAR_KIND_GAIJI 3
#define CHAR_KIND_SPACE 4
#define CHAR_KIND_DIGIT 5
#define CHAR_KIND_ASCII 6
#define CHAR_KIND_ZENKAKU_KIGOU 11
#define CHAR_KIND_ZENKAKU_DIGIT 12
#define CHAR_KIND_ZENKAKU_ALPHA 13
#define CHAR_KIND_ZENKAKU_HIRAGANA 14
#define CHAR_KIND_ZENKAKU_KATAKANA 15
#define CHAR_KIND_ZENKAKU_GREEK 16
#define CHAR_KIND_ZENKAKU_RUSIA 17
#define CHAR_KIND_ZENKAKU_KEISEN 18
#define CHAR_KIND_ZENKAKU_KANJI 19
#define CHAR_KIND_OTHER 99
gint char_kind(LOCATION *loc)
{
GdkWChar wc_buff[2];
char *p;
#ifdef HAVE_ICONV_H
iconv_t cd;
const char* icode = "euc-jp";
const char* ocode = "iso-2022-jp";
// const char* ocode = "shift_jis";
int r = 0;
size_t isize;
size_t osize;
char *outbuf;
char *result;
short kchar;
char *lang;
#endif
g_assert(loc != NULL);
if(loc->gaiji_no[0] != '\0') {
return(CHAR_KIND_GAIJI);
}
wc_buff[0] = loc->wc;
wc_buff[1] = 0x00000000;
p = gdk_wcstombs(wc_buff);
if(isalpha(*p)) {
return(CHAR_KIND_ALPHA);
}
if(isdigit(*p)) {
return(CHAR_KIND_DIGIT);
}
if(isspace(*p)) {
return(CHAR_KIND_SPACE);
}
if(isascii(*p)) {
return(CHAR_KIND_ASCII);
}
#ifdef HAVE_ICONV_H
// $B4A;z$H$R$i$,$J$J$I$r6hJL$9$k!#(B
// $B$$$C$?$s(BJIS$B%3!<%I$KJQ49$7$F$+$iHO0OHf3S$9$k!#(B
lang = getenv("LANG");
if(lang == NULL){
lang = getenv("LC_ALL");
if(lang == NULL){
fprintf(stderr, "Failed to get current locale.\n");
return(CHAR_KIND_OTHER);
}
}
if(strcmp(lang, "ja_JP.eucJP") == 0){
icode = "euc-jp";
} else if(strcmp(lang, "ja_JP.SJIS") == 0){
icode = "shift_jis";
} else {
return(CHAR_KIND_OTHER);
}
cd = iconv_open( ocode, icode );
if( (int)cd == -1 )
return(CHAR_KIND_OTHER);
isize = strlen(p) + 1;
osize = isize*2;
result = outbuf = (char*)malloc(osize);
r = iconv(cd, (char **)&p, &isize, &outbuf, &osize);
kchar = result[3];
kchar = kchar << 8;
kchar |= result[4];
if(kchar == 0x213c){
return(CHAR_KIND_ZENKAKU_KATAKANA);
}
if((0x2100 <= kchar) && (kchar <= 0x21ff)){
//$B5-9f(B
return(CHAR_KIND_ZENKAKU_KIGOU);
}
if((0x2200 <= kchar) && (kchar <= 0x22ff)){
//$B5-9f(B
return(CHAR_KIND_ZENKAKU_KIGOU);
}
if((0x2330 <= kchar) && (kchar <= 0x2339)){
//$B?t;z(B
return(CHAR_KIND_ZENKAKU_DIGIT);
}
if((0x2340 <= kchar) && (kchar <= 0x23ff)){
//$B%"%k%U%!%Y%C%H(B
return(CHAR_KIND_ZENKAKU_ALPHA);
}
if((0x2400 <= kchar) && (kchar <= 0x24ff)){
//$B$R$i$,$J(B
return(CHAR_KIND_ZENKAKU_HIRAGANA);
}
if((0x2500 <= kchar) && (kchar <= 0x25ff)){
//$B%+%?%+%J(B
return(CHAR_KIND_ZENKAKU_KATAKANA);
}
if((0x2600 <= kchar) && (kchar <= 0x26ff)){
//$B%.%j%7%cJ8;z(B
return(CHAR_KIND_ZENKAKU_GREEK);
}
if((0x2700 <= kchar) && (kchar <= 0x27ff)){
//$B%m%7%"J8;z(B?
return(CHAR_KIND_ZENKAKU_RUSIA);
}
if((0x2800 <= kchar) && (kchar <= 0x28ff)){
//$B7S@~(B
return(CHAR_KIND_ZENKAKU_KEISEN);
}
if((0x3000 <= kchar) && (kchar <= 0x74ff)){
//$B4A;z(B
return(CHAR_KIND_ZENKAKU_KANJI);
}
iconv_close(cd);
free(result);
#endif
return(CHAR_KIND_OTHER);
}
/*
1$BJ8;z$rH?E>$5$;$?$jLa$7$?$j$9$k(B
$BDL>o$NJ8;z$G$b30;z$G$bNI$$!#(B
reverse = TRUE $B$J$iH?E>!"(BFALSE$B$J$iLa$9!#(B
*/
static void reverse_selection(CONTENT_AREA *content_area, LOCATION *loc, gboolean reverse)
{
GdkGC *gc=NULL;
char *p;
GdkWChar wc_buff[2];
GdkPixmap *gaiji_pixmap = NULL;
GdkBitmap *mask;
gint width, height;
wc_buff[0] = loc->wc;
wc_buff[1] = 0x00000000;
p = gdk_wcstombs(wc_buff);
g_assert(loc != NULL);
gc = gdk_gc_new(content_area->area->window);
if(reverse == TRUE){
gdk_gc_set_foreground(gc, &content_area->area->style->bg[GTK_STATE_SELECTED]);
gdk_gc_set_background(gc, &content_area->area->style->bg[GTK_STATE_SELECTED]);
} else {
gdk_gc_set_foreground(gc, &content_area->area->style->bg[GTK_STATE_NORMAL]);
gdk_gc_set_background(gc, &content_area->area->style->bg[GTK_STATE_NORMAL]);
}
gdk_draw_rectangle( content_area->canvas->pixmap,
gc,
TRUE, loc->x,loc->y,
loc->width, loc->height);
if(reverse == TRUE){
gdk_gc_set_foreground(gc, &content_area->area->style->fg[GTK_STATE_SELECTED]);
gdk_gc_set_background(gc, &content_area->area->style->bg[GTK_STATE_SELECTED]);
} else {
if(loc->link_type == LINK_TYPE_JUMP){
gdk_gc_set_foreground(gc, &colors[COLOR_BLUE]);
} else if(loc->link_type == LINK_TYPE_WAVE){
gdk_gc_set_foreground(gc, &colors[COLOR_GREEN]);
} else if(loc->link_type == LINK_TYPE_MPEG){
gdk_gc_set_foreground(gc, &colors[COLOR_GREEN]);
} else if(loc->link_type == LINK_TYPE_KEYWORD){
gdk_gc_set_foreground(gc, &colors[COLOR_BROWN]);
} else {
gdk_gc_set_foreground(gc, &content_area->area->style->fg[GTK_STATE_NORMAL]);
}
gdk_gc_set_background(gc, &content_area->area->style->bg[GTK_STATE_NORMAL]);
}
if(loc->type == LOCATION_CHAR){
if(loc->link_type == LINK_TYPE_SUPERSCRIPT){
gdk_draw_text_wc(content_area->canvas->pixmap,
loc->font,
gc,
loc->x,
loc->y+font_ascent-6,
&(loc->wc), 1);
} else {
gdk_draw_text_wc(content_area->canvas->pixmap,
loc->font,
gc,
loc->x,
loc->y+font_ascent,
&(loc->wc), 1);
}
} else if(loc->type == LOCATION_GAIJI){
load_xbm(current_book_info, loc->gaiji_no, gc, &gaiji_pixmap, &mask, &width, &height);
gdk_draw_pixmap(content_area->canvas->pixmap,
gc,
gaiji_pixmap,
0,0,
loc->x,loc->y,
loc->width,loc->height);
if(gaiji_pixmap != NULL)
gdk_pixmap_unref(gaiji_pixmap);
if(mask != NULL)
gdk_bitmap_unref(mask);
} else {
fprintf(stderr, "Internal error : unknown location type\n");
exit(1);
}
gdk_draw_pixmap(content_area->area->window,
content_area->area->style->fg_gc[GTK_WIDGET_STATE(content_area->area)],
content_area->canvas->pixmap,
loc->x, loc->y,
loc->x, loc->y,
loc->width,
loc->height);
loc->reverse = reverse;
}
/*
$BC18l$rA*Br$9$k(B
$BJ8;z<o$,F1$8$b$N$rC18l$H$7$FH=CG$9$k(B
*/
void select_word(CONTENT_AREA *content_area, GList *center)
{
LOCATION *loc;
GList *loc_item;
gint kind;
g_assert(center != NULL);
g_assert(content_area != NULL);
content_area->selection_start = content_area->selection_end = center;
kind = char_kind((LOCATION *)(center->data));
loc_item = center;
while(loc_item){
loc = (LOCATION *)(loc_item->data);
if(kind == char_kind(loc))
content_area->selection_start = loc_item;
else
break;
loc_item = g_list_previous(loc_item);
}
loc_item = center;
while(loc_item){
loc = (LOCATION *)(loc_item->data);
if(kind == char_kind(loc))
content_area->selection_end = loc_item;
else
break;
loc_item = g_list_next(loc_item);
}
content_area->direction = DIRECTION_FORWARD;
loc_item = content_area->selection_start;
while(loc_item){
loc = (LOCATION *)(loc_item->data);
reverse_selection(content_area, loc, TRUE);
if(loc_item == content_area->selection_end)
break;
loc_item = g_list_next(loc_item);
}
if(!bauto_lookup)
gtk_selection_owner_set(content_area->area, GDK_SELECTION_PRIMARY,GDK_CURRENT_TIME);
}
static gint configure_event(GtkWidget *widget, GdkEventConfigure *event)
{
/*
gchar *text=NULL;
CONTENT_AREA *content_area;
content_area = gtk_object_get_user_data(GTK_OBJECT(widget));
if((widget->parent->allocation.width == content_area->old_width) &&
(widget->parent->allocation.height == content_area->old_height)) {
return TRUE;
}
content_area->old_width = widget->parent->allocation.width;
content_area->old_height = widget->parent->allocation.height;
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);
}
*/
return FALSE;
}
static gint expose_event (GtkWidget *widget, GdkEventExpose *event)
{
CONTENT_AREA *content_area;
content_area = gtk_object_get_user_data(GTK_OBJECT(widget));
gdk_draw_pixmap(content_area->area->window,
content_area->area->style->fg_gc[GTK_WIDGET_STATE(content_area->area)],
content_area->canvas->pixmap,
0, 0,
0, 0,
content_area->area->allocation.width,
content_area->area->allocation.height);
content_area->old_width = widget->parent->allocation.width;
content_area->old_height = widget->parent->allocation.height;
/*
if((widget->parent->allocation.width == content_area->old_width) &&
(widget->parent->allocation.height == content_area->old_height)) {
draw_from_buffer(content_area);
} else {
draw_from_buffer(content_area);
content_area->old_width = widget->parent->allocation.width;
content_area->old_height = widget->parent->allocation.height;
}
*/
return FALSE;
}
static gint click_event (GtkWidget *widget, GdkEventButton *event)
{
char *text;
gchar filename[512];
GList *link_item;
LINK *link;
GList *loc_item;
LOCATION *loc;
CONTENT_AREA *content_area;
content_area = gtk_object_get_user_data(GTK_OBJECT(widget));
if(event->type == GDK_BUTTON_PRESS){
if ((event->button == 2) || (event->button == 3)){
return(FALSE);
}
// $B%j%s%/$,$"$k$+$r%A%'%C%/(B
link_item = g_list_first(content_area->link);
while(link_item) {
link = (LINK *)(link_item->data);
if(((int)event->x >= link->start_x) &&
((int)event->x <= link->end_x) &&
((int)event->y >= link->start_y) &&
((int)event->y <= link->end_y)){
// $BB>$X$N%8%c%s%W(B
if(link->type & LINK_TYPE_JUMP){
text = ebook_get_text(
current_book_info,
link->page,
link->offset);
save_history(content_area,
current_book_info,
link->page, link->offset);
current_position.page = link->page;
current_position.offset = link->offset;
/*
if(bauto_lookup && bshow_popup){
show_popup(current_book_info, text, TRUE);
}
else
show_text(current_book_info, text);
*/
// content_area->show_func(((SEARCH_RESULT *)(search_result->data))->book_info, text);
content_area->show_func(current_book_info, text);
if(hex_dlg != NULL)
dump_hex();
if(text_dlg != NULL)
dump_text();
//$B$3$3$+$i2<$O(Bl$B$NCM$,=q$-49$o$C$F$$$k$N$G(B
// $B;2>H$7$F$O$$$1$J$$(B
free(text);
gtk_signal_emit_stop_by_name(GTK_OBJECT(widget), "button_press_event");
return(TRUE);
// $B2;@<$X$N%j%s%/(B
} else if (link->type & LINK_TYPE_WAVE){
sprintf(filename, "%s/ebview-%d.wav", tmp_dir, getpid());
ebook_output_wave(current_book_info,
filename,
link->page,
link->offset,
link->size);
play_external(filename, LINK_TYPE_WAVE);
// unlink(filename);
gtk_signal_emit_stop_by_name(GTK_OBJECT(widget), "button_press_event");
return(TRUE);
// $BF02h$X$N%j%s%/(B
} else if (link->type & LINK_TYPE_MPEG){
sprintf(filename, "%s/ebview-%d.mpg", tmp_dir, getpid());
ebook_output_mpeg(current_book_info,
link->filename,
filename);
play_external(filename, LINK_TYPE_MPEG);
// unlink(filename);
gtk_signal_emit_stop_by_name(GTK_OBJECT(widget), "button_press_event");
return(TRUE);
}
}
link_item = g_list_next(link_item);
}
// $B%j%s%/$G$O$J$$>l9g(B
// $BH?E>$7$F$$$k$b$N$,$"$C$?$i85$KLa$9(B
loc_item = content_area->location;
while(loc_item){
loc = (LOCATION *)(loc_item->data);
if(loc->reverse == TRUE){
reverse_selection(content_area, loc, FALSE);
// $B%$%?%j%C%/$N$H$-$KJ8;z$,7g$1$k$N$rKI$0$?$a!"(B
// 1$B$DA0$NJ8;z$r:FIA2h$9$k!#(B
if (g_list_previous(loc_item))
reverse_selection(content_area,
(LOCATION *)((g_list_previous(loc_item))->data),
FALSE);
loc->reverse = FALSE;
}
loc_item = g_list_next(loc_item);
}
loc_item = g_list_first(content_area->location);
while(loc_item){
loc = (LOCATION *)(loc_item->data);
if(((int)event->x >= loc->x) &&
((int)event->x <= loc->x+loc->width) &&
((int)event->y >= loc->y) &&
((int)event->y <= loc->y+loc->height)){
content_area->button_x = event->x;
content_area->button_y = event->y;
content_area->selection_start = loc_item;
content_area->selection_end = loc_item;
if(!bauto_lookup)
gtk_selection_owner_set(content_area->area, GDK_SELECTION_PRIMARY,GDK_CURRENT_TIME);
content_area->bbutton_down = TRUE;
return(FALSE);
}
loc_item = g_list_next(loc_item);
}
} else if((event->button == 1) && (event->type == GDK_2BUTTON_PRESS)){
loc_item = g_list_first(content_area->location);
while(loc_item){
loc = (LOCATION *)(loc_item->data);
if(((int)event->x >= loc->x) &&
((int)event->x <= loc->x+loc->width) &&
((int)event->y >= loc->y) &&
((int)event->y <= loc->y+loc->height)){
select_word(content_area, loc_item);
}
loc_item = g_list_next(loc_item);
}
}
return(FALSE);
}
static gint release_event (GtkWidget *widget, GdkEventButton *event)
{
CONTENT_AREA *content_area;
content_area = gtk_object_get_user_data(GTK_OBJECT(widget));
content_area->bbutton_down = FALSE;
return FALSE;
}
gboolean in_the_link = FALSE;
static gint motion_event(GtkWidget *widget, GdkEventMotion *event)
{
LINK *link;
GdkCursor *cursor;
LOCATION *loc;
LOCATION *loc_end;
gboolean line_skip;
GList *save_start, *save_end;
gint save_direction;
gboolean exist;
GList *loc_item;
GList *loc_item2;
GList *link_item;
CONTENT_AREA *content_area;
content_area = gtk_object_get_user_data(GTK_OBJECT(widget));
if(content_area->bbutton_down == TRUE){
if(content_area->selection_start == NULL){
return(FALSE);
}
if(content_area->selection_end == NULL){
return(FALSE);
}
save_start = content_area->selection_start;
save_end = content_area->selection_end;
save_direction = content_area->direction;
if(content_area->selection_start == content_area->selection_end){
loc = (LOCATION *)(content_area->selection_start->data);
if(loc->reverse == FALSE)
reverse_selection(content_area, (LOCATION *)(content_area->selection_start->data), TRUE);
}
// $B%\!<%@!<NN0h$@$C$?$iJd@5(B
if(event->x < h_border)
event->x = h_border;
if(event->y < v_space)
event->y = v_space;
//$BF1$8J8;z$NNN0hFb$@$C$?$i$J$K$b$7$J$$!#(B
loc_end = (LOCATION *)(content_area->selection_end->data);
if((loc_end != NULL) &&
((int)event->x >= loc_end->x) &&
((int)event->x <= loc_end->x+loc_end->width) &&
((int)event->y >= loc_end->y) &&
((int)event->y <= loc_end->y+loc_end->height))
{
return(FALSE);
}
content_area->direction = DIRECTION_FORWARD;
line_skip = FALSE;
// $B<!$N9T$K$$$C$?$+(B
if(content_area->button_y < event->y){
loc_item = g_list_first(content_area->location);
while(loc_item){
loc = (LOCATION *)(loc_item->data);
if(((LOCATION *)(content_area->selection_start->data))->y < loc->y){
// $B<!$N9T$KF~$C$?$+(B
if(event->y >= loc->y){
line_skip=TRUE;
content_area->direction = DIRECTION_FORWARD;
}
break;
}
loc_item = g_list_next(loc_item);
}
}
// $BA0$N9T$+(B
if(content_area->button_y > event->y){
if(event->y < ((LOCATION *)(content_area->selection_start->data))->y){
line_skip=TRUE;
content_area->direction = DIRECTION_BACKWARD;
}
}
// $BF1$89T$N>l9g(B
if(line_skip == FALSE){
// $B1&$K?J$s$G$$$k$+(B
if(((LOCATION *)(content_area->selection_start->data))->x < event->x){
content_area->direction = DIRECTION_FORWARD;
// $B$=$l$H$b:8$+(B
} else if(((LOCATION *)(content_area->selection_start->data))->x > event->x) {
content_area->direction = DIRECTION_BACKWARD;
} else {
return(FALSE);
}
}
// end$B$r7h$a$k(B
// direction$B$O$I$A$i$G$"$C$F$b(Bend$B$,=*E@$K$J$k(B
loc_item = content_area->selection_start;
while(loc_item){
loc = (LOCATION *)(loc_item->data);
if(((int)event->x >= loc->x) &&
((int)event->x <= loc->x+loc->width) &&
((int)event->y >= loc->y) &&
((int)event->y <= loc->y+loc->height)){
content_area->selection_end = loc_item;
break;
}
if(content_area->direction == DIRECTION_FORWARD)
loc_item = g_list_next(loc_item);
else
loc_item = g_list_previous(loc_item);
}
if(loc_item == NULL){
content_area->selection_start = save_start;
content_area->selection_end = save_end;
content_area->direction = save_direction;
return(FALSE);
}
// $B0JA0$OA*Br$5$l$F$$$?$,:#2s$OA*Br$5$l$F$$$J$$$b$N$OLa$9(B
loc_item = save_start;
while(loc_item){
loc = (LOCATION *)(loc_item->data);
exist = FALSE;
loc_item2 = content_area->selection_start;
while(loc_item2){
// $BA0$bA*Br$5$l$F$$$?(B
if(loc_item == loc_item2) {
exist = TRUE;
break;
}
if(loc_item2 == content_area->selection_end)
break;
if(content_area->direction == DIRECTION_FORWARD)
loc_item2 = g_list_next(loc_item2);
else
loc_item2 = g_list_previous(loc_item2);
}
if(exist == FALSE) {
if(loc->reverse == TRUE) {
reverse_selection(content_area, loc, FALSE);
// $B%$%?%j%C%/$N$H$-$KJ8;z$,7g$1$k$N$rKI$0$?$a!"(B
// 1$B$DA0$NJ8;z$r:FIA2h$9$k!#(B
if(g_list_previous(loc_item))
reverse_selection(content_area,
(LOCATION *)((g_list_previous(loc_item))->data),
FALSE);
}
}
if(loc_item == save_end)
break;
if(save_direction == DIRECTION_FORWARD)
loc_item = g_list_next(loc_item);
else
loc_item = g_list_previous(loc_item);
}
loc = (LOCATION *)(content_area->selection_start->data);
if(loc->reverse == FALSE)
reverse_selection(content_area, loc, TRUE);
// $B:#2s$OA*Br$5$l$F$$$F0JA0$OA*Br$5$l$F$$$J$+$C$?$b$N$OH?E>(B
loc_item = content_area->selection_start;
while(loc_item){
loc = (LOCATION *)(loc_item->data);
exist = FALSE;
loc_item2 = save_start;
while(loc_item2){
if(loc_item == loc_item2) {
exist = TRUE;
break;
}
if(loc_item2 == save_end)
break;
if(save_direction == DIRECTION_FORWARD)
loc_item2 = g_list_next(loc_item2);
else
loc_item2 = g_list_previous(loc_item2);
}
if(exist == FALSE)
reverse_selection(content_area, loc, TRUE);
if(loc_item == content_area->selection_end)
break;
if(content_area->direction == DIRECTION_FORWARD)
loc_item = g_list_next(loc_item);
else
loc_item = g_list_previous(loc_item);
}
if(!bauto_lookup)
gtk_selection_owner_set(content_area->area, GDK_SELECTION_PRIMARY,GDK_CURRENT_TIME);
return(FALSE);
}
link_item = content_area->link;
while(link_item) {
link = (LINK *)(link_item->data);
if(((int)event->x >= link->start_x) &&
((int)event->x <= link->end_x) &&
((int)event->y >= link->start_y) &&
((int)event->y <= link->end_y)){
if(in_the_link == FALSE){
gchar msg[512];
cursor = gdk_cursor_new (CURSOR_LINK);
gdk_window_set_cursor (content_area->area->window, cursor);
gdk_cursor_destroy (cursor);
in_the_link = TRUE;
if(link->type & LINK_TYPE_JUMP) {
sprintf(msg, "REFERENCE: page=%08x offset=%03x",
link->page, link->offset);
} else if(link->type & LINK_TYPE_WAVE) {
sprintf(msg, "WAVE: page=%08x offset=%03x size=%d",
link->page, link->offset, link->size);
} else if(link->type & LINK_TYPE_MPEG) {
sprintf(msg, "MPEG: filename=%s",
link->filename);
}
if(!bauto_lookup || !bshow_popup)
status_message(msg);
}
return(FALSE);
}
link_item = g_list_next(link_item);
}
if(in_the_link == TRUE){
cursor = gdk_cursor_new (CURSOR_NORMAL);
gdk_window_set_cursor (content_area->area->window, cursor);
gdk_cursor_destroy (cursor);
in_the_link = FALSE;
clear_status_message(NULL);
}
return(FALSE);
}
void
selection_get (GtkWidget *widget,
GtkSelectionData *selection_data,
guint info,
guint time,
gpointer data)
{
guchar *buffer;
gint len;
GdkAtom type = GDK_NONE;
gint format;
GdkWChar wc_buff[65536];
LOCATION *loc;
GList *loc_item;
guchar *ctext;
CONTENT_AREA *content_area;
content_area = gtk_object_get_user_data(GTK_OBJECT(widget));
if(selection_data->selection == clipboard_atom){
if(clipboard == NULL){
buffer = NULL;
len = 0;
} else {
buffer = clipboard;
len = strlen(buffer);
}
} else {
if (content_area->selection_start == NULL)
{
buffer = NULL;
len = 0;
}
else
{
len = 0;
if(content_area->direction == DIRECTION_FORWARD){
loc_item = content_area->selection_start;
while(loc_item){
loc = (LOCATION *)(loc_item->data);
if(loc->type == LOCATION_CHAR){
wc_buff[len] = loc->wc;
len++;
wc_buff[len] = 0x00000000;
}
if(loc_item == content_area->selection_end)
break;
loc_item = g_list_next(loc_item);
}
} else {
loc_item = content_area->selection_end;
while(loc_item){
loc = (LOCATION *)(loc_item->data);
if(loc->type == LOCATION_CHAR){
wc_buff[len] = loc->wc;
len++;
wc_buff[len] = 0x00000000;
}
if(loc_item == content_area->selection_start)
break;
loc_item = g_list_previous(loc_item);
}
}
buffer = gdk_wcstombs(wc_buff);
len = strlen(buffer);
}
}
switch (info)
{
case COMPOUND_TEXT:
type = gdk_atom_intern ("COMPOUND_TEXT",FALSE);
break;
case TEXT:
type = gdk_atom_intern ("COMPOUND_TEXT",FALSE);
break;
case STRING:
type = gdk_atom_intern ("STRING",FALSE);
break;
default:
fprintf(stderr, "unsupported data type requested\n");
}
gdk_string_to_compound_text(buffer, &type, &format, &ctext, &len);
if(ctext == NULL) {
fprintf(stderr, "gdk_string_to_compound_text failed\n");
} else {
gtk_selection_data_set (selection_data, type, 8, ctext, len);
gdk_free_compound_text(ctext);
}
}
gint selection_clear (GtkWidget *widget, GdkEventSelection *event)
{
GList *loc_item;
LOCATION *loc;
CONTENT_AREA *content_area;
content_area = gtk_object_get_user_data(GTK_OBJECT(widget));
// $BH?E>$7$F$$$k$b$N$r85$KLa$9(B
if((content_area->selection_start != NULL) && (content_area->selection_end != NULL)){
if(content_area->direction == DIRECTION_FORWARD){
loc_item = content_area->selection_start;
while(loc_item){
loc = (LOCATION *)(loc_item->data);
if(loc->reverse == TRUE) {
reverse_selection(content_area, loc, FALSE);
// $B%$%?%j%C%/$N$H$-$KJ8;z$,7g$1$k$N$rKI$0$?$a!"(B
// 1$B$DA0$NJ8;z$r:FIA2h$9$k!#(B
if(g_list_previous(loc_item))
reverse_selection(content_area,
(LOCATION *)((g_list_previous(loc_item))->data),
FALSE);
}
if(loc_item == content_area->selection_end)
break;
loc_item = g_list_next(loc_item);
}
} else {
loc_item = content_area->selection_end;
while(loc_item){
loc = (LOCATION *)(loc_item->data);
if(loc->reverse == TRUE) {
reverse_selection(content_area, loc, FALSE);
// $B%$%?%j%C%/$N$H$-$KJ8;z$,7g$1$k$N$rKI$0$?$a!"(B
// 1$B$DA0$NJ8;z$r:FIA2h$9$k!#(B
if(g_list_previous(loc_item))
reverse_selection(content_area,
(LOCATION *)((g_list_previous(loc_item))->data),
FALSE);
}
if(loc_item == content_area->selection_start)
break;
loc_item = g_list_previous(loc_item);
}
}
}
content_area->selection_start = NULL;
content_area->selection_end = NULL;
return TRUE;
}
CONTENT_AREA *create_content_area(gint width, gint height)
{
CONTENT_AREA *content_area;
static GtkTargetEntry targetlist[] = {
{ "STRING", 0, STRING },
{ "TEXT", 0, TEXT },
{ "COMPOUND_TEXT", 0, COMPOUND_TEXT }
};
static gint ntargets = sizeof(targetlist) / sizeof(targetlist[0]);
content_area = (CONTENT_AREA *)calloc(sizeof(CONTENT_AREA) , 1);
g_assert(content_area != NULL);
content_area->area = gtk_drawing_area_new();
g_assert(content_area->area != NULL);
gtk_object_set_user_data(GTK_OBJECT(content_area->area), content_area);
gtk_signal_connect( GTK_OBJECT (content_area->area), "expose_event",
(GtkSignalFunc)expose_event, (gpointer)content_area);
gtk_signal_connect( GTK_OBJECT(content_area->area),"configure_event",
(GtkSignalFunc)configure_event, (gpointer)content_area);
// gtk_signal_connect( GTK_OBJECT(canvas->area),"draw",
// (GtkSignalFunc)panel_configure_event, NULL);
gtk_signal_connect( GTK_OBJECT(content_area->area),"button_press_event",
(GtkSignalFunc)click_event, (gpointer)content_area);
gtk_signal_connect( GTK_OBJECT(content_area->area),"button_release_event",
(GtkSignalFunc)release_event, (gpointer)content_area);
gtk_signal_connect( GTK_OBJECT(content_area->area),"motion_notify_event",
(GtkSignalFunc)motion_event, (gpointer)content_area);
gtk_signal_connect (GTK_OBJECT(content_area->area), "selection_clear_event",
GTK_SIGNAL_FUNC (selection_clear), (gpointer)content_area);
clipboard_atom = gdk_atom_intern ("CLIPBOARD", FALSE);
gtk_selection_add_targets (content_area->area, GDK_SELECTION_PRIMARY,
targetlist, ntargets);
gtk_selection_add_targets (content_area->area, clipboard_atom,
targetlist, ntargets);
gtk_selection_add_targets (content_area->area, GDK_SELECTION_PRIMARY,
targetlist, ntargets);
gtk_signal_connect (GTK_OBJECT(content_area->area), "selection_get",
GTK_SIGNAL_FUNC (selection_get), (gpointer)content_area);
gtk_widget_set_events (content_area->area, GDK_EXPOSURE_MASK
| GDK_ENTER_NOTIFY_MASK
| GDK_LEAVE_NOTIFY_MASK
| GDK_KEY_PRESS_MASK
| GDK_BUTTON_PRESS_MASK
| GDK_BUTTON_RELEASE_MASK
// | GDK_BUTTON_MOTION_MASK
| GDK_POINTER_MOTION_MASK
// | GDK_POINTER_MOTION_HINT_MASK
);
return(content_area);
}
gboolean resize_content_area(CONTENT_AREA *content_area, gint width, gint height)
{
gtk_widget_set_usize( content_area->area, width, height);
}
gboolean clear_content_area(CONTENT_AREA *content_area)
{
clear_link(content_area);
clear_location(content_area);
}
gboolean destroy_content_area(CONTENT_AREA *content_area)
{
clear_content_area(content_area);
clear_history(content_area);
free(content_area);
}
syntax highlighted by Code2HTML, v. 0.9.1