Removed some code which got in the way of testing properly.
* widgets/test-minicard.c: Removed some code which got in the way of testing properly. * widgets/e-minicard-label.c (e_minicard_label_realize): Made the field text item editable. * widgets/Makefile.am: Added e-text-event-process*.[ch]. * widgets/e-text.c, widgets/e-text.h: Changed these to support editing. * widgets/e-text-event-processor.c, widgets/e-text-event-processor.h, widgets/e-text-event-processor-types.h, widgets/e-text-event-processor-emacs-like.c, widgets/e-text-event-processor-emacs-like.h: These are a new pair of classes which handle all events from the text item and convert them into commands. svn path=/trunk/; revision=1553
This commit is contained in:
39
ChangeLog
39
ChangeLog
@ -1,3 +1,42 @@
|
||||
2000-01-11 Christopher James Lahey <clahey@helixcode.com>
|
||||
|
||||
* widgets/test-minicard.c: Removed some code which got in the way
|
||||
of testing properly.
|
||||
|
||||
* widgets/e-minicard-label.c (e_minicard_label_realize): Made the
|
||||
field text item editable.
|
||||
|
||||
* widgets/Makefile.am: Added e-text-event-process*.[ch].
|
||||
|
||||
* widgets/e-text.c, widgets/e-text.h: Changed these to support
|
||||
editing.
|
||||
|
||||
* widgets/e-text-event-processor.c,
|
||||
widgets/e-text-event-processor.h,
|
||||
widgets/e-text-event-processor-types.h,
|
||||
widgets/e-text-event-processor-emacs-like.c,
|
||||
widgets/e-text-event-processor-emacs-like.h: These are a new pair
|
||||
of classes which handle all events from the text item and convert
|
||||
them into commands.
|
||||
|
||||
|
||||
2000-01-10 Christopher James Lahey <clahey@helixcode.com>
|
||||
|
||||
* widgets/Makefile.am: Added minicard and text stuff.
|
||||
|
||||
* widgets/e-minicard.c, widgets/e-minicard.h,
|
||||
widgets/e-minicard-label.c, widgets/e-minicard-label.h: Added
|
||||
canvas items for the minicard view in the contact manager.
|
||||
|
||||
* widgets/test-minicard.c, widgets/test-minicard-label.c: Tests
|
||||
for the minicard items.
|
||||
|
||||
* widgets/e-text.h, widgets/e-text.c: New canvas item. Based on
|
||||
GnomeCanvasText. Adds ellipsis capabilities. Used in
|
||||
e-minicard*.[ch].
|
||||
|
||||
* widgets/.cvsignore: Added minicard-test and minicard-label-test.
|
||||
|
||||
2000-01-06 Miguel de Icaza <miguel@gnu.org>
|
||||
|
||||
* configure.in: Add Bonobo detection, Bonobo flags for compilation
|
||||
|
@ -239,6 +239,7 @@ e_minicard_label_realize (GnomeCanvasItem *item)
|
||||
"use_ellipsis", TRUE,
|
||||
"font", "lucidasans-10",
|
||||
"fill_color", "black",
|
||||
"editable", TRUE,
|
||||
NULL );
|
||||
|
||||
if ( e_minicard_label->field_text )
|
||||
|
@ -61,11 +61,6 @@ static void about_callback( GtkWidget *widget, gpointer data )
|
||||
gtk_widget_show (about);
|
||||
}
|
||||
|
||||
static void button_press_callback( GtkWidget *widget, gpointer data )
|
||||
{
|
||||
gnome_canvas_item_grab_focus( card );
|
||||
}
|
||||
|
||||
int main( int argc, char *argv[] )
|
||||
{
|
||||
GtkWidget *app;
|
||||
@ -102,7 +97,6 @@ int main( int argc, char *argv[] )
|
||||
|
||||
gnome_app_set_contents( GNOME_APP( app ), canvas );
|
||||
|
||||
|
||||
/* Connect the signals */
|
||||
gtk_signal_connect( GTK_OBJECT( app ), "destroy",
|
||||
GTK_SIGNAL_FUNC( destroy_callback ),
|
||||
@ -112,10 +106,6 @@ int main( int argc, char *argv[] )
|
||||
GTK_SIGNAL_FUNC( allocate_callback ),
|
||||
( gpointer ) app );
|
||||
|
||||
gtk_signal_connect( GTK_OBJECT( canvas ), "button_press_event",
|
||||
GTK_SIGNAL_FUNC( button_press_callback ),
|
||||
( gpointer ) app );
|
||||
|
||||
gtk_widget_show_all( app );
|
||||
|
||||
gtk_main();
|
||||
|
@ -239,6 +239,7 @@ e_minicard_label_realize (GnomeCanvasItem *item)
|
||||
"use_ellipsis", TRUE,
|
||||
"font", "lucidasans-10",
|
||||
"fill_color", "black",
|
||||
"editable", TRUE,
|
||||
NULL );
|
||||
|
||||
if ( e_minicard_label->field_text )
|
||||
|
@ -61,11 +61,6 @@ static void about_callback( GtkWidget *widget, gpointer data )
|
||||
gtk_widget_show (about);
|
||||
}
|
||||
|
||||
static void button_press_callback( GtkWidget *widget, gpointer data )
|
||||
{
|
||||
gnome_canvas_item_grab_focus( card );
|
||||
}
|
||||
|
||||
int main( int argc, char *argv[] )
|
||||
{
|
||||
GtkWidget *app;
|
||||
@ -102,7 +97,6 @@ int main( int argc, char *argv[] )
|
||||
|
||||
gnome_app_set_contents( GNOME_APP( app ), canvas );
|
||||
|
||||
|
||||
/* Connect the signals */
|
||||
gtk_signal_connect( GTK_OBJECT( app ), "destroy",
|
||||
GTK_SIGNAL_FUNC( destroy_callback ),
|
||||
@ -112,10 +106,6 @@ int main( int argc, char *argv[] )
|
||||
GTK_SIGNAL_FUNC( allocate_callback ),
|
||||
( gpointer ) app );
|
||||
|
||||
gtk_signal_connect( GTK_OBJECT( canvas ), "button_press_event",
|
||||
GTK_SIGNAL_FUNC( button_press_callback ),
|
||||
( gpointer ) app );
|
||||
|
||||
gtk_widget_show_all( app );
|
||||
|
||||
gtk_main();
|
||||
|
327
e-util/e-text-event-processor-emacs-like.c
Normal file
327
e-util/e-text-event-processor-emacs-like.c
Normal file
@ -0,0 +1,327 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/* e-text-event-processor.c
|
||||
* Copyright (C) 2000 Helix Code, Inc.
|
||||
* Author: Chris Lahey <clahey@helixcode.com>
|
||||
*
|
||||
* This library 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 library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <gnome.h>
|
||||
#include "e-text-event-processor-emacs-like.h"
|
||||
static void e_text_event_processor_emacs_like_init (ETextEventProcessorEmacsLike *card);
|
||||
static void e_text_event_processor_emacs_like_class_init (ETextEventProcessorEmacsLikeClass *klass);
|
||||
static gint e_text_event_processor_emacs_like_event (ETextEventProcessor *tep, ETextEventProcessorEvent *event);
|
||||
|
||||
static ETextEventProcessorClass *parent_class = NULL;
|
||||
|
||||
/* The arguments we take */
|
||||
enum {
|
||||
ARG_0
|
||||
};
|
||||
|
||||
static const ETextEventProcessorCommand control_keys[26] =
|
||||
{
|
||||
{ E_TEP_START_OF_LINE, E_TEP_MOVE, 0, "" }, /* a */
|
||||
{ E_TEP_BACKWARD_CHARACTER, E_TEP_MOVE, 0, "" }, /* b */
|
||||
{ E_TEP_SELECTION, E_TEP_COPY, 0, "" }, /* c */
|
||||
{ E_TEP_FORWARD_CHARACTER, E_TEP_DELETE, 0, "" }, /* d */
|
||||
{ E_TEP_END_OF_LINE, E_TEP_MOVE, 0, "" }, /* e */
|
||||
{ E_TEP_FORWARD_CHARACTER, E_TEP_MOVE, 0, "" }, /* f */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* g */
|
||||
{ E_TEP_BACKWARD_CHARACTER, E_TEP_DELETE, 0, "" }, /* h */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* i */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* j */
|
||||
{ E_TEP_END_OF_LINE, E_TEP_DELETE, 0, "" }, /* k */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* l */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* m */
|
||||
{ E_TEP_FORWARD_LINE, E_TEP_MOVE, 0, "" }, /* n */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* o */
|
||||
{ E_TEP_BACKWARD_LINE, E_TEP_MOVE, 0, "" }, /* p */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* q */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* r */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* s */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* t */
|
||||
{ E_TEP_START_OF_LINE, E_TEP_DELETE, 0, "" }, /* u */
|
||||
{ E_TEP_SELECTION, E_TEP_PASTE, 0, "" }, /* v */
|
||||
{ E_TEP_BACKWARD_WORD, E_TEP_DELETE, 0, "" }, /* w */
|
||||
{ E_TEP_SELECTION, E_TEP_PASTE, 0, "" }, /* x */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* y */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" } /* z */
|
||||
};
|
||||
|
||||
static const ETextEventProcessorCommand alt_keys[26] =
|
||||
{
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* a */
|
||||
{ E_TEP_BACKWARD_WORD, E_TEP_MOVE, 0, "" }, /* b */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* c */
|
||||
{ E_TEP_FORWARD_WORD, E_TEP_DELETE, 0, "" }, /* d */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* e */
|
||||
{ E_TEP_FORWARD_WORD, E_TEP_MOVE, 0, "" }, /* f */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* g */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* h */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* i */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* j */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* k */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* l */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* m */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* n */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* o */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* p */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* q */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* r */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* s */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* t */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* u */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* v */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* w */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* x */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* y */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" } /* z */
|
||||
|
||||
};
|
||||
|
||||
GtkType
|
||||
e_text_event_processor_emacs_like_get_type (void)
|
||||
{
|
||||
static GtkType text_event_processor_emacs_like_type = 0;
|
||||
|
||||
if (!text_event_processor_emacs_like_type)
|
||||
{
|
||||
static const GtkTypeInfo text_event_processor_emacs_like_info =
|
||||
{
|
||||
"ETextEventProcessorEmacsLike",
|
||||
sizeof (ETextEventProcessorEmacsLike),
|
||||
sizeof (ETextEventProcessorEmacsLikeClass),
|
||||
(GtkClassInitFunc) e_text_event_processor_emacs_like_class_init,
|
||||
(GtkObjectInitFunc) e_text_event_processor_emacs_like_init,
|
||||
/* reserved_1 */ NULL,
|
||||
/* reserved_2 */ NULL,
|
||||
(GtkClassInitFunc) NULL,
|
||||
};
|
||||
|
||||
text_event_processor_emacs_like_type = gtk_type_unique (e_text_event_processor_get_type (), &text_event_processor_emacs_like_info);
|
||||
}
|
||||
|
||||
return text_event_processor_emacs_like_type;
|
||||
}
|
||||
|
||||
static void
|
||||
e_text_event_processor_emacs_like_class_init (ETextEventProcessorEmacsLikeClass *klass)
|
||||
{
|
||||
GtkObjectClass *object_class;
|
||||
ETextEventProcessorClass *processor_class;
|
||||
|
||||
object_class = (GtkObjectClass*) klass;
|
||||
processor_class = (ETextEventProcessorClass*) klass;
|
||||
|
||||
parent_class = gtk_type_class (e_text_event_processor_get_type ());
|
||||
|
||||
processor_class->event = e_text_event_processor_emacs_like_event;
|
||||
}
|
||||
|
||||
static void
|
||||
e_text_event_processor_emacs_like_init (ETextEventProcessorEmacsLike *tep)
|
||||
{
|
||||
}
|
||||
|
||||
static gint
|
||||
e_text_event_processor_emacs_like_event (ETextEventProcessor *tep, ETextEventProcessorEvent *event)
|
||||
{
|
||||
ETextEventProcessorCommand command;
|
||||
ETextEventProcessorEmacsLike *tep_el = E_TEXT_EVENT_PROCESSOR_EMACS_LIKE(tep);
|
||||
switch (event->type) {
|
||||
case GDK_BUTTON_PRESS:
|
||||
if (event->button.button == 1) {
|
||||
if (event->button.state & GDK_SHIFT_MASK)
|
||||
command.action = E_TEP_SELECT;
|
||||
else
|
||||
command.action = E_TEP_MOVE;
|
||||
command.position = E_TEP_VALUE;
|
||||
command.value = event->button.position;
|
||||
tep_el->mouse_down = TRUE;
|
||||
}
|
||||
break;
|
||||
case GDK_BUTTON_RELEASE:
|
||||
if (event->button.button == 1) {
|
||||
tep_el->mouse_down = FALSE;
|
||||
}
|
||||
break;
|
||||
case GDK_MOTION_NOTIFY:
|
||||
if (tep_el->mouse_down) {
|
||||
command.action = E_TEP_SELECT;
|
||||
command.position = E_TEP_VALUE;
|
||||
command.value = event->motion.position;
|
||||
}
|
||||
break;
|
||||
case GDK_KEY_PRESS:
|
||||
{
|
||||
ETextEventProcessorEventKey key = event->key;
|
||||
if (key.state & GDK_SHIFT_MASK)
|
||||
command.action = E_TEP_SELECT;
|
||||
else
|
||||
command.action = E_TEP_MOVE;
|
||||
switch(key.keyval) {
|
||||
case GDK_Home:
|
||||
if (key.state & GDK_CONTROL_MASK)
|
||||
command.position = E_TEP_START_OF_BUFFER;
|
||||
else
|
||||
command.position = E_TEP_START_OF_LINE;
|
||||
break;
|
||||
case GDK_End:
|
||||
if (key.state & GDK_CONTROL_MASK)
|
||||
command.position = E_TEP_END_OF_BUFFER;
|
||||
else
|
||||
command.position = E_TEP_END_OF_LINE;
|
||||
break;
|
||||
case GDK_Page_Up: command.position = E_TEP_BACKWARD_PAGE; break;
|
||||
case GDK_Page_Down: command.position = E_TEP_FORWARD_PAGE; break;
|
||||
/* CUA has Ctrl-Up/Ctrl-Down as paragraph up down */
|
||||
case GDK_Up: command.position = E_TEP_BACKWARD_LINE; break;
|
||||
case GDK_Down: command.position = E_TEP_FORWARD_LINE; break;
|
||||
case GDK_Left:
|
||||
if (key.state & GDK_CONTROL_MASK)
|
||||
command.position = E_TEP_BACKWARD_WORD;
|
||||
else
|
||||
command.position = E_TEP_BACKWARD_CHARACTER;
|
||||
break;
|
||||
case GDK_Right:
|
||||
if (key.state & GDK_CONTROL_MASK)
|
||||
command.position = E_TEP_FORWARD_WORD;
|
||||
else
|
||||
command.position = E_TEP_FORWARD_CHARACTER;
|
||||
break;
|
||||
|
||||
case GDK_BackSpace:
|
||||
command.action = E_TEP_DELETE;
|
||||
if (key.state & GDK_CONTROL_MASK)
|
||||
command.position = E_TEP_BACKWARD_WORD;
|
||||
else
|
||||
command.position = E_TEP_BACKWARD_CHARACTER;
|
||||
break;
|
||||
case GDK_Clear:
|
||||
command.action = E_TEP_DELETE;
|
||||
command.position = E_TEP_END_OF_LINE;
|
||||
break;
|
||||
case GDK_Insert:
|
||||
if (key.state & GDK_SHIFT_MASK) {
|
||||
command.action = E_TEP_PASTE;
|
||||
command.position = E_TEP_SELECTION;
|
||||
} else if (key.state & GDK_CONTROL_MASK) {
|
||||
command.action = E_TEP_COPY;
|
||||
command.position = E_TEP_SELECTION;
|
||||
} else {
|
||||
/* gtk_toggle_insert(text) -- IMPLEMENT */
|
||||
}
|
||||
break;
|
||||
case GDK_Delete:
|
||||
if (key.state & GDK_CONTROL_MASK){
|
||||
command.action = E_TEP_DELETE;
|
||||
command.position = E_TEP_FORWARD_WORD;
|
||||
} else if (key.state & GDK_SHIFT_MASK) {
|
||||
command.action = E_TEP_COPY;
|
||||
|
||||
command.action = E_TEP_DELETE;
|
||||
command.position = E_TEP_SELECTION;
|
||||
} else {
|
||||
command.action = E_TEP_DELETE;
|
||||
command.position = E_TEP_FORWARD_CHARACTER;
|
||||
}
|
||||
break;
|
||||
case GDK_Tab:
|
||||
command.action = E_TEP_INSERT;
|
||||
command.position = E_TEP_SELECTION;
|
||||
command.value = 1;
|
||||
command.string = "\t";
|
||||
break;
|
||||
case GDK_Return:
|
||||
if (key.state & GDK_CONTROL_MASK) {
|
||||
command.action = E_TEP_ACTIVATE;
|
||||
command.position = E_TEP_SELECTION;
|
||||
} else {
|
||||
command.action = E_TEP_INSERT;
|
||||
command.position = E_TEP_SELECTION;
|
||||
command.value = 1;
|
||||
command.string = "\n";
|
||||
}
|
||||
break;
|
||||
case GDK_Escape:
|
||||
command.action = E_TEP_NOP;
|
||||
command.position = E_TEP_SELECTION;
|
||||
/* Don't insert literally */
|
||||
break;
|
||||
|
||||
default:
|
||||
if (key.state & GDK_CONTROL_MASK) {
|
||||
if ((key.keyval >= 'A') && (key.keyval <= 'Z'))
|
||||
key.keyval -= 'A' - 'a';
|
||||
|
||||
if ((key.keyval >= 'a') && (key.keyval <= 'z')) {
|
||||
command.position = control_keys[(int) (key.keyval - 'a')].position;
|
||||
if (control_keys[(int) (key.keyval - 'a')].action != E_TEP_MOVE)
|
||||
command.action = control_keys[(int) (key.keyval - 'a')].action;
|
||||
command.value = control_keys[(int) (key.keyval - 'a')].value;
|
||||
command.string = control_keys[(int) (key.keyval - 'a')].string;
|
||||
}
|
||||
|
||||
if (key.keyval == 'x') {
|
||||
}
|
||||
|
||||
break;
|
||||
} else if (key.state & GDK_MOD1_MASK) {
|
||||
if ((key.keyval >= 'A') && (key.keyval <= 'Z'))
|
||||
key.keyval -= 'A' - 'a';
|
||||
|
||||
if ((key.keyval >= 'a') && (key.keyval <= 'z')) {
|
||||
command.position = alt_keys[(int) (key.keyval - 'a')].position;
|
||||
if (alt_keys[(int) (key.keyval - 'a')].action != E_TEP_MOVE)
|
||||
command.action = alt_keys[(int) (key.keyval - 'a')].action;
|
||||
command.value = alt_keys[(int) (key.keyval - 'a')].value;
|
||||
command.string = alt_keys[(int) (key.keyval - 'a')].string;
|
||||
}
|
||||
} else if (key.length > 0) {
|
||||
command.action = E_TEP_INSERT;
|
||||
command.position = E_TEP_SELECTION;
|
||||
command.value = strlen(key.string);
|
||||
command.string = key.string;
|
||||
|
||||
} else {
|
||||
command.action = E_TEP_NOP;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case GDK_KEY_RELEASE:
|
||||
command.action = E_TEP_NOP;
|
||||
break;
|
||||
default:
|
||||
command.action = E_TEP_NOP;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (command.action != E_TEP_NOP) {
|
||||
gtk_signal_emit_by_name (GTK_OBJECT (tep), "command", &command);
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
ETextEventProcessor *
|
||||
e_text_event_processor_emacs_like_new (void)
|
||||
{
|
||||
ETextEventProcessorEmacsLike *retval = gtk_type_new (e_text_event_processor_emacs_like_get_type ());
|
||||
return E_TEXT_EVENT_PROCESSOR (retval);
|
||||
}
|
||||
|
68
e-util/e-text-event-processor-emacs-like.h
Normal file
68
e-util/e-text-event-processor-emacs-like.h
Normal file
@ -0,0 +1,68 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/* e-text-event-processor-emacs-like.h
|
||||
* Copyright (C) 2000 Helix Code, Inc.
|
||||
* Author: Chris Lahey <clahey@helixcode.com>
|
||||
*
|
||||
* This library 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 library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
#ifndef __E_TEXT_EVENT_PROCESSOR_EMACS_LIKE_H__
|
||||
#define __E_TEXT_EVENT_PROCESSOR_EMACS_LIKE_H__
|
||||
|
||||
#include <gnome.h>
|
||||
#include "e-text-event-processor.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#pragma }
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/* ETextEventProcessorEmacsLike - Turns events on a text widget into commands. Uses an emacs-ish interface.
|
||||
*
|
||||
*/
|
||||
|
||||
#define E_TEXT_EVENT_PROCESSOR_EMACS_LIKE_TYPE (e_text_event_processor_emacs_like_get_type ())
|
||||
#define E_TEXT_EVENT_PROCESSOR_EMACS_LIKE(obj) (GTK_CHECK_CAST ((obj), E_TEXT_EVENT_PROCESSOR_EMACS_LIKE_TYPE, ETextEventProcessorEmacsLike))
|
||||
#define E_TEXT_EVENT_PROCESSOR_EMACS_LIKE_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), E_TEXT_EVENT_PROCESSOR_EMACS_LIKE_TYPE, ETextEventProcessorEmacsLikeClass))
|
||||
#define E_IS_TEXT_EVENT_PROCESSOR_EMACS_LIKE(obj) (GTK_CHECK_TYPE ((obj), E_TEXT_EVENT_PROCESSOR_EMACS_LIKE_TYPE))
|
||||
#define E_IS_TEXT_EVENT_PROCESSOR_EMACS_LIKE_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((obj), E_TEXT_EVENT_PROCESSOR_EMACS_LIKE_TYPE))
|
||||
|
||||
|
||||
typedef struct _ETextEventProcessorEmacsLike ETextEventProcessorEmacsLike;
|
||||
typedef struct _ETextEventProcessorEmacsLikeClass ETextEventProcessorEmacsLikeClass;
|
||||
|
||||
struct _ETextEventProcessorEmacsLike
|
||||
{
|
||||
ETextEventProcessor parent;
|
||||
|
||||
/* object specific fields */
|
||||
gboolean mouse_down;
|
||||
};
|
||||
|
||||
struct _ETextEventProcessorEmacsLikeClass
|
||||
{
|
||||
ETextEventProcessorClass parent_class;
|
||||
};
|
||||
|
||||
|
||||
GtkType e_text_event_processor_emacs_like_get_type (void);
|
||||
ETextEventProcessor *e_text_event_processor_emacs_like_new (void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
|
||||
#endif /* __E_TEXT_EVENT_PROCESSOR_EMACS_LIKE_H__ */
|
131
e-util/e-text-event-processor-types.h
Normal file
131
e-util/e-text-event-processor-types.h
Normal file
@ -0,0 +1,131 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/* e-text-event-processor.h
|
||||
* Copyright (C) 2000 Helix Code, Inc.
|
||||
* Author: Chris Lahey <clahey@helixcode.com>
|
||||
*
|
||||
* This library 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 library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the GTK+ Team and others 1997-1999. See the AUTHORS
|
||||
* file for a list of people on the GTK+ Team. See the ChangeLog
|
||||
* files for a list of changes. These files are distributed with
|
||||
* GTK+ at ftp://ftp.gtk.org/pub/gtk/.
|
||||
*/
|
||||
|
||||
#ifndef __E_TEXT_EVENT_PROCESSOR_TYPES_H__
|
||||
#define __E_TEXT_EVENT_PROCESSOR_TYPES_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#pragma }
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#include <gdk/gdktypes.h>
|
||||
|
||||
typedef enum _ETextEventProcessorCommandPosition ETextEventProcessorCommandPosition;
|
||||
typedef enum _ETextEventProcessorCommandAction ETextEventProcessorCommandAction;
|
||||
typedef struct _ETextEventProcessorCommand ETextEventProcessorCommand;
|
||||
|
||||
typedef union _ETextEventProcessorEvent ETextEventProcessorEvent;
|
||||
typedef struct _ETextEventProcessorEventButton ETextEventProcessorEventButton;
|
||||
typedef struct _ETextEventProcessorEventKey ETextEventProcessorEventKey;
|
||||
typedef struct _ETextEventProcessorEventMotion ETextEventProcessorEventMotion;
|
||||
|
||||
enum _ETextEventProcessorCommandPosition {
|
||||
E_TEP_VALUE,
|
||||
E_TEP_SELECTION,
|
||||
|
||||
E_TEP_START_OF_BUFFER,
|
||||
E_TEP_END_OF_BUFFER,
|
||||
|
||||
E_TEP_START_OF_LINE,
|
||||
E_TEP_END_OF_LINE,
|
||||
|
||||
E_TEP_FORWARD_CHARACTER,
|
||||
E_TEP_BACKWARD_CHARACTER,
|
||||
|
||||
E_TEP_FORWARD_WORD,
|
||||
E_TEP_BACKWARD_WORD,
|
||||
|
||||
E_TEP_FORWARD_LINE,
|
||||
E_TEP_BACKWARD_LINE,
|
||||
|
||||
E_TEP_FORWARD_PARAGRAPH,
|
||||
E_TEP_BACKWARD_PARAGRAPH,
|
||||
|
||||
E_TEP_FORWARD_PAGE,
|
||||
E_TEP_BACKWARD_PAGE
|
||||
};
|
||||
|
||||
enum _ETextEventProcessorCommandAction {
|
||||
E_TEP_MOVE,
|
||||
E_TEP_SELECT,
|
||||
E_TEP_DELETE,
|
||||
|
||||
E_TEP_INSERT,
|
||||
E_TEP_COPY,
|
||||
E_TEP_PASTE,
|
||||
E_TEP_SET_SELECT_BY_WORD,
|
||||
E_TEP_ACTIVATE,
|
||||
|
||||
E_TEP_NOP
|
||||
};
|
||||
|
||||
struct _ETextEventProcessorCommand {
|
||||
ETextEventProcessorCommandPosition position;
|
||||
ETextEventProcessorCommandAction action;
|
||||
int value;
|
||||
char *string;
|
||||
};
|
||||
|
||||
struct _ETextEventProcessorEventButton {
|
||||
GdkEventType type;
|
||||
guint32 time;
|
||||
guint state;
|
||||
guint button;
|
||||
gint position;
|
||||
};
|
||||
|
||||
struct _ETextEventProcessorEventKey {
|
||||
GdkEventType type;
|
||||
guint32 time;
|
||||
guint state;
|
||||
guint keyval;
|
||||
gint length;
|
||||
gchar *string;
|
||||
};
|
||||
|
||||
struct _ETextEventProcessorEventMotion {
|
||||
GdkEventType type;
|
||||
guint32 time;
|
||||
guint state;
|
||||
gint position;
|
||||
};
|
||||
|
||||
union _ETextEventProcessorEvent {
|
||||
GdkEventType type;
|
||||
ETextEventProcessorEventButton button;
|
||||
ETextEventProcessorEventKey key;
|
||||
ETextEventProcessorEventMotion motion;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
|
||||
#endif /* __E_TEXT_EVENT_PROCESSOR_TYPES_H__ */
|
103
e-util/e-text-event-processor.c
Normal file
103
e-util/e-text-event-processor.c
Normal file
@ -0,0 +1,103 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/* e-text-event-processor.c
|
||||
* Copyright (C) 2000 Helix Code, Inc.
|
||||
* Author: Chris Lahey <clahey@helixcode.com>
|
||||
*
|
||||
* This library 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 library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <gnome.h>
|
||||
#include "e-text-event-processor.h"
|
||||
static void e_text_event_processor_init (ETextEventProcessor *card);
|
||||
static void e_text_event_processor_class_init (ETextEventProcessorClass *klass);
|
||||
|
||||
static GtkObjectClass *parent_class = NULL;
|
||||
|
||||
/* The arguments we take */
|
||||
enum {
|
||||
ARG_0
|
||||
};
|
||||
|
||||
enum {
|
||||
E_TEP_EVENT,
|
||||
E_TEP_LAST_SIGNAL
|
||||
};
|
||||
|
||||
static guint e_tep_signals[E_TEP_LAST_SIGNAL] = { 0 };
|
||||
|
||||
GtkType
|
||||
e_text_event_processor_get_type (void)
|
||||
{
|
||||
static GtkType text_event_processor_type = 0;
|
||||
|
||||
if (!text_event_processor_type)
|
||||
{
|
||||
static const GtkTypeInfo text_event_processor_info =
|
||||
{
|
||||
"ETextEventProcessor",
|
||||
sizeof (ETextEventProcessor),
|
||||
sizeof (ETextEventProcessorClass),
|
||||
(GtkClassInitFunc) e_text_event_processor_class_init,
|
||||
(GtkObjectInitFunc) e_text_event_processor_init,
|
||||
/* reserved_1 */ NULL,
|
||||
/* reserved_2 */ NULL,
|
||||
(GtkClassInitFunc) NULL,
|
||||
};
|
||||
|
||||
text_event_processor_type = gtk_type_unique (gtk_object_get_type (), &text_event_processor_info);
|
||||
}
|
||||
|
||||
return text_event_processor_type;
|
||||
}
|
||||
|
||||
static void
|
||||
e_text_event_processor_class_init (ETextEventProcessorClass *klass)
|
||||
{
|
||||
GtkObjectClass *object_class;
|
||||
|
||||
object_class = (GtkObjectClass*) klass;
|
||||
|
||||
parent_class = gtk_type_class (gtk_object_get_type ());
|
||||
|
||||
e_tep_signals[E_TEP_EVENT] =
|
||||
gtk_signal_new ("command",
|
||||
GTK_RUN_LAST,
|
||||
object_class->type,
|
||||
GTK_SIGNAL_OFFSET (ETextEventProcessorClass, command),
|
||||
gtk_marshal_NONE__POINTER,
|
||||
GTK_TYPE_NONE, 1,
|
||||
GTK_TYPE_POINTER);
|
||||
|
||||
gtk_object_class_add_signals (object_class, e_tep_signals, E_TEP_LAST_SIGNAL);
|
||||
|
||||
klass->event = NULL;
|
||||
klass->command = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
e_text_event_processor_init (ETextEventProcessor *tep)
|
||||
{
|
||||
}
|
||||
|
||||
gint
|
||||
e_text_event_processor_handle_event (ETextEventProcessor *tep, ETextEventProcessorEvent *event)
|
||||
{
|
||||
if (E_TEXT_EVENT_PROCESSOR_CLASS(GTK_OBJECT(tep)->klass)->event) {
|
||||
return E_TEXT_EVENT_PROCESSOR_CLASS(GTK_OBJECT(tep)->klass)->event(tep, event);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
74
e-util/e-text-event-processor.h
Normal file
74
e-util/e-text-event-processor.h
Normal file
@ -0,0 +1,74 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/* e-text-event-processor.h
|
||||
* Copyright (C) 2000 Helix Code, Inc.
|
||||
* Author: Chris Lahey <clahey@helixcode.com>
|
||||
*
|
||||
* This library 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 library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
#ifndef __E_TEXT_EVENT_PROCESSOR_H__
|
||||
#define __E_TEXT_EVENT_PROCESSOR_H__
|
||||
|
||||
#include <gnome.h>
|
||||
#include "e-text-event-processor-types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#pragma }
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/* ETextEventProcessor - Turns events on a text widget into commands.
|
||||
*
|
||||
*/
|
||||
|
||||
#define E_TEXT_EVENT_PROCESSOR_TYPE (e_text_event_processor_get_type ())
|
||||
#define E_TEXT_EVENT_PROCESSOR(obj) (GTK_CHECK_CAST ((obj), E_TEXT_EVENT_PROCESSOR_TYPE, ETextEventProcessor))
|
||||
#define E_TEXT_EVENT_PROCESSOR_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), E_TEXT_EVENT_PROCESSOR_TYPE, ETextEventProcessorClass))
|
||||
#define E_IS_TEXT_EVENT_PROCESSOR(obj) (GTK_CHECK_TYPE ((obj), E_TEXT_EVENT_PROCESSOR_TYPE))
|
||||
#define E_IS_TEXT_EVENT_PROCESSOR_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((obj), E_TEXT_EVENT_PROCESSOR_TYPE))
|
||||
|
||||
|
||||
typedef struct _ETextEventProcessor ETextEventProcessor;
|
||||
typedef struct _ETextEventProcessorClass ETextEventProcessorClass;
|
||||
|
||||
struct _ETextEventProcessor
|
||||
{
|
||||
GtkObject parent;
|
||||
|
||||
/* object specific fields */
|
||||
|
||||
};
|
||||
|
||||
struct _ETextEventProcessorClass
|
||||
{
|
||||
GtkObjectClass parent_class;
|
||||
|
||||
/* signals */
|
||||
void (* command) (ETextEventProcessor *tep, ETextEventProcessorCommand *command);
|
||||
|
||||
/* virtual functions */
|
||||
gint (* event) (ETextEventProcessor *tep, ETextEventProcessorEvent *event);
|
||||
};
|
||||
|
||||
|
||||
GtkType e_text_event_processor_get_type (void);
|
||||
gint e_text_event_processor_handle_event (ETextEventProcessor *tep, ETextEventProcessorEvent *event);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
|
||||
#endif /* __E_TEXT_EVENT_PROCESSOR_H__ */
|
@ -18,7 +18,11 @@ libevolutionwidgets_a_SOURCES = \
|
||||
e-minicard-label.c \
|
||||
e-minicard-label.h \
|
||||
e-text.c \
|
||||
e-text.h
|
||||
e-text.h \
|
||||
e-text-event-processor.c \
|
||||
e-text-event-processor.h \
|
||||
e-text-event-processor-emacs-like.c \
|
||||
e-text-event-processor-emacs-like.h
|
||||
|
||||
noinst_PROGRAMS = \
|
||||
minicard-label-test \
|
||||
|
@ -239,6 +239,7 @@ e_minicard_label_realize (GnomeCanvasItem *item)
|
||||
"use_ellipsis", TRUE,
|
||||
"font", "lucidasans-10",
|
||||
"fill_color", "black",
|
||||
"editable", TRUE,
|
||||
NULL );
|
||||
|
||||
if ( e_minicard_label->field_text )
|
||||
|
@ -239,6 +239,7 @@ e_minicard_label_realize (GnomeCanvasItem *item)
|
||||
"use_ellipsis", TRUE,
|
||||
"font", "lucidasans-10",
|
||||
"fill_color", "black",
|
||||
"editable", TRUE,
|
||||
NULL );
|
||||
|
||||
if ( e_minicard_label->field_text )
|
||||
|
@ -61,11 +61,6 @@ static void about_callback( GtkWidget *widget, gpointer data )
|
||||
gtk_widget_show (about);
|
||||
}
|
||||
|
||||
static void button_press_callback( GtkWidget *widget, gpointer data )
|
||||
{
|
||||
gnome_canvas_item_grab_focus( card );
|
||||
}
|
||||
|
||||
int main( int argc, char *argv[] )
|
||||
{
|
||||
GtkWidget *app;
|
||||
@ -102,7 +97,6 @@ int main( int argc, char *argv[] )
|
||||
|
||||
gnome_app_set_contents( GNOME_APP( app ), canvas );
|
||||
|
||||
|
||||
/* Connect the signals */
|
||||
gtk_signal_connect( GTK_OBJECT( app ), "destroy",
|
||||
GTK_SIGNAL_FUNC( destroy_callback ),
|
||||
@ -112,10 +106,6 @@ int main( int argc, char *argv[] )
|
||||
GTK_SIGNAL_FUNC( allocate_callback ),
|
||||
( gpointer ) app );
|
||||
|
||||
gtk_signal_connect( GTK_OBJECT( canvas ), "button_press_event",
|
||||
GTK_SIGNAL_FUNC( button_press_callback ),
|
||||
( gpointer ) app );
|
||||
|
||||
gtk_widget_show_all( app );
|
||||
|
||||
gtk_main();
|
||||
|
327
widgets/e-text-event-processor-emacs-like.c
Normal file
327
widgets/e-text-event-processor-emacs-like.c
Normal file
@ -0,0 +1,327 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/* e-text-event-processor.c
|
||||
* Copyright (C) 2000 Helix Code, Inc.
|
||||
* Author: Chris Lahey <clahey@helixcode.com>
|
||||
*
|
||||
* This library 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 library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <gnome.h>
|
||||
#include "e-text-event-processor-emacs-like.h"
|
||||
static void e_text_event_processor_emacs_like_init (ETextEventProcessorEmacsLike *card);
|
||||
static void e_text_event_processor_emacs_like_class_init (ETextEventProcessorEmacsLikeClass *klass);
|
||||
static gint e_text_event_processor_emacs_like_event (ETextEventProcessor *tep, ETextEventProcessorEvent *event);
|
||||
|
||||
static ETextEventProcessorClass *parent_class = NULL;
|
||||
|
||||
/* The arguments we take */
|
||||
enum {
|
||||
ARG_0
|
||||
};
|
||||
|
||||
static const ETextEventProcessorCommand control_keys[26] =
|
||||
{
|
||||
{ E_TEP_START_OF_LINE, E_TEP_MOVE, 0, "" }, /* a */
|
||||
{ E_TEP_BACKWARD_CHARACTER, E_TEP_MOVE, 0, "" }, /* b */
|
||||
{ E_TEP_SELECTION, E_TEP_COPY, 0, "" }, /* c */
|
||||
{ E_TEP_FORWARD_CHARACTER, E_TEP_DELETE, 0, "" }, /* d */
|
||||
{ E_TEP_END_OF_LINE, E_TEP_MOVE, 0, "" }, /* e */
|
||||
{ E_TEP_FORWARD_CHARACTER, E_TEP_MOVE, 0, "" }, /* f */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* g */
|
||||
{ E_TEP_BACKWARD_CHARACTER, E_TEP_DELETE, 0, "" }, /* h */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* i */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* j */
|
||||
{ E_TEP_END_OF_LINE, E_TEP_DELETE, 0, "" }, /* k */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* l */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* m */
|
||||
{ E_TEP_FORWARD_LINE, E_TEP_MOVE, 0, "" }, /* n */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* o */
|
||||
{ E_TEP_BACKWARD_LINE, E_TEP_MOVE, 0, "" }, /* p */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* q */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* r */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* s */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* t */
|
||||
{ E_TEP_START_OF_LINE, E_TEP_DELETE, 0, "" }, /* u */
|
||||
{ E_TEP_SELECTION, E_TEP_PASTE, 0, "" }, /* v */
|
||||
{ E_TEP_BACKWARD_WORD, E_TEP_DELETE, 0, "" }, /* w */
|
||||
{ E_TEP_SELECTION, E_TEP_PASTE, 0, "" }, /* x */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* y */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" } /* z */
|
||||
};
|
||||
|
||||
static const ETextEventProcessorCommand alt_keys[26] =
|
||||
{
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* a */
|
||||
{ E_TEP_BACKWARD_WORD, E_TEP_MOVE, 0, "" }, /* b */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* c */
|
||||
{ E_TEP_FORWARD_WORD, E_TEP_DELETE, 0, "" }, /* d */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* e */
|
||||
{ E_TEP_FORWARD_WORD, E_TEP_MOVE, 0, "" }, /* f */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* g */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* h */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* i */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* j */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* k */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* l */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* m */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* n */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* o */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* p */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* q */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* r */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* s */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* t */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* u */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* v */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* w */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* x */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* y */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" } /* z */
|
||||
|
||||
};
|
||||
|
||||
GtkType
|
||||
e_text_event_processor_emacs_like_get_type (void)
|
||||
{
|
||||
static GtkType text_event_processor_emacs_like_type = 0;
|
||||
|
||||
if (!text_event_processor_emacs_like_type)
|
||||
{
|
||||
static const GtkTypeInfo text_event_processor_emacs_like_info =
|
||||
{
|
||||
"ETextEventProcessorEmacsLike",
|
||||
sizeof (ETextEventProcessorEmacsLike),
|
||||
sizeof (ETextEventProcessorEmacsLikeClass),
|
||||
(GtkClassInitFunc) e_text_event_processor_emacs_like_class_init,
|
||||
(GtkObjectInitFunc) e_text_event_processor_emacs_like_init,
|
||||
/* reserved_1 */ NULL,
|
||||
/* reserved_2 */ NULL,
|
||||
(GtkClassInitFunc) NULL,
|
||||
};
|
||||
|
||||
text_event_processor_emacs_like_type = gtk_type_unique (e_text_event_processor_get_type (), &text_event_processor_emacs_like_info);
|
||||
}
|
||||
|
||||
return text_event_processor_emacs_like_type;
|
||||
}
|
||||
|
||||
static void
|
||||
e_text_event_processor_emacs_like_class_init (ETextEventProcessorEmacsLikeClass *klass)
|
||||
{
|
||||
GtkObjectClass *object_class;
|
||||
ETextEventProcessorClass *processor_class;
|
||||
|
||||
object_class = (GtkObjectClass*) klass;
|
||||
processor_class = (ETextEventProcessorClass*) klass;
|
||||
|
||||
parent_class = gtk_type_class (e_text_event_processor_get_type ());
|
||||
|
||||
processor_class->event = e_text_event_processor_emacs_like_event;
|
||||
}
|
||||
|
||||
static void
|
||||
e_text_event_processor_emacs_like_init (ETextEventProcessorEmacsLike *tep)
|
||||
{
|
||||
}
|
||||
|
||||
static gint
|
||||
e_text_event_processor_emacs_like_event (ETextEventProcessor *tep, ETextEventProcessorEvent *event)
|
||||
{
|
||||
ETextEventProcessorCommand command;
|
||||
ETextEventProcessorEmacsLike *tep_el = E_TEXT_EVENT_PROCESSOR_EMACS_LIKE(tep);
|
||||
switch (event->type) {
|
||||
case GDK_BUTTON_PRESS:
|
||||
if (event->button.button == 1) {
|
||||
if (event->button.state & GDK_SHIFT_MASK)
|
||||
command.action = E_TEP_SELECT;
|
||||
else
|
||||
command.action = E_TEP_MOVE;
|
||||
command.position = E_TEP_VALUE;
|
||||
command.value = event->button.position;
|
||||
tep_el->mouse_down = TRUE;
|
||||
}
|
||||
break;
|
||||
case GDK_BUTTON_RELEASE:
|
||||
if (event->button.button == 1) {
|
||||
tep_el->mouse_down = FALSE;
|
||||
}
|
||||
break;
|
||||
case GDK_MOTION_NOTIFY:
|
||||
if (tep_el->mouse_down) {
|
||||
command.action = E_TEP_SELECT;
|
||||
command.position = E_TEP_VALUE;
|
||||
command.value = event->motion.position;
|
||||
}
|
||||
break;
|
||||
case GDK_KEY_PRESS:
|
||||
{
|
||||
ETextEventProcessorEventKey key = event->key;
|
||||
if (key.state & GDK_SHIFT_MASK)
|
||||
command.action = E_TEP_SELECT;
|
||||
else
|
||||
command.action = E_TEP_MOVE;
|
||||
switch(key.keyval) {
|
||||
case GDK_Home:
|
||||
if (key.state & GDK_CONTROL_MASK)
|
||||
command.position = E_TEP_START_OF_BUFFER;
|
||||
else
|
||||
command.position = E_TEP_START_OF_LINE;
|
||||
break;
|
||||
case GDK_End:
|
||||
if (key.state & GDK_CONTROL_MASK)
|
||||
command.position = E_TEP_END_OF_BUFFER;
|
||||
else
|
||||
command.position = E_TEP_END_OF_LINE;
|
||||
break;
|
||||
case GDK_Page_Up: command.position = E_TEP_BACKWARD_PAGE; break;
|
||||
case GDK_Page_Down: command.position = E_TEP_FORWARD_PAGE; break;
|
||||
/* CUA has Ctrl-Up/Ctrl-Down as paragraph up down */
|
||||
case GDK_Up: command.position = E_TEP_BACKWARD_LINE; break;
|
||||
case GDK_Down: command.position = E_TEP_FORWARD_LINE; break;
|
||||
case GDK_Left:
|
||||
if (key.state & GDK_CONTROL_MASK)
|
||||
command.position = E_TEP_BACKWARD_WORD;
|
||||
else
|
||||
command.position = E_TEP_BACKWARD_CHARACTER;
|
||||
break;
|
||||
case GDK_Right:
|
||||
if (key.state & GDK_CONTROL_MASK)
|
||||
command.position = E_TEP_FORWARD_WORD;
|
||||
else
|
||||
command.position = E_TEP_FORWARD_CHARACTER;
|
||||
break;
|
||||
|
||||
case GDK_BackSpace:
|
||||
command.action = E_TEP_DELETE;
|
||||
if (key.state & GDK_CONTROL_MASK)
|
||||
command.position = E_TEP_BACKWARD_WORD;
|
||||
else
|
||||
command.position = E_TEP_BACKWARD_CHARACTER;
|
||||
break;
|
||||
case GDK_Clear:
|
||||
command.action = E_TEP_DELETE;
|
||||
command.position = E_TEP_END_OF_LINE;
|
||||
break;
|
||||
case GDK_Insert:
|
||||
if (key.state & GDK_SHIFT_MASK) {
|
||||
command.action = E_TEP_PASTE;
|
||||
command.position = E_TEP_SELECTION;
|
||||
} else if (key.state & GDK_CONTROL_MASK) {
|
||||
command.action = E_TEP_COPY;
|
||||
command.position = E_TEP_SELECTION;
|
||||
} else {
|
||||
/* gtk_toggle_insert(text) -- IMPLEMENT */
|
||||
}
|
||||
break;
|
||||
case GDK_Delete:
|
||||
if (key.state & GDK_CONTROL_MASK){
|
||||
command.action = E_TEP_DELETE;
|
||||
command.position = E_TEP_FORWARD_WORD;
|
||||
} else if (key.state & GDK_SHIFT_MASK) {
|
||||
command.action = E_TEP_COPY;
|
||||
|
||||
command.action = E_TEP_DELETE;
|
||||
command.position = E_TEP_SELECTION;
|
||||
} else {
|
||||
command.action = E_TEP_DELETE;
|
||||
command.position = E_TEP_FORWARD_CHARACTER;
|
||||
}
|
||||
break;
|
||||
case GDK_Tab:
|
||||
command.action = E_TEP_INSERT;
|
||||
command.position = E_TEP_SELECTION;
|
||||
command.value = 1;
|
||||
command.string = "\t";
|
||||
break;
|
||||
case GDK_Return:
|
||||
if (key.state & GDK_CONTROL_MASK) {
|
||||
command.action = E_TEP_ACTIVATE;
|
||||
command.position = E_TEP_SELECTION;
|
||||
} else {
|
||||
command.action = E_TEP_INSERT;
|
||||
command.position = E_TEP_SELECTION;
|
||||
command.value = 1;
|
||||
command.string = "\n";
|
||||
}
|
||||
break;
|
||||
case GDK_Escape:
|
||||
command.action = E_TEP_NOP;
|
||||
command.position = E_TEP_SELECTION;
|
||||
/* Don't insert literally */
|
||||
break;
|
||||
|
||||
default:
|
||||
if (key.state & GDK_CONTROL_MASK) {
|
||||
if ((key.keyval >= 'A') && (key.keyval <= 'Z'))
|
||||
key.keyval -= 'A' - 'a';
|
||||
|
||||
if ((key.keyval >= 'a') && (key.keyval <= 'z')) {
|
||||
command.position = control_keys[(int) (key.keyval - 'a')].position;
|
||||
if (control_keys[(int) (key.keyval - 'a')].action != E_TEP_MOVE)
|
||||
command.action = control_keys[(int) (key.keyval - 'a')].action;
|
||||
command.value = control_keys[(int) (key.keyval - 'a')].value;
|
||||
command.string = control_keys[(int) (key.keyval - 'a')].string;
|
||||
}
|
||||
|
||||
if (key.keyval == 'x') {
|
||||
}
|
||||
|
||||
break;
|
||||
} else if (key.state & GDK_MOD1_MASK) {
|
||||
if ((key.keyval >= 'A') && (key.keyval <= 'Z'))
|
||||
key.keyval -= 'A' - 'a';
|
||||
|
||||
if ((key.keyval >= 'a') && (key.keyval <= 'z')) {
|
||||
command.position = alt_keys[(int) (key.keyval - 'a')].position;
|
||||
if (alt_keys[(int) (key.keyval - 'a')].action != E_TEP_MOVE)
|
||||
command.action = alt_keys[(int) (key.keyval - 'a')].action;
|
||||
command.value = alt_keys[(int) (key.keyval - 'a')].value;
|
||||
command.string = alt_keys[(int) (key.keyval - 'a')].string;
|
||||
}
|
||||
} else if (key.length > 0) {
|
||||
command.action = E_TEP_INSERT;
|
||||
command.position = E_TEP_SELECTION;
|
||||
command.value = strlen(key.string);
|
||||
command.string = key.string;
|
||||
|
||||
} else {
|
||||
command.action = E_TEP_NOP;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case GDK_KEY_RELEASE:
|
||||
command.action = E_TEP_NOP;
|
||||
break;
|
||||
default:
|
||||
command.action = E_TEP_NOP;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (command.action != E_TEP_NOP) {
|
||||
gtk_signal_emit_by_name (GTK_OBJECT (tep), "command", &command);
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
ETextEventProcessor *
|
||||
e_text_event_processor_emacs_like_new (void)
|
||||
{
|
||||
ETextEventProcessorEmacsLike *retval = gtk_type_new (e_text_event_processor_emacs_like_get_type ());
|
||||
return E_TEXT_EVENT_PROCESSOR (retval);
|
||||
}
|
||||
|
68
widgets/e-text-event-processor-emacs-like.h
Normal file
68
widgets/e-text-event-processor-emacs-like.h
Normal file
@ -0,0 +1,68 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/* e-text-event-processor-emacs-like.h
|
||||
* Copyright (C) 2000 Helix Code, Inc.
|
||||
* Author: Chris Lahey <clahey@helixcode.com>
|
||||
*
|
||||
* This library 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 library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
#ifndef __E_TEXT_EVENT_PROCESSOR_EMACS_LIKE_H__
|
||||
#define __E_TEXT_EVENT_PROCESSOR_EMACS_LIKE_H__
|
||||
|
||||
#include <gnome.h>
|
||||
#include "e-text-event-processor.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#pragma }
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/* ETextEventProcessorEmacsLike - Turns events on a text widget into commands. Uses an emacs-ish interface.
|
||||
*
|
||||
*/
|
||||
|
||||
#define E_TEXT_EVENT_PROCESSOR_EMACS_LIKE_TYPE (e_text_event_processor_emacs_like_get_type ())
|
||||
#define E_TEXT_EVENT_PROCESSOR_EMACS_LIKE(obj) (GTK_CHECK_CAST ((obj), E_TEXT_EVENT_PROCESSOR_EMACS_LIKE_TYPE, ETextEventProcessorEmacsLike))
|
||||
#define E_TEXT_EVENT_PROCESSOR_EMACS_LIKE_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), E_TEXT_EVENT_PROCESSOR_EMACS_LIKE_TYPE, ETextEventProcessorEmacsLikeClass))
|
||||
#define E_IS_TEXT_EVENT_PROCESSOR_EMACS_LIKE(obj) (GTK_CHECK_TYPE ((obj), E_TEXT_EVENT_PROCESSOR_EMACS_LIKE_TYPE))
|
||||
#define E_IS_TEXT_EVENT_PROCESSOR_EMACS_LIKE_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((obj), E_TEXT_EVENT_PROCESSOR_EMACS_LIKE_TYPE))
|
||||
|
||||
|
||||
typedef struct _ETextEventProcessorEmacsLike ETextEventProcessorEmacsLike;
|
||||
typedef struct _ETextEventProcessorEmacsLikeClass ETextEventProcessorEmacsLikeClass;
|
||||
|
||||
struct _ETextEventProcessorEmacsLike
|
||||
{
|
||||
ETextEventProcessor parent;
|
||||
|
||||
/* object specific fields */
|
||||
gboolean mouse_down;
|
||||
};
|
||||
|
||||
struct _ETextEventProcessorEmacsLikeClass
|
||||
{
|
||||
ETextEventProcessorClass parent_class;
|
||||
};
|
||||
|
||||
|
||||
GtkType e_text_event_processor_emacs_like_get_type (void);
|
||||
ETextEventProcessor *e_text_event_processor_emacs_like_new (void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
|
||||
#endif /* __E_TEXT_EVENT_PROCESSOR_EMACS_LIKE_H__ */
|
131
widgets/e-text-event-processor-types.h
Normal file
131
widgets/e-text-event-processor-types.h
Normal file
@ -0,0 +1,131 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/* e-text-event-processor.h
|
||||
* Copyright (C) 2000 Helix Code, Inc.
|
||||
* Author: Chris Lahey <clahey@helixcode.com>
|
||||
*
|
||||
* This library 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 library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the GTK+ Team and others 1997-1999. See the AUTHORS
|
||||
* file for a list of people on the GTK+ Team. See the ChangeLog
|
||||
* files for a list of changes. These files are distributed with
|
||||
* GTK+ at ftp://ftp.gtk.org/pub/gtk/.
|
||||
*/
|
||||
|
||||
#ifndef __E_TEXT_EVENT_PROCESSOR_TYPES_H__
|
||||
#define __E_TEXT_EVENT_PROCESSOR_TYPES_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#pragma }
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#include <gdk/gdktypes.h>
|
||||
|
||||
typedef enum _ETextEventProcessorCommandPosition ETextEventProcessorCommandPosition;
|
||||
typedef enum _ETextEventProcessorCommandAction ETextEventProcessorCommandAction;
|
||||
typedef struct _ETextEventProcessorCommand ETextEventProcessorCommand;
|
||||
|
||||
typedef union _ETextEventProcessorEvent ETextEventProcessorEvent;
|
||||
typedef struct _ETextEventProcessorEventButton ETextEventProcessorEventButton;
|
||||
typedef struct _ETextEventProcessorEventKey ETextEventProcessorEventKey;
|
||||
typedef struct _ETextEventProcessorEventMotion ETextEventProcessorEventMotion;
|
||||
|
||||
enum _ETextEventProcessorCommandPosition {
|
||||
E_TEP_VALUE,
|
||||
E_TEP_SELECTION,
|
||||
|
||||
E_TEP_START_OF_BUFFER,
|
||||
E_TEP_END_OF_BUFFER,
|
||||
|
||||
E_TEP_START_OF_LINE,
|
||||
E_TEP_END_OF_LINE,
|
||||
|
||||
E_TEP_FORWARD_CHARACTER,
|
||||
E_TEP_BACKWARD_CHARACTER,
|
||||
|
||||
E_TEP_FORWARD_WORD,
|
||||
E_TEP_BACKWARD_WORD,
|
||||
|
||||
E_TEP_FORWARD_LINE,
|
||||
E_TEP_BACKWARD_LINE,
|
||||
|
||||
E_TEP_FORWARD_PARAGRAPH,
|
||||
E_TEP_BACKWARD_PARAGRAPH,
|
||||
|
||||
E_TEP_FORWARD_PAGE,
|
||||
E_TEP_BACKWARD_PAGE
|
||||
};
|
||||
|
||||
enum _ETextEventProcessorCommandAction {
|
||||
E_TEP_MOVE,
|
||||
E_TEP_SELECT,
|
||||
E_TEP_DELETE,
|
||||
|
||||
E_TEP_INSERT,
|
||||
E_TEP_COPY,
|
||||
E_TEP_PASTE,
|
||||
E_TEP_SET_SELECT_BY_WORD,
|
||||
E_TEP_ACTIVATE,
|
||||
|
||||
E_TEP_NOP
|
||||
};
|
||||
|
||||
struct _ETextEventProcessorCommand {
|
||||
ETextEventProcessorCommandPosition position;
|
||||
ETextEventProcessorCommandAction action;
|
||||
int value;
|
||||
char *string;
|
||||
};
|
||||
|
||||
struct _ETextEventProcessorEventButton {
|
||||
GdkEventType type;
|
||||
guint32 time;
|
||||
guint state;
|
||||
guint button;
|
||||
gint position;
|
||||
};
|
||||
|
||||
struct _ETextEventProcessorEventKey {
|
||||
GdkEventType type;
|
||||
guint32 time;
|
||||
guint state;
|
||||
guint keyval;
|
||||
gint length;
|
||||
gchar *string;
|
||||
};
|
||||
|
||||
struct _ETextEventProcessorEventMotion {
|
||||
GdkEventType type;
|
||||
guint32 time;
|
||||
guint state;
|
||||
gint position;
|
||||
};
|
||||
|
||||
union _ETextEventProcessorEvent {
|
||||
GdkEventType type;
|
||||
ETextEventProcessorEventButton button;
|
||||
ETextEventProcessorEventKey key;
|
||||
ETextEventProcessorEventMotion motion;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
|
||||
#endif /* __E_TEXT_EVENT_PROCESSOR_TYPES_H__ */
|
103
widgets/e-text-event-processor.c
Normal file
103
widgets/e-text-event-processor.c
Normal file
@ -0,0 +1,103 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/* e-text-event-processor.c
|
||||
* Copyright (C) 2000 Helix Code, Inc.
|
||||
* Author: Chris Lahey <clahey@helixcode.com>
|
||||
*
|
||||
* This library 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 library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <gnome.h>
|
||||
#include "e-text-event-processor.h"
|
||||
static void e_text_event_processor_init (ETextEventProcessor *card);
|
||||
static void e_text_event_processor_class_init (ETextEventProcessorClass *klass);
|
||||
|
||||
static GtkObjectClass *parent_class = NULL;
|
||||
|
||||
/* The arguments we take */
|
||||
enum {
|
||||
ARG_0
|
||||
};
|
||||
|
||||
enum {
|
||||
E_TEP_EVENT,
|
||||
E_TEP_LAST_SIGNAL
|
||||
};
|
||||
|
||||
static guint e_tep_signals[E_TEP_LAST_SIGNAL] = { 0 };
|
||||
|
||||
GtkType
|
||||
e_text_event_processor_get_type (void)
|
||||
{
|
||||
static GtkType text_event_processor_type = 0;
|
||||
|
||||
if (!text_event_processor_type)
|
||||
{
|
||||
static const GtkTypeInfo text_event_processor_info =
|
||||
{
|
||||
"ETextEventProcessor",
|
||||
sizeof (ETextEventProcessor),
|
||||
sizeof (ETextEventProcessorClass),
|
||||
(GtkClassInitFunc) e_text_event_processor_class_init,
|
||||
(GtkObjectInitFunc) e_text_event_processor_init,
|
||||
/* reserved_1 */ NULL,
|
||||
/* reserved_2 */ NULL,
|
||||
(GtkClassInitFunc) NULL,
|
||||
};
|
||||
|
||||
text_event_processor_type = gtk_type_unique (gtk_object_get_type (), &text_event_processor_info);
|
||||
}
|
||||
|
||||
return text_event_processor_type;
|
||||
}
|
||||
|
||||
static void
|
||||
e_text_event_processor_class_init (ETextEventProcessorClass *klass)
|
||||
{
|
||||
GtkObjectClass *object_class;
|
||||
|
||||
object_class = (GtkObjectClass*) klass;
|
||||
|
||||
parent_class = gtk_type_class (gtk_object_get_type ());
|
||||
|
||||
e_tep_signals[E_TEP_EVENT] =
|
||||
gtk_signal_new ("command",
|
||||
GTK_RUN_LAST,
|
||||
object_class->type,
|
||||
GTK_SIGNAL_OFFSET (ETextEventProcessorClass, command),
|
||||
gtk_marshal_NONE__POINTER,
|
||||
GTK_TYPE_NONE, 1,
|
||||
GTK_TYPE_POINTER);
|
||||
|
||||
gtk_object_class_add_signals (object_class, e_tep_signals, E_TEP_LAST_SIGNAL);
|
||||
|
||||
klass->event = NULL;
|
||||
klass->command = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
e_text_event_processor_init (ETextEventProcessor *tep)
|
||||
{
|
||||
}
|
||||
|
||||
gint
|
||||
e_text_event_processor_handle_event (ETextEventProcessor *tep, ETextEventProcessorEvent *event)
|
||||
{
|
||||
if (E_TEXT_EVENT_PROCESSOR_CLASS(GTK_OBJECT(tep)->klass)->event) {
|
||||
return E_TEXT_EVENT_PROCESSOR_CLASS(GTK_OBJECT(tep)->klass)->event(tep, event);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
74
widgets/e-text-event-processor.h
Normal file
74
widgets/e-text-event-processor.h
Normal file
@ -0,0 +1,74 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/* e-text-event-processor.h
|
||||
* Copyright (C) 2000 Helix Code, Inc.
|
||||
* Author: Chris Lahey <clahey@helixcode.com>
|
||||
*
|
||||
* This library 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 library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
#ifndef __E_TEXT_EVENT_PROCESSOR_H__
|
||||
#define __E_TEXT_EVENT_PROCESSOR_H__
|
||||
|
||||
#include <gnome.h>
|
||||
#include "e-text-event-processor-types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#pragma }
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/* ETextEventProcessor - Turns events on a text widget into commands.
|
||||
*
|
||||
*/
|
||||
|
||||
#define E_TEXT_EVENT_PROCESSOR_TYPE (e_text_event_processor_get_type ())
|
||||
#define E_TEXT_EVENT_PROCESSOR(obj) (GTK_CHECK_CAST ((obj), E_TEXT_EVENT_PROCESSOR_TYPE, ETextEventProcessor))
|
||||
#define E_TEXT_EVENT_PROCESSOR_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), E_TEXT_EVENT_PROCESSOR_TYPE, ETextEventProcessorClass))
|
||||
#define E_IS_TEXT_EVENT_PROCESSOR(obj) (GTK_CHECK_TYPE ((obj), E_TEXT_EVENT_PROCESSOR_TYPE))
|
||||
#define E_IS_TEXT_EVENT_PROCESSOR_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((obj), E_TEXT_EVENT_PROCESSOR_TYPE))
|
||||
|
||||
|
||||
typedef struct _ETextEventProcessor ETextEventProcessor;
|
||||
typedef struct _ETextEventProcessorClass ETextEventProcessorClass;
|
||||
|
||||
struct _ETextEventProcessor
|
||||
{
|
||||
GtkObject parent;
|
||||
|
||||
/* object specific fields */
|
||||
|
||||
};
|
||||
|
||||
struct _ETextEventProcessorClass
|
||||
{
|
||||
GtkObjectClass parent_class;
|
||||
|
||||
/* signals */
|
||||
void (* command) (ETextEventProcessor *tep, ETextEventProcessorCommand *command);
|
||||
|
||||
/* virtual functions */
|
||||
gint (* event) (ETextEventProcessor *tep, ETextEventProcessorEvent *event);
|
||||
};
|
||||
|
||||
|
||||
GtkType e_text_event_processor_get_type (void);
|
||||
gint e_text_event_processor_handle_event (ETextEventProcessor *tep, ETextEventProcessorEvent *event);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
|
||||
#endif /* __E_TEXT_EVENT_PROCESSOR_H__ */
|
412
widgets/e-text.c
412
widgets/e-text.c
@ -18,12 +18,15 @@
|
||||
|
||||
#include <config.h>
|
||||
#include <math.h>
|
||||
#include <ctype.h>
|
||||
#include "e-text.h"
|
||||
#include <gdk/gdkx.h> /* for BlackPixel */
|
||||
#include <libart_lgpl/art_affine.h>
|
||||
#include <libart_lgpl/art_rgb.h>
|
||||
#include <libart_lgpl/art_rgb_bitmap_affine.h>
|
||||
|
||||
#include "e-text-event-processor-emacs-like.h"
|
||||
|
||||
|
||||
|
||||
/* This defines a line of text */
|
||||
@ -58,6 +61,7 @@ enum {
|
||||
ARG_FILL_STIPPLE,
|
||||
ARG_TEXT_WIDTH,
|
||||
ARG_TEXT_HEIGHT,
|
||||
ARG_EDITABLE,
|
||||
ARG_USE_ELLIPSIS,
|
||||
ARG_ELLIPSIS
|
||||
};
|
||||
@ -80,6 +84,9 @@ static double e_text_point (GnomeCanvasItem *item, double x, double y, int cx, i
|
||||
static void e_text_bounds (GnomeCanvasItem *item,
|
||||
double *x1, double *y1, double *x2, double *y2);
|
||||
static void e_text_render (GnomeCanvasItem *item, GnomeCanvasBuf *buf);
|
||||
static gint e_text_event (GnomeCanvasItem *item, GdkEvent *event);
|
||||
|
||||
static void e_text_command(ETextEventProcessor *tep, ETextEventProcessorCommand *command, gpointer data);
|
||||
|
||||
static ETextSuckFont *e_suck_font (GdkFont *font);
|
||||
static void e_suck_font_free (ETextSuckFont *suckfont);
|
||||
@ -171,6 +178,8 @@ e_text_class_init (ETextClass *class)
|
||||
GTK_TYPE_DOUBLE, GTK_ARG_READABLE, ARG_TEXT_WIDTH);
|
||||
gtk_object_add_arg_type ("EText::text_height",
|
||||
GTK_TYPE_DOUBLE, GTK_ARG_READABLE, ARG_TEXT_HEIGHT);
|
||||
gtk_object_add_arg_type ("EText::editable",
|
||||
GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_EDITABLE);
|
||||
gtk_object_add_arg_type ("EText::use_ellipsis",
|
||||
GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_USE_ELLIPSIS);
|
||||
gtk_object_add_arg_type ("EText::ellipsis",
|
||||
@ -187,6 +196,7 @@ e_text_class_init (ETextClass *class)
|
||||
item_class->point = e_text_point;
|
||||
item_class->bounds = e_text_bounds;
|
||||
item_class->render = e_text_render;
|
||||
item_class->event = e_text_event;
|
||||
}
|
||||
|
||||
/* Object initialization function for the text item */
|
||||
@ -201,9 +211,18 @@ e_text_init (EText *text)
|
||||
text->clip_height = 0.0;
|
||||
text->xofs = 0.0;
|
||||
text->yofs = 0.0;
|
||||
|
||||
text->ellipsis = NULL;
|
||||
text->use_ellipsis = FALSE;
|
||||
text->ellipsis_width = 0;
|
||||
|
||||
text->editable = FALSE;
|
||||
text->editing = FALSE;
|
||||
text->xofs_edit = 0;
|
||||
|
||||
text->selection_start = 0;
|
||||
text->selection_end = 0;
|
||||
text->select_by_word = FALSE;
|
||||
}
|
||||
|
||||
/* Destroy handler for the text item */
|
||||
@ -457,6 +476,7 @@ calc_line_widths (EText *text)
|
||||
|
||||
if (text->clip &&
|
||||
text->use_ellipsis &&
|
||||
! text->editing &&
|
||||
lines->width > text->clip_width) {
|
||||
if (text->font) {
|
||||
lines->ellipsis_length = 0;
|
||||
@ -729,6 +749,10 @@ e_text_set_arg (GtkObject *object, GtkArg *arg, guint arg_id)
|
||||
set_stipple (text, GTK_VALUE_BOXED (*arg), FALSE);
|
||||
break;
|
||||
|
||||
case ARG_EDITABLE:
|
||||
text->editable = GTK_VALUE_BOOL (*arg);
|
||||
break;
|
||||
|
||||
case ARG_USE_ELLIPSIS:
|
||||
text->use_ellipsis = GTK_VALUE_BOOL (*arg);
|
||||
calc_line_widths (text);
|
||||
@ -839,6 +863,10 @@ e_text_get_arg (GtkObject *object, GtkArg *arg, guint arg_id)
|
||||
GTK_VALUE_DOUBLE (*arg) = text->height / text->item.canvas->pixels_per_unit;
|
||||
break;
|
||||
|
||||
case ARG_EDITABLE:
|
||||
GTK_VALUE_BOOL (*arg) = text->editable;
|
||||
break;
|
||||
|
||||
case ARG_USE_ELLIPSIS:
|
||||
GTK_VALUE_BOOL (*arg) = text->use_ellipsis;
|
||||
break;
|
||||
@ -1016,6 +1044,19 @@ get_line_xpos (EText *text, struct line *line)
|
||||
return x;
|
||||
}
|
||||
|
||||
static void
|
||||
_get_tep(EText *text)
|
||||
{
|
||||
if (!text->tep) {
|
||||
text->tep = e_text_event_processor_emacs_like_new();
|
||||
gtk_signal_connect(GTK_OBJECT(text->tep),
|
||||
"command",
|
||||
GTK_SIGNAL_FUNC(e_text_command),
|
||||
(gpointer) text);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/* Draw handler for the text item */
|
||||
static void
|
||||
e_text_draw (GnomeCanvasItem *item, GdkDrawable *drawable,
|
||||
@ -1026,8 +1067,14 @@ e_text_draw (GnomeCanvasItem *item, GdkDrawable *drawable,
|
||||
struct line *lines;
|
||||
int i;
|
||||
int xpos, ypos;
|
||||
int start_char, end_char;
|
||||
int sel_start, sel_end;
|
||||
GdkRectangle sel_rect;
|
||||
GdkGC *fg_gc;
|
||||
GnomeCanvas *canvas;
|
||||
|
||||
text = E_TEXT (item);
|
||||
canvas = GNOME_CANVAS_ITEM(text)->canvas;
|
||||
|
||||
if (!text->text || !text->font)
|
||||
return;
|
||||
@ -1039,6 +1086,7 @@ e_text_draw (GnomeCanvasItem *item, GdkDrawable *drawable,
|
||||
rect.height = text->clip_cheight;
|
||||
|
||||
gdk_gc_set_clip_rectangle (text->gc, &rect);
|
||||
gdk_gc_set_clip_rectangle (GTK_WIDGET(canvas)->style->fg_gc[GTK_STATE_SELECTED], &rect);
|
||||
}
|
||||
lines = text->lines;
|
||||
ypos = text->cy + text->font->ascent;
|
||||
@ -1049,6 +1097,86 @@ e_text_draw (GnomeCanvasItem *item, GdkDrawable *drawable,
|
||||
for (i = 0; i < text->num_lines; i++) {
|
||||
if (lines->length != 0) {
|
||||
xpos = get_line_xpos (text, lines);
|
||||
if (text->editing) {
|
||||
xpos -= text->xofs_edit;
|
||||
start_char = lines->text - text->text;
|
||||
end_char = start_char + lines->length;
|
||||
sel_start = text->selection_start;
|
||||
sel_end = text->selection_end;
|
||||
if (sel_start > sel_end ) {
|
||||
sel_start ^= sel_end;
|
||||
sel_end ^= sel_start;
|
||||
sel_start ^= sel_end;
|
||||
}
|
||||
if ( sel_start < start_char )
|
||||
sel_start = start_char;
|
||||
if ( sel_end > end_char )
|
||||
sel_end = end_char;
|
||||
if ( sel_start < sel_end ) {
|
||||
sel_rect.x = xpos - x + gdk_text_width (text->font,
|
||||
lines->text,
|
||||
sel_start - start_char);
|
||||
sel_rect.y = ypos - y - text->font->ascent;
|
||||
sel_rect.width = gdk_text_width (text->font,
|
||||
lines->text + sel_start - start_char,
|
||||
sel_end - sel_start);
|
||||
sel_rect.height = text->font->ascent + text->font->descent;
|
||||
gdk_draw_rectangle (drawable,
|
||||
text->gc,
|
||||
TRUE,
|
||||
sel_rect.x,
|
||||
sel_rect.y,
|
||||
sel_rect.width,
|
||||
sel_rect.height);
|
||||
gdk_draw_text (drawable,
|
||||
text->font,
|
||||
text->gc,
|
||||
xpos - x,
|
||||
ypos - y,
|
||||
lines->text,
|
||||
sel_start - start_char);
|
||||
fg_gc = GTK_WIDGET(canvas)->style->fg_gc[GTK_STATE_SELECTED];
|
||||
gdk_draw_text (drawable,
|
||||
text->font,
|
||||
fg_gc,
|
||||
xpos - x + gdk_text_width (text->font,
|
||||
lines->text,
|
||||
sel_start - start_char),
|
||||
ypos - y,
|
||||
lines->text + sel_start - start_char,
|
||||
sel_end - sel_start);
|
||||
gdk_draw_text (drawable,
|
||||
text->font,
|
||||
text->gc,
|
||||
xpos - x + gdk_text_width (text->font,
|
||||
lines->text,
|
||||
sel_end - start_char),
|
||||
ypos - y,
|
||||
lines->text + sel_end - start_char,
|
||||
end_char - sel_end);
|
||||
} else {
|
||||
gdk_draw_text (drawable,
|
||||
text->font,
|
||||
text->gc,
|
||||
xpos - x,
|
||||
ypos - y,
|
||||
lines->text,
|
||||
lines->length);
|
||||
}
|
||||
if (text->selection_start == text->selection_end &&
|
||||
text->selection_start >= start_char &&
|
||||
text->selection_start <= end_char) {
|
||||
gdk_draw_rectangle (drawable,
|
||||
text->gc,
|
||||
TRUE,
|
||||
xpos - x + gdk_text_width (text->font,
|
||||
lines->text,
|
||||
sel_start - start_char),
|
||||
ypos - y - text->font->ascent,
|
||||
1,
|
||||
text->font->ascent + text->font->descent);
|
||||
}
|
||||
} else {
|
||||
if ( text->clip && text->use_ellipsis && lines->ellipsis_length < lines->length) {
|
||||
gdk_draw_text (drawable,
|
||||
text->font,
|
||||
@ -1075,13 +1203,16 @@ e_text_draw (GnomeCanvasItem *item, GdkDrawable *drawable,
|
||||
lines->text,
|
||||
lines->length);
|
||||
}
|
||||
}
|
||||
|
||||
ypos += text->font->ascent + text->font->descent;
|
||||
lines++;
|
||||
}
|
||||
|
||||
if (text->clip)
|
||||
if (text->clip) {
|
||||
gdk_gc_set_clip_rectangle (text->gc, NULL);
|
||||
gdk_gc_set_clip_rectangle (GTK_WIDGET(GNOME_CANVAS_ITEM(text)->canvas)->style->fg_gc[GTK_STATE_SELECTED], NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/* Render handler for the text item */
|
||||
@ -1308,6 +1439,285 @@ e_text_bounds (GnomeCanvasItem *item, double *x1, double *y1, double *x2, double
|
||||
*y2 = *y1 + height;
|
||||
}
|
||||
|
||||
static gint
|
||||
_get_position_from_xy (EText *text, gint x, gint y)
|
||||
{
|
||||
int i, j;
|
||||
int ypos = text->cy;
|
||||
int xpos;
|
||||
struct line *lines;
|
||||
j = 0;
|
||||
while (y > ypos)
|
||||
{
|
||||
ypos += text->font->ascent + text->font->descent;
|
||||
j ++;
|
||||
}
|
||||
j--;
|
||||
if (j >= text->num_lines)
|
||||
j = text->num_lines - 1;
|
||||
if (j < 0)
|
||||
j = 0;
|
||||
i = 0;
|
||||
lines = text->lines;
|
||||
lines += j;
|
||||
xpos = get_line_xpos (text, lines);
|
||||
for(i = 0; i < lines->length; i++) {
|
||||
int charwidth = gdk_text_width(text->font,
|
||||
lines->text + i,
|
||||
1);
|
||||
xpos += charwidth / 2;
|
||||
if (xpos > x)
|
||||
break;
|
||||
xpos += (charwidth + 1) / 2;
|
||||
}
|
||||
return lines->text + i - text->text;
|
||||
}
|
||||
|
||||
static gint
|
||||
e_text_event (GnomeCanvasItem *item, GdkEvent *event)
|
||||
{
|
||||
EText *text = E_TEXT(item);
|
||||
ETextEventProcessorEvent e_tep_event;
|
||||
|
||||
gint return_val;
|
||||
|
||||
e_tep_event.type = event->type;
|
||||
switch (event->type) {
|
||||
case GDK_FOCUS_CHANGE:
|
||||
if (text->editable) {
|
||||
GdkEventFocus *focus_event;
|
||||
focus_event = (GdkEventFocus *) event;
|
||||
if (focus_event->in) {
|
||||
if(!text->editing) {
|
||||
text->editing = TRUE;
|
||||
text->selection_start = 0;
|
||||
text->selection_end = 0;
|
||||
text->select_by_word = FALSE;
|
||||
text->xofs_edit = 0;
|
||||
}
|
||||
} else {
|
||||
text->editing = FALSE;
|
||||
}
|
||||
calc_line_widths (text);
|
||||
}
|
||||
return_val = 0;
|
||||
break;
|
||||
case GDK_KEY_PRESS: /* Fall Through */
|
||||
case GDK_KEY_RELEASE:
|
||||
if (text->editing) {
|
||||
GdkEventKey key = event->key;
|
||||
e_tep_event.key.time = key.time;
|
||||
e_tep_event.key.state = key.state;
|
||||
e_tep_event.key.keyval = key.keyval;
|
||||
e_tep_event.key.length = key.length;
|
||||
e_tep_event.key.string = key.string;
|
||||
_get_tep(text);
|
||||
return e_text_event_processor_handle_event (text->tep,
|
||||
&e_tep_event);
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
break;
|
||||
case GDK_BUTTON_PRESS: /* Fall Through */
|
||||
case GDK_BUTTON_RELEASE:
|
||||
if (text->editing) {
|
||||
GdkEventButton button = event->button;
|
||||
e_tep_event.button.time = button.time;
|
||||
e_tep_event.button.state = button.state;
|
||||
e_tep_event.button.button = button.button;
|
||||
e_tep_event.button.position = _get_position_from_xy(text, button.x, button.y);
|
||||
_get_tep(text);
|
||||
return_val = e_text_event_processor_handle_event (text->tep,
|
||||
&e_tep_event);
|
||||
} else if (text->editable && event->type == GDK_BUTTON_RELEASE) {
|
||||
gnome_canvas_item_grab_focus (item);
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case GDK_MOTION_NOTIFY:
|
||||
if (text->editing) {
|
||||
GdkEventMotion motion = event->motion;
|
||||
e_tep_event.motion.time = motion.time;
|
||||
e_tep_event.motion.state = motion.state;
|
||||
e_tep_event.motion.position = _get_position_from_xy(text, motion.x, motion.y);
|
||||
_get_tep(text);
|
||||
return_val = e_text_event_processor_handle_event (text->tep,
|
||||
&e_tep_event);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (return_val)
|
||||
return return_val;
|
||||
if (GNOME_CANVAS_ITEM_CLASS(parent_class)->event)
|
||||
return GNOME_CANVAS_ITEM_CLASS(parent_class)->event(item, event);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
_get_position(EText *text, ETextEventProcessorCommand *command)
|
||||
{
|
||||
int i;
|
||||
int length;
|
||||
|
||||
switch (command->position) {
|
||||
|
||||
case E_TEP_VALUE:
|
||||
return command->value;
|
||||
|
||||
case E_TEP_SELECTION:
|
||||
return text->selection_end;
|
||||
|
||||
case E_TEP_START_OF_BUFFER:
|
||||
return 0;
|
||||
case E_TEP_END_OF_BUFFER:
|
||||
return strlen(text->text);
|
||||
|
||||
case E_TEP_START_OF_LINE:
|
||||
for (i = text->selection_end - 2; i > 0; i--)
|
||||
if (text->text[i] == '\n') {
|
||||
i++;
|
||||
break;
|
||||
}
|
||||
return i;
|
||||
case E_TEP_END_OF_LINE:
|
||||
length = strlen(text->text);
|
||||
for (i = text->selection_end + 1; i < length; i++)
|
||||
if (text->text[i] == '\n') {
|
||||
break;
|
||||
}
|
||||
if (i > length)
|
||||
i = length;
|
||||
return i;
|
||||
|
||||
case E_TEP_FORWARD_CHARACTER:
|
||||
length = strlen(text->text);
|
||||
i = text->selection_end + 1;
|
||||
if (i > length)
|
||||
i = length;
|
||||
return i;
|
||||
case E_TEP_BACKWARD_CHARACTER:
|
||||
i = text->selection_end - 1;
|
||||
if (i < 0)
|
||||
i = 0;
|
||||
return i;
|
||||
|
||||
case E_TEP_FORWARD_WORD:
|
||||
length = strlen(text->text);
|
||||
for (i = text->selection_end + 1; i < length; i++)
|
||||
if (isspace(text->text[i])) {
|
||||
break;
|
||||
}
|
||||
if (i > length)
|
||||
i = length;
|
||||
return i;
|
||||
case E_TEP_BACKWARD_WORD:
|
||||
for (i = text->selection_end - 2; i > 0; i--)
|
||||
if (isspace(text->text[i])) {
|
||||
i++;
|
||||
break;
|
||||
}
|
||||
if (i < 0)
|
||||
i = 0;
|
||||
return i;
|
||||
|
||||
case E_TEP_FORWARD_LINE:
|
||||
case E_TEP_BACKWARD_LINE:
|
||||
|
||||
case E_TEP_FORWARD_PARAGRAPH:
|
||||
case E_TEP_BACKWARD_PARAGRAPH:
|
||||
|
||||
case E_TEP_FORWARD_PAGE:
|
||||
case E_TEP_BACKWARD_PAGE:
|
||||
return text->selection_end;
|
||||
default:
|
||||
return text->selection_end;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_delete_selection(EText *text)
|
||||
{
|
||||
gint length = strlen(text->text);
|
||||
if (text->selection_end == text->selection_start)
|
||||
return;
|
||||
if (text->selection_end < text->selection_start) {
|
||||
text->selection_end ^= text->selection_start;
|
||||
text->selection_start ^= text->selection_end;
|
||||
text->selection_end ^= text->selection_start;
|
||||
}
|
||||
memmove( text->text + text->selection_start,
|
||||
text->text + text->selection_end,
|
||||
length - text->selection_end + 1 );
|
||||
length -= text->selection_end - text->selection_start;
|
||||
text->selection_end = text->selection_start;
|
||||
}
|
||||
|
||||
static void
|
||||
_insert(EText *text, char *string, int value)
|
||||
{
|
||||
if (value > 0) {
|
||||
char *temp;
|
||||
gint length = strlen(text->text);
|
||||
temp = g_new(gchar, length + value + 1);
|
||||
strncpy(temp, text->text, text->selection_start);
|
||||
strncpy(temp + text->selection_start, string, value);
|
||||
strcpy(temp + text->selection_start + value, text->text + text->selection_start);
|
||||
g_free(text->text);
|
||||
text->text = temp;
|
||||
text->selection_start += value;
|
||||
text->selection_end = text->selection_start;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
e_text_command(ETextEventProcessor *tep, ETextEventProcessorCommand *command, gpointer data)
|
||||
{
|
||||
EText *text = E_TEXT(data);
|
||||
switch (command->action) {
|
||||
case E_TEP_MOVE:
|
||||
text->selection_start = _get_position(text, command);
|
||||
text->selection_end = text->selection_start;
|
||||
break;
|
||||
case E_TEP_SELECT:
|
||||
text->selection_end = _get_position(text, command);
|
||||
break;
|
||||
case E_TEP_DELETE:
|
||||
if (text->selection_end == text->selection_start) {
|
||||
text->selection_end = _get_position(text, command);
|
||||
}
|
||||
_delete_selection(text);
|
||||
split_into_lines (text);
|
||||
recalc_bounds (text);
|
||||
break;
|
||||
|
||||
case E_TEP_INSERT:
|
||||
if (text->selection_end != text->selection_start) {
|
||||
_delete_selection(text);
|
||||
}
|
||||
_insert(text, command->string, command->value);
|
||||
split_into_lines (text);
|
||||
recalc_bounds (text);
|
||||
break;
|
||||
case E_TEP_COPY:
|
||||
if (text->selection_end != text->selection_start) {
|
||||
}
|
||||
break;
|
||||
case E_TEP_PASTE:
|
||||
break;
|
||||
case E_TEP_ACTIVATE:
|
||||
break;
|
||||
case E_TEP_SET_SELECT_BY_WORD:
|
||||
text->select_by_word = command->value;
|
||||
break;
|
||||
case E_TEP_NOP:
|
||||
break;
|
||||
}
|
||||
gnome_canvas_item_request_update (GNOME_CANVAS_ITEM(text));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Routines for sucking fonts from the X server */
|
||||
|
@ -20,6 +20,7 @@
|
||||
#define E_TEXT_H
|
||||
|
||||
#include <gnome.h>
|
||||
#include "e-text-event-processor.h"
|
||||
|
||||
|
||||
BEGIN_GNOME_DECLS
|
||||
@ -59,8 +60,15 @@ BEGIN_GNOME_DECLS
|
||||
* text_height double R Used to query the rendered height of the text
|
||||
*
|
||||
* These are ignored in the AA version:
|
||||
* editable boolean RW Can this item be edited
|
||||
* use_ellipsis boolean RW Whether to use ellipsises if text gets cut off. Meaningless if clip == false.
|
||||
* ellipsis string RW The characters to use as ellipsis. NULL = "...".
|
||||
*
|
||||
* These are not implemented yet:
|
||||
* multi_line boolean RW Line wrap when not editing.
|
||||
* multi_line_on_edit boolean RW Switch to line wrap when editing.
|
||||
* background boolean RW Draw a background rectangle.
|
||||
* background_on_edit boolean RW Draw a background when editing.
|
||||
*/
|
||||
|
||||
#define E_TYPE_TEXT (e_text_get_type ())
|
||||
@ -129,6 +137,18 @@ struct _EText {
|
||||
char *ellipsis; /* The ellipsis characters. NULL = "...". */
|
||||
double ellipsis_width; /* The width of the ellipsis. */
|
||||
gboolean use_ellipsis; /* Whether to use the ellipsis. */
|
||||
|
||||
gboolean editable; /* Item is editable */
|
||||
gboolean editing; /* Item is currently being edited */
|
||||
|
||||
int xofs_edit; /* Offset because of editing */
|
||||
|
||||
/* This needs to be reworked a bit once we get line wrapping. */
|
||||
int selection_start; /* Start of selection */
|
||||
int selection_end; /* End of selection */
|
||||
gboolean select_by_word; /* Current selection is by word */
|
||||
|
||||
ETextEventProcessor *tep; /* Text Event Processor */
|
||||
};
|
||||
|
||||
struct _ETextClass {
|
||||
|
327
widgets/e-text/e-text-event-processor-emacs-like.c
Normal file
327
widgets/e-text/e-text-event-processor-emacs-like.c
Normal file
@ -0,0 +1,327 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/* e-text-event-processor.c
|
||||
* Copyright (C) 2000 Helix Code, Inc.
|
||||
* Author: Chris Lahey <clahey@helixcode.com>
|
||||
*
|
||||
* This library 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 library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <gnome.h>
|
||||
#include "e-text-event-processor-emacs-like.h"
|
||||
static void e_text_event_processor_emacs_like_init (ETextEventProcessorEmacsLike *card);
|
||||
static void e_text_event_processor_emacs_like_class_init (ETextEventProcessorEmacsLikeClass *klass);
|
||||
static gint e_text_event_processor_emacs_like_event (ETextEventProcessor *tep, ETextEventProcessorEvent *event);
|
||||
|
||||
static ETextEventProcessorClass *parent_class = NULL;
|
||||
|
||||
/* The arguments we take */
|
||||
enum {
|
||||
ARG_0
|
||||
};
|
||||
|
||||
static const ETextEventProcessorCommand control_keys[26] =
|
||||
{
|
||||
{ E_TEP_START_OF_LINE, E_TEP_MOVE, 0, "" }, /* a */
|
||||
{ E_TEP_BACKWARD_CHARACTER, E_TEP_MOVE, 0, "" }, /* b */
|
||||
{ E_TEP_SELECTION, E_TEP_COPY, 0, "" }, /* c */
|
||||
{ E_TEP_FORWARD_CHARACTER, E_TEP_DELETE, 0, "" }, /* d */
|
||||
{ E_TEP_END_OF_LINE, E_TEP_MOVE, 0, "" }, /* e */
|
||||
{ E_TEP_FORWARD_CHARACTER, E_TEP_MOVE, 0, "" }, /* f */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* g */
|
||||
{ E_TEP_BACKWARD_CHARACTER, E_TEP_DELETE, 0, "" }, /* h */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* i */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* j */
|
||||
{ E_TEP_END_OF_LINE, E_TEP_DELETE, 0, "" }, /* k */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* l */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* m */
|
||||
{ E_TEP_FORWARD_LINE, E_TEP_MOVE, 0, "" }, /* n */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* o */
|
||||
{ E_TEP_BACKWARD_LINE, E_TEP_MOVE, 0, "" }, /* p */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* q */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* r */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* s */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* t */
|
||||
{ E_TEP_START_OF_LINE, E_TEP_DELETE, 0, "" }, /* u */
|
||||
{ E_TEP_SELECTION, E_TEP_PASTE, 0, "" }, /* v */
|
||||
{ E_TEP_BACKWARD_WORD, E_TEP_DELETE, 0, "" }, /* w */
|
||||
{ E_TEP_SELECTION, E_TEP_PASTE, 0, "" }, /* x */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* y */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" } /* z */
|
||||
};
|
||||
|
||||
static const ETextEventProcessorCommand alt_keys[26] =
|
||||
{
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* a */
|
||||
{ E_TEP_BACKWARD_WORD, E_TEP_MOVE, 0, "" }, /* b */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* c */
|
||||
{ E_TEP_FORWARD_WORD, E_TEP_DELETE, 0, "" }, /* d */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* e */
|
||||
{ E_TEP_FORWARD_WORD, E_TEP_MOVE, 0, "" }, /* f */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* g */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* h */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* i */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* j */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* k */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* l */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* m */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* n */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* o */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* p */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* q */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* r */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* s */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* t */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* u */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* v */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* w */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* x */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* y */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" } /* z */
|
||||
|
||||
};
|
||||
|
||||
GtkType
|
||||
e_text_event_processor_emacs_like_get_type (void)
|
||||
{
|
||||
static GtkType text_event_processor_emacs_like_type = 0;
|
||||
|
||||
if (!text_event_processor_emacs_like_type)
|
||||
{
|
||||
static const GtkTypeInfo text_event_processor_emacs_like_info =
|
||||
{
|
||||
"ETextEventProcessorEmacsLike",
|
||||
sizeof (ETextEventProcessorEmacsLike),
|
||||
sizeof (ETextEventProcessorEmacsLikeClass),
|
||||
(GtkClassInitFunc) e_text_event_processor_emacs_like_class_init,
|
||||
(GtkObjectInitFunc) e_text_event_processor_emacs_like_init,
|
||||
/* reserved_1 */ NULL,
|
||||
/* reserved_2 */ NULL,
|
||||
(GtkClassInitFunc) NULL,
|
||||
};
|
||||
|
||||
text_event_processor_emacs_like_type = gtk_type_unique (e_text_event_processor_get_type (), &text_event_processor_emacs_like_info);
|
||||
}
|
||||
|
||||
return text_event_processor_emacs_like_type;
|
||||
}
|
||||
|
||||
static void
|
||||
e_text_event_processor_emacs_like_class_init (ETextEventProcessorEmacsLikeClass *klass)
|
||||
{
|
||||
GtkObjectClass *object_class;
|
||||
ETextEventProcessorClass *processor_class;
|
||||
|
||||
object_class = (GtkObjectClass*) klass;
|
||||
processor_class = (ETextEventProcessorClass*) klass;
|
||||
|
||||
parent_class = gtk_type_class (e_text_event_processor_get_type ());
|
||||
|
||||
processor_class->event = e_text_event_processor_emacs_like_event;
|
||||
}
|
||||
|
||||
static void
|
||||
e_text_event_processor_emacs_like_init (ETextEventProcessorEmacsLike *tep)
|
||||
{
|
||||
}
|
||||
|
||||
static gint
|
||||
e_text_event_processor_emacs_like_event (ETextEventProcessor *tep, ETextEventProcessorEvent *event)
|
||||
{
|
||||
ETextEventProcessorCommand command;
|
||||
ETextEventProcessorEmacsLike *tep_el = E_TEXT_EVENT_PROCESSOR_EMACS_LIKE(tep);
|
||||
switch (event->type) {
|
||||
case GDK_BUTTON_PRESS:
|
||||
if (event->button.button == 1) {
|
||||
if (event->button.state & GDK_SHIFT_MASK)
|
||||
command.action = E_TEP_SELECT;
|
||||
else
|
||||
command.action = E_TEP_MOVE;
|
||||
command.position = E_TEP_VALUE;
|
||||
command.value = event->button.position;
|
||||
tep_el->mouse_down = TRUE;
|
||||
}
|
||||
break;
|
||||
case GDK_BUTTON_RELEASE:
|
||||
if (event->button.button == 1) {
|
||||
tep_el->mouse_down = FALSE;
|
||||
}
|
||||
break;
|
||||
case GDK_MOTION_NOTIFY:
|
||||
if (tep_el->mouse_down) {
|
||||
command.action = E_TEP_SELECT;
|
||||
command.position = E_TEP_VALUE;
|
||||
command.value = event->motion.position;
|
||||
}
|
||||
break;
|
||||
case GDK_KEY_PRESS:
|
||||
{
|
||||
ETextEventProcessorEventKey key = event->key;
|
||||
if (key.state & GDK_SHIFT_MASK)
|
||||
command.action = E_TEP_SELECT;
|
||||
else
|
||||
command.action = E_TEP_MOVE;
|
||||
switch(key.keyval) {
|
||||
case GDK_Home:
|
||||
if (key.state & GDK_CONTROL_MASK)
|
||||
command.position = E_TEP_START_OF_BUFFER;
|
||||
else
|
||||
command.position = E_TEP_START_OF_LINE;
|
||||
break;
|
||||
case GDK_End:
|
||||
if (key.state & GDK_CONTROL_MASK)
|
||||
command.position = E_TEP_END_OF_BUFFER;
|
||||
else
|
||||
command.position = E_TEP_END_OF_LINE;
|
||||
break;
|
||||
case GDK_Page_Up: command.position = E_TEP_BACKWARD_PAGE; break;
|
||||
case GDK_Page_Down: command.position = E_TEP_FORWARD_PAGE; break;
|
||||
/* CUA has Ctrl-Up/Ctrl-Down as paragraph up down */
|
||||
case GDK_Up: command.position = E_TEP_BACKWARD_LINE; break;
|
||||
case GDK_Down: command.position = E_TEP_FORWARD_LINE; break;
|
||||
case GDK_Left:
|
||||
if (key.state & GDK_CONTROL_MASK)
|
||||
command.position = E_TEP_BACKWARD_WORD;
|
||||
else
|
||||
command.position = E_TEP_BACKWARD_CHARACTER;
|
||||
break;
|
||||
case GDK_Right:
|
||||
if (key.state & GDK_CONTROL_MASK)
|
||||
command.position = E_TEP_FORWARD_WORD;
|
||||
else
|
||||
command.position = E_TEP_FORWARD_CHARACTER;
|
||||
break;
|
||||
|
||||
case GDK_BackSpace:
|
||||
command.action = E_TEP_DELETE;
|
||||
if (key.state & GDK_CONTROL_MASK)
|
||||
command.position = E_TEP_BACKWARD_WORD;
|
||||
else
|
||||
command.position = E_TEP_BACKWARD_CHARACTER;
|
||||
break;
|
||||
case GDK_Clear:
|
||||
command.action = E_TEP_DELETE;
|
||||
command.position = E_TEP_END_OF_LINE;
|
||||
break;
|
||||
case GDK_Insert:
|
||||
if (key.state & GDK_SHIFT_MASK) {
|
||||
command.action = E_TEP_PASTE;
|
||||
command.position = E_TEP_SELECTION;
|
||||
} else if (key.state & GDK_CONTROL_MASK) {
|
||||
command.action = E_TEP_COPY;
|
||||
command.position = E_TEP_SELECTION;
|
||||
} else {
|
||||
/* gtk_toggle_insert(text) -- IMPLEMENT */
|
||||
}
|
||||
break;
|
||||
case GDK_Delete:
|
||||
if (key.state & GDK_CONTROL_MASK){
|
||||
command.action = E_TEP_DELETE;
|
||||
command.position = E_TEP_FORWARD_WORD;
|
||||
} else if (key.state & GDK_SHIFT_MASK) {
|
||||
command.action = E_TEP_COPY;
|
||||
|
||||
command.action = E_TEP_DELETE;
|
||||
command.position = E_TEP_SELECTION;
|
||||
} else {
|
||||
command.action = E_TEP_DELETE;
|
||||
command.position = E_TEP_FORWARD_CHARACTER;
|
||||
}
|
||||
break;
|
||||
case GDK_Tab:
|
||||
command.action = E_TEP_INSERT;
|
||||
command.position = E_TEP_SELECTION;
|
||||
command.value = 1;
|
||||
command.string = "\t";
|
||||
break;
|
||||
case GDK_Return:
|
||||
if (key.state & GDK_CONTROL_MASK) {
|
||||
command.action = E_TEP_ACTIVATE;
|
||||
command.position = E_TEP_SELECTION;
|
||||
} else {
|
||||
command.action = E_TEP_INSERT;
|
||||
command.position = E_TEP_SELECTION;
|
||||
command.value = 1;
|
||||
command.string = "\n";
|
||||
}
|
||||
break;
|
||||
case GDK_Escape:
|
||||
command.action = E_TEP_NOP;
|
||||
command.position = E_TEP_SELECTION;
|
||||
/* Don't insert literally */
|
||||
break;
|
||||
|
||||
default:
|
||||
if (key.state & GDK_CONTROL_MASK) {
|
||||
if ((key.keyval >= 'A') && (key.keyval <= 'Z'))
|
||||
key.keyval -= 'A' - 'a';
|
||||
|
||||
if ((key.keyval >= 'a') && (key.keyval <= 'z')) {
|
||||
command.position = control_keys[(int) (key.keyval - 'a')].position;
|
||||
if (control_keys[(int) (key.keyval - 'a')].action != E_TEP_MOVE)
|
||||
command.action = control_keys[(int) (key.keyval - 'a')].action;
|
||||
command.value = control_keys[(int) (key.keyval - 'a')].value;
|
||||
command.string = control_keys[(int) (key.keyval - 'a')].string;
|
||||
}
|
||||
|
||||
if (key.keyval == 'x') {
|
||||
}
|
||||
|
||||
break;
|
||||
} else if (key.state & GDK_MOD1_MASK) {
|
||||
if ((key.keyval >= 'A') && (key.keyval <= 'Z'))
|
||||
key.keyval -= 'A' - 'a';
|
||||
|
||||
if ((key.keyval >= 'a') && (key.keyval <= 'z')) {
|
||||
command.position = alt_keys[(int) (key.keyval - 'a')].position;
|
||||
if (alt_keys[(int) (key.keyval - 'a')].action != E_TEP_MOVE)
|
||||
command.action = alt_keys[(int) (key.keyval - 'a')].action;
|
||||
command.value = alt_keys[(int) (key.keyval - 'a')].value;
|
||||
command.string = alt_keys[(int) (key.keyval - 'a')].string;
|
||||
}
|
||||
} else if (key.length > 0) {
|
||||
command.action = E_TEP_INSERT;
|
||||
command.position = E_TEP_SELECTION;
|
||||
command.value = strlen(key.string);
|
||||
command.string = key.string;
|
||||
|
||||
} else {
|
||||
command.action = E_TEP_NOP;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case GDK_KEY_RELEASE:
|
||||
command.action = E_TEP_NOP;
|
||||
break;
|
||||
default:
|
||||
command.action = E_TEP_NOP;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (command.action != E_TEP_NOP) {
|
||||
gtk_signal_emit_by_name (GTK_OBJECT (tep), "command", &command);
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
ETextEventProcessor *
|
||||
e_text_event_processor_emacs_like_new (void)
|
||||
{
|
||||
ETextEventProcessorEmacsLike *retval = gtk_type_new (e_text_event_processor_emacs_like_get_type ());
|
||||
return E_TEXT_EVENT_PROCESSOR (retval);
|
||||
}
|
||||
|
68
widgets/e-text/e-text-event-processor-emacs-like.h
Normal file
68
widgets/e-text/e-text-event-processor-emacs-like.h
Normal file
@ -0,0 +1,68 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/* e-text-event-processor-emacs-like.h
|
||||
* Copyright (C) 2000 Helix Code, Inc.
|
||||
* Author: Chris Lahey <clahey@helixcode.com>
|
||||
*
|
||||
* This library 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 library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
#ifndef __E_TEXT_EVENT_PROCESSOR_EMACS_LIKE_H__
|
||||
#define __E_TEXT_EVENT_PROCESSOR_EMACS_LIKE_H__
|
||||
|
||||
#include <gnome.h>
|
||||
#include "e-text-event-processor.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#pragma }
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/* ETextEventProcessorEmacsLike - Turns events on a text widget into commands. Uses an emacs-ish interface.
|
||||
*
|
||||
*/
|
||||
|
||||
#define E_TEXT_EVENT_PROCESSOR_EMACS_LIKE_TYPE (e_text_event_processor_emacs_like_get_type ())
|
||||
#define E_TEXT_EVENT_PROCESSOR_EMACS_LIKE(obj) (GTK_CHECK_CAST ((obj), E_TEXT_EVENT_PROCESSOR_EMACS_LIKE_TYPE, ETextEventProcessorEmacsLike))
|
||||
#define E_TEXT_EVENT_PROCESSOR_EMACS_LIKE_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), E_TEXT_EVENT_PROCESSOR_EMACS_LIKE_TYPE, ETextEventProcessorEmacsLikeClass))
|
||||
#define E_IS_TEXT_EVENT_PROCESSOR_EMACS_LIKE(obj) (GTK_CHECK_TYPE ((obj), E_TEXT_EVENT_PROCESSOR_EMACS_LIKE_TYPE))
|
||||
#define E_IS_TEXT_EVENT_PROCESSOR_EMACS_LIKE_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((obj), E_TEXT_EVENT_PROCESSOR_EMACS_LIKE_TYPE))
|
||||
|
||||
|
||||
typedef struct _ETextEventProcessorEmacsLike ETextEventProcessorEmacsLike;
|
||||
typedef struct _ETextEventProcessorEmacsLikeClass ETextEventProcessorEmacsLikeClass;
|
||||
|
||||
struct _ETextEventProcessorEmacsLike
|
||||
{
|
||||
ETextEventProcessor parent;
|
||||
|
||||
/* object specific fields */
|
||||
gboolean mouse_down;
|
||||
};
|
||||
|
||||
struct _ETextEventProcessorEmacsLikeClass
|
||||
{
|
||||
ETextEventProcessorClass parent_class;
|
||||
};
|
||||
|
||||
|
||||
GtkType e_text_event_processor_emacs_like_get_type (void);
|
||||
ETextEventProcessor *e_text_event_processor_emacs_like_new (void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
|
||||
#endif /* __E_TEXT_EVENT_PROCESSOR_EMACS_LIKE_H__ */
|
131
widgets/e-text/e-text-event-processor-types.h
Normal file
131
widgets/e-text/e-text-event-processor-types.h
Normal file
@ -0,0 +1,131 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/* e-text-event-processor.h
|
||||
* Copyright (C) 2000 Helix Code, Inc.
|
||||
* Author: Chris Lahey <clahey@helixcode.com>
|
||||
*
|
||||
* This library 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 library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the GTK+ Team and others 1997-1999. See the AUTHORS
|
||||
* file for a list of people on the GTK+ Team. See the ChangeLog
|
||||
* files for a list of changes. These files are distributed with
|
||||
* GTK+ at ftp://ftp.gtk.org/pub/gtk/.
|
||||
*/
|
||||
|
||||
#ifndef __E_TEXT_EVENT_PROCESSOR_TYPES_H__
|
||||
#define __E_TEXT_EVENT_PROCESSOR_TYPES_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#pragma }
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#include <gdk/gdktypes.h>
|
||||
|
||||
typedef enum _ETextEventProcessorCommandPosition ETextEventProcessorCommandPosition;
|
||||
typedef enum _ETextEventProcessorCommandAction ETextEventProcessorCommandAction;
|
||||
typedef struct _ETextEventProcessorCommand ETextEventProcessorCommand;
|
||||
|
||||
typedef union _ETextEventProcessorEvent ETextEventProcessorEvent;
|
||||
typedef struct _ETextEventProcessorEventButton ETextEventProcessorEventButton;
|
||||
typedef struct _ETextEventProcessorEventKey ETextEventProcessorEventKey;
|
||||
typedef struct _ETextEventProcessorEventMotion ETextEventProcessorEventMotion;
|
||||
|
||||
enum _ETextEventProcessorCommandPosition {
|
||||
E_TEP_VALUE,
|
||||
E_TEP_SELECTION,
|
||||
|
||||
E_TEP_START_OF_BUFFER,
|
||||
E_TEP_END_OF_BUFFER,
|
||||
|
||||
E_TEP_START_OF_LINE,
|
||||
E_TEP_END_OF_LINE,
|
||||
|
||||
E_TEP_FORWARD_CHARACTER,
|
||||
E_TEP_BACKWARD_CHARACTER,
|
||||
|
||||
E_TEP_FORWARD_WORD,
|
||||
E_TEP_BACKWARD_WORD,
|
||||
|
||||
E_TEP_FORWARD_LINE,
|
||||
E_TEP_BACKWARD_LINE,
|
||||
|
||||
E_TEP_FORWARD_PARAGRAPH,
|
||||
E_TEP_BACKWARD_PARAGRAPH,
|
||||
|
||||
E_TEP_FORWARD_PAGE,
|
||||
E_TEP_BACKWARD_PAGE
|
||||
};
|
||||
|
||||
enum _ETextEventProcessorCommandAction {
|
||||
E_TEP_MOVE,
|
||||
E_TEP_SELECT,
|
||||
E_TEP_DELETE,
|
||||
|
||||
E_TEP_INSERT,
|
||||
E_TEP_COPY,
|
||||
E_TEP_PASTE,
|
||||
E_TEP_SET_SELECT_BY_WORD,
|
||||
E_TEP_ACTIVATE,
|
||||
|
||||
E_TEP_NOP
|
||||
};
|
||||
|
||||
struct _ETextEventProcessorCommand {
|
||||
ETextEventProcessorCommandPosition position;
|
||||
ETextEventProcessorCommandAction action;
|
||||
int value;
|
||||
char *string;
|
||||
};
|
||||
|
||||
struct _ETextEventProcessorEventButton {
|
||||
GdkEventType type;
|
||||
guint32 time;
|
||||
guint state;
|
||||
guint button;
|
||||
gint position;
|
||||
};
|
||||
|
||||
struct _ETextEventProcessorEventKey {
|
||||
GdkEventType type;
|
||||
guint32 time;
|
||||
guint state;
|
||||
guint keyval;
|
||||
gint length;
|
||||
gchar *string;
|
||||
};
|
||||
|
||||
struct _ETextEventProcessorEventMotion {
|
||||
GdkEventType type;
|
||||
guint32 time;
|
||||
guint state;
|
||||
gint position;
|
||||
};
|
||||
|
||||
union _ETextEventProcessorEvent {
|
||||
GdkEventType type;
|
||||
ETextEventProcessorEventButton button;
|
||||
ETextEventProcessorEventKey key;
|
||||
ETextEventProcessorEventMotion motion;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
|
||||
#endif /* __E_TEXT_EVENT_PROCESSOR_TYPES_H__ */
|
103
widgets/e-text/e-text-event-processor.c
Normal file
103
widgets/e-text/e-text-event-processor.c
Normal file
@ -0,0 +1,103 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/* e-text-event-processor.c
|
||||
* Copyright (C) 2000 Helix Code, Inc.
|
||||
* Author: Chris Lahey <clahey@helixcode.com>
|
||||
*
|
||||
* This library 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 library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <gnome.h>
|
||||
#include "e-text-event-processor.h"
|
||||
static void e_text_event_processor_init (ETextEventProcessor *card);
|
||||
static void e_text_event_processor_class_init (ETextEventProcessorClass *klass);
|
||||
|
||||
static GtkObjectClass *parent_class = NULL;
|
||||
|
||||
/* The arguments we take */
|
||||
enum {
|
||||
ARG_0
|
||||
};
|
||||
|
||||
enum {
|
||||
E_TEP_EVENT,
|
||||
E_TEP_LAST_SIGNAL
|
||||
};
|
||||
|
||||
static guint e_tep_signals[E_TEP_LAST_SIGNAL] = { 0 };
|
||||
|
||||
GtkType
|
||||
e_text_event_processor_get_type (void)
|
||||
{
|
||||
static GtkType text_event_processor_type = 0;
|
||||
|
||||
if (!text_event_processor_type)
|
||||
{
|
||||
static const GtkTypeInfo text_event_processor_info =
|
||||
{
|
||||
"ETextEventProcessor",
|
||||
sizeof (ETextEventProcessor),
|
||||
sizeof (ETextEventProcessorClass),
|
||||
(GtkClassInitFunc) e_text_event_processor_class_init,
|
||||
(GtkObjectInitFunc) e_text_event_processor_init,
|
||||
/* reserved_1 */ NULL,
|
||||
/* reserved_2 */ NULL,
|
||||
(GtkClassInitFunc) NULL,
|
||||
};
|
||||
|
||||
text_event_processor_type = gtk_type_unique (gtk_object_get_type (), &text_event_processor_info);
|
||||
}
|
||||
|
||||
return text_event_processor_type;
|
||||
}
|
||||
|
||||
static void
|
||||
e_text_event_processor_class_init (ETextEventProcessorClass *klass)
|
||||
{
|
||||
GtkObjectClass *object_class;
|
||||
|
||||
object_class = (GtkObjectClass*) klass;
|
||||
|
||||
parent_class = gtk_type_class (gtk_object_get_type ());
|
||||
|
||||
e_tep_signals[E_TEP_EVENT] =
|
||||
gtk_signal_new ("command",
|
||||
GTK_RUN_LAST,
|
||||
object_class->type,
|
||||
GTK_SIGNAL_OFFSET (ETextEventProcessorClass, command),
|
||||
gtk_marshal_NONE__POINTER,
|
||||
GTK_TYPE_NONE, 1,
|
||||
GTK_TYPE_POINTER);
|
||||
|
||||
gtk_object_class_add_signals (object_class, e_tep_signals, E_TEP_LAST_SIGNAL);
|
||||
|
||||
klass->event = NULL;
|
||||
klass->command = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
e_text_event_processor_init (ETextEventProcessor *tep)
|
||||
{
|
||||
}
|
||||
|
||||
gint
|
||||
e_text_event_processor_handle_event (ETextEventProcessor *tep, ETextEventProcessorEvent *event)
|
||||
{
|
||||
if (E_TEXT_EVENT_PROCESSOR_CLASS(GTK_OBJECT(tep)->klass)->event) {
|
||||
return E_TEXT_EVENT_PROCESSOR_CLASS(GTK_OBJECT(tep)->klass)->event(tep, event);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
74
widgets/e-text/e-text-event-processor.h
Normal file
74
widgets/e-text/e-text-event-processor.h
Normal file
@ -0,0 +1,74 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/* e-text-event-processor.h
|
||||
* Copyright (C) 2000 Helix Code, Inc.
|
||||
* Author: Chris Lahey <clahey@helixcode.com>
|
||||
*
|
||||
* This library 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 library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
#ifndef __E_TEXT_EVENT_PROCESSOR_H__
|
||||
#define __E_TEXT_EVENT_PROCESSOR_H__
|
||||
|
||||
#include <gnome.h>
|
||||
#include "e-text-event-processor-types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#pragma }
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/* ETextEventProcessor - Turns events on a text widget into commands.
|
||||
*
|
||||
*/
|
||||
|
||||
#define E_TEXT_EVENT_PROCESSOR_TYPE (e_text_event_processor_get_type ())
|
||||
#define E_TEXT_EVENT_PROCESSOR(obj) (GTK_CHECK_CAST ((obj), E_TEXT_EVENT_PROCESSOR_TYPE, ETextEventProcessor))
|
||||
#define E_TEXT_EVENT_PROCESSOR_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), E_TEXT_EVENT_PROCESSOR_TYPE, ETextEventProcessorClass))
|
||||
#define E_IS_TEXT_EVENT_PROCESSOR(obj) (GTK_CHECK_TYPE ((obj), E_TEXT_EVENT_PROCESSOR_TYPE))
|
||||
#define E_IS_TEXT_EVENT_PROCESSOR_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((obj), E_TEXT_EVENT_PROCESSOR_TYPE))
|
||||
|
||||
|
||||
typedef struct _ETextEventProcessor ETextEventProcessor;
|
||||
typedef struct _ETextEventProcessorClass ETextEventProcessorClass;
|
||||
|
||||
struct _ETextEventProcessor
|
||||
{
|
||||
GtkObject parent;
|
||||
|
||||
/* object specific fields */
|
||||
|
||||
};
|
||||
|
||||
struct _ETextEventProcessorClass
|
||||
{
|
||||
GtkObjectClass parent_class;
|
||||
|
||||
/* signals */
|
||||
void (* command) (ETextEventProcessor *tep, ETextEventProcessorCommand *command);
|
||||
|
||||
/* virtual functions */
|
||||
gint (* event) (ETextEventProcessor *tep, ETextEventProcessorEvent *event);
|
||||
};
|
||||
|
||||
|
||||
GtkType e_text_event_processor_get_type (void);
|
||||
gint e_text_event_processor_handle_event (ETextEventProcessor *tep, ETextEventProcessorEvent *event);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
|
||||
#endif /* __E_TEXT_EVENT_PROCESSOR_H__ */
|
@ -18,12 +18,15 @@
|
||||
|
||||
#include <config.h>
|
||||
#include <math.h>
|
||||
#include <ctype.h>
|
||||
#include "e-text.h"
|
||||
#include <gdk/gdkx.h> /* for BlackPixel */
|
||||
#include <libart_lgpl/art_affine.h>
|
||||
#include <libart_lgpl/art_rgb.h>
|
||||
#include <libart_lgpl/art_rgb_bitmap_affine.h>
|
||||
|
||||
#include "e-text-event-processor-emacs-like.h"
|
||||
|
||||
|
||||
|
||||
/* This defines a line of text */
|
||||
@ -58,6 +61,7 @@ enum {
|
||||
ARG_FILL_STIPPLE,
|
||||
ARG_TEXT_WIDTH,
|
||||
ARG_TEXT_HEIGHT,
|
||||
ARG_EDITABLE,
|
||||
ARG_USE_ELLIPSIS,
|
||||
ARG_ELLIPSIS
|
||||
};
|
||||
@ -80,6 +84,9 @@ static double e_text_point (GnomeCanvasItem *item, double x, double y, int cx, i
|
||||
static void e_text_bounds (GnomeCanvasItem *item,
|
||||
double *x1, double *y1, double *x2, double *y2);
|
||||
static void e_text_render (GnomeCanvasItem *item, GnomeCanvasBuf *buf);
|
||||
static gint e_text_event (GnomeCanvasItem *item, GdkEvent *event);
|
||||
|
||||
static void e_text_command(ETextEventProcessor *tep, ETextEventProcessorCommand *command, gpointer data);
|
||||
|
||||
static ETextSuckFont *e_suck_font (GdkFont *font);
|
||||
static void e_suck_font_free (ETextSuckFont *suckfont);
|
||||
@ -171,6 +178,8 @@ e_text_class_init (ETextClass *class)
|
||||
GTK_TYPE_DOUBLE, GTK_ARG_READABLE, ARG_TEXT_WIDTH);
|
||||
gtk_object_add_arg_type ("EText::text_height",
|
||||
GTK_TYPE_DOUBLE, GTK_ARG_READABLE, ARG_TEXT_HEIGHT);
|
||||
gtk_object_add_arg_type ("EText::editable",
|
||||
GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_EDITABLE);
|
||||
gtk_object_add_arg_type ("EText::use_ellipsis",
|
||||
GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_USE_ELLIPSIS);
|
||||
gtk_object_add_arg_type ("EText::ellipsis",
|
||||
@ -187,6 +196,7 @@ e_text_class_init (ETextClass *class)
|
||||
item_class->point = e_text_point;
|
||||
item_class->bounds = e_text_bounds;
|
||||
item_class->render = e_text_render;
|
||||
item_class->event = e_text_event;
|
||||
}
|
||||
|
||||
/* Object initialization function for the text item */
|
||||
@ -201,9 +211,18 @@ e_text_init (EText *text)
|
||||
text->clip_height = 0.0;
|
||||
text->xofs = 0.0;
|
||||
text->yofs = 0.0;
|
||||
|
||||
text->ellipsis = NULL;
|
||||
text->use_ellipsis = FALSE;
|
||||
text->ellipsis_width = 0;
|
||||
|
||||
text->editable = FALSE;
|
||||
text->editing = FALSE;
|
||||
text->xofs_edit = 0;
|
||||
|
||||
text->selection_start = 0;
|
||||
text->selection_end = 0;
|
||||
text->select_by_word = FALSE;
|
||||
}
|
||||
|
||||
/* Destroy handler for the text item */
|
||||
@ -457,6 +476,7 @@ calc_line_widths (EText *text)
|
||||
|
||||
if (text->clip &&
|
||||
text->use_ellipsis &&
|
||||
! text->editing &&
|
||||
lines->width > text->clip_width) {
|
||||
if (text->font) {
|
||||
lines->ellipsis_length = 0;
|
||||
@ -729,6 +749,10 @@ e_text_set_arg (GtkObject *object, GtkArg *arg, guint arg_id)
|
||||
set_stipple (text, GTK_VALUE_BOXED (*arg), FALSE);
|
||||
break;
|
||||
|
||||
case ARG_EDITABLE:
|
||||
text->editable = GTK_VALUE_BOOL (*arg);
|
||||
break;
|
||||
|
||||
case ARG_USE_ELLIPSIS:
|
||||
text->use_ellipsis = GTK_VALUE_BOOL (*arg);
|
||||
calc_line_widths (text);
|
||||
@ -839,6 +863,10 @@ e_text_get_arg (GtkObject *object, GtkArg *arg, guint arg_id)
|
||||
GTK_VALUE_DOUBLE (*arg) = text->height / text->item.canvas->pixels_per_unit;
|
||||
break;
|
||||
|
||||
case ARG_EDITABLE:
|
||||
GTK_VALUE_BOOL (*arg) = text->editable;
|
||||
break;
|
||||
|
||||
case ARG_USE_ELLIPSIS:
|
||||
GTK_VALUE_BOOL (*arg) = text->use_ellipsis;
|
||||
break;
|
||||
@ -1016,6 +1044,19 @@ get_line_xpos (EText *text, struct line *line)
|
||||
return x;
|
||||
}
|
||||
|
||||
static void
|
||||
_get_tep(EText *text)
|
||||
{
|
||||
if (!text->tep) {
|
||||
text->tep = e_text_event_processor_emacs_like_new();
|
||||
gtk_signal_connect(GTK_OBJECT(text->tep),
|
||||
"command",
|
||||
GTK_SIGNAL_FUNC(e_text_command),
|
||||
(gpointer) text);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/* Draw handler for the text item */
|
||||
static void
|
||||
e_text_draw (GnomeCanvasItem *item, GdkDrawable *drawable,
|
||||
@ -1026,8 +1067,14 @@ e_text_draw (GnomeCanvasItem *item, GdkDrawable *drawable,
|
||||
struct line *lines;
|
||||
int i;
|
||||
int xpos, ypos;
|
||||
int start_char, end_char;
|
||||
int sel_start, sel_end;
|
||||
GdkRectangle sel_rect;
|
||||
GdkGC *fg_gc;
|
||||
GnomeCanvas *canvas;
|
||||
|
||||
text = E_TEXT (item);
|
||||
canvas = GNOME_CANVAS_ITEM(text)->canvas;
|
||||
|
||||
if (!text->text || !text->font)
|
||||
return;
|
||||
@ -1039,6 +1086,7 @@ e_text_draw (GnomeCanvasItem *item, GdkDrawable *drawable,
|
||||
rect.height = text->clip_cheight;
|
||||
|
||||
gdk_gc_set_clip_rectangle (text->gc, &rect);
|
||||
gdk_gc_set_clip_rectangle (GTK_WIDGET(canvas)->style->fg_gc[GTK_STATE_SELECTED], &rect);
|
||||
}
|
||||
lines = text->lines;
|
||||
ypos = text->cy + text->font->ascent;
|
||||
@ -1049,6 +1097,86 @@ e_text_draw (GnomeCanvasItem *item, GdkDrawable *drawable,
|
||||
for (i = 0; i < text->num_lines; i++) {
|
||||
if (lines->length != 0) {
|
||||
xpos = get_line_xpos (text, lines);
|
||||
if (text->editing) {
|
||||
xpos -= text->xofs_edit;
|
||||
start_char = lines->text - text->text;
|
||||
end_char = start_char + lines->length;
|
||||
sel_start = text->selection_start;
|
||||
sel_end = text->selection_end;
|
||||
if (sel_start > sel_end ) {
|
||||
sel_start ^= sel_end;
|
||||
sel_end ^= sel_start;
|
||||
sel_start ^= sel_end;
|
||||
}
|
||||
if ( sel_start < start_char )
|
||||
sel_start = start_char;
|
||||
if ( sel_end > end_char )
|
||||
sel_end = end_char;
|
||||
if ( sel_start < sel_end ) {
|
||||
sel_rect.x = xpos - x + gdk_text_width (text->font,
|
||||
lines->text,
|
||||
sel_start - start_char);
|
||||
sel_rect.y = ypos - y - text->font->ascent;
|
||||
sel_rect.width = gdk_text_width (text->font,
|
||||
lines->text + sel_start - start_char,
|
||||
sel_end - sel_start);
|
||||
sel_rect.height = text->font->ascent + text->font->descent;
|
||||
gdk_draw_rectangle (drawable,
|
||||
text->gc,
|
||||
TRUE,
|
||||
sel_rect.x,
|
||||
sel_rect.y,
|
||||
sel_rect.width,
|
||||
sel_rect.height);
|
||||
gdk_draw_text (drawable,
|
||||
text->font,
|
||||
text->gc,
|
||||
xpos - x,
|
||||
ypos - y,
|
||||
lines->text,
|
||||
sel_start - start_char);
|
||||
fg_gc = GTK_WIDGET(canvas)->style->fg_gc[GTK_STATE_SELECTED];
|
||||
gdk_draw_text (drawable,
|
||||
text->font,
|
||||
fg_gc,
|
||||
xpos - x + gdk_text_width (text->font,
|
||||
lines->text,
|
||||
sel_start - start_char),
|
||||
ypos - y,
|
||||
lines->text + sel_start - start_char,
|
||||
sel_end - sel_start);
|
||||
gdk_draw_text (drawable,
|
||||
text->font,
|
||||
text->gc,
|
||||
xpos - x + gdk_text_width (text->font,
|
||||
lines->text,
|
||||
sel_end - start_char),
|
||||
ypos - y,
|
||||
lines->text + sel_end - start_char,
|
||||
end_char - sel_end);
|
||||
} else {
|
||||
gdk_draw_text (drawable,
|
||||
text->font,
|
||||
text->gc,
|
||||
xpos - x,
|
||||
ypos - y,
|
||||
lines->text,
|
||||
lines->length);
|
||||
}
|
||||
if (text->selection_start == text->selection_end &&
|
||||
text->selection_start >= start_char &&
|
||||
text->selection_start <= end_char) {
|
||||
gdk_draw_rectangle (drawable,
|
||||
text->gc,
|
||||
TRUE,
|
||||
xpos - x + gdk_text_width (text->font,
|
||||
lines->text,
|
||||
sel_start - start_char),
|
||||
ypos - y - text->font->ascent,
|
||||
1,
|
||||
text->font->ascent + text->font->descent);
|
||||
}
|
||||
} else {
|
||||
if ( text->clip && text->use_ellipsis && lines->ellipsis_length < lines->length) {
|
||||
gdk_draw_text (drawable,
|
||||
text->font,
|
||||
@ -1075,13 +1203,16 @@ e_text_draw (GnomeCanvasItem *item, GdkDrawable *drawable,
|
||||
lines->text,
|
||||
lines->length);
|
||||
}
|
||||
}
|
||||
|
||||
ypos += text->font->ascent + text->font->descent;
|
||||
lines++;
|
||||
}
|
||||
|
||||
if (text->clip)
|
||||
if (text->clip) {
|
||||
gdk_gc_set_clip_rectangle (text->gc, NULL);
|
||||
gdk_gc_set_clip_rectangle (GTK_WIDGET(GNOME_CANVAS_ITEM(text)->canvas)->style->fg_gc[GTK_STATE_SELECTED], NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/* Render handler for the text item */
|
||||
@ -1308,6 +1439,285 @@ e_text_bounds (GnomeCanvasItem *item, double *x1, double *y1, double *x2, double
|
||||
*y2 = *y1 + height;
|
||||
}
|
||||
|
||||
static gint
|
||||
_get_position_from_xy (EText *text, gint x, gint y)
|
||||
{
|
||||
int i, j;
|
||||
int ypos = text->cy;
|
||||
int xpos;
|
||||
struct line *lines;
|
||||
j = 0;
|
||||
while (y > ypos)
|
||||
{
|
||||
ypos += text->font->ascent + text->font->descent;
|
||||
j ++;
|
||||
}
|
||||
j--;
|
||||
if (j >= text->num_lines)
|
||||
j = text->num_lines - 1;
|
||||
if (j < 0)
|
||||
j = 0;
|
||||
i = 0;
|
||||
lines = text->lines;
|
||||
lines += j;
|
||||
xpos = get_line_xpos (text, lines);
|
||||
for(i = 0; i < lines->length; i++) {
|
||||
int charwidth = gdk_text_width(text->font,
|
||||
lines->text + i,
|
||||
1);
|
||||
xpos += charwidth / 2;
|
||||
if (xpos > x)
|
||||
break;
|
||||
xpos += (charwidth + 1) / 2;
|
||||
}
|
||||
return lines->text + i - text->text;
|
||||
}
|
||||
|
||||
static gint
|
||||
e_text_event (GnomeCanvasItem *item, GdkEvent *event)
|
||||
{
|
||||
EText *text = E_TEXT(item);
|
||||
ETextEventProcessorEvent e_tep_event;
|
||||
|
||||
gint return_val;
|
||||
|
||||
e_tep_event.type = event->type;
|
||||
switch (event->type) {
|
||||
case GDK_FOCUS_CHANGE:
|
||||
if (text->editable) {
|
||||
GdkEventFocus *focus_event;
|
||||
focus_event = (GdkEventFocus *) event;
|
||||
if (focus_event->in) {
|
||||
if(!text->editing) {
|
||||
text->editing = TRUE;
|
||||
text->selection_start = 0;
|
||||
text->selection_end = 0;
|
||||
text->select_by_word = FALSE;
|
||||
text->xofs_edit = 0;
|
||||
}
|
||||
} else {
|
||||
text->editing = FALSE;
|
||||
}
|
||||
calc_line_widths (text);
|
||||
}
|
||||
return_val = 0;
|
||||
break;
|
||||
case GDK_KEY_PRESS: /* Fall Through */
|
||||
case GDK_KEY_RELEASE:
|
||||
if (text->editing) {
|
||||
GdkEventKey key = event->key;
|
||||
e_tep_event.key.time = key.time;
|
||||
e_tep_event.key.state = key.state;
|
||||
e_tep_event.key.keyval = key.keyval;
|
||||
e_tep_event.key.length = key.length;
|
||||
e_tep_event.key.string = key.string;
|
||||
_get_tep(text);
|
||||
return e_text_event_processor_handle_event (text->tep,
|
||||
&e_tep_event);
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
break;
|
||||
case GDK_BUTTON_PRESS: /* Fall Through */
|
||||
case GDK_BUTTON_RELEASE:
|
||||
if (text->editing) {
|
||||
GdkEventButton button = event->button;
|
||||
e_tep_event.button.time = button.time;
|
||||
e_tep_event.button.state = button.state;
|
||||
e_tep_event.button.button = button.button;
|
||||
e_tep_event.button.position = _get_position_from_xy(text, button.x, button.y);
|
||||
_get_tep(text);
|
||||
return_val = e_text_event_processor_handle_event (text->tep,
|
||||
&e_tep_event);
|
||||
} else if (text->editable && event->type == GDK_BUTTON_RELEASE) {
|
||||
gnome_canvas_item_grab_focus (item);
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case GDK_MOTION_NOTIFY:
|
||||
if (text->editing) {
|
||||
GdkEventMotion motion = event->motion;
|
||||
e_tep_event.motion.time = motion.time;
|
||||
e_tep_event.motion.state = motion.state;
|
||||
e_tep_event.motion.position = _get_position_from_xy(text, motion.x, motion.y);
|
||||
_get_tep(text);
|
||||
return_val = e_text_event_processor_handle_event (text->tep,
|
||||
&e_tep_event);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (return_val)
|
||||
return return_val;
|
||||
if (GNOME_CANVAS_ITEM_CLASS(parent_class)->event)
|
||||
return GNOME_CANVAS_ITEM_CLASS(parent_class)->event(item, event);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
_get_position(EText *text, ETextEventProcessorCommand *command)
|
||||
{
|
||||
int i;
|
||||
int length;
|
||||
|
||||
switch (command->position) {
|
||||
|
||||
case E_TEP_VALUE:
|
||||
return command->value;
|
||||
|
||||
case E_TEP_SELECTION:
|
||||
return text->selection_end;
|
||||
|
||||
case E_TEP_START_OF_BUFFER:
|
||||
return 0;
|
||||
case E_TEP_END_OF_BUFFER:
|
||||
return strlen(text->text);
|
||||
|
||||
case E_TEP_START_OF_LINE:
|
||||
for (i = text->selection_end - 2; i > 0; i--)
|
||||
if (text->text[i] == '\n') {
|
||||
i++;
|
||||
break;
|
||||
}
|
||||
return i;
|
||||
case E_TEP_END_OF_LINE:
|
||||
length = strlen(text->text);
|
||||
for (i = text->selection_end + 1; i < length; i++)
|
||||
if (text->text[i] == '\n') {
|
||||
break;
|
||||
}
|
||||
if (i > length)
|
||||
i = length;
|
||||
return i;
|
||||
|
||||
case E_TEP_FORWARD_CHARACTER:
|
||||
length = strlen(text->text);
|
||||
i = text->selection_end + 1;
|
||||
if (i > length)
|
||||
i = length;
|
||||
return i;
|
||||
case E_TEP_BACKWARD_CHARACTER:
|
||||
i = text->selection_end - 1;
|
||||
if (i < 0)
|
||||
i = 0;
|
||||
return i;
|
||||
|
||||
case E_TEP_FORWARD_WORD:
|
||||
length = strlen(text->text);
|
||||
for (i = text->selection_end + 1; i < length; i++)
|
||||
if (isspace(text->text[i])) {
|
||||
break;
|
||||
}
|
||||
if (i > length)
|
||||
i = length;
|
||||
return i;
|
||||
case E_TEP_BACKWARD_WORD:
|
||||
for (i = text->selection_end - 2; i > 0; i--)
|
||||
if (isspace(text->text[i])) {
|
||||
i++;
|
||||
break;
|
||||
}
|
||||
if (i < 0)
|
||||
i = 0;
|
||||
return i;
|
||||
|
||||
case E_TEP_FORWARD_LINE:
|
||||
case E_TEP_BACKWARD_LINE:
|
||||
|
||||
case E_TEP_FORWARD_PARAGRAPH:
|
||||
case E_TEP_BACKWARD_PARAGRAPH:
|
||||
|
||||
case E_TEP_FORWARD_PAGE:
|
||||
case E_TEP_BACKWARD_PAGE:
|
||||
return text->selection_end;
|
||||
default:
|
||||
return text->selection_end;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_delete_selection(EText *text)
|
||||
{
|
||||
gint length = strlen(text->text);
|
||||
if (text->selection_end == text->selection_start)
|
||||
return;
|
||||
if (text->selection_end < text->selection_start) {
|
||||
text->selection_end ^= text->selection_start;
|
||||
text->selection_start ^= text->selection_end;
|
||||
text->selection_end ^= text->selection_start;
|
||||
}
|
||||
memmove( text->text + text->selection_start,
|
||||
text->text + text->selection_end,
|
||||
length - text->selection_end + 1 );
|
||||
length -= text->selection_end - text->selection_start;
|
||||
text->selection_end = text->selection_start;
|
||||
}
|
||||
|
||||
static void
|
||||
_insert(EText *text, char *string, int value)
|
||||
{
|
||||
if (value > 0) {
|
||||
char *temp;
|
||||
gint length = strlen(text->text);
|
||||
temp = g_new(gchar, length + value + 1);
|
||||
strncpy(temp, text->text, text->selection_start);
|
||||
strncpy(temp + text->selection_start, string, value);
|
||||
strcpy(temp + text->selection_start + value, text->text + text->selection_start);
|
||||
g_free(text->text);
|
||||
text->text = temp;
|
||||
text->selection_start += value;
|
||||
text->selection_end = text->selection_start;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
e_text_command(ETextEventProcessor *tep, ETextEventProcessorCommand *command, gpointer data)
|
||||
{
|
||||
EText *text = E_TEXT(data);
|
||||
switch (command->action) {
|
||||
case E_TEP_MOVE:
|
||||
text->selection_start = _get_position(text, command);
|
||||
text->selection_end = text->selection_start;
|
||||
break;
|
||||
case E_TEP_SELECT:
|
||||
text->selection_end = _get_position(text, command);
|
||||
break;
|
||||
case E_TEP_DELETE:
|
||||
if (text->selection_end == text->selection_start) {
|
||||
text->selection_end = _get_position(text, command);
|
||||
}
|
||||
_delete_selection(text);
|
||||
split_into_lines (text);
|
||||
recalc_bounds (text);
|
||||
break;
|
||||
|
||||
case E_TEP_INSERT:
|
||||
if (text->selection_end != text->selection_start) {
|
||||
_delete_selection(text);
|
||||
}
|
||||
_insert(text, command->string, command->value);
|
||||
split_into_lines (text);
|
||||
recalc_bounds (text);
|
||||
break;
|
||||
case E_TEP_COPY:
|
||||
if (text->selection_end != text->selection_start) {
|
||||
}
|
||||
break;
|
||||
case E_TEP_PASTE:
|
||||
break;
|
||||
case E_TEP_ACTIVATE:
|
||||
break;
|
||||
case E_TEP_SET_SELECT_BY_WORD:
|
||||
text->select_by_word = command->value;
|
||||
break;
|
||||
case E_TEP_NOP:
|
||||
break;
|
||||
}
|
||||
gnome_canvas_item_request_update (GNOME_CANVAS_ITEM(text));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Routines for sucking fonts from the X server */
|
||||
|
@ -20,6 +20,7 @@
|
||||
#define E_TEXT_H
|
||||
|
||||
#include <gnome.h>
|
||||
#include "e-text-event-processor.h"
|
||||
|
||||
|
||||
BEGIN_GNOME_DECLS
|
||||
@ -59,8 +60,15 @@ BEGIN_GNOME_DECLS
|
||||
* text_height double R Used to query the rendered height of the text
|
||||
*
|
||||
* These are ignored in the AA version:
|
||||
* editable boolean RW Can this item be edited
|
||||
* use_ellipsis boolean RW Whether to use ellipsises if text gets cut off. Meaningless if clip == false.
|
||||
* ellipsis string RW The characters to use as ellipsis. NULL = "...".
|
||||
*
|
||||
* These are not implemented yet:
|
||||
* multi_line boolean RW Line wrap when not editing.
|
||||
* multi_line_on_edit boolean RW Switch to line wrap when editing.
|
||||
* background boolean RW Draw a background rectangle.
|
||||
* background_on_edit boolean RW Draw a background when editing.
|
||||
*/
|
||||
|
||||
#define E_TYPE_TEXT (e_text_get_type ())
|
||||
@ -129,6 +137,18 @@ struct _EText {
|
||||
char *ellipsis; /* The ellipsis characters. NULL = "...". */
|
||||
double ellipsis_width; /* The width of the ellipsis. */
|
||||
gboolean use_ellipsis; /* Whether to use the ellipsis. */
|
||||
|
||||
gboolean editable; /* Item is editable */
|
||||
gboolean editing; /* Item is currently being edited */
|
||||
|
||||
int xofs_edit; /* Offset because of editing */
|
||||
|
||||
/* This needs to be reworked a bit once we get line wrapping. */
|
||||
int selection_start; /* Start of selection */
|
||||
int selection_end; /* End of selection */
|
||||
gboolean select_by_word; /* Current selection is by word */
|
||||
|
||||
ETextEventProcessor *tep; /* Text Event Processor */
|
||||
};
|
||||
|
||||
struct _ETextClass {
|
||||
|
@ -61,11 +61,6 @@ static void about_callback( GtkWidget *widget, gpointer data )
|
||||
gtk_widget_show (about);
|
||||
}
|
||||
|
||||
static void button_press_callback( GtkWidget *widget, gpointer data )
|
||||
{
|
||||
gnome_canvas_item_grab_focus( card );
|
||||
}
|
||||
|
||||
int main( int argc, char *argv[] )
|
||||
{
|
||||
GtkWidget *app;
|
||||
@ -102,7 +97,6 @@ int main( int argc, char *argv[] )
|
||||
|
||||
gnome_app_set_contents( GNOME_APP( app ), canvas );
|
||||
|
||||
|
||||
/* Connect the signals */
|
||||
gtk_signal_connect( GTK_OBJECT( app ), "destroy",
|
||||
GTK_SIGNAL_FUNC( destroy_callback ),
|
||||
@ -112,10 +106,6 @@ int main( int argc, char *argv[] )
|
||||
GTK_SIGNAL_FUNC( allocate_callback ),
|
||||
( gpointer ) app );
|
||||
|
||||
gtk_signal_connect( GTK_OBJECT( canvas ), "button_press_event",
|
||||
GTK_SIGNAL_FUNC( button_press_callback ),
|
||||
( gpointer ) app );
|
||||
|
||||
gtk_widget_show_all( app );
|
||||
|
||||
gtk_main();
|
||||
|
327
widgets/text/e-text-event-processor-emacs-like.c
Normal file
327
widgets/text/e-text-event-processor-emacs-like.c
Normal file
@ -0,0 +1,327 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/* e-text-event-processor.c
|
||||
* Copyright (C) 2000 Helix Code, Inc.
|
||||
* Author: Chris Lahey <clahey@helixcode.com>
|
||||
*
|
||||
* This library 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 library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <gnome.h>
|
||||
#include "e-text-event-processor-emacs-like.h"
|
||||
static void e_text_event_processor_emacs_like_init (ETextEventProcessorEmacsLike *card);
|
||||
static void e_text_event_processor_emacs_like_class_init (ETextEventProcessorEmacsLikeClass *klass);
|
||||
static gint e_text_event_processor_emacs_like_event (ETextEventProcessor *tep, ETextEventProcessorEvent *event);
|
||||
|
||||
static ETextEventProcessorClass *parent_class = NULL;
|
||||
|
||||
/* The arguments we take */
|
||||
enum {
|
||||
ARG_0
|
||||
};
|
||||
|
||||
static const ETextEventProcessorCommand control_keys[26] =
|
||||
{
|
||||
{ E_TEP_START_OF_LINE, E_TEP_MOVE, 0, "" }, /* a */
|
||||
{ E_TEP_BACKWARD_CHARACTER, E_TEP_MOVE, 0, "" }, /* b */
|
||||
{ E_TEP_SELECTION, E_TEP_COPY, 0, "" }, /* c */
|
||||
{ E_TEP_FORWARD_CHARACTER, E_TEP_DELETE, 0, "" }, /* d */
|
||||
{ E_TEP_END_OF_LINE, E_TEP_MOVE, 0, "" }, /* e */
|
||||
{ E_TEP_FORWARD_CHARACTER, E_TEP_MOVE, 0, "" }, /* f */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* g */
|
||||
{ E_TEP_BACKWARD_CHARACTER, E_TEP_DELETE, 0, "" }, /* h */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* i */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* j */
|
||||
{ E_TEP_END_OF_LINE, E_TEP_DELETE, 0, "" }, /* k */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* l */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* m */
|
||||
{ E_TEP_FORWARD_LINE, E_TEP_MOVE, 0, "" }, /* n */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* o */
|
||||
{ E_TEP_BACKWARD_LINE, E_TEP_MOVE, 0, "" }, /* p */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* q */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* r */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* s */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* t */
|
||||
{ E_TEP_START_OF_LINE, E_TEP_DELETE, 0, "" }, /* u */
|
||||
{ E_TEP_SELECTION, E_TEP_PASTE, 0, "" }, /* v */
|
||||
{ E_TEP_BACKWARD_WORD, E_TEP_DELETE, 0, "" }, /* w */
|
||||
{ E_TEP_SELECTION, E_TEP_PASTE, 0, "" }, /* x */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* y */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" } /* z */
|
||||
};
|
||||
|
||||
static const ETextEventProcessorCommand alt_keys[26] =
|
||||
{
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* a */
|
||||
{ E_TEP_BACKWARD_WORD, E_TEP_MOVE, 0, "" }, /* b */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* c */
|
||||
{ E_TEP_FORWARD_WORD, E_TEP_DELETE, 0, "" }, /* d */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* e */
|
||||
{ E_TEP_FORWARD_WORD, E_TEP_MOVE, 0, "" }, /* f */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* g */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* h */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* i */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* j */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* k */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* l */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* m */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* n */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* o */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* p */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* q */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* r */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* s */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* t */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* u */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* v */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* w */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* x */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" }, /* y */
|
||||
{ E_TEP_SELECTION, E_TEP_NOP, 0, "" } /* z */
|
||||
|
||||
};
|
||||
|
||||
GtkType
|
||||
e_text_event_processor_emacs_like_get_type (void)
|
||||
{
|
||||
static GtkType text_event_processor_emacs_like_type = 0;
|
||||
|
||||
if (!text_event_processor_emacs_like_type)
|
||||
{
|
||||
static const GtkTypeInfo text_event_processor_emacs_like_info =
|
||||
{
|
||||
"ETextEventProcessorEmacsLike",
|
||||
sizeof (ETextEventProcessorEmacsLike),
|
||||
sizeof (ETextEventProcessorEmacsLikeClass),
|
||||
(GtkClassInitFunc) e_text_event_processor_emacs_like_class_init,
|
||||
(GtkObjectInitFunc) e_text_event_processor_emacs_like_init,
|
||||
/* reserved_1 */ NULL,
|
||||
/* reserved_2 */ NULL,
|
||||
(GtkClassInitFunc) NULL,
|
||||
};
|
||||
|
||||
text_event_processor_emacs_like_type = gtk_type_unique (e_text_event_processor_get_type (), &text_event_processor_emacs_like_info);
|
||||
}
|
||||
|
||||
return text_event_processor_emacs_like_type;
|
||||
}
|
||||
|
||||
static void
|
||||
e_text_event_processor_emacs_like_class_init (ETextEventProcessorEmacsLikeClass *klass)
|
||||
{
|
||||
GtkObjectClass *object_class;
|
||||
ETextEventProcessorClass *processor_class;
|
||||
|
||||
object_class = (GtkObjectClass*) klass;
|
||||
processor_class = (ETextEventProcessorClass*) klass;
|
||||
|
||||
parent_class = gtk_type_class (e_text_event_processor_get_type ());
|
||||
|
||||
processor_class->event = e_text_event_processor_emacs_like_event;
|
||||
}
|
||||
|
||||
static void
|
||||
e_text_event_processor_emacs_like_init (ETextEventProcessorEmacsLike *tep)
|
||||
{
|
||||
}
|
||||
|
||||
static gint
|
||||
e_text_event_processor_emacs_like_event (ETextEventProcessor *tep, ETextEventProcessorEvent *event)
|
||||
{
|
||||
ETextEventProcessorCommand command;
|
||||
ETextEventProcessorEmacsLike *tep_el = E_TEXT_EVENT_PROCESSOR_EMACS_LIKE(tep);
|
||||
switch (event->type) {
|
||||
case GDK_BUTTON_PRESS:
|
||||
if (event->button.button == 1) {
|
||||
if (event->button.state & GDK_SHIFT_MASK)
|
||||
command.action = E_TEP_SELECT;
|
||||
else
|
||||
command.action = E_TEP_MOVE;
|
||||
command.position = E_TEP_VALUE;
|
||||
command.value = event->button.position;
|
||||
tep_el->mouse_down = TRUE;
|
||||
}
|
||||
break;
|
||||
case GDK_BUTTON_RELEASE:
|
||||
if (event->button.button == 1) {
|
||||
tep_el->mouse_down = FALSE;
|
||||
}
|
||||
break;
|
||||
case GDK_MOTION_NOTIFY:
|
||||
if (tep_el->mouse_down) {
|
||||
command.action = E_TEP_SELECT;
|
||||
command.position = E_TEP_VALUE;
|
||||
command.value = event->motion.position;
|
||||
}
|
||||
break;
|
||||
case GDK_KEY_PRESS:
|
||||
{
|
||||
ETextEventProcessorEventKey key = event->key;
|
||||
if (key.state & GDK_SHIFT_MASK)
|
||||
command.action = E_TEP_SELECT;
|
||||
else
|
||||
command.action = E_TEP_MOVE;
|
||||
switch(key.keyval) {
|
||||
case GDK_Home:
|
||||
if (key.state & GDK_CONTROL_MASK)
|
||||
command.position = E_TEP_START_OF_BUFFER;
|
||||
else
|
||||
command.position = E_TEP_START_OF_LINE;
|
||||
break;
|
||||
case GDK_End:
|
||||
if (key.state & GDK_CONTROL_MASK)
|
||||
command.position = E_TEP_END_OF_BUFFER;
|
||||
else
|
||||
command.position = E_TEP_END_OF_LINE;
|
||||
break;
|
||||
case GDK_Page_Up: command.position = E_TEP_BACKWARD_PAGE; break;
|
||||
case GDK_Page_Down: command.position = E_TEP_FORWARD_PAGE; break;
|
||||
/* CUA has Ctrl-Up/Ctrl-Down as paragraph up down */
|
||||
case GDK_Up: command.position = E_TEP_BACKWARD_LINE; break;
|
||||
case GDK_Down: command.position = E_TEP_FORWARD_LINE; break;
|
||||
case GDK_Left:
|
||||
if (key.state & GDK_CONTROL_MASK)
|
||||
command.position = E_TEP_BACKWARD_WORD;
|
||||
else
|
||||
command.position = E_TEP_BACKWARD_CHARACTER;
|
||||
break;
|
||||
case GDK_Right:
|
||||
if (key.state & GDK_CONTROL_MASK)
|
||||
command.position = E_TEP_FORWARD_WORD;
|
||||
else
|
||||
command.position = E_TEP_FORWARD_CHARACTER;
|
||||
break;
|
||||
|
||||
case GDK_BackSpace:
|
||||
command.action = E_TEP_DELETE;
|
||||
if (key.state & GDK_CONTROL_MASK)
|
||||
command.position = E_TEP_BACKWARD_WORD;
|
||||
else
|
||||
command.position = E_TEP_BACKWARD_CHARACTER;
|
||||
break;
|
||||
case GDK_Clear:
|
||||
command.action = E_TEP_DELETE;
|
||||
command.position = E_TEP_END_OF_LINE;
|
||||
break;
|
||||
case GDK_Insert:
|
||||
if (key.state & GDK_SHIFT_MASK) {
|
||||
command.action = E_TEP_PASTE;
|
||||
command.position = E_TEP_SELECTION;
|
||||
} else if (key.state & GDK_CONTROL_MASK) {
|
||||
command.action = E_TEP_COPY;
|
||||
command.position = E_TEP_SELECTION;
|
||||
} else {
|
||||
/* gtk_toggle_insert(text) -- IMPLEMENT */
|
||||
}
|
||||
break;
|
||||
case GDK_Delete:
|
||||
if (key.state & GDK_CONTROL_MASK){
|
||||
command.action = E_TEP_DELETE;
|
||||
command.position = E_TEP_FORWARD_WORD;
|
||||
} else if (key.state & GDK_SHIFT_MASK) {
|
||||
command.action = E_TEP_COPY;
|
||||
|
||||
command.action = E_TEP_DELETE;
|
||||
command.position = E_TEP_SELECTION;
|
||||
} else {
|
||||
command.action = E_TEP_DELETE;
|
||||
command.position = E_TEP_FORWARD_CHARACTER;
|
||||
}
|
||||
break;
|
||||
case GDK_Tab:
|
||||
command.action = E_TEP_INSERT;
|
||||
command.position = E_TEP_SELECTION;
|
||||
command.value = 1;
|
||||
command.string = "\t";
|
||||
break;
|
||||
case GDK_Return:
|
||||
if (key.state & GDK_CONTROL_MASK) {
|
||||
command.action = E_TEP_ACTIVATE;
|
||||
command.position = E_TEP_SELECTION;
|
||||
} else {
|
||||
command.action = E_TEP_INSERT;
|
||||
command.position = E_TEP_SELECTION;
|
||||
command.value = 1;
|
||||
command.string = "\n";
|
||||
}
|
||||
break;
|
||||
case GDK_Escape:
|
||||
command.action = E_TEP_NOP;
|
||||
command.position = E_TEP_SELECTION;
|
||||
/* Don't insert literally */
|
||||
break;
|
||||
|
||||
default:
|
||||
if (key.state & GDK_CONTROL_MASK) {
|
||||
if ((key.keyval >= 'A') && (key.keyval <= 'Z'))
|
||||
key.keyval -= 'A' - 'a';
|
||||
|
||||
if ((key.keyval >= 'a') && (key.keyval <= 'z')) {
|
||||
command.position = control_keys[(int) (key.keyval - 'a')].position;
|
||||
if (control_keys[(int) (key.keyval - 'a')].action != E_TEP_MOVE)
|
||||
command.action = control_keys[(int) (key.keyval - 'a')].action;
|
||||
command.value = control_keys[(int) (key.keyval - 'a')].value;
|
||||
command.string = control_keys[(int) (key.keyval - 'a')].string;
|
||||
}
|
||||
|
||||
if (key.keyval == 'x') {
|
||||
}
|
||||
|
||||
break;
|
||||
} else if (key.state & GDK_MOD1_MASK) {
|
||||
if ((key.keyval >= 'A') && (key.keyval <= 'Z'))
|
||||
key.keyval -= 'A' - 'a';
|
||||
|
||||
if ((key.keyval >= 'a') && (key.keyval <= 'z')) {
|
||||
command.position = alt_keys[(int) (key.keyval - 'a')].position;
|
||||
if (alt_keys[(int) (key.keyval - 'a')].action != E_TEP_MOVE)
|
||||
command.action = alt_keys[(int) (key.keyval - 'a')].action;
|
||||
command.value = alt_keys[(int) (key.keyval - 'a')].value;
|
||||
command.string = alt_keys[(int) (key.keyval - 'a')].string;
|
||||
}
|
||||
} else if (key.length > 0) {
|
||||
command.action = E_TEP_INSERT;
|
||||
command.position = E_TEP_SELECTION;
|
||||
command.value = strlen(key.string);
|
||||
command.string = key.string;
|
||||
|
||||
} else {
|
||||
command.action = E_TEP_NOP;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case GDK_KEY_RELEASE:
|
||||
command.action = E_TEP_NOP;
|
||||
break;
|
||||
default:
|
||||
command.action = E_TEP_NOP;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (command.action != E_TEP_NOP) {
|
||||
gtk_signal_emit_by_name (GTK_OBJECT (tep), "command", &command);
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
ETextEventProcessor *
|
||||
e_text_event_processor_emacs_like_new (void)
|
||||
{
|
||||
ETextEventProcessorEmacsLike *retval = gtk_type_new (e_text_event_processor_emacs_like_get_type ());
|
||||
return E_TEXT_EVENT_PROCESSOR (retval);
|
||||
}
|
||||
|
68
widgets/text/e-text-event-processor-emacs-like.h
Normal file
68
widgets/text/e-text-event-processor-emacs-like.h
Normal file
@ -0,0 +1,68 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/* e-text-event-processor-emacs-like.h
|
||||
* Copyright (C) 2000 Helix Code, Inc.
|
||||
* Author: Chris Lahey <clahey@helixcode.com>
|
||||
*
|
||||
* This library 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 library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
#ifndef __E_TEXT_EVENT_PROCESSOR_EMACS_LIKE_H__
|
||||
#define __E_TEXT_EVENT_PROCESSOR_EMACS_LIKE_H__
|
||||
|
||||
#include <gnome.h>
|
||||
#include "e-text-event-processor.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#pragma }
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/* ETextEventProcessorEmacsLike - Turns events on a text widget into commands. Uses an emacs-ish interface.
|
||||
*
|
||||
*/
|
||||
|
||||
#define E_TEXT_EVENT_PROCESSOR_EMACS_LIKE_TYPE (e_text_event_processor_emacs_like_get_type ())
|
||||
#define E_TEXT_EVENT_PROCESSOR_EMACS_LIKE(obj) (GTK_CHECK_CAST ((obj), E_TEXT_EVENT_PROCESSOR_EMACS_LIKE_TYPE, ETextEventProcessorEmacsLike))
|
||||
#define E_TEXT_EVENT_PROCESSOR_EMACS_LIKE_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), E_TEXT_EVENT_PROCESSOR_EMACS_LIKE_TYPE, ETextEventProcessorEmacsLikeClass))
|
||||
#define E_IS_TEXT_EVENT_PROCESSOR_EMACS_LIKE(obj) (GTK_CHECK_TYPE ((obj), E_TEXT_EVENT_PROCESSOR_EMACS_LIKE_TYPE))
|
||||
#define E_IS_TEXT_EVENT_PROCESSOR_EMACS_LIKE_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((obj), E_TEXT_EVENT_PROCESSOR_EMACS_LIKE_TYPE))
|
||||
|
||||
|
||||
typedef struct _ETextEventProcessorEmacsLike ETextEventProcessorEmacsLike;
|
||||
typedef struct _ETextEventProcessorEmacsLikeClass ETextEventProcessorEmacsLikeClass;
|
||||
|
||||
struct _ETextEventProcessorEmacsLike
|
||||
{
|
||||
ETextEventProcessor parent;
|
||||
|
||||
/* object specific fields */
|
||||
gboolean mouse_down;
|
||||
};
|
||||
|
||||
struct _ETextEventProcessorEmacsLikeClass
|
||||
{
|
||||
ETextEventProcessorClass parent_class;
|
||||
};
|
||||
|
||||
|
||||
GtkType e_text_event_processor_emacs_like_get_type (void);
|
||||
ETextEventProcessor *e_text_event_processor_emacs_like_new (void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
|
||||
#endif /* __E_TEXT_EVENT_PROCESSOR_EMACS_LIKE_H__ */
|
131
widgets/text/e-text-event-processor-types.h
Normal file
131
widgets/text/e-text-event-processor-types.h
Normal file
@ -0,0 +1,131 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/* e-text-event-processor.h
|
||||
* Copyright (C) 2000 Helix Code, Inc.
|
||||
* Author: Chris Lahey <clahey@helixcode.com>
|
||||
*
|
||||
* This library 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 library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Modified by the GTK+ Team and others 1997-1999. See the AUTHORS
|
||||
* file for a list of people on the GTK+ Team. See the ChangeLog
|
||||
* files for a list of changes. These files are distributed with
|
||||
* GTK+ at ftp://ftp.gtk.org/pub/gtk/.
|
||||
*/
|
||||
|
||||
#ifndef __E_TEXT_EVENT_PROCESSOR_TYPES_H__
|
||||
#define __E_TEXT_EVENT_PROCESSOR_TYPES_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#pragma }
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#include <gdk/gdktypes.h>
|
||||
|
||||
typedef enum _ETextEventProcessorCommandPosition ETextEventProcessorCommandPosition;
|
||||
typedef enum _ETextEventProcessorCommandAction ETextEventProcessorCommandAction;
|
||||
typedef struct _ETextEventProcessorCommand ETextEventProcessorCommand;
|
||||
|
||||
typedef union _ETextEventProcessorEvent ETextEventProcessorEvent;
|
||||
typedef struct _ETextEventProcessorEventButton ETextEventProcessorEventButton;
|
||||
typedef struct _ETextEventProcessorEventKey ETextEventProcessorEventKey;
|
||||
typedef struct _ETextEventProcessorEventMotion ETextEventProcessorEventMotion;
|
||||
|
||||
enum _ETextEventProcessorCommandPosition {
|
||||
E_TEP_VALUE,
|
||||
E_TEP_SELECTION,
|
||||
|
||||
E_TEP_START_OF_BUFFER,
|
||||
E_TEP_END_OF_BUFFER,
|
||||
|
||||
E_TEP_START_OF_LINE,
|
||||
E_TEP_END_OF_LINE,
|
||||
|
||||
E_TEP_FORWARD_CHARACTER,
|
||||
E_TEP_BACKWARD_CHARACTER,
|
||||
|
||||
E_TEP_FORWARD_WORD,
|
||||
E_TEP_BACKWARD_WORD,
|
||||
|
||||
E_TEP_FORWARD_LINE,
|
||||
E_TEP_BACKWARD_LINE,
|
||||
|
||||
E_TEP_FORWARD_PARAGRAPH,
|
||||
E_TEP_BACKWARD_PARAGRAPH,
|
||||
|
||||
E_TEP_FORWARD_PAGE,
|
||||
E_TEP_BACKWARD_PAGE
|
||||
};
|
||||
|
||||
enum _ETextEventProcessorCommandAction {
|
||||
E_TEP_MOVE,
|
||||
E_TEP_SELECT,
|
||||
E_TEP_DELETE,
|
||||
|
||||
E_TEP_INSERT,
|
||||
E_TEP_COPY,
|
||||
E_TEP_PASTE,
|
||||
E_TEP_SET_SELECT_BY_WORD,
|
||||
E_TEP_ACTIVATE,
|
||||
|
||||
E_TEP_NOP
|
||||
};
|
||||
|
||||
struct _ETextEventProcessorCommand {
|
||||
ETextEventProcessorCommandPosition position;
|
||||
ETextEventProcessorCommandAction action;
|
||||
int value;
|
||||
char *string;
|
||||
};
|
||||
|
||||
struct _ETextEventProcessorEventButton {
|
||||
GdkEventType type;
|
||||
guint32 time;
|
||||
guint state;
|
||||
guint button;
|
||||
gint position;
|
||||
};
|
||||
|
||||
struct _ETextEventProcessorEventKey {
|
||||
GdkEventType type;
|
||||
guint32 time;
|
||||
guint state;
|
||||
guint keyval;
|
||||
gint length;
|
||||
gchar *string;
|
||||
};
|
||||
|
||||
struct _ETextEventProcessorEventMotion {
|
||||
GdkEventType type;
|
||||
guint32 time;
|
||||
guint state;
|
||||
gint position;
|
||||
};
|
||||
|
||||
union _ETextEventProcessorEvent {
|
||||
GdkEventType type;
|
||||
ETextEventProcessorEventButton button;
|
||||
ETextEventProcessorEventKey key;
|
||||
ETextEventProcessorEventMotion motion;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
|
||||
#endif /* __E_TEXT_EVENT_PROCESSOR_TYPES_H__ */
|
103
widgets/text/e-text-event-processor.c
Normal file
103
widgets/text/e-text-event-processor.c
Normal file
@ -0,0 +1,103 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/* e-text-event-processor.c
|
||||
* Copyright (C) 2000 Helix Code, Inc.
|
||||
* Author: Chris Lahey <clahey@helixcode.com>
|
||||
*
|
||||
* This library 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 library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <gnome.h>
|
||||
#include "e-text-event-processor.h"
|
||||
static void e_text_event_processor_init (ETextEventProcessor *card);
|
||||
static void e_text_event_processor_class_init (ETextEventProcessorClass *klass);
|
||||
|
||||
static GtkObjectClass *parent_class = NULL;
|
||||
|
||||
/* The arguments we take */
|
||||
enum {
|
||||
ARG_0
|
||||
};
|
||||
|
||||
enum {
|
||||
E_TEP_EVENT,
|
||||
E_TEP_LAST_SIGNAL
|
||||
};
|
||||
|
||||
static guint e_tep_signals[E_TEP_LAST_SIGNAL] = { 0 };
|
||||
|
||||
GtkType
|
||||
e_text_event_processor_get_type (void)
|
||||
{
|
||||
static GtkType text_event_processor_type = 0;
|
||||
|
||||
if (!text_event_processor_type)
|
||||
{
|
||||
static const GtkTypeInfo text_event_processor_info =
|
||||
{
|
||||
"ETextEventProcessor",
|
||||
sizeof (ETextEventProcessor),
|
||||
sizeof (ETextEventProcessorClass),
|
||||
(GtkClassInitFunc) e_text_event_processor_class_init,
|
||||
(GtkObjectInitFunc) e_text_event_processor_init,
|
||||
/* reserved_1 */ NULL,
|
||||
/* reserved_2 */ NULL,
|
||||
(GtkClassInitFunc) NULL,
|
||||
};
|
||||
|
||||
text_event_processor_type = gtk_type_unique (gtk_object_get_type (), &text_event_processor_info);
|
||||
}
|
||||
|
||||
return text_event_processor_type;
|
||||
}
|
||||
|
||||
static void
|
||||
e_text_event_processor_class_init (ETextEventProcessorClass *klass)
|
||||
{
|
||||
GtkObjectClass *object_class;
|
||||
|
||||
object_class = (GtkObjectClass*) klass;
|
||||
|
||||
parent_class = gtk_type_class (gtk_object_get_type ());
|
||||
|
||||
e_tep_signals[E_TEP_EVENT] =
|
||||
gtk_signal_new ("command",
|
||||
GTK_RUN_LAST,
|
||||
object_class->type,
|
||||
GTK_SIGNAL_OFFSET (ETextEventProcessorClass, command),
|
||||
gtk_marshal_NONE__POINTER,
|
||||
GTK_TYPE_NONE, 1,
|
||||
GTK_TYPE_POINTER);
|
||||
|
||||
gtk_object_class_add_signals (object_class, e_tep_signals, E_TEP_LAST_SIGNAL);
|
||||
|
||||
klass->event = NULL;
|
||||
klass->command = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
e_text_event_processor_init (ETextEventProcessor *tep)
|
||||
{
|
||||
}
|
||||
|
||||
gint
|
||||
e_text_event_processor_handle_event (ETextEventProcessor *tep, ETextEventProcessorEvent *event)
|
||||
{
|
||||
if (E_TEXT_EVENT_PROCESSOR_CLASS(GTK_OBJECT(tep)->klass)->event) {
|
||||
return E_TEXT_EVENT_PROCESSOR_CLASS(GTK_OBJECT(tep)->klass)->event(tep, event);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
74
widgets/text/e-text-event-processor.h
Normal file
74
widgets/text/e-text-event-processor.h
Normal file
@ -0,0 +1,74 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/* e-text-event-processor.h
|
||||
* Copyright (C) 2000 Helix Code, Inc.
|
||||
* Author: Chris Lahey <clahey@helixcode.com>
|
||||
*
|
||||
* This library 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 library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
#ifndef __E_TEXT_EVENT_PROCESSOR_H__
|
||||
#define __E_TEXT_EVENT_PROCESSOR_H__
|
||||
|
||||
#include <gnome.h>
|
||||
#include "e-text-event-processor-types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#pragma }
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/* ETextEventProcessor - Turns events on a text widget into commands.
|
||||
*
|
||||
*/
|
||||
|
||||
#define E_TEXT_EVENT_PROCESSOR_TYPE (e_text_event_processor_get_type ())
|
||||
#define E_TEXT_EVENT_PROCESSOR(obj) (GTK_CHECK_CAST ((obj), E_TEXT_EVENT_PROCESSOR_TYPE, ETextEventProcessor))
|
||||
#define E_TEXT_EVENT_PROCESSOR_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), E_TEXT_EVENT_PROCESSOR_TYPE, ETextEventProcessorClass))
|
||||
#define E_IS_TEXT_EVENT_PROCESSOR(obj) (GTK_CHECK_TYPE ((obj), E_TEXT_EVENT_PROCESSOR_TYPE))
|
||||
#define E_IS_TEXT_EVENT_PROCESSOR_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((obj), E_TEXT_EVENT_PROCESSOR_TYPE))
|
||||
|
||||
|
||||
typedef struct _ETextEventProcessor ETextEventProcessor;
|
||||
typedef struct _ETextEventProcessorClass ETextEventProcessorClass;
|
||||
|
||||
struct _ETextEventProcessor
|
||||
{
|
||||
GtkObject parent;
|
||||
|
||||
/* object specific fields */
|
||||
|
||||
};
|
||||
|
||||
struct _ETextEventProcessorClass
|
||||
{
|
||||
GtkObjectClass parent_class;
|
||||
|
||||
/* signals */
|
||||
void (* command) (ETextEventProcessor *tep, ETextEventProcessorCommand *command);
|
||||
|
||||
/* virtual functions */
|
||||
gint (* event) (ETextEventProcessor *tep, ETextEventProcessorEvent *event);
|
||||
};
|
||||
|
||||
|
||||
GtkType e_text_event_processor_get_type (void);
|
||||
gint e_text_event_processor_handle_event (ETextEventProcessor *tep, ETextEventProcessorEvent *event);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
|
||||
#endif /* __E_TEXT_EVENT_PROCESSOR_H__ */
|
@ -18,12 +18,15 @@
|
||||
|
||||
#include <config.h>
|
||||
#include <math.h>
|
||||
#include <ctype.h>
|
||||
#include "e-text.h"
|
||||
#include <gdk/gdkx.h> /* for BlackPixel */
|
||||
#include <libart_lgpl/art_affine.h>
|
||||
#include <libart_lgpl/art_rgb.h>
|
||||
#include <libart_lgpl/art_rgb_bitmap_affine.h>
|
||||
|
||||
#include "e-text-event-processor-emacs-like.h"
|
||||
|
||||
|
||||
|
||||
/* This defines a line of text */
|
||||
@ -58,6 +61,7 @@ enum {
|
||||
ARG_FILL_STIPPLE,
|
||||
ARG_TEXT_WIDTH,
|
||||
ARG_TEXT_HEIGHT,
|
||||
ARG_EDITABLE,
|
||||
ARG_USE_ELLIPSIS,
|
||||
ARG_ELLIPSIS
|
||||
};
|
||||
@ -80,6 +84,9 @@ static double e_text_point (GnomeCanvasItem *item, double x, double y, int cx, i
|
||||
static void e_text_bounds (GnomeCanvasItem *item,
|
||||
double *x1, double *y1, double *x2, double *y2);
|
||||
static void e_text_render (GnomeCanvasItem *item, GnomeCanvasBuf *buf);
|
||||
static gint e_text_event (GnomeCanvasItem *item, GdkEvent *event);
|
||||
|
||||
static void e_text_command(ETextEventProcessor *tep, ETextEventProcessorCommand *command, gpointer data);
|
||||
|
||||
static ETextSuckFont *e_suck_font (GdkFont *font);
|
||||
static void e_suck_font_free (ETextSuckFont *suckfont);
|
||||
@ -171,6 +178,8 @@ e_text_class_init (ETextClass *class)
|
||||
GTK_TYPE_DOUBLE, GTK_ARG_READABLE, ARG_TEXT_WIDTH);
|
||||
gtk_object_add_arg_type ("EText::text_height",
|
||||
GTK_TYPE_DOUBLE, GTK_ARG_READABLE, ARG_TEXT_HEIGHT);
|
||||
gtk_object_add_arg_type ("EText::editable",
|
||||
GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_EDITABLE);
|
||||
gtk_object_add_arg_type ("EText::use_ellipsis",
|
||||
GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_USE_ELLIPSIS);
|
||||
gtk_object_add_arg_type ("EText::ellipsis",
|
||||
@ -187,6 +196,7 @@ e_text_class_init (ETextClass *class)
|
||||
item_class->point = e_text_point;
|
||||
item_class->bounds = e_text_bounds;
|
||||
item_class->render = e_text_render;
|
||||
item_class->event = e_text_event;
|
||||
}
|
||||
|
||||
/* Object initialization function for the text item */
|
||||
@ -201,9 +211,18 @@ e_text_init (EText *text)
|
||||
text->clip_height = 0.0;
|
||||
text->xofs = 0.0;
|
||||
text->yofs = 0.0;
|
||||
|
||||
text->ellipsis = NULL;
|
||||
text->use_ellipsis = FALSE;
|
||||
text->ellipsis_width = 0;
|
||||
|
||||
text->editable = FALSE;
|
||||
text->editing = FALSE;
|
||||
text->xofs_edit = 0;
|
||||
|
||||
text->selection_start = 0;
|
||||
text->selection_end = 0;
|
||||
text->select_by_word = FALSE;
|
||||
}
|
||||
|
||||
/* Destroy handler for the text item */
|
||||
@ -457,6 +476,7 @@ calc_line_widths (EText *text)
|
||||
|
||||
if (text->clip &&
|
||||
text->use_ellipsis &&
|
||||
! text->editing &&
|
||||
lines->width > text->clip_width) {
|
||||
if (text->font) {
|
||||
lines->ellipsis_length = 0;
|
||||
@ -729,6 +749,10 @@ e_text_set_arg (GtkObject *object, GtkArg *arg, guint arg_id)
|
||||
set_stipple (text, GTK_VALUE_BOXED (*arg), FALSE);
|
||||
break;
|
||||
|
||||
case ARG_EDITABLE:
|
||||
text->editable = GTK_VALUE_BOOL (*arg);
|
||||
break;
|
||||
|
||||
case ARG_USE_ELLIPSIS:
|
||||
text->use_ellipsis = GTK_VALUE_BOOL (*arg);
|
||||
calc_line_widths (text);
|
||||
@ -839,6 +863,10 @@ e_text_get_arg (GtkObject *object, GtkArg *arg, guint arg_id)
|
||||
GTK_VALUE_DOUBLE (*arg) = text->height / text->item.canvas->pixels_per_unit;
|
||||
break;
|
||||
|
||||
case ARG_EDITABLE:
|
||||
GTK_VALUE_BOOL (*arg) = text->editable;
|
||||
break;
|
||||
|
||||
case ARG_USE_ELLIPSIS:
|
||||
GTK_VALUE_BOOL (*arg) = text->use_ellipsis;
|
||||
break;
|
||||
@ -1016,6 +1044,19 @@ get_line_xpos (EText *text, struct line *line)
|
||||
return x;
|
||||
}
|
||||
|
||||
static void
|
||||
_get_tep(EText *text)
|
||||
{
|
||||
if (!text->tep) {
|
||||
text->tep = e_text_event_processor_emacs_like_new();
|
||||
gtk_signal_connect(GTK_OBJECT(text->tep),
|
||||
"command",
|
||||
GTK_SIGNAL_FUNC(e_text_command),
|
||||
(gpointer) text);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/* Draw handler for the text item */
|
||||
static void
|
||||
e_text_draw (GnomeCanvasItem *item, GdkDrawable *drawable,
|
||||
@ -1026,8 +1067,14 @@ e_text_draw (GnomeCanvasItem *item, GdkDrawable *drawable,
|
||||
struct line *lines;
|
||||
int i;
|
||||
int xpos, ypos;
|
||||
int start_char, end_char;
|
||||
int sel_start, sel_end;
|
||||
GdkRectangle sel_rect;
|
||||
GdkGC *fg_gc;
|
||||
GnomeCanvas *canvas;
|
||||
|
||||
text = E_TEXT (item);
|
||||
canvas = GNOME_CANVAS_ITEM(text)->canvas;
|
||||
|
||||
if (!text->text || !text->font)
|
||||
return;
|
||||
@ -1039,6 +1086,7 @@ e_text_draw (GnomeCanvasItem *item, GdkDrawable *drawable,
|
||||
rect.height = text->clip_cheight;
|
||||
|
||||
gdk_gc_set_clip_rectangle (text->gc, &rect);
|
||||
gdk_gc_set_clip_rectangle (GTK_WIDGET(canvas)->style->fg_gc[GTK_STATE_SELECTED], &rect);
|
||||
}
|
||||
lines = text->lines;
|
||||
ypos = text->cy + text->font->ascent;
|
||||
@ -1049,6 +1097,86 @@ e_text_draw (GnomeCanvasItem *item, GdkDrawable *drawable,
|
||||
for (i = 0; i < text->num_lines; i++) {
|
||||
if (lines->length != 0) {
|
||||
xpos = get_line_xpos (text, lines);
|
||||
if (text->editing) {
|
||||
xpos -= text->xofs_edit;
|
||||
start_char = lines->text - text->text;
|
||||
end_char = start_char + lines->length;
|
||||
sel_start = text->selection_start;
|
||||
sel_end = text->selection_end;
|
||||
if (sel_start > sel_end ) {
|
||||
sel_start ^= sel_end;
|
||||
sel_end ^= sel_start;
|
||||
sel_start ^= sel_end;
|
||||
}
|
||||
if ( sel_start < start_char )
|
||||
sel_start = start_char;
|
||||
if ( sel_end > end_char )
|
||||
sel_end = end_char;
|
||||
if ( sel_start < sel_end ) {
|
||||
sel_rect.x = xpos - x + gdk_text_width (text->font,
|
||||
lines->text,
|
||||
sel_start - start_char);
|
||||
sel_rect.y = ypos - y - text->font->ascent;
|
||||
sel_rect.width = gdk_text_width (text->font,
|
||||
lines->text + sel_start - start_char,
|
||||
sel_end - sel_start);
|
||||
sel_rect.height = text->font->ascent + text->font->descent;
|
||||
gdk_draw_rectangle (drawable,
|
||||
text->gc,
|
||||
TRUE,
|
||||
sel_rect.x,
|
||||
sel_rect.y,
|
||||
sel_rect.width,
|
||||
sel_rect.height);
|
||||
gdk_draw_text (drawable,
|
||||
text->font,
|
||||
text->gc,
|
||||
xpos - x,
|
||||
ypos - y,
|
||||
lines->text,
|
||||
sel_start - start_char);
|
||||
fg_gc = GTK_WIDGET(canvas)->style->fg_gc[GTK_STATE_SELECTED];
|
||||
gdk_draw_text (drawable,
|
||||
text->font,
|
||||
fg_gc,
|
||||
xpos - x + gdk_text_width (text->font,
|
||||
lines->text,
|
||||
sel_start - start_char),
|
||||
ypos - y,
|
||||
lines->text + sel_start - start_char,
|
||||
sel_end - sel_start);
|
||||
gdk_draw_text (drawable,
|
||||
text->font,
|
||||
text->gc,
|
||||
xpos - x + gdk_text_width (text->font,
|
||||
lines->text,
|
||||
sel_end - start_char),
|
||||
ypos - y,
|
||||
lines->text + sel_end - start_char,
|
||||
end_char - sel_end);
|
||||
} else {
|
||||
gdk_draw_text (drawable,
|
||||
text->font,
|
||||
text->gc,
|
||||
xpos - x,
|
||||
ypos - y,
|
||||
lines->text,
|
||||
lines->length);
|
||||
}
|
||||
if (text->selection_start == text->selection_end &&
|
||||
text->selection_start >= start_char &&
|
||||
text->selection_start <= end_char) {
|
||||
gdk_draw_rectangle (drawable,
|
||||
text->gc,
|
||||
TRUE,
|
||||
xpos - x + gdk_text_width (text->font,
|
||||
lines->text,
|
||||
sel_start - start_char),
|
||||
ypos - y - text->font->ascent,
|
||||
1,
|
||||
text->font->ascent + text->font->descent);
|
||||
}
|
||||
} else {
|
||||
if ( text->clip && text->use_ellipsis && lines->ellipsis_length < lines->length) {
|
||||
gdk_draw_text (drawable,
|
||||
text->font,
|
||||
@ -1075,13 +1203,16 @@ e_text_draw (GnomeCanvasItem *item, GdkDrawable *drawable,
|
||||
lines->text,
|
||||
lines->length);
|
||||
}
|
||||
}
|
||||
|
||||
ypos += text->font->ascent + text->font->descent;
|
||||
lines++;
|
||||
}
|
||||
|
||||
if (text->clip)
|
||||
if (text->clip) {
|
||||
gdk_gc_set_clip_rectangle (text->gc, NULL);
|
||||
gdk_gc_set_clip_rectangle (GTK_WIDGET(GNOME_CANVAS_ITEM(text)->canvas)->style->fg_gc[GTK_STATE_SELECTED], NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/* Render handler for the text item */
|
||||
@ -1308,6 +1439,285 @@ e_text_bounds (GnomeCanvasItem *item, double *x1, double *y1, double *x2, double
|
||||
*y2 = *y1 + height;
|
||||
}
|
||||
|
||||
static gint
|
||||
_get_position_from_xy (EText *text, gint x, gint y)
|
||||
{
|
||||
int i, j;
|
||||
int ypos = text->cy;
|
||||
int xpos;
|
||||
struct line *lines;
|
||||
j = 0;
|
||||
while (y > ypos)
|
||||
{
|
||||
ypos += text->font->ascent + text->font->descent;
|
||||
j ++;
|
||||
}
|
||||
j--;
|
||||
if (j >= text->num_lines)
|
||||
j = text->num_lines - 1;
|
||||
if (j < 0)
|
||||
j = 0;
|
||||
i = 0;
|
||||
lines = text->lines;
|
||||
lines += j;
|
||||
xpos = get_line_xpos (text, lines);
|
||||
for(i = 0; i < lines->length; i++) {
|
||||
int charwidth = gdk_text_width(text->font,
|
||||
lines->text + i,
|
||||
1);
|
||||
xpos += charwidth / 2;
|
||||
if (xpos > x)
|
||||
break;
|
||||
xpos += (charwidth + 1) / 2;
|
||||
}
|
||||
return lines->text + i - text->text;
|
||||
}
|
||||
|
||||
static gint
|
||||
e_text_event (GnomeCanvasItem *item, GdkEvent *event)
|
||||
{
|
||||
EText *text = E_TEXT(item);
|
||||
ETextEventProcessorEvent e_tep_event;
|
||||
|
||||
gint return_val;
|
||||
|
||||
e_tep_event.type = event->type;
|
||||
switch (event->type) {
|
||||
case GDK_FOCUS_CHANGE:
|
||||
if (text->editable) {
|
||||
GdkEventFocus *focus_event;
|
||||
focus_event = (GdkEventFocus *) event;
|
||||
if (focus_event->in) {
|
||||
if(!text->editing) {
|
||||
text->editing = TRUE;
|
||||
text->selection_start = 0;
|
||||
text->selection_end = 0;
|
||||
text->select_by_word = FALSE;
|
||||
text->xofs_edit = 0;
|
||||
}
|
||||
} else {
|
||||
text->editing = FALSE;
|
||||
}
|
||||
calc_line_widths (text);
|
||||
}
|
||||
return_val = 0;
|
||||
break;
|
||||
case GDK_KEY_PRESS: /* Fall Through */
|
||||
case GDK_KEY_RELEASE:
|
||||
if (text->editing) {
|
||||
GdkEventKey key = event->key;
|
||||
e_tep_event.key.time = key.time;
|
||||
e_tep_event.key.state = key.state;
|
||||
e_tep_event.key.keyval = key.keyval;
|
||||
e_tep_event.key.length = key.length;
|
||||
e_tep_event.key.string = key.string;
|
||||
_get_tep(text);
|
||||
return e_text_event_processor_handle_event (text->tep,
|
||||
&e_tep_event);
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
break;
|
||||
case GDK_BUTTON_PRESS: /* Fall Through */
|
||||
case GDK_BUTTON_RELEASE:
|
||||
if (text->editing) {
|
||||
GdkEventButton button = event->button;
|
||||
e_tep_event.button.time = button.time;
|
||||
e_tep_event.button.state = button.state;
|
||||
e_tep_event.button.button = button.button;
|
||||
e_tep_event.button.position = _get_position_from_xy(text, button.x, button.y);
|
||||
_get_tep(text);
|
||||
return_val = e_text_event_processor_handle_event (text->tep,
|
||||
&e_tep_event);
|
||||
} else if (text->editable && event->type == GDK_BUTTON_RELEASE) {
|
||||
gnome_canvas_item_grab_focus (item);
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case GDK_MOTION_NOTIFY:
|
||||
if (text->editing) {
|
||||
GdkEventMotion motion = event->motion;
|
||||
e_tep_event.motion.time = motion.time;
|
||||
e_tep_event.motion.state = motion.state;
|
||||
e_tep_event.motion.position = _get_position_from_xy(text, motion.x, motion.y);
|
||||
_get_tep(text);
|
||||
return_val = e_text_event_processor_handle_event (text->tep,
|
||||
&e_tep_event);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (return_val)
|
||||
return return_val;
|
||||
if (GNOME_CANVAS_ITEM_CLASS(parent_class)->event)
|
||||
return GNOME_CANVAS_ITEM_CLASS(parent_class)->event(item, event);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
_get_position(EText *text, ETextEventProcessorCommand *command)
|
||||
{
|
||||
int i;
|
||||
int length;
|
||||
|
||||
switch (command->position) {
|
||||
|
||||
case E_TEP_VALUE:
|
||||
return command->value;
|
||||
|
||||
case E_TEP_SELECTION:
|
||||
return text->selection_end;
|
||||
|
||||
case E_TEP_START_OF_BUFFER:
|
||||
return 0;
|
||||
case E_TEP_END_OF_BUFFER:
|
||||
return strlen(text->text);
|
||||
|
||||
case E_TEP_START_OF_LINE:
|
||||
for (i = text->selection_end - 2; i > 0; i--)
|
||||
if (text->text[i] == '\n') {
|
||||
i++;
|
||||
break;
|
||||
}
|
||||
return i;
|
||||
case E_TEP_END_OF_LINE:
|
||||
length = strlen(text->text);
|
||||
for (i = text->selection_end + 1; i < length; i++)
|
||||
if (text->text[i] == '\n') {
|
||||
break;
|
||||
}
|
||||
if (i > length)
|
||||
i = length;
|
||||
return i;
|
||||
|
||||
case E_TEP_FORWARD_CHARACTER:
|
||||
length = strlen(text->text);
|
||||
i = text->selection_end + 1;
|
||||
if (i > length)
|
||||
i = length;
|
||||
return i;
|
||||
case E_TEP_BACKWARD_CHARACTER:
|
||||
i = text->selection_end - 1;
|
||||
if (i < 0)
|
||||
i = 0;
|
||||
return i;
|
||||
|
||||
case E_TEP_FORWARD_WORD:
|
||||
length = strlen(text->text);
|
||||
for (i = text->selection_end + 1; i < length; i++)
|
||||
if (isspace(text->text[i])) {
|
||||
break;
|
||||
}
|
||||
if (i > length)
|
||||
i = length;
|
||||
return i;
|
||||
case E_TEP_BACKWARD_WORD:
|
||||
for (i = text->selection_end - 2; i > 0; i--)
|
||||
if (isspace(text->text[i])) {
|
||||
i++;
|
||||
break;
|
||||
}
|
||||
if (i < 0)
|
||||
i = 0;
|
||||
return i;
|
||||
|
||||
case E_TEP_FORWARD_LINE:
|
||||
case E_TEP_BACKWARD_LINE:
|
||||
|
||||
case E_TEP_FORWARD_PARAGRAPH:
|
||||
case E_TEP_BACKWARD_PARAGRAPH:
|
||||
|
||||
case E_TEP_FORWARD_PAGE:
|
||||
case E_TEP_BACKWARD_PAGE:
|
||||
return text->selection_end;
|
||||
default:
|
||||
return text->selection_end;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_delete_selection(EText *text)
|
||||
{
|
||||
gint length = strlen(text->text);
|
||||
if (text->selection_end == text->selection_start)
|
||||
return;
|
||||
if (text->selection_end < text->selection_start) {
|
||||
text->selection_end ^= text->selection_start;
|
||||
text->selection_start ^= text->selection_end;
|
||||
text->selection_end ^= text->selection_start;
|
||||
}
|
||||
memmove( text->text + text->selection_start,
|
||||
text->text + text->selection_end,
|
||||
length - text->selection_end + 1 );
|
||||
length -= text->selection_end - text->selection_start;
|
||||
text->selection_end = text->selection_start;
|
||||
}
|
||||
|
||||
static void
|
||||
_insert(EText *text, char *string, int value)
|
||||
{
|
||||
if (value > 0) {
|
||||
char *temp;
|
||||
gint length = strlen(text->text);
|
||||
temp = g_new(gchar, length + value + 1);
|
||||
strncpy(temp, text->text, text->selection_start);
|
||||
strncpy(temp + text->selection_start, string, value);
|
||||
strcpy(temp + text->selection_start + value, text->text + text->selection_start);
|
||||
g_free(text->text);
|
||||
text->text = temp;
|
||||
text->selection_start += value;
|
||||
text->selection_end = text->selection_start;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
e_text_command(ETextEventProcessor *tep, ETextEventProcessorCommand *command, gpointer data)
|
||||
{
|
||||
EText *text = E_TEXT(data);
|
||||
switch (command->action) {
|
||||
case E_TEP_MOVE:
|
||||
text->selection_start = _get_position(text, command);
|
||||
text->selection_end = text->selection_start;
|
||||
break;
|
||||
case E_TEP_SELECT:
|
||||
text->selection_end = _get_position(text, command);
|
||||
break;
|
||||
case E_TEP_DELETE:
|
||||
if (text->selection_end == text->selection_start) {
|
||||
text->selection_end = _get_position(text, command);
|
||||
}
|
||||
_delete_selection(text);
|
||||
split_into_lines (text);
|
||||
recalc_bounds (text);
|
||||
break;
|
||||
|
||||
case E_TEP_INSERT:
|
||||
if (text->selection_end != text->selection_start) {
|
||||
_delete_selection(text);
|
||||
}
|
||||
_insert(text, command->string, command->value);
|
||||
split_into_lines (text);
|
||||
recalc_bounds (text);
|
||||
break;
|
||||
case E_TEP_COPY:
|
||||
if (text->selection_end != text->selection_start) {
|
||||
}
|
||||
break;
|
||||
case E_TEP_PASTE:
|
||||
break;
|
||||
case E_TEP_ACTIVATE:
|
||||
break;
|
||||
case E_TEP_SET_SELECT_BY_WORD:
|
||||
text->select_by_word = command->value;
|
||||
break;
|
||||
case E_TEP_NOP:
|
||||
break;
|
||||
}
|
||||
gnome_canvas_item_request_update (GNOME_CANVAS_ITEM(text));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Routines for sucking fonts from the X server */
|
||||
|
@ -20,6 +20,7 @@
|
||||
#define E_TEXT_H
|
||||
|
||||
#include <gnome.h>
|
||||
#include "e-text-event-processor.h"
|
||||
|
||||
|
||||
BEGIN_GNOME_DECLS
|
||||
@ -59,8 +60,15 @@ BEGIN_GNOME_DECLS
|
||||
* text_height double R Used to query the rendered height of the text
|
||||
*
|
||||
* These are ignored in the AA version:
|
||||
* editable boolean RW Can this item be edited
|
||||
* use_ellipsis boolean RW Whether to use ellipsises if text gets cut off. Meaningless if clip == false.
|
||||
* ellipsis string RW The characters to use as ellipsis. NULL = "...".
|
||||
*
|
||||
* These are not implemented yet:
|
||||
* multi_line boolean RW Line wrap when not editing.
|
||||
* multi_line_on_edit boolean RW Switch to line wrap when editing.
|
||||
* background boolean RW Draw a background rectangle.
|
||||
* background_on_edit boolean RW Draw a background when editing.
|
||||
*/
|
||||
|
||||
#define E_TYPE_TEXT (e_text_get_type ())
|
||||
@ -129,6 +137,18 @@ struct _EText {
|
||||
char *ellipsis; /* The ellipsis characters. NULL = "...". */
|
||||
double ellipsis_width; /* The width of the ellipsis. */
|
||||
gboolean use_ellipsis; /* Whether to use the ellipsis. */
|
||||
|
||||
gboolean editable; /* Item is editable */
|
||||
gboolean editing; /* Item is currently being edited */
|
||||
|
||||
int xofs_edit; /* Offset because of editing */
|
||||
|
||||
/* This needs to be reworked a bit once we get line wrapping. */
|
||||
int selection_start; /* Start of selection */
|
||||
int selection_end; /* End of selection */
|
||||
gboolean select_by_word; /* Current selection is by word */
|
||||
|
||||
ETextEventProcessor *tep; /* Text Event Processor */
|
||||
};
|
||||
|
||||
struct _ETextClass {
|
||||
|
Reference in New Issue
Block a user