diff options
author | Milan Crha <mcrha@redhat.com> | 2009-05-20 22:50:00 +0800 |
---|---|---|
committer | Milan Crha <mcrha@redhat.com> | 2009-05-20 22:50:00 +0800 |
commit | f4cf9af33ccde3142a3011e8b2dbcfb4cbc9ae81 (patch) | |
tree | 1c0228db536f5fa0efc6e0f779bb86df610989d0 /widgets | |
parent | 3acc45b10c9849aa5385a762b4d139472916dca1 (diff) | |
download | gsoc2013-evolution-f4cf9af33ccde3142a3011e8b2dbcfb4cbc9ae81.tar.gz gsoc2013-evolution-f4cf9af33ccde3142a3011e8b2dbcfb4cbc9ae81.tar.zst gsoc2013-evolution-f4cf9af33ccde3142a3011e8b2dbcfb4cbc9ae81.zip |
Use -no-undefined on Linux too
There still left two things opened, search for KILL-BONOBO to find them.
One is in calendar's Makefile.am, one in composer.
Diffstat (limited to 'widgets')
78 files changed, 9534 insertions, 2254 deletions
diff --git a/widgets/Makefile.am b/widgets/Makefile.am index 347c0f7c66..99305b844e 100644 --- a/widgets/Makefile.am +++ b/widgets/Makefile.am @@ -1,9 +1,9 @@ SUBDIRS = \ - table \ - text \ misc \ + text \ e-timezone-dialog \ + table \ menus EXTRA_DIST = \ diff --git a/widgets/menus/gal-view-collection.c b/widgets/menus/gal-view-collection.c index 890ee3ea7f..9541f0fb9c 100644 --- a/widgets/menus/gal-view-collection.c +++ b/widgets/menus/gal-view-collection.c @@ -33,7 +33,7 @@ #include <glib/gi18n.h> #include "e-util/e-util.h" #include "e-util/e-xml-utils.h" -#include "misc/e-unicode.h" +#include "e-util/e-unicode.h" #include "gal-view-collection.h" diff --git a/widgets/menus/gal-view-instance.c b/widgets/menus/gal-view-instance.c index 19ec402fa3..40a9e5262a 100644 --- a/widgets/menus/gal-view-instance.c +++ b/widgets/menus/gal-view-instance.c @@ -38,7 +38,7 @@ #include <glib/gi18n.h> #include "e-util/e-util.h" #include "e-util/e-xml-utils.h" -#include "misc/e-unicode.h" +#include "e-util/e-unicode.h" #include "gal-define-views-dialog.h" #include "gal-view-instance.h" diff --git a/widgets/menus/gal-view-new-dialog.c b/widgets/menus/gal-view-new-dialog.c index 061c04b71a..8716764c49 100644 --- a/widgets/menus/gal-view-new-dialog.c +++ b/widgets/menus/gal-view-new-dialog.c @@ -27,7 +27,7 @@ #include <glib/gi18n.h> #include "e-util/e-util.h" #include "e-util/e-util-private.h" -#include "misc/e-unicode.h" +#include "e-util/e-unicode.h" #include "gal-define-views-model.h" #include "gal-view-new-dialog.h" diff --git a/widgets/misc/Makefile.am b/widgets/misc/Makefile.am index 212d67557b..bd2c9f9f36 100644 --- a/widgets/misc/Makefile.am +++ b/widgets/misc/Makefile.am @@ -1,10 +1,5 @@ -if OS_WIN32 -WIN32_BOOTSTRAP_LIBS = $(top_builddir)/win32/libfilter.la -endif - INCLUDES = \ -I$(top_srcdir) \ - -I$(top_srcdir)/a11y/widgets \ -I$(top_srcdir)/filter \ -I$(top_srcdir)/widgets \ -DEVOLUTION_IMAGES=\""$(imagesdir)"\" \ @@ -50,13 +45,10 @@ widgetsinclude_HEADERS = \ e-attachment-view.h \ e-calendar.h \ e-calendar-item.h \ - e-camel-activity.h \ e-canvas.h \ e-canvas-background.h \ e-canvas-utils.h \ e-canvas-vbox.h \ - e-cell-date-edit.h \ - e-cell-percent.h \ e-cell-renderer-combo.h \ e-charset-picker.h \ e-colors.h \ @@ -75,8 +67,6 @@ widgetsinclude_HEADERS = \ e-popup-menu.h \ e-preferences-window.h \ e-printable.h \ - e-reflow.h \ - e-reflow-model.h \ e-search-bar.h \ e-selection-model.h \ e-selection-model-array.h \ @@ -91,8 +81,10 @@ widgetsinclude_HEADERS = \ e-spinner.c \ e-spinner.h \ e-timeout-activity.h \ - e-unicode.h \ - e-url-entry.h + e-url-entry.h \ + a11y/ea-calendar-cell.h \ + a11y/ea-calendar-item.h \ + a11y/ea-widgets.h libemiscwidgets_la_SOURCES = \ $(widgetsinclude_HEADERS) \ @@ -115,13 +107,10 @@ libemiscwidgets_la_SOURCES = \ e-attachment-view.c \ e-calendar.c \ e-calendar-item.c \ - e-camel-activity.c \ e-canvas.c \ e-canvas-background.c \ e-canvas-utils.c \ e-canvas-vbox.c \ - e-cell-date-edit.c \ - e-cell-percent.c \ e-cell-renderer-combo.c \ e-charset-picker.c \ e-colors.c \ @@ -140,8 +129,6 @@ libemiscwidgets_la_SOURCES = \ e-popup-menu.c \ e-preferences-window.c \ e-printable.c \ - e-reflow-model.c \ - e-reflow.c \ e-search-bar.c \ e-selection-model.c \ e-selection-model-array.c \ @@ -154,20 +141,20 @@ libemiscwidgets_la_SOURCES = \ e-signature-script-dialog.c \ e-signature-tree-view.c \ e-timeout-activity.c \ - e-unicode.c \ - e-url-entry.c + e-url-entry.c \ + a11y/ea-calendar-cell.c \ + a11y/ea-calendar-item.c \ + a11y/ea-widgets.c libemiscwidgets_la_LDFLAGS = $(NO_UNDEFINED) -libemiscwidgets_la_LIBADD = \ - $(top_builddir)/e-util/libeutil.la \ - $(top_builddir)/filter/libfilter.la \ - $(top_builddir)/widgets/table/libetable.la \ - $(top_builddir)/widgets/text/libetext.la \ - $(top_builddir)/a11y/widgets/libevolution-widgets-a11y.la \ - $(top_builddir)/a11y/libevolution-a11y.la \ - $(EVOLUTION_MAIL_LIBS) \ - $(GNOME_PLATFORM_LIBS) \ +libemiscwidgets_la_LIBADD = \ + $(top_builddir)/e-util/libeutil.la \ + $(top_builddir)/filter/libfilter.la \ + $(top_builddir)/a11y/libevolution-a11y.la \ + $(EVOLUTION_MAIL_LIBS) \ + $(GNOME_PLATFORM_LIBS) \ + $(MATH_LIB) \ $(ICONV_LIBS) noinst_PROGRAMS = \ diff --git a/widgets/misc/a11y/ea-calendar-cell.c b/widgets/misc/a11y/ea-calendar-cell.c new file mode 100644 index 0000000000..8173d6d25f --- /dev/null +++ b/widgets/misc/a11y/ea-calendar-cell.c @@ -0,0 +1,387 @@ +/* + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Authors: + * Bolian Yin <bolian.yin@sun.com> + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include <gtk/gtk.h> +#include <e-util/e-util.h> +#include "ea-calendar-cell.h" +#include "ea-calendar-item.h" +#include "a11y/ea-factory.h" + +/* ECalendarCell */ + +static void e_calendar_cell_class_init (ECalendarCellClass *class); + +EA_FACTORY_GOBJECT (EA_TYPE_CALENDAR_CELL, ea_calendar_cell, ea_calendar_cell_new) + +GType +e_calendar_cell_get_type (void) +{ + static GType type = 0; + + if (!type) { + static GTypeInfo tinfo = { + sizeof (ECalendarCellClass), + (GBaseInitFunc) NULL, /* base init */ + (GBaseFinalizeFunc) NULL, /* base finalize */ + (GClassInitFunc) e_calendar_cell_class_init, /* class init */ + (GClassFinalizeFunc) NULL, /* class finalize */ + NULL, /* class data */ + sizeof (ECalendarCell), /* instance size */ + 0, /* nb preallocs */ + (GInstanceInitFunc) NULL, /* instance init */ + NULL /* value table */ + }; + + type = g_type_register_static (G_TYPE_OBJECT, + "ECalendarCell", &tinfo, 0); + } + + return type; +} + +static void +e_calendar_cell_class_init (ECalendarCellClass *class) +{ + EA_SET_FACTORY (e_calendar_cell_get_type (), ea_calendar_cell); +} + +ECalendarCell * +e_calendar_cell_new (ECalendarItem *calitem, gint row, gint column) +{ + GObject *object; + ECalendarCell *cell; + + g_return_val_if_fail (E_IS_CALENDAR_ITEM (calitem), NULL); + + object = g_object_new (E_TYPE_CALENDAR_CELL, NULL); + cell = E_CALENDAR_CELL (object); + cell->calitem = calitem; + cell->row = row; + cell->column = column; + +#ifdef ACC_DEBUG + g_print ("EvoAcc: e_calendar_cell created %p\n", (void *)cell); +#endif + + return cell; +} + +/* EaCalendarCell */ + +static void ea_calendar_cell_class_init (EaCalendarCellClass *klass); +static void ea_calendar_cell_init (EaCalendarCell *a11y); + +static G_CONST_RETURN gchar* ea_calendar_cell_get_name (AtkObject *accessible); +static G_CONST_RETURN gchar* ea_calendar_cell_get_description (AtkObject *accessible); +static AtkObject * ea_calendar_cell_get_parent (AtkObject *accessible); +static gint ea_calendar_cell_get_index_in_parent (AtkObject *accessible); +static AtkStateSet *ea_calendar_cell_ref_state_set (AtkObject *accessible); + +/* component interface */ +static void atk_component_interface_init (AtkComponentIface *iface); +static void component_interface_get_extents (AtkComponent *component, + gint *x, gint *y, + gint *width, gint *height, + AtkCoordType coord_type); +static gboolean component_interface_grab_focus (AtkComponent *component); + +static gpointer parent_class = NULL; + +#ifdef ACC_DEBUG +static gint n_ea_calendar_cell_created = 0, n_ea_calendar_cell_destroyed = 0; +static void ea_calendar_cell_finalize (GObject *object); +#endif + +GType +ea_calendar_cell_get_type (void) +{ + static GType type = 0; + + if (!type) { + static GTypeInfo tinfo = { + sizeof (EaCalendarCellClass), + (GBaseInitFunc) NULL, /* base init */ + (GBaseFinalizeFunc) NULL, /* base finalize */ + (GClassInitFunc) ea_calendar_cell_class_init, /* class init */ + (GClassFinalizeFunc) NULL, /* class finalize */ + NULL, /* class data */ + sizeof (EaCalendarCell), /* instance size */ + 0, /* nb preallocs */ + (GInstanceInitFunc) ea_calendar_cell_init, /* instance init */ + NULL /* value table */ + }; + + static const GInterfaceInfo atk_component_info = { + (GInterfaceInitFunc) atk_component_interface_init, + (GInterfaceFinalizeFunc) NULL, + NULL + }; + + type = g_type_register_static (ATK_TYPE_GOBJECT_ACCESSIBLE, + "EaCalendarCell", &tinfo, 0); + g_type_add_interface_static (type, ATK_TYPE_COMPONENT, + &atk_component_info); + } + + return type; +} + +static void +ea_calendar_cell_class_init (EaCalendarCellClass *klass) +{ + AtkObjectClass *class = ATK_OBJECT_CLASS (klass); + +#ifdef ACC_DEBUG + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + gobject_class->finalize = ea_calendar_cell_finalize; +#endif + + parent_class = g_type_class_peek_parent (klass); + + class->get_name = ea_calendar_cell_get_name; + class->get_description = ea_calendar_cell_get_description; + + class->get_parent = ea_calendar_cell_get_parent; + class->get_index_in_parent = ea_calendar_cell_get_index_in_parent; + class->ref_state_set = ea_calendar_cell_ref_state_set; +} + +static void +ea_calendar_cell_init (EaCalendarCell *a11y) +{ + a11y->state_set = atk_state_set_new (); + atk_state_set_add_state (a11y->state_set, ATK_STATE_TRANSIENT); + atk_state_set_add_state (a11y->state_set, ATK_STATE_ENABLED); + atk_state_set_add_state (a11y->state_set, ATK_STATE_SENSITIVE); + atk_state_set_add_state (a11y->state_set, ATK_STATE_SELECTABLE); + atk_state_set_add_state (a11y->state_set, ATK_STATE_SHOWING); + atk_state_set_add_state (a11y->state_set, ATK_STATE_FOCUSABLE); +} + +AtkObject* +ea_calendar_cell_new (GObject *obj) +{ + gpointer object; + AtkObject *atk_object; + + g_return_val_if_fail (E_IS_CALENDAR_CELL (obj), NULL); + object = g_object_new (EA_TYPE_CALENDAR_CELL, NULL); + atk_object = ATK_OBJECT (object); + atk_object_initialize (atk_object, obj); + atk_object->role = ATK_ROLE_TABLE_CELL; + +#ifdef ACC_DEBUG + ++n_ea_calendar_cell_created; + g_print ("ACC_DEBUG: n_ea_calendar_cell_created = %d\n", + n_ea_calendar_cell_created); +#endif + return atk_object; +} + +#ifdef ACC_DEBUG +static void ea_calendar_cell_finalize (GObject *object) +{ + G_OBJECT_CLASS (parent_class)->finalize (object); + + ++n_ea_calendar_cell_destroyed; + g_print ("ACC_DEBUG: n_ea_calendar_cell_destroyed = %d\n", + n_ea_calendar_cell_destroyed); +} +#endif + +static G_CONST_RETURN gchar* +ea_calendar_cell_get_name (AtkObject *accessible) +{ + GObject *g_obj; + + g_return_val_if_fail (EA_IS_CALENDAR_CELL (accessible), NULL); + + g_obj = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE(accessible)); + if (!g_obj) + /* defunct object*/ + return NULL; + + if (!accessible->name) { + AtkObject *atk_obj; + EaCalendarItem *ea_calitem; + ECalendarCell *cell; + gint day_index; + gint year, month, day; + gchar buffer[128]; + + cell = E_CALENDAR_CELL (g_obj); + atk_obj = ea_calendar_cell_get_parent (accessible); + ea_calitem = EA_CALENDAR_ITEM (atk_obj); + day_index = atk_table_get_index_at (ATK_TABLE (ea_calitem), + cell->row, cell->column); + e_calendar_item_get_date_for_offset (cell->calitem, day_index, + &year, &month, &day); + + g_snprintf (buffer, 128, "%d-%d-%d", year, month + 1, day); + ATK_OBJECT_CLASS (parent_class)->set_name (accessible, buffer); + } + return accessible->name; +} + +static G_CONST_RETURN gchar* +ea_calendar_cell_get_description (AtkObject *accessible) +{ + return ea_calendar_cell_get_name (accessible); +} + +static AtkObject * +ea_calendar_cell_get_parent (AtkObject *accessible) +{ + GObject *g_obj; + ECalendarCell *cell; + ECalendarItem *calitem; + + g_return_val_if_fail (EA_IS_CALENDAR_CELL (accessible), NULL); + + g_obj = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE(accessible)); + if (!g_obj) + /* defunct object*/ + return NULL; + + cell = E_CALENDAR_CELL (g_obj); + calitem = cell->calitem; + return atk_gobject_accessible_for_object (G_OBJECT (calitem)); +} + +static gint +ea_calendar_cell_get_index_in_parent (AtkObject *accessible) +{ + GObject *g_obj; + ECalendarCell *cell; + AtkObject *parent; + + g_return_val_if_fail (EA_IS_CALENDAR_CELL (accessible), -1); + + g_obj = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE(accessible)); + if (!g_obj) + return -1; + cell = E_CALENDAR_CELL (g_obj); + parent = atk_object_get_parent (accessible); + return atk_table_get_index_at (ATK_TABLE (parent), + cell->row, cell->column); +} + +static AtkStateSet * +ea_calendar_cell_ref_state_set (AtkObject *accessible) +{ + EaCalendarCell *atk_cell = EA_CALENDAR_CELL (accessible); + + g_return_val_if_fail (atk_cell->state_set, NULL); + + g_object_ref(atk_cell->state_set); + + return atk_cell->state_set; + +} + +/* Atk Component Interface */ + +static void +atk_component_interface_init (AtkComponentIface *iface) +{ + g_return_if_fail (iface != NULL); + + iface->get_extents = component_interface_get_extents; + iface->grab_focus = component_interface_grab_focus; +} + +static void +component_interface_get_extents (AtkComponent *component, + gint *x, gint *y, gint *width, gint *height, + AtkCoordType coord_type) +{ + GObject *g_obj; + AtkObject *atk_obj, *atk_canvas; + ECalendarCell *cell; + ECalendarItem *calitem; + EaCalendarItem *ea_calitem; + gint day_index; + gint year, month, day; + gint canvas_x, canvas_y, canvas_width, canvas_height; + + *x = *y = *width = *height = 0; + + g_return_if_fail (EA_IS_CALENDAR_CELL (component)); + + + g_obj = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE(component)); + if (!g_obj) + /* defunct object*/ + return; + + cell = E_CALENDAR_CELL (g_obj); + calitem = cell->calitem; + atk_obj = atk_gobject_accessible_for_object (G_OBJECT (calitem)); + ea_calitem = EA_CALENDAR_ITEM (atk_obj); + day_index = atk_table_get_index_at (ATK_TABLE (ea_calitem), + cell->row, cell->column); + e_calendar_item_get_date_for_offset (calitem, day_index, + &year, &month, &day); + + if (!e_calendar_item_get_day_extents (calitem, + year, month, day, + x, y, width, height)) + return; + atk_canvas = atk_object_get_parent (ATK_OBJECT (ea_calitem)); + atk_component_get_extents (ATK_COMPONENT (atk_canvas), + &canvas_x, &canvas_y, + &canvas_width, &canvas_height, + coord_type); + *x += canvas_x; + *y += canvas_y; +} + +static gboolean +component_interface_grab_focus (AtkComponent *component) +{ + GObject *g_obj; + GtkWidget *toplevel; + AtkObject *ea_calitem; + ECalendarItem *calitem; + EaCalendarCell *a11y; + gint index; + + a11y = EA_CALENDAR_CELL (component); + ea_calitem = ea_calendar_cell_get_parent (ATK_OBJECT (a11y)); + + g_obj = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE(ea_calitem)); + calitem = E_CALENDAR_ITEM (g_obj); + + index = atk_object_get_index_in_parent (ATK_OBJECT (a11y)); + + atk_selection_clear_selection (ATK_SELECTION (ea_calitem)); + atk_selection_add_selection (ATK_SELECTION (ea_calitem), index); + + gtk_widget_grab_focus (GTK_WIDGET (GNOME_CANVAS_ITEM (calitem)->canvas)); + toplevel = gtk_widget_get_toplevel (GTK_WIDGET (GNOME_CANVAS_ITEM (calitem)->canvas)); + if (toplevel && GTK_WIDGET_TOPLEVEL (toplevel)) + gtk_window_present (GTK_WINDOW (toplevel)); + + return TRUE; + +} diff --git a/widgets/misc/a11y/ea-calendar-cell.h b/widgets/misc/a11y/ea-calendar-cell.h new file mode 100644 index 0000000000..a07b7e8bbc --- /dev/null +++ b/widgets/misc/a11y/ea-calendar-cell.h @@ -0,0 +1,90 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Authors: + * Bolian Yin <bolian.yin@sun.com> + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef __EA_CALENDAR_CELL_H__ +#define __EA_CALENDAR_CELL_H__ + +#include <atk/atkgobjectaccessible.h> +#include "misc/e-calendar-item.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#define E_TYPE_CALENDAR_CELL (e_calendar_cell_get_type ()) +#define E_CALENDAR_CELL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), E_TYPE_CALENDAR_CELL, ECalendarCell)) +#define E_CALENDAR_CELL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), E_TYPE_CALENDAR_CELL, ECalendarCellClass)) +#define E_IS_CALENDAR_CELL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), E_TYPE_CALENDAR_CELL)) +#define E_IS_CALENDAR_CELL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), E_TYPE_CALENDAR_CELL)) +#define E_CALENDAR_CELL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), E_TYPE_CALENDAR_CELL, ECalendarCellClass)) + +typedef struct _ECalendarCell ECalendarCell; +typedef struct _ECalendarCellClass ECalendarCellClass; + +struct _ECalendarCell +{ + GObject parent; + ECalendarItem *calitem; + gint row; + gint column; +}; + +GType e_calendar_cell_get_type (void); + +struct _ECalendarCellClass +{ + GObjectClass parent_class; +}; + +ECalendarCell * e_calendar_cell_new (ECalendarItem *calitem, + gint row, gint column); + +#define EA_TYPE_CALENDAR_CELL (ea_calendar_cell_get_type ()) +#define EA_CALENDAR_CELL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EA_TYPE_CALENDAR_CELL, EaCalendarCell)) +#define EA_CALENDAR_CELL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EA_TYPE_CALENDAR_CELL, EaCalendarCellClass)) +#define EA_IS_CALENDAR_CELL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EA_TYPE_CALENDAR_CELL)) +#define EA_IS_CALENDAR_CELL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EA_TYPE_CALENDAR_CELL)) +#define EA_CALENDAR_CELL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EA_TYPE_CALENDAR_CELL, EaCalendarCellClass)) + +typedef struct _EaCalendarCell EaCalendarCell; +typedef struct _EaCalendarCellClass EaCalendarCellClass; + +struct _EaCalendarCell +{ + AtkGObjectAccessible parent; + AtkStateSet *state_set; +}; + +GType ea_calendar_cell_get_type (void); + +struct _EaCalendarCellClass +{ + AtkGObjectAccessibleClass parent_class; +}; + +AtkObject* ea_calendar_cell_new (GObject *gobj); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __EA_CALENDAR_CELL_H__ */ diff --git a/widgets/misc/a11y/ea-calendar-item.c b/widgets/misc/a11y/ea-calendar-item.c new file mode 100644 index 0000000000..66f40a92a0 --- /dev/null +++ b/widgets/misc/a11y/ea-calendar-item.c @@ -0,0 +1,1314 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Authors: + * Bolian Yin <bolian.yin@sun.com> + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include <stdio.h> +#include <time.h> +#include <string.h> +#include <libgnomecanvas/gnome-canvas.h> +#include <glib.h> +#include <e-util/e-util.h> +#include <glib/gi18n.h> +#include <libedataserver/e-data-server-util.h> +#include "ea-calendar-item.h" +#include "ea-calendar-cell.h" +#include "a11y/ea-cell-table.h" + +#define EA_CALENDAR_COLUMN_NUM E_CALENDAR_COLS_PER_MONTH + +/* EaCalendarItem */ +static void ea_calendar_item_class_init (EaCalendarItemClass *klass); +static void ea_calendar_item_finalize (GObject *object); + +static G_CONST_RETURN gchar* ea_calendar_item_get_name (AtkObject *accessible); +static G_CONST_RETURN gchar* ea_calendar_item_get_description (AtkObject *accessible); +static gint ea_calendar_item_get_n_children (AtkObject *accessible); +static AtkObject *ea_calendar_item_ref_child (AtkObject *accessible, gint index); +static AtkStateSet* ea_calendar_item_ref_state_set (AtkObject *accessible); + +/* atk table interface */ +static void atk_table_interface_init (AtkTableIface *iface); +static gint table_interface_get_index_at (AtkTable *table, + gint row, + gint column); +static gint table_interface_get_column_at_index (AtkTable *table, + gint index); +static gint table_interface_get_row_at_index (AtkTable *table, + gint index); +static AtkObject* table_interface_ref_at (AtkTable *table, + gint row, + gint column); +static gint table_interface_get_n_rows (AtkTable *table); +static gint table_interface_get_n_columns (AtkTable *table); +static gint table_interface_get_column_extent_at (AtkTable *table, + gint row, + gint column); +static gint table_interface_get_row_extent_at (AtkTable *table, + gint row, + gint column); + +static gboolean table_interface_is_row_selected (AtkTable *table, + gint row); +static gboolean table_interface_is_column_selected (AtkTable *table, + gint row); +static gboolean table_interface_is_selected (AtkTable *table, + gint row, + gint column); +static gint table_interface_get_selected_rows (AtkTable *table, + gint **rows_selected); +static gint table_interface_get_selected_columns (AtkTable *table, + gint **columns_selected); +static gboolean table_interface_add_row_selection (AtkTable *table, gint row); +static gboolean table_interface_remove_row_selection (AtkTable *table, + gint row); +static gboolean table_interface_add_column_selection (AtkTable *table, + gint column); +static gboolean table_interface_remove_column_selection (AtkTable *table, + gint column); +static AtkObject* table_interface_get_row_header (AtkTable *table, gint row); +static AtkObject* table_interface_get_column_header (AtkTable *table, + gint in_col); +static AtkObject* table_interface_get_caption (AtkTable *table); + +static G_CONST_RETURN gchar* +table_interface_get_column_description (AtkTable *table, gint in_col); + +static G_CONST_RETURN gchar* +table_interface_get_row_description (AtkTable *table, gint row); + +static AtkObject* table_interface_get_summary (AtkTable *table); + +/* atk selection interface */ +static void atk_selection_interface_init (AtkSelectionIface *iface); +static gboolean selection_interface_add_selection (AtkSelection *selection, + gint i); +static gboolean selection_interface_clear_selection (AtkSelection *selection); +static AtkObject* selection_interface_ref_selection (AtkSelection *selection, + gint i); +static gint selection_interface_get_selection_count (AtkSelection *selection); +static gboolean selection_interface_is_child_selected (AtkSelection *selection, + gint i); + +/* callbacks */ +static void selection_preview_change_cb (ECalendarItem *calitem); +static void date_range_changed_cb (ECalendarItem *calitem); + +/* helpers */ +static EaCellTable *ea_calendar_item_get_cell_data (EaCalendarItem *ea_calitem); +static void ea_calendar_item_destory_cell_data (EaCalendarItem *ea_calitem); +static gboolean ea_calendar_item_get_column_label (EaCalendarItem *ea_calitem, + gint column, + gchar *buffer, + gint buffer_size); +static gboolean ea_calendar_item_get_row_label (EaCalendarItem *ea_calitem, + gint row, + gchar *buffer, + gint buffer_size); +static gboolean e_calendar_item_get_offset_for_date (ECalendarItem *calitem, + gint year, gint month, gint day, + gint *offset); +static void ea_calendar_set_focus_object (EaCalendarItem *ea_calitem, + AtkObject *item_cell); + +#ifdef ACC_DEBUG +static gint n_ea_calendar_item_created = 0; +static gint n_ea_calendar_item_destroyed = 0; +#endif + +static gpointer parent_class = NULL; + +GType +ea_calendar_item_get_type (void) +{ + static GType type = 0; + AtkObjectFactory *factory; + GTypeQuery query; + GType derived_atk_type; + + if (!type) { + static GTypeInfo tinfo = { + sizeof (EaCalendarItemClass), + (GBaseInitFunc) NULL, /* base init */ + (GBaseFinalizeFunc) NULL, /* base finalize */ + (GClassInitFunc) ea_calendar_item_class_init, /* class init */ + (GClassFinalizeFunc) NULL, /* class finalize */ + NULL, /* class data */ + sizeof (EaCalendarItem), /* instance size */ + 0, /* nb preallocs */ + (GInstanceInitFunc) NULL, /* instance init */ + NULL /* value table */ + }; + + static const GInterfaceInfo atk_table_info = { + (GInterfaceInitFunc) atk_table_interface_init, + (GInterfaceFinalizeFunc) NULL, + NULL + }; + static const GInterfaceInfo atk_selection_info = { + (GInterfaceInitFunc) atk_selection_interface_init, + (GInterfaceFinalizeFunc) NULL, + NULL + }; + + /* + * Figure out the size of the class and instance + * we are run-time deriving from (GailCanvasItem, in this case) + */ + + factory = atk_registry_get_factory (atk_get_default_registry (), + GNOME_TYPE_CANVAS_ITEM); + derived_atk_type = atk_object_factory_get_accessible_type (factory); + g_type_query (derived_atk_type, &query); + + tinfo.class_size = query.class_size; + tinfo.instance_size = query.instance_size; + + type = g_type_register_static (derived_atk_type, + "EaCalendarItem", &tinfo, 0); + g_type_add_interface_static (type, ATK_TYPE_TABLE, + &atk_table_info); + g_type_add_interface_static (type, ATK_TYPE_SELECTION, + &atk_selection_info); + } + + return type; +} + +static void +ea_calendar_item_class_init (EaCalendarItemClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + AtkObjectClass *class = ATK_OBJECT_CLASS (klass); + + gobject_class->finalize = ea_calendar_item_finalize; + parent_class = g_type_class_peek_parent (klass); + + class->get_name = ea_calendar_item_get_name; + class->get_description = ea_calendar_item_get_description; + class->ref_state_set = ea_calendar_item_ref_state_set; + + class->get_n_children = ea_calendar_item_get_n_children; + class->ref_child = ea_calendar_item_ref_child; +} + +AtkObject* +ea_calendar_item_new (GObject *obj) +{ + gpointer object; + AtkObject *atk_object; + AtkObject *item_cell; + + g_return_val_if_fail (E_IS_CALENDAR_ITEM (obj), NULL); + object = g_object_new (EA_TYPE_CALENDAR_ITEM, NULL); + atk_object = ATK_OBJECT (object); + atk_object_initialize (atk_object, obj); + atk_object->role = ATK_ROLE_CALENDAR; + + item_cell = atk_selection_ref_selection (ATK_SELECTION (atk_object), + 0); + if (item_cell) + ea_calendar_set_focus_object (EA_CALENDAR_ITEM (atk_object), item_cell); + +#ifdef ACC_DEBUG + ++n_ea_calendar_item_created; + g_print ("ACC_DEBUG: n_ea_calendar_item_created = %d\n", + n_ea_calendar_item_created); +#endif + /* connect signal handlers */ + g_signal_connect (obj, "selection_preview_changed", + G_CALLBACK (selection_preview_change_cb), + atk_object); + g_signal_connect (obj, "date_range_changed", + G_CALLBACK (date_range_changed_cb), + atk_object); + + return atk_object; +} + +static void +ea_calendar_item_finalize (GObject *object) +{ + EaCalendarItem *ea_calitem; + + g_return_if_fail (EA_IS_CALENDAR_ITEM (object)); + + ea_calitem = EA_CALENDAR_ITEM (object); + + /* Free the allocated cell data */ + ea_calendar_item_destory_cell_data (ea_calitem); + + G_OBJECT_CLASS (parent_class)->finalize (object); +#ifdef ACC_DEBUG + ++n_ea_calendar_item_destroyed; + printf ("ACC_DEBUG: n_ea_calendar_item_destroyed = %d\n", + n_ea_calendar_item_destroyed); +#endif +} + +static G_CONST_RETURN gchar* +ea_calendar_item_get_name (AtkObject *accessible) +{ + GObject *g_obj; + ECalendarItem *calitem; + gint start_year, start_month, start_day; + gint end_year, end_month, end_day; + gchar *name_str = NULL; + gchar buffer_start[128] = ""; + gchar buffer_end[128] = ""; + struct tm day_start = { 0 }; + struct tm day_end = { 0 }; + + g_return_val_if_fail (EA_IS_CALENDAR_ITEM (accessible), NULL); + + g_obj = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE(accessible)); + if (!g_obj) + return NULL; + g_return_val_if_fail (E_IS_CALENDAR_ITEM (g_obj), NULL); + + calitem = E_CALENDAR_ITEM (g_obj); + if (e_calendar_item_get_date_range (calitem, + &start_year, &start_month, &start_day, + &end_year, &end_month, &end_day)) { + + day_start.tm_year = start_year - 1900; + day_start.tm_mon = start_month; + day_start.tm_mday = start_day; + day_start.tm_isdst = -1; + e_utf8_strftime (buffer_start, sizeof (buffer_start), _("%d %B %Y"), &day_start); + + day_end.tm_year = end_year - 1900; + day_end.tm_mon = end_month; + day_end.tm_mday = end_day; + day_end.tm_isdst = -1; + e_utf8_strftime (buffer_end, sizeof (buffer_end), _("%d %B %Y"), &day_end); + + name_str = g_strdup_printf (_("Calendar: from %s to %s"), buffer_start, buffer_end); + } + +#if 0 + if (e_calendar_item_get_selection (calitem, &select_start, &select_end)) { + GDate select_start, select_end; + gint year1, year2, month1, month2, day1, day2; + + year1 = g_date_get_year (&select_start); + month1 = g_date_get_month (&select_start); + day1 = g_date_get_day (&select_start); + + year2 = g_date_get_year (&select_end); + month2 = g_date_get_month (&select_end); + day2 = g_date_get_day (&select_end); + + sprintf (new_name + strlen (new_name), + " : current selection: from %d-%d-%d to %d-%d-%d.", + year1, month1, day1, + year2, month2, day2); + } +#endif + + ATK_OBJECT_CLASS (parent_class)->set_name (accessible, name_str); + g_free (name_str); + + return accessible->name; +} + +static G_CONST_RETURN gchar* +ea_calendar_item_get_description (AtkObject *accessible) +{ + if (accessible->description) + return accessible->description; + + return _("evolution calendar item"); +} + +static AtkStateSet* +ea_calendar_item_ref_state_set (AtkObject *accessible) +{ + AtkStateSet *state_set; + GObject *g_obj; + + state_set = ATK_OBJECT_CLASS (parent_class)->ref_state_set (accessible); + g_obj = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE(accessible)); + if (!g_obj) + return state_set; + + atk_state_set_add_state (state_set, ATK_STATE_ENABLED); + atk_state_set_add_state (state_set, ATK_STATE_SENSITIVE); + + return state_set; +} + +static gint +ea_calendar_item_get_n_children (AtkObject *accessible) +{ + AtkGObjectAccessible *atk_gobj; + GObject *g_obj; + ECalendarItem *calitem; + gint n_children = 0; + gint start_year, start_month, start_day; + gint end_year, end_month, end_day; + GDate *start_date, *end_date; + + g_return_val_if_fail (EA_IS_CALENDAR_ITEM (accessible), -1); + + atk_gobj = ATK_GOBJECT_ACCESSIBLE (accessible); + g_obj = atk_gobject_accessible_get_object (atk_gobj); + if (!g_obj) + return -1; + + calitem = E_CALENDAR_ITEM (g_obj); + if (!e_calendar_item_get_date_range (calitem, &start_year, + &start_month, &start_day, + &end_year, &end_month, + &end_day)) + return 0; + + start_date = g_date_new_dmy (start_day, start_month + 1, start_year); + end_date = g_date_new_dmy (end_day, end_month + 1, end_year); + + n_children = g_date_days_between (start_date, end_date) + 1; + g_free (start_date); + g_free (end_date); + return n_children; +} + +static AtkObject * +ea_calendar_item_ref_child (AtkObject *accessible, gint index) +{ + AtkGObjectAccessible *atk_gobj; + GObject *g_obj; + ECalendarItem *calitem; + gint n_children; + ECalendarCell *cell; + EaCellTable *cell_data; + EaCalendarItem *ea_calitem; + + g_return_val_if_fail (EA_IS_CALENDAR_ITEM (accessible), NULL); + + atk_gobj = ATK_GOBJECT_ACCESSIBLE (accessible); + g_obj = atk_gobject_accessible_get_object (atk_gobj); + if (!g_obj) + return NULL; + + calitem = E_CALENDAR_ITEM (g_obj); + + n_children = ea_calendar_item_get_n_children (accessible); + if (index < 0 || index >= n_children) + return NULL; + + ea_calitem = EA_CALENDAR_ITEM (accessible); + cell_data = ea_calendar_item_get_cell_data (ea_calitem); + if (!cell_data) + return NULL; + + cell = ea_cell_table_get_cell_at_index (cell_data, index); + if (!cell) { + cell = e_calendar_cell_new (calitem, + index / EA_CALENDAR_COLUMN_NUM, + index % EA_CALENDAR_COLUMN_NUM); + ea_cell_table_set_cell_at_index (cell_data, index, cell); + g_object_unref (cell); + } + +#ifdef ACC_DEBUG + g_print ("AccDebug: ea_calendar_item children[%d]=%p\n", index, + (gpointer)cell); +#endif + return g_object_ref (atk_gobject_accessible_for_object (G_OBJECT(cell))); +} + +/* atk table interface */ + +static void +atk_table_interface_init (AtkTableIface *iface) +{ + g_return_if_fail (iface != NULL); + + iface->ref_at = table_interface_ref_at; + + iface->get_n_rows = table_interface_get_n_rows; + iface->get_n_columns = table_interface_get_n_columns; + iface->get_index_at = table_interface_get_index_at; + iface->get_column_at_index = table_interface_get_column_at_index; + iface->get_row_at_index = table_interface_get_row_at_index; + iface->get_column_extent_at = table_interface_get_column_extent_at; + iface->get_row_extent_at = table_interface_get_row_extent_at; + + iface->is_selected = table_interface_is_selected; + iface->get_selected_rows = table_interface_get_selected_rows; + iface->get_selected_columns = table_interface_get_selected_columns; + iface->is_row_selected = table_interface_is_row_selected; + iface->is_column_selected = table_interface_is_column_selected; + iface->add_row_selection = table_interface_add_row_selection; + iface->remove_row_selection = table_interface_remove_row_selection; + iface->add_column_selection = table_interface_add_column_selection; + iface->remove_column_selection = table_interface_remove_column_selection; + + iface->get_row_header = table_interface_get_row_header; + iface->get_column_header = table_interface_get_column_header; + iface->get_caption = table_interface_get_caption; + iface->get_summary = table_interface_get_summary; + iface->get_row_description = table_interface_get_row_description; + iface->get_column_description = table_interface_get_column_description; +} + +static AtkObject* +table_interface_ref_at (AtkTable *table, + gint row, + gint column) +{ + gint index; + + EaCalendarItem* ea_calitem = EA_CALENDAR_ITEM (table); + index = EA_CALENDAR_COLUMN_NUM * row + column; + return ea_calendar_item_ref_child (ATK_OBJECT (ea_calitem), index); +} + +static gint +table_interface_get_n_rows (AtkTable *table) +{ + AtkGObjectAccessible *atk_gobj; + GObject *g_obj; + EaCalendarItem* ea_calitem = EA_CALENDAR_ITEM (table); + gint n_children; + + atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_calitem); + g_obj = atk_gobject_accessible_get_object (atk_gobj); + if (!g_obj) + return -1; + + n_children = ea_calendar_item_get_n_children (ATK_OBJECT (ea_calitem)); + return (n_children - 1) / EA_CALENDAR_COLUMN_NUM + 1; +} + +static gint +table_interface_get_n_columns (AtkTable *table) +{ + AtkGObjectAccessible *atk_gobj; + GObject *g_obj; + EaCalendarItem* ea_calitem = EA_CALENDAR_ITEM (table); + + atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_calitem); + g_obj = atk_gobject_accessible_get_object (atk_gobj); + if (!g_obj) + return -1; + + return EA_CALENDAR_COLUMN_NUM; +} + +static gint +table_interface_get_index_at (AtkTable *table, + gint row, + gint column) +{ + AtkGObjectAccessible *atk_gobj; + GObject *g_obj; + EaCalendarItem* ea_calitem = EA_CALENDAR_ITEM (table); + + atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_calitem); + g_obj = atk_gobject_accessible_get_object (atk_gobj); + if (!g_obj) + return -1; + + return row * EA_CALENDAR_COLUMN_NUM + column; +} + +static gint +table_interface_get_column_at_index (AtkTable *table, + gint index) +{ + AtkGObjectAccessible *atk_gobj; + GObject *g_obj; + EaCalendarItem* ea_calitem = EA_CALENDAR_ITEM (table); + gint n_children; + + atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_calitem); + g_obj = atk_gobject_accessible_get_object (atk_gobj); + if (!g_obj) + return -1; + + n_children = ea_calendar_item_get_n_children (ATK_OBJECT (ea_calitem)); + if (index >= 0 && index < n_children) + return index % EA_CALENDAR_COLUMN_NUM; + return -1; +} + +static gint +table_interface_get_row_at_index (AtkTable *table, + gint index) +{ + AtkGObjectAccessible *atk_gobj; + GObject *g_obj; + EaCalendarItem* ea_calitem = EA_CALENDAR_ITEM (table); + gint n_children; + + atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_calitem); + g_obj = atk_gobject_accessible_get_object (atk_gobj); + if (!g_obj) + return -1; + + n_children = ea_calendar_item_get_n_children (ATK_OBJECT (ea_calitem)); + if (index >= 0 && index < n_children) + return index / EA_CALENDAR_COLUMN_NUM; + return -1; +} + +static gint +table_interface_get_column_extent_at (AtkTable *table, + gint row, + gint column) +{ + AtkGObjectAccessible *atk_gobj; + GObject *g_obj; + ECalendarItem *calitem; + EaCalendarItem* ea_calitem = EA_CALENDAR_ITEM (table); + + atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_calitem); + g_obj = atk_gobject_accessible_get_object (atk_gobj); + if (!g_obj) + return FALSE; + + calitem = E_CALENDAR_ITEM (g_obj); + return calitem->cell_width; +} + +static gint +table_interface_get_row_extent_at (AtkTable *table, + gint row, gint column) +{ + AtkGObjectAccessible *atk_gobj; + GObject *g_obj; + ECalendarItem *calitem; + EaCalendarItem* ea_calitem = EA_CALENDAR_ITEM (table); + + atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_calitem); + g_obj = atk_gobject_accessible_get_object (atk_gobj); + if (!g_obj) + return FALSE; + + calitem = E_CALENDAR_ITEM (g_obj); + return calitem->cell_height; +} + +/* any day in the row is selected, the row is selected */ +static gboolean +table_interface_is_row_selected (AtkTable *table, + gint row) +{ + AtkGObjectAccessible *atk_gobj; + GObject *g_obj; + gint n_rows; + ECalendarItem *calitem; + gint row_index_start, row_index_end; + gint sel_index_start, sel_index_end; + + GDate start_date, end_date; + + g_return_val_if_fail (EA_IS_CALENDAR_ITEM (table), FALSE); + + atk_gobj = ATK_GOBJECT_ACCESSIBLE (table); + g_obj = atk_gobject_accessible_get_object (atk_gobj); + if (!g_obj) + return FALSE; + + n_rows = table_interface_get_n_rows (table); + if (row < 0 || row >= n_rows) + return FALSE; + + row_index_start = row * EA_CALENDAR_COLUMN_NUM; + row_index_end = row_index_start + EA_CALENDAR_COLUMN_NUM - 1; + + calitem = E_CALENDAR_ITEM (g_obj); + if (!e_calendar_item_get_selection (calitem, &start_date, &end_date)) + return FALSE; + + e_calendar_item_get_offset_for_date (calitem, + g_date_get_year (&start_date), + g_date_get_month (&start_date), + g_date_get_day (&start_date), + &sel_index_start); + e_calendar_item_get_offset_for_date (calitem, + g_date_get_year (&end_date), + g_date_get_month (&end_date), + g_date_get_day (&end_date), + &sel_index_end); + + if ((sel_index_start < row_index_start && + sel_index_end >= row_index_start) || + (sel_index_start >= row_index_start && + sel_index_start <= row_index_end)) + return TRUE; + return FALSE; +} + +static gboolean +table_interface_is_selected (AtkTable *table, + gint row, + gint column) +{ + AtkGObjectAccessible *atk_gobj; + GObject *g_obj; + gint n_rows, n_columns; + ECalendarItem *calitem; + gint index; + gint sel_index_start, sel_index_end; + + GDate start_date, end_date; + + g_return_val_if_fail (EA_IS_CALENDAR_ITEM (table), FALSE); + + atk_gobj = ATK_GOBJECT_ACCESSIBLE (table); + g_obj = atk_gobject_accessible_get_object (atk_gobj); + if (!g_obj) + return FALSE; + + n_rows = table_interface_get_n_rows (table); + if (row < 0 || row >= n_rows) + return FALSE; + n_columns = table_interface_get_n_columns (table); + if (column < 0 || column >= n_columns) + return FALSE; + + index = table_interface_get_index_at (table, row, column); + + calitem = E_CALENDAR_ITEM (g_obj); + if (!e_calendar_item_get_selection (calitem, &start_date, &end_date)) + return FALSE; + + e_calendar_item_get_offset_for_date (calitem, + g_date_get_year (&start_date), + g_date_get_month (&start_date), + g_date_get_day (&start_date), + &sel_index_start); + e_calendar_item_get_offset_for_date (calitem, + g_date_get_year (&end_date), + g_date_get_month (&end_date), + g_date_get_day (&end_date), &sel_index_end); + + if (sel_index_start <= index && sel_index_end >= index) + return TRUE; + return FALSE; +} + +static gboolean +table_interface_is_column_selected (AtkTable *table, + gint column) +{ + return FALSE; +} + +static gint +table_interface_get_selected_rows (AtkTable *table, + gint **rows_selected) +{ + *rows_selected = NULL; + return -1; +} + +static gint +table_interface_get_selected_columns (AtkTable *table, + gint **columns_selected) +{ + *columns_selected = NULL; + return -1; +} + +static gboolean +table_interface_add_row_selection (AtkTable *table, + gint row) +{ + return FALSE; +} + +static gboolean +table_interface_remove_row_selection (AtkTable *table, + gint row) +{ + return FALSE; +} + +static gboolean +table_interface_add_column_selection (AtkTable *table, + gint column) +{ + return FALSE; +} + +static gboolean +table_interface_remove_column_selection (AtkTable *table, + gint column) +{ + /* FIXME: NOT IMPLEMENTED */ + return FALSE; +} + +static AtkObject* +table_interface_get_row_header (AtkTable *table, + gint row) +{ + /* FIXME: NOT IMPLEMENTED */ + return NULL; +} + +static AtkObject* +table_interface_get_column_header (AtkTable *table, + gint in_col) +{ + /* FIXME: NOT IMPLEMENTED */ + return NULL; +} + +static AtkObject* +table_interface_get_caption (AtkTable *table) +{ + /* FIXME: NOT IMPLEMENTED */ + return NULL; +} + +static G_CONST_RETURN gchar* +table_interface_get_column_description (AtkTable *table, gint in_col) +{ + AtkGObjectAccessible *atk_gobj; + GObject *g_obj; + EaCalendarItem* ea_calitem = EA_CALENDAR_ITEM (table); + const gchar *description = NULL; + EaCellTable *cell_data; + gint n_columns; + + atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_calitem); + g_obj = atk_gobject_accessible_get_object (atk_gobj); + if (!g_obj) + return NULL; + + n_columns = table_interface_get_n_columns (table); + if (in_col < 0 || in_col >= n_columns) + return NULL; + cell_data = ea_calendar_item_get_cell_data (ea_calitem); + if (!cell_data) + return NULL; + + description = ea_cell_table_get_column_label (cell_data, in_col); + if (!description) { + gchar buffer[128] = "column description"; + ea_calendar_item_get_column_label (ea_calitem, in_col, + buffer, sizeof (buffer)); + ea_cell_table_set_column_label (cell_data, in_col, buffer); + description = ea_cell_table_get_column_label (cell_data, + in_col); + } + return description; +} + +static G_CONST_RETURN gchar* +table_interface_get_row_description (AtkTable *table, gint row) +{ + AtkGObjectAccessible *atk_gobj; + GObject *g_obj; + EaCalendarItem* ea_calitem = EA_CALENDAR_ITEM (table); + const gchar *description = NULL; + EaCellTable *cell_data; + gint n_rows; + + atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_calitem); + g_obj = atk_gobject_accessible_get_object (atk_gobj); + if (!g_obj) + return NULL; + + n_rows = table_interface_get_n_rows (table); + if (row < 0 || row >= n_rows) + return NULL; + cell_data = ea_calendar_item_get_cell_data (ea_calitem); + if (!cell_data) + return NULL; + + description = ea_cell_table_get_row_label (cell_data, row); + if (!description) { + gchar buffer[128] = "row description"; + ea_calendar_item_get_row_label (ea_calitem, row, + buffer, sizeof (buffer)); + ea_cell_table_set_row_label (cell_data, row, buffer); + description = ea_cell_table_get_row_label (cell_data, + row); + } + return description; +} + +static AtkObject* +table_interface_get_summary (AtkTable *table) +{ + /* FIXME: NOT IMPLEMENTED */ + return NULL; +} + +/* atkselection interface */ + +static void +atk_selection_interface_init (AtkSelectionIface *iface) +{ + g_return_if_fail (iface != NULL); + + iface->add_selection = selection_interface_add_selection; + iface->clear_selection = selection_interface_clear_selection; + iface->ref_selection = selection_interface_ref_selection; + iface->get_selection_count = selection_interface_get_selection_count; + iface->is_child_selected = selection_interface_is_child_selected; +} + +static gboolean +selection_interface_add_selection (AtkSelection *selection, gint index) +{ + AtkGObjectAccessible *atk_gobj; + GObject *g_obj; + ECalendarItem *calitem; + EaCalendarItem* ea_calitem = EA_CALENDAR_ITEM (selection); + gint year, month, day; + GDate start_date, end_date; + + atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_calitem); + g_obj = atk_gobject_accessible_get_object (atk_gobj); + if (!g_obj) + return FALSE; + + calitem = E_CALENDAR_ITEM (g_obj); + if (!e_calendar_item_get_date_for_offset (calitem, index, + &year, &month, &day)) + return FALSE; + + /* FIXME: not support mulit-selection */ + g_date_set_dmy (&start_date, day, month + 1, year); + end_date = start_date; + e_calendar_item_set_selection (calitem, &start_date, &end_date); + return TRUE; +} + +static gboolean +selection_interface_clear_selection (AtkSelection *selection) +{ + AtkGObjectAccessible *atk_gobj; + GObject *g_obj; + ECalendarItem *calitem; + EaCalendarItem* ea_calitem = EA_CALENDAR_ITEM (selection); + + atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_calitem); + g_obj = atk_gobject_accessible_get_object (atk_gobj); + if (!g_obj) + return FALSE; + + calitem = E_CALENDAR_ITEM (g_obj); + e_calendar_item_set_selection (calitem, NULL, NULL); + + return TRUE; +} + +static AtkObject* +selection_interface_ref_selection (AtkSelection *selection, gint i) +{ + GObject *g_obj; + ECalendarItem *calitem; + EaCalendarItem* ea_calitem = EA_CALENDAR_ITEM (selection); + gint count, sel_offset; + GDate start_date, end_date; + + count = selection_interface_get_selection_count (selection); + if (i < 0 || i >= count) + return NULL; + + g_obj = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (ea_calitem)); + + calitem = E_CALENDAR_ITEM (g_obj); + if (!e_calendar_item_get_selection (calitem, &start_date, &end_date)) + return NULL; + if (!e_calendar_item_get_offset_for_date (calitem, + g_date_get_year (&start_date), + g_date_get_month (&start_date) - 1, + g_date_get_day (&start_date), + &sel_offset)) + return NULL; + + return ea_calendar_item_ref_child (ATK_OBJECT (selection), sel_offset + i); +} + +static gint +selection_interface_get_selection_count (AtkSelection *selection) +{ + AtkGObjectAccessible *atk_gobj; + GObject *g_obj; + ECalendarItem *calitem; + EaCalendarItem* ea_calitem = EA_CALENDAR_ITEM (selection); + GDate start_date, end_date; + + atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_calitem); + g_obj = atk_gobject_accessible_get_object (atk_gobj); + if (!g_obj) + return 0; + + calitem = E_CALENDAR_ITEM (g_obj); + if (e_calendar_item_get_selection (calitem, &start_date, &end_date)) + return g_date_days_between (&start_date, &end_date) + 1; + else + return 0; +} + +static gboolean +selection_interface_is_child_selected (AtkSelection *selection, gint index) +{ + AtkGObjectAccessible *atk_gobj; + GObject *g_obj; + EaCalendarItem* ea_calitem = EA_CALENDAR_ITEM (selection); + gint row, column, n_children; + + atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_calitem); + g_obj = atk_gobject_accessible_get_object (atk_gobj); + if (!g_obj) + return FALSE; + + n_children = atk_object_get_n_accessible_children (ATK_OBJECT (selection)); + if (index < 0 || index >= n_children) + return FALSE; + + row = index / EA_CALENDAR_COLUMN_NUM; + column = index % EA_CALENDAR_COLUMN_NUM; + + return table_interface_is_selected (ATK_TABLE (selection), row, column); +} + +/* callbacks */ + +static void +selection_preview_change_cb (ECalendarItem *calitem) +{ + AtkObject *atk_obj; + AtkObject *item_cell; + + g_return_if_fail (E_IS_CALENDAR_ITEM (calitem)); + atk_obj = atk_gobject_accessible_for_object (G_OBJECT (calitem)); + ea_calendar_item_destory_cell_data (EA_CALENDAR_ITEM (atk_obj)); + + /* only deal with the first selected child, for now */ + item_cell = atk_selection_ref_selection (ATK_SELECTION (atk_obj), + 0); + + if (item_cell) + ea_calendar_set_focus_object (EA_CALENDAR_ITEM (atk_obj), item_cell); + + g_signal_emit_by_name (atk_obj, + "active-descendant-changed", + item_cell); + g_signal_emit_by_name (atk_obj, "selection_changed"); +} + +static void +date_range_changed_cb (ECalendarItem *calitem) +{ + AtkObject *atk_obj; + AtkObject *item_cell; + + g_return_if_fail (E_IS_CALENDAR_ITEM (calitem)); + atk_obj = atk_gobject_accessible_for_object (G_OBJECT (calitem)); + ea_calendar_item_destory_cell_data (EA_CALENDAR_ITEM (atk_obj)); + + item_cell = atk_selection_ref_selection (ATK_SELECTION (atk_obj), + 0); + if (item_cell) + ea_calendar_set_focus_object (EA_CALENDAR_ITEM (atk_obj), item_cell); + + g_signal_emit_by_name (atk_obj, "model_changed"); +} + +/* helpers */ + +static EaCellTable * +ea_calendar_item_get_cell_data (EaCalendarItem *ea_calitem) +{ + AtkGObjectAccessible *atk_gobj; + GObject *g_obj; + EaCellTable *cell_data; + + g_return_val_if_fail (ea_calitem, NULL); + + atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_calitem); + g_obj = atk_gobject_accessible_get_object (atk_gobj); + if (!g_obj) + return NULL; + + cell_data = g_object_get_data (G_OBJECT(ea_calitem), + "ea-calendar-cell-table"); + + if (!cell_data) { + gint n_cells = ea_calendar_item_get_n_children (ATK_OBJECT(ea_calitem)); + cell_data = ea_cell_table_create (n_cells/EA_CALENDAR_COLUMN_NUM, + EA_CALENDAR_COLUMN_NUM, + FALSE); + g_object_set_data (G_OBJECT(ea_calitem), + "ea-calendar-cell-table", cell_data); + } + return cell_data; +} + +static void +ea_calendar_item_destory_cell_data (EaCalendarItem *ea_calitem) +{ + EaCellTable *cell_data; + + g_return_if_fail (ea_calitem); + + cell_data = g_object_get_data (G_OBJECT(ea_calitem), + "ea-calendar-cell-table"); + if (cell_data) { + g_object_set_data (G_OBJECT(ea_calitem), + "ea-calendar-cell-table", NULL); + ea_cell_table_destroy (cell_data); + } +} + +static gboolean +ea_calendar_item_get_row_label (EaCalendarItem *ea_calitem, gint row, + gchar *buffer, gint buffer_size) +{ + AtkGObjectAccessible *atk_gobj; + GObject *g_obj; + ECalendarItem *calitem; + gint index, week_num; + gint year, month, day; + + g_return_val_if_fail (ea_calitem, FALSE); + + atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_calitem); + g_obj = atk_gobject_accessible_get_object (atk_gobj); + if (!g_obj) + return FALSE; + + calitem = E_CALENDAR_ITEM (g_obj); + + index = atk_table_get_index_at (ATK_TABLE (ea_calitem), row, 0); + if (!e_calendar_item_get_date_for_offset (calitem, index, + &year, &month, &day)) + return FALSE; + + week_num = e_calendar_item_get_week_number (calitem, + day, month, year); + + g_snprintf (buffer, buffer_size, "week number : %d", week_num); + return TRUE; +} + +static gboolean +ea_calendar_item_get_column_label (EaCalendarItem *ea_calitem, gint column, + gchar *buffer, gint buffer_size) +{ + AtkGObjectAccessible *atk_gobj; + GObject *g_obj; + ECalendarItem *calitem; + const gchar *abbr_name; + + g_return_val_if_fail (ea_calitem, FALSE); + + atk_gobj = ATK_GOBJECT_ACCESSIBLE (ea_calitem); + g_obj = atk_gobject_accessible_get_object (atk_gobj); + if (!g_obj) + return FALSE; + + /* Columns are 0 = Monday ... 6 = Sunday */ + calitem = E_CALENDAR_ITEM (g_obj); + abbr_name = e_get_weekday_name (column + 1, TRUE); + g_strlcpy (buffer, abbr_name, buffer_size); + + return TRUE; +} + +/* the coordinate the e-calendar canvas coord */ +gboolean +e_calendar_item_get_day_extents (ECalendarItem *calitem, + gint year, gint month, gint date, + gint *x, gint *y, + gint *width, gint *height) +{ + GnomeCanvasItem *item; + GtkWidget *widget; + GtkStyle *style; + PangoFontDescription *font_desc; + PangoContext *pango_context; + PangoFontMetrics *font_metrics; + gint char_height, xthickness, ythickness, text_y; + gint new_year, new_month, num_months, months_offset; + gint month_x, month_y, month_cell_x, month_cell_y; + gint month_row, month_col; + gint day_row, day_col; + gint days_from_week_start; + + g_return_val_if_fail (E_IS_CALENDAR_ITEM (calitem), FALSE); + + item = GNOME_CANVAS_ITEM (calitem); + widget = GTK_WIDGET (item->canvas); + style = widget->style; + + /* Set up Pango prerequisites */ + font_desc = calitem->font_desc; + if (!font_desc) + font_desc = style->font_desc; + pango_context = gtk_widget_get_pango_context (widget); + font_metrics = pango_context_get_metrics (pango_context, font_desc, + pango_context_get_language (pango_context)); + + char_height = + PANGO_PIXELS (pango_font_metrics_get_ascent (font_metrics)) + + PANGO_PIXELS (pango_font_metrics_get_descent (font_metrics)); + + xthickness = style->xthickness; + ythickness = style->ythickness; + + new_year = year; + new_month = month; + e_calendar_item_normalize_date (calitem, &new_year, &new_month); + num_months = calitem->rows * calitem->cols; + months_offset = (new_year - calitem->year) * 12 + + new_month - calitem->month; + + if (months_offset > num_months || months_offset < 0) + return FALSE; + + month_row = months_offset / calitem->cols; + month_col = months_offset % calitem->cols; + + month_x = item->x1 + xthickness + calitem->x_offset + + month_col * calitem->month_width; + month_y = item->y1 + ythickness + month_row * calitem->month_height; + + month_cell_x = month_x + E_CALENDAR_ITEM_XPAD_BEFORE_WEEK_NUMBERS + + calitem->month_lpad + E_CALENDAR_ITEM_XPAD_BEFORE_CELLS; + text_y = month_y + ythickness * 2 + + E_CALENDAR_ITEM_YPAD_ABOVE_MONTH_NAME + + char_height + E_CALENDAR_ITEM_YPAD_BELOW_MONTH_NAME + + E_CALENDAR_ITEM_YPAD_ABOVE_DAY_LETTERS + calitem->month_tpad; + + month_cell_y = text_y + char_height + + E_CALENDAR_ITEM_YPAD_BELOW_DAY_LETTERS + 1 + + E_CALENDAR_ITEM_YPAD_ABOVE_CELLS; + + days_from_week_start = + e_calendar_item_get_n_days_from_week_start (calitem, new_year, + new_month); + day_row = (date + days_from_week_start - 1) / EA_CALENDAR_COLUMN_NUM; + day_col = (date + days_from_week_start - 1) % EA_CALENDAR_COLUMN_NUM; + + *x = month_cell_x + day_col * calitem->cell_width; + *y = month_cell_y + day_row * calitem->cell_height; + *width = calitem->cell_width; + *height = calitem->cell_height; + + return TRUE; +} + +/* month is from 0 to 11 */ +gboolean +e_calendar_item_get_date_for_offset (ECalendarItem *calitem, gint day_offset, + gint *year, gint *month, gint *day) +{ + gint start_year, start_month, start_day; + gint end_year, end_month, end_day; + GDate *start_date; + + g_return_val_if_fail (E_IS_CALENDAR_ITEM (calitem), FALSE); + + if (!e_calendar_item_get_date_range (calitem, &start_year, + &start_month, &start_day, + &end_year, &end_month, + &end_day)) + return FALSE; + + start_date = g_date_new_dmy (start_day, start_month + 1, start_year); + + g_date_add_days (start_date, day_offset); + + *year = g_date_get_year (start_date); + *month = g_date_get_month (start_date) - 1; + *day = g_date_get_day (start_date); + + return TRUE; +} + +/* the arg month is from 0 to 11 */ +static gboolean +e_calendar_item_get_offset_for_date (ECalendarItem *calitem, + gint year, gint month, gint day, + gint *offset) +{ + gint start_year, start_month, start_day; + gint end_year, end_month, end_day; + GDate *start_date, *end_date; + + *offset = 0; + g_return_val_if_fail (E_IS_CALENDAR_ITEM (calitem), FALSE); + + if (!e_calendar_item_get_date_range (calitem, &start_year, + &start_month, &start_day, + &end_year, &end_month, + &end_day)) + return FALSE; + + start_date = g_date_new_dmy (start_day, start_month + 1, start_year); + end_date = g_date_new_dmy (day, month + 1, year); + + *offset = g_date_days_between (start_date, end_date); + g_free (start_date); + g_free (end_date); + + return TRUE; +} + +gint +e_calendar_item_get_n_days_from_week_start (ECalendarItem *calitem, + gint year, gint month) +{ + struct tm tmp_tm; + gint start_weekday, days_from_week_start; + + memset (&tmp_tm, 0, sizeof (tmp_tm)); + tmp_tm.tm_year = year - 1900; + tmp_tm.tm_mon = month; + tmp_tm.tm_mday = 1; + tmp_tm.tm_isdst = -1; + mktime (&tmp_tm); + start_weekday = (tmp_tm.tm_wday + 6) % 7; /* 0 to 6 */ + days_from_week_start = (start_weekday + 7 - calitem->week_start_day) + % 7; + return days_from_week_start; +} + +static void +ea_calendar_set_focus_object (EaCalendarItem *ea_calitem, AtkObject *item_cell) +{ + AtkStateSet *state_set, *old_state_set; + AtkObject *old_cell; + + old_cell = (AtkObject *)g_object_get_data (G_OBJECT(ea_calitem), "gail-focus-object"); + if (old_cell && EA_IS_CALENDAR_CELL (old_cell)) { + old_state_set = atk_object_ref_state_set (old_cell); + atk_state_set_remove_state (old_state_set, ATK_STATE_FOCUSED); + g_object_unref (old_state_set); + } + if (old_cell) + g_object_unref (old_cell); + + state_set = atk_object_ref_state_set (item_cell); + atk_state_set_add_state (state_set, ATK_STATE_FOCUSED); + g_object_set_data (G_OBJECT(ea_calitem), "gail-focus-object", item_cell); + g_object_unref (state_set); +} diff --git a/widgets/misc/a11y/ea-calendar-item.h b/widgets/misc/a11y/ea-calendar-item.h new file mode 100644 index 0000000000..87b825b479 --- /dev/null +++ b/widgets/misc/a11y/ea-calendar-item.h @@ -0,0 +1,72 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Authors: + * Bolian Yin <bolian.yin@sun.com> + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef __EA_CALENDAR_ITEM_H__ +#define __EA_CALENDAR_ITEM_H__ + +#include <atk/atkgobjectaccessible.h> +#include <misc/e-calendar-item.h> + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#define EA_TYPE_CALENDAR_ITEM (ea_calendar_item_get_type ()) +#define EA_CALENDAR_ITEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EA_TYPE_CALENDAR_ITEM, EaCalendarItem)) +#define EA_CALENDAR_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EA_TYPE_CALENDAR_ITEM, EaCalendarItemClass)) +#define EA_IS_CALENDAR_ITEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EA_TYPE_CALENDAR_ITEM)) +#define EA_IS_CALENDAR_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EA_TYPE_CALENDAR_ITEM)) +#define EA_CALENDAR_ITEM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EA_TYPE_CALENDAR_ITEM, EaCalendarItemClass)) + +typedef struct _EaCalendarItem EaCalendarItem; +typedef struct _EaCalendarItemClass EaCalendarItemClass; + +struct _EaCalendarItem +{ + AtkGObjectAccessible parent; +}; + +GType ea_calendar_item_get_type (void); + +struct _EaCalendarItemClass +{ + AtkGObjectAccessibleClass parent_class; +}; + +AtkObject *ea_calendar_item_new (GObject *obj); +gboolean e_calendar_item_get_day_extents (ECalendarItem *calitem, + gint year, gint month, gint date, + gint *x, gint *y, + gint *width, gint *height); +gboolean e_calendar_item_get_date_for_offset (ECalendarItem *calitem, + gint day_offset, + gint *year, gint *month, + gint *day); +gint e_calendar_item_get_n_days_from_week_start (ECalendarItem *calitem, + gint year, gint month); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + + +#endif /* __EA_CALENDAR_ITEM_H__ */ diff --git a/widgets/misc/a11y/ea-widgets.c b/widgets/misc/a11y/ea-widgets.c new file mode 100644 index 0000000000..239299da0b --- /dev/null +++ b/widgets/misc/a11y/ea-widgets.c @@ -0,0 +1,32 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Authors: + * Bolian Yin <bolian.yin@sun.com> + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include "a11y/ea-factory.h" +#include "ea-calendar-item.h" +#include "ea-widgets.h" + +EA_FACTORY_GOBJECT (EA_TYPE_CALENDAR_ITEM, ea_calendar_item, ea_calendar_item_new) + +void e_calendar_item_a11y_init (void) +{ + EA_SET_FACTORY (e_calendar_item_get_type (), ea_calendar_item); +} diff --git a/widgets/misc/a11y/ea-widgets.h b/widgets/misc/a11y/ea-widgets.h new file mode 100644 index 0000000000..d19c908293 --- /dev/null +++ b/widgets/misc/a11y/ea-widgets.h @@ -0,0 +1,32 @@ +/* + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Authors: + * Bolian Yin <bolian.yin@sun.com> + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +/* Evolution Accessibility +*/ + +#ifndef _EA_WIDGETS_H__ +#define _EA_WIDGETS_H__ + +void e_calendar_item_a11y_init (void); + +#endif /* _EA_WIDGETS_H__ */ diff --git a/widgets/misc/e-calendar-item.c b/widgets/misc/e-calendar-item.c index 32e74dd535..d5f5efd462 100644 --- a/widgets/misc/e-calendar-item.c +++ b/widgets/misc/e-calendar-item.c @@ -26,7 +26,7 @@ #endif #include "e-calendar-item.h" -#include "ea-widgets.h" +#include "a11y/ea-widgets.h" #include <time.h> #include <string.h> diff --git a/widgets/misc/e-search-bar.c b/widgets/misc/e-search-bar.c index 050f840fa8..a588b73b0c 100644 --- a/widgets/misc/e-search-bar.c +++ b/widgets/misc/e-search-bar.c @@ -31,11 +31,11 @@ #include <glib/gi18n.h> #include <gdk/gdkkeysyms.h> #include <e-util/e-util.h> +#include <e-util/e-unicode.h> #include <e-action-combo-box.h> #include <e-gui-utils.h> #include <e-icon-entry.h> -#include <e-unicode.h> #define E_SEARCH_BAR_GET_PRIVATE(obj) \ (G_TYPE_INSTANCE_GET_PRIVATE \ diff --git a/widgets/misc/e-unicode.c b/widgets/misc/e-unicode.c deleted file mode 100644 index 9d660b6600..0000000000 --- a/widgets/misc/e-unicode.c +++ /dev/null @@ -1,2052 +0,0 @@ -/* - * e-unicode.c - utf-8 support functions for gal - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see <http://www.gnu.org/licenses/> - * - * - * Authors: - * Lauris Kaplinski <lauris@ximian.com> - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -/* - * TODO: Break simple ligatures in e_utf8_strstrcasedecomp - */ - -#include <config.h> - -#include <stdlib.h> -#include <string.h> -#include <stdio.h> -#include <ctype.h> -#include <iconv.h> -#ifdef HAVE_ALLOCA_H -#include <alloca.h> -#endif - -#include <gdk/gdkkeysyms.h> -#include <gtk/gtk.h> -#include <libxml/xmlmemory.h> - -#include <camel/camel-iconv.h> - -#include <glib/gi18n.h> -#include "e-unicode.h" - -#define d(x) - -#define FONT_TESTING -#define MAX_DECOMP 8 - -static gint e_canonical_decomposition (gunichar ch, gunichar * buf); -static gunichar e_stripped_char (gunichar ch); - -/* FIXME: this has not been ported fully yet - non ASCII people beware. */ - -/* - * This my favourite - * - * strstr doing case insensitive, decomposing search - * - * Lauris - */ - -const gchar * -e_utf8_strstrcasedecomp (const gchar *haystack, const gchar *needle) -{ - gunichar *nuni; - gunichar unival; - gint nlen; - const gchar *o, *p; - - if (haystack == NULL) return NULL; - if (needle == NULL) return NULL; - if (strlen (needle) == 0) return haystack; - if (strlen (haystack) == 0) return NULL; - - nuni = alloca (sizeof (gunichar) * strlen (needle)); - - nlen = 0; - for (p = e_unicode_get_utf8 (needle, &unival); p && unival; p = e_unicode_get_utf8 (p, &unival)) { - gint sc; - sc = e_stripped_char (unival); - if (sc) { - nuni[nlen++] = sc; - } - } - /* NULL means there was illegal utf-8 sequence */ - if (!p) return NULL; - /* If everything is correct, we have decomposed, lowercase, stripped needle */ - if (nlen < 1) return haystack; - - o = haystack; - for (p = e_unicode_get_utf8 (o, &unival); p && unival; p = e_unicode_get_utf8 (p, &unival)) { - gint sc; - sc = e_stripped_char (unival); - if (sc) { - /* We have valid stripped char */ - if (sc == nuni[0]) { - const gchar *q = p; - gint npos = 1; - while (npos < nlen) { - q = e_unicode_get_utf8 (q, &unival); - if (!q || !unival) return NULL; - sc = e_stripped_char (unival); - if ((!sc) || (sc != nuni[npos])) break; - npos++; - } - if (npos == nlen) { - return o; - } - } - } - o = p; - } - - return NULL; -} - -const gchar * -e_utf8_strstrcase (const gchar *haystack, const gchar *needle) -{ - gunichar *nuni; - gunichar unival; - gint nlen; - const gchar *o, *p; - - if (haystack == NULL) return NULL; - if (needle == NULL) return NULL; - if (strlen (needle) == 0) return haystack; - if (strlen (haystack) == 0) return NULL; - - nuni = alloca (sizeof (gunichar) * strlen (needle)); - - nlen = 0; - for (p = e_unicode_get_utf8 (needle, &unival); p && unival; p = e_unicode_get_utf8 (p, &unival)) { - nuni[nlen++] = g_unichar_tolower (unival); - } - /* NULL means there was illegal utf-8 sequence */ - if (!p) return NULL; - - o = haystack; - for (p = e_unicode_get_utf8 (o, &unival); p && unival; p = e_unicode_get_utf8 (p, &unival)) { - gint sc; - sc = g_unichar_tolower (unival); - /* We have valid stripped char */ - if (sc == nuni[0]) { - const gchar *q = p; - gint npos = 1; - while (npos < nlen) { - q = e_unicode_get_utf8 (q, &unival); - if (!q || !unival) return NULL; - sc = g_unichar_tolower (unival); - if (sc != nuni[npos]) break; - npos++; - } - if (npos == nlen) { - return o; - } - } - o = p; - } - - return NULL; -} - -#if 0 -const gchar * -e_utf8_strstrcase (const gchar *haystack, const gchar *needle) -{ - gchar *p; - gunichar *huni, *nuni; - gunichar unival; - gint hlen, nlen, hp, np; - - if (haystack == NULL) return NULL; - if (needle == NULL) return NULL; - if (strlen (needle) == 0) return haystack; - - huni = alloca (sizeof (gunichar) * strlen (haystack)); - - for (hlen = 0, p = e_unicode_get_utf8 (haystack, &unival); p && unival; hlen++, p = e_unicode_get_utf8 (p, &unival)) { - huni[hlen] = g_unichar_tolower (unival); - } - - if (!p) return NULL; - if (hlen == 0) return NULL; - - nuni = alloca (sizeof (gunichar) * strlen (needle)); - - for (nlen = 0, p = e_unicode_get_utf8 (needle, &unival); p && unival; nlen++, p = e_unicode_get_utf8 (p, &unival)) { - nuni[nlen] = g_unichar_tolower (unival); - } - - if (!p) return NULL; - if (nlen == 0) return NULL; - - if (hlen < nlen) return NULL; - - for (hp = 0; hp <= hlen - nlen; hp++) { - for (np = 0; np < nlen; np++) { - if (huni[hp + np] != nuni[np]) break; - } - if (np == nlen) return haystack + unicode_offset_to_index (haystack, hp); - } - - return NULL; -} -#endif - -gchar * -e_utf8_from_gtk_event_key (GtkWidget *widget, guint keyval, const gchar *string) -{ - gint unival; - gchar *utf; - gint unilen; - - if (keyval == GDK_VoidSymbol) { - utf = e_utf8_from_locale_string (string); - } else { - unival = gdk_keyval_to_unicode (keyval); - - if (unival < ' ') return NULL; - - utf = g_new (gchar, 7); - - unilen = e_unichar_to_utf8 (unival, utf); - - utf[unilen] = '\0'; - } - - return utf; -} - -gchar * -e_utf8_from_iconv_string_sized (iconv_t ic, const gchar *string, gint bytes) -{ - char *new, *ob; - const char *ib; - size_t ibl, obl; - - if (!string) return NULL; - - if (ic == (iconv_t) -1) { - gint i; - /* iso-8859-1 */ - ib = (char *) string; - new = ob = (char *)g_new (unsigned char, bytes * 2 + 1); - for (i = 0; i < (bytes); i ++) { - ob += e_unichar_to_utf8 (ib[i], ob); - } - *ob = '\0'; - return new; - } - - ib = string; - ibl = bytes; - new = ob = g_new (gchar, ibl * 6 + 1); - obl = ibl * 6; - - while (ibl > 0) { - camel_iconv (ic, &ib, &ibl, &ob, &obl); - if (ibl > 0) { - gint len; - if ((*ib & 0x80) == 0x00) len = 1; - else if ((*ib &0xe0) == 0xc0) len = 2; - else if ((*ib &0xf0) == 0xe0) len = 3; - else if ((*ib &0xf8) == 0xf0) len = 4; - else { - g_warning ("Invalid UTF-8 sequence"); - break; - } - ib += len; - ibl = bytes - (ib - string); - if (ibl > bytes) ibl = 0; - *ob++ = '_'; - obl--; - } - } - - *ob = '\0'; - - return new; -} - -gchar * -e_utf8_from_iconv_string (iconv_t ic, const gchar *string) -{ - if (!string) return NULL; - return e_utf8_from_iconv_string_sized (ic, string, strlen (string)); -} - -gchar * -e_utf8_to_iconv_string_sized (iconv_t ic, const gchar *string, gint bytes) -{ - char *new, *ob; - const char *ib; - size_t ibl, obl; - - if (!string) return NULL; - - if (ic == (iconv_t) -1) { - gint len; - const gchar *u; - gunichar uc; - - new = (char *)g_new (unsigned char, bytes * 4 + 1); - u = string; - len = 0; - - while ((u) && (u - string < bytes)) { - u = e_unicode_get_utf8 (u, &uc); - new[len++] = uc & 0xff; - } - new[len] = '\0'; - return new; - } - - ib = string; - ibl = bytes; - new = ob = g_new (char, ibl * 4 + 4); - obl = ibl * 4; - - while (ibl > 0) { - camel_iconv (ic, &ib, &ibl, &ob, &obl); - if (ibl > 0) { - gint len; - if ((*ib & 0x80) == 0x00) len = 1; - else if ((*ib &0xe0) == 0xc0) len = 2; - else if ((*ib &0xf0) == 0xe0) len = 3; - else if ((*ib &0xf8) == 0xf0) len = 4; - else { - g_warning ("Invalid UTF-8 sequence"); - break; - } - ib += len; - ibl = bytes - (ib - string); - if (ibl > bytes) ibl = 0; - - /* FIXME: this is wrong... what if the destination charset is 16 or 32 bit? */ - *ob++ = '_'; - obl--; - } - } - - /* Make sure to terminate with plenty of padding */ - memset (ob, 0, 4); - - return new; -} - -gchar * -e_utf8_to_iconv_string (iconv_t ic, const gchar *string) -{ - if (!string) return NULL; - return e_utf8_to_iconv_string_sized (ic, string, strlen (string)); -} - -gchar * -e_utf8_from_charset_string_sized (const gchar *charset, const gchar *string, gint bytes) -{ - iconv_t ic; - char *ret; - - if (!string) return NULL; - - ic = camel_iconv_open("utf-8", charset); - ret = e_utf8_from_iconv_string_sized (ic, string, bytes); - camel_iconv_close(ic); - - return ret; -} - -gchar * -e_utf8_from_charset_string (const gchar *charset, const gchar *string) -{ - if (!string) return NULL; - return e_utf8_from_charset_string_sized (charset, string, strlen (string)); -} - -gchar * -e_utf8_to_charset_string_sized (const gchar *charset, const gchar *string, gint bytes) -{ - iconv_t ic; - char *ret; - - if (!string) return NULL; - - ic = camel_iconv_open(charset, "utf-8"); - ret = e_utf8_to_iconv_string_sized (ic, string, bytes); - camel_iconv_close(ic); - - return ret; -} - -gchar * -e_utf8_to_charset_string (const gchar *charset, const gchar *string) -{ - if (!string) return NULL; - return e_utf8_to_charset_string_sized (charset, string, strlen (string)); -} - -gchar * -e_utf8_from_locale_string_sized (const gchar *string, gint bytes) -{ - iconv_t ic; - char *ret; - - if (!string) return NULL; - - ic = camel_iconv_open("utf-8", camel_iconv_locale_charset()); - ret = e_utf8_from_iconv_string_sized (ic, string, bytes); - camel_iconv_close(ic); - - return ret; -} - -gchar * -e_utf8_from_locale_string (const gchar *string) -{ - if (!string) return NULL; - return e_utf8_from_locale_string_sized (string, strlen (string)); -} - -gchar * -e_utf8_to_locale_string_sized (const gchar *string, gint bytes) -{ - iconv_t ic; - char *ret; - - if (!string) return NULL; - - ic = camel_iconv_open(camel_iconv_locale_charset(), "utf-8"); - ret = e_utf8_to_iconv_string_sized (ic, string, bytes); - camel_iconv_close(ic); - - return ret; -} - -gchar * -e_utf8_to_locale_string (const gchar *string) -{ - if (!string) return NULL; - return e_utf8_to_locale_string_sized (string, strlen (string)); -} - -gboolean -e_utf8_is_ascii (const gchar *string) -{ - char c; - - g_return_val_if_fail (string != NULL, FALSE); - - for (; (c = *string); string++) { - if (c & 0x80) - return FALSE; - } - - return TRUE; -} - -gchar * -e_utf8_gtk_entry_get_text (GtkEntry *entry) -{ - return g_strdup (gtk_entry_get_text (entry)); -} - -gchar * -e_utf8_gtk_editable_get_text (GtkEditable *editable) -{ - return gtk_editable_get_chars (editable, 0, -1); -} - -gchar * -e_utf8_gtk_editable_get_chars (GtkEditable *editable, gint start, gint end) -{ - return gtk_editable_get_chars (editable, start, end); -} - -void -e_utf8_gtk_editable_insert_text (GtkEditable *editable, const gchar *text, gint length, gint *position) -{ - gtk_editable_insert_text (editable, text, length, position); -} - -void -e_utf8_gtk_editable_set_text (GtkEditable *editable, const gchar *text) -{ - int position; - - gtk_editable_delete_text(editable, 0, -1); - gtk_editable_insert_text (editable, text, strlen (text), &position); -} - -void -e_utf8_gtk_entry_set_text (GtkEntry *entry, const gchar *text) -{ - if (!text) - gtk_entry_set_text(entry, ""); - else - gtk_entry_set_text (entry, text); -} - -/* - * Translate \U+XXXX\ sequences to utf8 chars - */ - -gchar * -e_utf8_xml1_decode (const gchar *text) -{ - const guchar *c; - gchar *u, *d; - int len, s; - - g_return_val_if_fail (text != NULL, NULL); - - len = strlen (text)+1; - /* len * 2 is absolute maximum */ - u = d = g_malloc (len * 2); - - c = (guchar *)text; - s = 0; - while (s < len) { - if ((s <= (len - 8)) && - (c[s ] == '\\') && - (c[s + 1] == 'U' ) && - (c[s + 2] == '+' ) && - isxdigit (c[s + 3]) && - isxdigit (c[s + 4]) && - isxdigit (c[s + 5]) && - isxdigit (c[s + 6]) && - (c[s + 7] == '\\')) { - /* Valid \U+XXXX\ sequence */ - int unival; - unival = strtol ((char *)(c + s + 3), NULL, 16); - d += e_unichar_to_utf8 (unival, d); - s += 8; - } else if (c[s] > 127) { - /* fixme: We assume iso-8859-1 currently */ - d += e_unichar_to_utf8 (c[s], d); - s += 1; - } else { - *d++ = c[s++]; - } - } - *d++ = '\0'; - u = g_realloc (u, (d - u)); - - return u; -} - -gchar * -e_utf8_xml1_encode (const gchar *text) -{ - gchar *u, *d, *c; - unsigned int unival; - int len; - - g_return_val_if_fail (text != NULL, NULL); - - len = 0; - for (u = e_unicode_get_utf8 (text, &unival); u && unival; u = e_unicode_get_utf8 (u, &unival)) { - if ((unival >= 0x80) || (unival == '\\')) { - len += 8; - } else { - len += 1; - } - } - d = c = (char *)g_new (guchar, len + 1); - - for (u = e_unicode_get_utf8 (text, &unival); u && unival; u = e_unicode_get_utf8 (u, &unival)) { - if ((unival >= 0x80) || (unival == '\\')) { - *c++ = '\\'; - *c++ = 'U'; - *c++ = '+'; - c += sprintf (c, "%04x", unival); - *c++ = '\\'; - } else { - *c++ = unival; - } - } - *c = '\0'; - - return d; -} - -/** - * e_unichar_to_utf8: - * @c: a ISO10646 character code - * @outbuf: output buffer, must have at least 6 bytes of space. - * If %NULL, the length will be computed and returned - * and nothing will be written to @out. - * - * Convert a single character to utf8 - * - * Return value: number of bytes written - **/ - -gint -e_unichar_to_utf8 (gint c, gchar *outbuf) -{ - size_t len = 0; - int first; - int i; - - if (c < 0x80) - { - first = 0; - len = 1; - } - else if (c < 0x800) - { - first = 0xc0; - len = 2; - } - else if (c < 0x10000) - { - first = 0xe0; - len = 3; - } - else if (c < 0x200000) - { - first = 0xf0; - len = 4; - } - else if (c < 0x4000000) - { - first = 0xf8; - len = 5; - } - else - { - first = 0xfc; - len = 6; - } - - if (outbuf) - { - for (i = len - 1; i > 0; --i) - { - outbuf[i] = (c & 0x3f) | 0x80; - c >>= 6; - } - outbuf[0] = c | first; - } - - return len; -} - -gchar * -e_unicode_get_utf8 (const gchar *text, gunichar *out) -{ - *out = g_utf8_get_char (text); - return (*out == (gunichar)-1) ? NULL : g_utf8_next_char (text); -} - -/* - * Canonical decomposition - * - * It is copied here from libunicode, because we do not want malloc - * - */ - -typedef struct -{ - unsigned short ch; - char *expansion; -} e_decomposition; - -static e_decomposition e_decomp_table[] = -{ - { 0x00c0, "\x00\x41\x03\x00\0" }, - { 0x00c1, "\x00\x41\x03\x01\0" }, - { 0x00c2, "\x00\x41\x03\x02\0" }, - { 0x00c3, "\x00\x41\x03\x03\0" }, - { 0x00c4, "\x00\x41\x03\x08\0" }, - { 0x00c5, "\x00\x41\x03\x0a\0" }, - { 0x00c7, "\x00\x43\x03\x27\0" }, - { 0x00c8, "\x00\x45\x03\x00\0" }, - { 0x00c9, "\x00\x45\x03\x01\0" }, - { 0x00ca, "\x00\x45\x03\x02\0" }, - { 0x00cb, "\x00\x45\x03\x08\0" }, - { 0x00cc, "\x00\x49\x03\x00\0" }, - { 0x00cd, "\x00\x49\x03\x01\0" }, - { 0x00ce, "\x00\x49\x03\x02\0" }, - { 0x00cf, "\x00\x49\x03\x08\0" }, - { 0x00d1, "\x00\x4e\x03\x03\0" }, - { 0x00d2, "\x00\x4f\x03\x00\0" }, - { 0x00d3, "\x00\x4f\x03\x01\0" }, - { 0x00d4, "\x00\x4f\x03\x02\0" }, - { 0x00d5, "\x00\x4f\x03\x03\0" }, - { 0x00d6, "\x00\x4f\x03\x08\0" }, - { 0x00d9, "\x00\x55\x03\x00\0" }, - { 0x00da, "\x00\x55\x03\x01\0" }, - { 0x00db, "\x00\x55\x03\x02\0" }, - { 0x00dc, "\x00\x55\x03\x08\0" }, - { 0x00dd, "\x00\x59\x03\x01\0" }, - { 0x00e0, "\x00\x61\x03\x00\0" }, - { 0x00e1, "\x00\x61\x03\x01\0" }, - { 0x00e2, "\x00\x61\x03\x02\0" }, - { 0x00e3, "\x00\x61\x03\x03\0" }, - { 0x00e4, "\x00\x61\x03\x08\0" }, - { 0x00e5, "\x00\x61\x03\x0a\0" }, - { 0x00e7, "\x00\x63\x03\x27\0" }, - { 0x00e8, "\x00\x65\x03\x00\0" }, - { 0x00e9, "\x00\x65\x03\x01\0" }, - { 0x00ea, "\x00\x65\x03\x02\0" }, - { 0x00eb, "\x00\x65\x03\x08\0" }, - { 0x00ec, "\x00\x69\x03\x00\0" }, - { 0x00ed, "\x00\x69\x03\x01\0" }, - { 0x00ee, "\x00\x69\x03\x02\0" }, - { 0x00ef, "\x00\x69\x03\x08\0" }, - { 0x00f1, "\x00\x6e\x03\x03\0" }, - { 0x00f2, "\x00\x6f\x03\x00\0" }, - { 0x00f3, "\x00\x6f\x03\x01\0" }, - { 0x00f4, "\x00\x6f\x03\x02\0" }, - { 0x00f5, "\x00\x6f\x03\x03\0" }, - { 0x00f6, "\x00\x6f\x03\x08\0" }, - { 0x00f9, "\x00\x75\x03\x00\0" }, - { 0x00fa, "\x00\x75\x03\x01\0" }, - { 0x00fb, "\x00\x75\x03\x02\0" }, - { 0x00fc, "\x00\x75\x03\x08\0" }, - { 0x00fd, "\x00\x79\x03\x01\0" }, - { 0x00ff, "\x00\x79\x03\x08\0" }, - { 0x0100, "\x00\x41\x03\x04\0" }, - { 0x0101, "\x00\x61\x03\x04\0" }, - { 0x0102, "\x00\x41\x03\x06\0" }, - { 0x0103, "\x00\x61\x03\x06\0" }, - { 0x0104, "\x00\x41\x03\x28\0" }, - { 0x0105, "\x00\x61\x03\x28\0" }, - { 0x0106, "\x00\x43\x03\x01\0" }, - { 0x0107, "\x00\x63\x03\x01\0" }, - { 0x0108, "\x00\x43\x03\x02\0" }, - { 0x0109, "\x00\x63\x03\x02\0" }, - { 0x010a, "\x00\x43\x03\x07\0" }, - { 0x010b, "\x00\x63\x03\x07\0" }, - { 0x010c, "\x00\x43\x03\x0c\0" }, - { 0x010d, "\x00\x63\x03\x0c\0" }, - { 0x010e, "\x00\x44\x03\x0c\0" }, - { 0x010f, "\x00\x64\x03\x0c\0" }, - { 0x0112, "\x00\x45\x03\x04\0" }, - { 0x0113, "\x00\x65\x03\x04\0" }, - { 0x0114, "\x00\x45\x03\x06\0" }, - { 0x0115, "\x00\x65\x03\x06\0" }, - { 0x0116, "\x00\x45\x03\x07\0" }, - { 0x0117, "\x00\x65\x03\x07\0" }, - { 0x0118, "\x00\x45\x03\x28\0" }, - { 0x0119, "\x00\x65\x03\x28\0" }, - { 0x011a, "\x00\x45\x03\x0c\0" }, - { 0x011b, "\x00\x65\x03\x0c\0" }, - { 0x011c, "\x00\x47\x03\x02\0" }, - { 0x011d, "\x00\x67\x03\x02\0" }, - { 0x011e, "\x00\x47\x03\x06\0" }, - { 0x011f, "\x00\x67\x03\x06\0" }, - { 0x0120, "\x00\x47\x03\x07\0" }, - { 0x0121, "\x00\x67\x03\x07\0" }, - { 0x0122, "\x00\x47\x03\x27\0" }, - { 0x0123, "\x00\x67\x03\x27\0" }, - { 0x0124, "\x00\x48\x03\x02\0" }, - { 0x0125, "\x00\x68\x03\x02\0" }, - { 0x0128, "\x00\x49\x03\x03\0" }, - { 0x0129, "\x00\x69\x03\x03\0" }, - { 0x012a, "\x00\x49\x03\x04\0" }, - { 0x012b, "\x00\x69\x03\x04\0" }, - { 0x012c, "\x00\x49\x03\x06\0" }, - { 0x012d, "\x00\x69\x03\x06\0" }, - { 0x012e, "\x00\x49\x03\x28\0" }, - { 0x012f, "\x00\x69\x03\x28\0" }, - { 0x0130, "\x00\x49\x03\x07\0" }, - { 0x0134, "\x00\x4a\x03\x02\0" }, - { 0x0135, "\x00\x6a\x03\x02\0" }, - { 0x0136, "\x00\x4b\x03\x27\0" }, - { 0x0137, "\x00\x6b\x03\x27\0" }, - { 0x0139, "\x00\x4c\x03\x01\0" }, - { 0x013a, "\x00\x6c\x03\x01\0" }, - { 0x013b, "\x00\x4c\x03\x27\0" }, - { 0x013c, "\x00\x6c\x03\x27\0" }, - { 0x013d, "\x00\x4c\x03\x0c\0" }, - { 0x013e, "\x00\x6c\x03\x0c\0" }, - { 0x0143, "\x00\x4e\x03\x01\0" }, - { 0x0144, "\x00\x6e\x03\x01\0" }, - { 0x0145, "\x00\x4e\x03\x27\0" }, - { 0x0146, "\x00\x6e\x03\x27\0" }, - { 0x0147, "\x00\x4e\x03\x0c\0" }, - { 0x0148, "\x00\x6e\x03\x0c\0" }, - { 0x014c, "\x00\x4f\x03\x04\0" }, - { 0x014d, "\x00\x6f\x03\x04\0" }, - { 0x014e, "\x00\x4f\x03\x06\0" }, - { 0x014f, "\x00\x6f\x03\x06\0" }, - { 0x0150, "\x00\x4f\x03\x0b\0" }, - { 0x0151, "\x00\x6f\x03\x0b\0" }, - { 0x0154, "\x00\x52\x03\x01\0" }, - { 0x0155, "\x00\x72\x03\x01\0" }, - { 0x0156, "\x00\x52\x03\x27\0" }, - { 0x0157, "\x00\x72\x03\x27\0" }, - { 0x0158, "\x00\x52\x03\x0c\0" }, - { 0x0159, "\x00\x72\x03\x0c\0" }, - { 0x015a, "\x00\x53\x03\x01\0" }, - { 0x015b, "\x00\x73\x03\x01\0" }, - { 0x015c, "\x00\x53\x03\x02\0" }, - { 0x015d, "\x00\x73\x03\x02\0" }, - { 0x015e, "\x00\x53\x03\x27\0" }, - { 0x015f, "\x00\x73\x03\x27\0" }, - { 0x0160, "\x00\x53\x03\x0c\0" }, - { 0x0161, "\x00\x73\x03\x0c\0" }, - { 0x0162, "\x00\x54\x03\x27\0" }, - { 0x0163, "\x00\x74\x03\x27\0" }, - { 0x0164, "\x00\x54\x03\x0c\0" }, - { 0x0165, "\x00\x74\x03\x0c\0" }, - { 0x0168, "\x00\x55\x03\x03\0" }, - { 0x0169, "\x00\x75\x03\x03\0" }, - { 0x016a, "\x00\x55\x03\x04\0" }, - { 0x016b, "\x00\x75\x03\x04\0" }, - { 0x016c, "\x00\x55\x03\x06\0" }, - { 0x016d, "\x00\x75\x03\x06\0" }, - { 0x016e, "\x00\x55\x03\x0a\0" }, - { 0x016f, "\x00\x75\x03\x0a\0" }, - { 0x0170, "\x00\x55\x03\x0b\0" }, - { 0x0171, "\x00\x75\x03\x0b\0" }, - { 0x0172, "\x00\x55\x03\x28\0" }, - { 0x0173, "\x00\x75\x03\x28\0" }, - { 0x0174, "\x00\x57\x03\x02\0" }, - { 0x0175, "\x00\x77\x03\x02\0" }, - { 0x0176, "\x00\x59\x03\x02\0" }, - { 0x0177, "\x00\x79\x03\x02\0" }, - { 0x0178, "\x00\x59\x03\x08\0" }, - { 0x0179, "\x00\x5a\x03\x01\0" }, - { 0x017a, "\x00\x7a\x03\x01\0" }, - { 0x017b, "\x00\x5a\x03\x07\0" }, - { 0x017c, "\x00\x7a\x03\x07\0" }, - { 0x017d, "\x00\x5a\x03\x0c\0" }, - { 0x017e, "\x00\x7a\x03\x0c\0" }, - { 0x01a0, "\x00\x4f\x03\x1b\0" }, - { 0x01a1, "\x00\x6f\x03\x1b\0" }, - { 0x01af, "\x00\x55\x03\x1b\0" }, - { 0x01b0, "\x00\x75\x03\x1b\0" }, - { 0x01cd, "\x00\x41\x03\x0c\0" }, - { 0x01ce, "\x00\x61\x03\x0c\0" }, - { 0x01cf, "\x00\x49\x03\x0c\0" }, - { 0x01d0, "\x00\x69\x03\x0c\0" }, - { 0x01d1, "\x00\x4f\x03\x0c\0" }, - { 0x01d2, "\x00\x6f\x03\x0c\0" }, - { 0x01d3, "\x00\x55\x03\x0c\0" }, - { 0x01d4, "\x00\x75\x03\x0c\0" }, - { 0x01d5, "\x00\x55\x03\x08\x03\x04\0" }, - { 0x01d6, "\x00\x75\x03\x08\x03\x04\0" }, - { 0x01d7, "\x00\x55\x03\x08\x03\x01\0" }, - { 0x01d8, "\x00\x75\x03\x08\x03\x01\0" }, - { 0x01d9, "\x00\x55\x03\x08\x03\x0c\0" }, - { 0x01da, "\x00\x75\x03\x08\x03\x0c\0" }, - { 0x01db, "\x00\x55\x03\x08\x03\x00\0" }, - { 0x01dc, "\x00\x75\x03\x08\x03\x00\0" }, - { 0x01de, "\x00\x41\x03\x08\x03\x04\0" }, - { 0x01df, "\x00\x61\x03\x08\x03\x04\0" }, - { 0x01e0, "\x00\x41\x03\x07\x03\x04\0" }, - { 0x01e1, "\x00\x61\x03\x07\x03\x04\0" }, - { 0x01e2, "\x00\xc6\x03\x04\0" }, - { 0x01e3, "\x00\xe6\x03\x04\0" }, - { 0x01e6, "\x00\x47\x03\x0c\0" }, - { 0x01e7, "\x00\x67\x03\x0c\0" }, - { 0x01e8, "\x00\x4b\x03\x0c\0" }, - { 0x01e9, "\x00\x6b\x03\x0c\0" }, - { 0x01ea, "\x00\x4f\x03\x28\0" }, - { 0x01eb, "\x00\x6f\x03\x28\0" }, - { 0x01ec, "\x00\x4f\x03\x28\x03\x04\0" }, - { 0x01ed, "\x00\x6f\x03\x28\x03\x04\0" }, - { 0x01ee, "\x01\xb7\x03\x0c\0" }, - { 0x01ef, "\x02\x92\x03\x0c\0" }, - { 0x01f0, "\x00\x6a\x03\x0c\0" }, - { 0x01f4, "\x00\x47\x03\x01\0" }, - { 0x01f5, "\x00\x67\x03\x01\0" }, - { 0x01fa, "\x00\x41\x03\x0a\x03\x01\0" }, - { 0x01fb, "\x00\x61\x03\x0a\x03\x01\0" }, - { 0x01fc, "\x00\xc6\x03\x01\0" }, - { 0x01fd, "\x00\xe6\x03\x01\0" }, - { 0x01fe, "\x00\xd8\x03\x01\0" }, - { 0x01ff, "\x00\xf8\x03\x01\0" }, - { 0x0200, "\x00\x41\x03\x0f\0" }, - { 0x0201, "\x00\x61\x03\x0f\0" }, - { 0x0202, "\x00\x41\x03\x11\0" }, - { 0x0203, "\x00\x61\x03\x11\0" }, - { 0x0204, "\x00\x45\x03\x0f\0" }, - { 0x0205, "\x00\x65\x03\x0f\0" }, - { 0x0206, "\x00\x45\x03\x11\0" }, - { 0x0207, "\x00\x65\x03\x11\0" }, - { 0x0208, "\x00\x49\x03\x0f\0" }, - { 0x0209, "\x00\x69\x03\x0f\0" }, - { 0x020a, "\x00\x49\x03\x11\0" }, - { 0x020b, "\x00\x69\x03\x11\0" }, - { 0x020c, "\x00\x4f\x03\x0f\0" }, - { 0x020d, "\x00\x6f\x03\x0f\0" }, - { 0x020e, "\x00\x4f\x03\x11\0" }, - { 0x020f, "\x00\x6f\x03\x11\0" }, - { 0x0210, "\x00\x52\x03\x0f\0" }, - { 0x0211, "\x00\x72\x03\x0f\0" }, - { 0x0212, "\x00\x52\x03\x11\0" }, - { 0x0213, "\x00\x72\x03\x11\0" }, - { 0x0214, "\x00\x55\x03\x0f\0" }, - { 0x0215, "\x00\x75\x03\x0f\0" }, - { 0x0216, "\x00\x55\x03\x11\0" }, - { 0x0217, "\x00\x75\x03\x11\0" }, - { 0x0340, "\x03\x00\0" }, - { 0x0341, "\x03\x01\0" }, - { 0x0343, "\x03\x13\0" }, - { 0x0344, "\x03\x08\x03\x01\0" }, - { 0x0374, "\x02\xb9\0" }, - { 0x037e, "\x00\x3b\0" }, - { 0x0385, "\x00\xa8\x03\x01\0" }, - { 0x0386, "\x03\x91\x03\x01\0" }, - { 0x0387, "\x00\xb7\0" }, - { 0x0388, "\x03\x95\x03\x01\0" }, - { 0x0389, "\x03\x97\x03\x01\0" }, - { 0x038a, "\x03\x99\x03\x01\0" }, - { 0x038c, "\x03\x9f\x03\x01\0" }, - { 0x038e, "\x03\xa5\x03\x01\0" }, - { 0x038f, "\x03\xa9\x03\x01\0" }, - { 0x0390, "\x03\xb9\x03\x08\x03\x01\0" }, - { 0x03aa, "\x03\x99\x03\x08\0" }, - { 0x03ab, "\x03\xa5\x03\x08\0" }, - { 0x03ac, "\x03\xb1\x03\x01\0" }, - { 0x03ad, "\x03\xb5\x03\x01\0" }, - { 0x03ae, "\x03\xb7\x03\x01\0" }, - { 0x03af, "\x03\xb9\x03\x01\0" }, - { 0x03b0, "\x03\xc5\x03\x08\x03\x01\0" }, - { 0x03ca, "\x03\xb9\x03\x08\0" }, - { 0x03cb, "\x03\xc5\x03\x08\0" }, - { 0x03cc, "\x03\xbf\x03\x01\0" }, - { 0x03cd, "\x03\xc5\x03\x01\0" }, - { 0x03ce, "\x03\xc9\x03\x01\0" }, - { 0x03d3, "\x03\xd2\x03\x01\0" }, - { 0x03d4, "\x03\xd2\x03\x08\0" }, - { 0x0401, "\x04\x15\x03\x08\0" }, - { 0x0403, "\x04\x13\x03\x01\0" }, - { 0x0407, "\x04\x06\x03\x08\0" }, - { 0x040c, "\x04\x1a\x03\x01\0" }, - { 0x040e, "\x04\x23\x03\x06\0" }, - { 0x0419, "\x04\x18\x03\x06\0" }, - { 0x0439, "\x04\x38\x03\x06\0" }, - { 0x0451, "\x04\x35\x03\x08\0" }, - { 0x0453, "\x04\x33\x03\x01\0" }, - { 0x0457, "\x04\x56\x03\x08\0" }, - { 0x045c, "\x04\x3a\x03\x01\0" }, - { 0x045e, "\x04\x43\x03\x06\0" }, - { 0x0476, "\x04\x74\x03\x0f\0" }, - { 0x0477, "\x04\x75\x03\x0f\0" }, - { 0x04c1, "\x04\x16\x03\x06\0" }, - { 0x04c2, "\x04\x36\x03\x06\0" }, - { 0x04d0, "\x04\x10\x03\x06\0" }, - { 0x04d1, "\x04\x30\x03\x06\0" }, - { 0x04d2, "\x04\x10\x03\x08\0" }, - { 0x04d3, "\x04\x30\x03\x08\0" }, - { 0x04d6, "\x04\x15\x03\x06\0" }, - { 0x04d7, "\x04\x35\x03\x06\0" }, - { 0x04da, "\x04\xd8\x03\x08\0" }, - { 0x04db, "\x04\xd9\x03\x08\0" }, - { 0x04dc, "\x04\x16\x03\x08\0" }, - { 0x04dd, "\x04\x36\x03\x08\0" }, - { 0x04de, "\x04\x17\x03\x08\0" }, - { 0x04df, "\x04\x37\x03\x08\0" }, - { 0x04e2, "\x04\x18\x03\x04\0" }, - { 0x04e3, "\x04\x38\x03\x04\0" }, - { 0x04e4, "\x04\x18\x03\x08\0" }, - { 0x04e5, "\x04\x38\x03\x08\0" }, - { 0x04e6, "\x04\x1e\x03\x08\0" }, - { 0x04e7, "\x04\x3e\x03\x08\0" }, - { 0x04ea, "\x04\xe8\x03\x08\0" }, - { 0x04eb, "\x04\xe9\x03\x08\0" }, - { 0x04ee, "\x04\x23\x03\x04\0" }, - { 0x04ef, "\x04\x43\x03\x04\0" }, - { 0x04f0, "\x04\x23\x03\x08\0" }, - { 0x04f1, "\x04\x43\x03\x08\0" }, - { 0x04f2, "\x04\x23\x03\x0b\0" }, - { 0x04f3, "\x04\x43\x03\x0b\0" }, - { 0x04f4, "\x04\x27\x03\x08\0" }, - { 0x04f5, "\x04\x47\x03\x08\0" }, - { 0x04f8, "\x04\x2b\x03\x08\0" }, - { 0x04f9, "\x04\x4b\x03\x08\0" }, - { 0x0929, "\x09\x28\x09\x3c\0" }, - { 0x0931, "\x09\x30\x09\x3c\0" }, - { 0x0934, "\x09\x33\x09\x3c\0" }, - { 0x0958, "\x09\x15\x09\x3c\0" }, - { 0x0959, "\x09\x16\x09\x3c\0" }, - { 0x095a, "\x09\x17\x09\x3c\0" }, - { 0x095b, "\x09\x1c\x09\x3c\0" }, - { 0x095c, "\x09\x21\x09\x3c\0" }, - { 0x095d, "\x09\x22\x09\x3c\0" }, - { 0x095e, "\x09\x2b\x09\x3c\0" }, - { 0x095f, "\x09\x2f\x09\x3c\0" }, - { 0x09b0, "\x09\xac\x09\xbc\0" }, - { 0x09cb, "\x09\xc7\x09\xbe\0" }, - { 0x09cc, "\x09\xc7\x09\xd7\0" }, - { 0x09dc, "\x09\xa1\x09\xbc\0" }, - { 0x09dd, "\x09\xa2\x09\xbc\0" }, - { 0x09df, "\x09\xaf\x09\xbc\0" }, - { 0x0a59, "\x0a\x16\x0a\x3c\0" }, - { 0x0a5a, "\x0a\x17\x0a\x3c\0" }, - { 0x0a5b, "\x0a\x1c\x0a\x3c\0" }, - { 0x0a5c, "\x0a\x21\x0a\x3c\0" }, - { 0x0a5e, "\x0a\x2b\x0a\x3c\0" }, - { 0x0b48, "\x0b\x47\x0b\x56\0" }, - { 0x0b4b, "\x0b\x47\x0b\x3e\0" }, - { 0x0b4c, "\x0b\x47\x0b\x57\0" }, - { 0x0b5c, "\x0b\x21\x0b\x3c\0" }, - { 0x0b5d, "\x0b\x22\x0b\x3c\0" }, - { 0x0b5f, "\x0b\x2f\x0b\x3c\0" }, - { 0x0b94, "\x0b\x92\x0b\xd7\0" }, - { 0x0bca, "\x0b\xc6\x0b\xbe\0" }, - { 0x0bcb, "\x0b\xc7\x0b\xbe\0" }, - { 0x0bcc, "\x0b\xc6\x0b\xd7\0" }, - { 0x0c48, "\x0c\x46\x0c\x56\0" }, - { 0x0cc0, "\x0c\xbf\x0c\xd5\0" }, - { 0x0cc7, "\x0c\xc6\x0c\xd5\0" }, - { 0x0cc8, "\x0c\xc6\x0c\xd6\0" }, - { 0x0cca, "\x0c\xc6\x0c\xc2\0" }, - { 0x0ccb, "\x0c\xc6\x0c\xc2\x0c\xd5\0" }, - { 0x0d4a, "\x0d\x46\x0d\x3e\0" }, - { 0x0d4b, "\x0d\x47\x0d\x3e\0" }, - { 0x0d4c, "\x0d\x46\x0d\x57\0" }, - { 0x0e33, "\x0e\x4d\x0e\x32\0" }, - { 0x0eb3, "\x0e\xcd\x0e\xb2\0" }, - { 0x0f43, "\x0f\x42\x0f\xb7\0" }, - { 0x0f4d, "\x0f\x4c\x0f\xb7\0" }, - { 0x0f52, "\x0f\x51\x0f\xb7\0" }, - { 0x0f57, "\x0f\x56\x0f\xb7\0" }, - { 0x0f5c, "\x0f\x5b\x0f\xb7\0" }, - { 0x0f69, "\x0f\x40\x0f\xb5\0" }, - { 0x0f73, "\x0f\x71\x0f\x72\0" }, - { 0x0f75, "\x0f\x71\x0f\x74\0" }, - { 0x0f76, "\x0f\xb2\x0f\x80\0" }, - { 0x0f78, "\x0f\xb3\x0f\x80\0" }, - { 0x0f81, "\x0f\x71\x0f\x80\0" }, - { 0x0f93, "\x0f\x92\x0f\xb7\0" }, - { 0x0f9d, "\x0f\x9c\x0f\xb7\0" }, - { 0x0fa2, "\x0f\xa1\x0f\xb7\0" }, - { 0x0fa7, "\x0f\xa6\x0f\xb7\0" }, - { 0x0fac, "\x0f\xab\x0f\xb7\0" }, - { 0x0fb9, "\x0f\x90\x0f\xb5\0" }, - { 0x1e00, "\x00\x41\x03\x25\0" }, - { 0x1e01, "\x00\x61\x03\x25\0" }, - { 0x1e02, "\x00\x42\x03\x07\0" }, - { 0x1e03, "\x00\x62\x03\x07\0" }, - { 0x1e04, "\x00\x42\x03\x23\0" }, - { 0x1e05, "\x00\x62\x03\x23\0" }, - { 0x1e06, "\x00\x42\x03\x31\0" }, - { 0x1e07, "\x00\x62\x03\x31\0" }, - { 0x1e08, "\x00\x43\x03\x27\x03\x01\0" }, - { 0x1e09, "\x00\x63\x03\x27\x03\x01\0" }, - { 0x1e0a, "\x00\x44\x03\x07\0" }, - { 0x1e0b, "\x00\x64\x03\x07\0" }, - { 0x1e0c, "\x00\x44\x03\x23\0" }, - { 0x1e0d, "\x00\x64\x03\x23\0" }, - { 0x1e0e, "\x00\x44\x03\x31\0" }, - { 0x1e0f, "\x00\x64\x03\x31\0" }, - { 0x1e10, "\x00\x44\x03\x27\0" }, - { 0x1e11, "\x00\x64\x03\x27\0" }, - { 0x1e12, "\x00\x44\x03\x2d\0" }, - { 0x1e13, "\x00\x64\x03\x2d\0" }, - { 0x1e14, "\x00\x45\x03\x04\x03\x00\0" }, - { 0x1e15, "\x00\x65\x03\x04\x03\x00\0" }, - { 0x1e16, "\x00\x45\x03\x04\x03\x01\0" }, - { 0x1e17, "\x00\x65\x03\x04\x03\x01\0" }, - { 0x1e18, "\x00\x45\x03\x2d\0" }, - { 0x1e19, "\x00\x65\x03\x2d\0" }, - { 0x1e1a, "\x00\x45\x03\x30\0" }, - { 0x1e1b, "\x00\x65\x03\x30\0" }, - { 0x1e1c, "\x00\x45\x03\x27\x03\x06\0" }, - { 0x1e1d, "\x00\x65\x03\x27\x03\x06\0" }, - { 0x1e1e, "\x00\x46\x03\x07\0" }, - { 0x1e1f, "\x00\x66\x03\x07\0" }, - { 0x1e20, "\x00\x47\x03\x04\0" }, - { 0x1e21, "\x00\x67\x03\x04\0" }, - { 0x1e22, "\x00\x48\x03\x07\0" }, - { 0x1e23, "\x00\x68\x03\x07\0" }, - { 0x1e24, "\x00\x48\x03\x23\0" }, - { 0x1e25, "\x00\x68\x03\x23\0" }, - { 0x1e26, "\x00\x48\x03\x08\0" }, - { 0x1e27, "\x00\x68\x03\x08\0" }, - { 0x1e28, "\x00\x48\x03\x27\0" }, - { 0x1e29, "\x00\x68\x03\x27\0" }, - { 0x1e2a, "\x00\x48\x03\x2e\0" }, - { 0x1e2b, "\x00\x68\x03\x2e\0" }, - { 0x1e2c, "\x00\x49\x03\x30\0" }, - { 0x1e2d, "\x00\x69\x03\x30\0" }, - { 0x1e2e, "\x00\x49\x03\x08\x03\x01\0" }, - { 0x1e2f, "\x00\x69\x03\x08\x03\x01\0" }, - { 0x1e30, "\x00\x4b\x03\x01\0" }, - { 0x1e31, "\x00\x6b\x03\x01\0" }, - { 0x1e32, "\x00\x4b\x03\x23\0" }, - { 0x1e33, "\x00\x6b\x03\x23\0" }, - { 0x1e34, "\x00\x4b\x03\x31\0" }, - { 0x1e35, "\x00\x6b\x03\x31\0" }, - { 0x1e36, "\x00\x4c\x03\x23\0" }, - { 0x1e37, "\x00\x6c\x03\x23\0" }, - { 0x1e38, "\x00\x4c\x03\x23\x03\x04\0" }, - { 0x1e39, "\x00\x6c\x03\x23\x03\x04\0" }, - { 0x1e3a, "\x00\x4c\x03\x31\0" }, - { 0x1e3b, "\x00\x6c\x03\x31\0" }, - { 0x1e3c, "\x00\x4c\x03\x2d\0" }, - { 0x1e3d, "\x00\x6c\x03\x2d\0" }, - { 0x1e3e, "\x00\x4d\x03\x01\0" }, - { 0x1e3f, "\x00\x6d\x03\x01\0" }, - { 0x1e40, "\x00\x4d\x03\x07\0" }, - { 0x1e41, "\x00\x6d\x03\x07\0" }, - { 0x1e42, "\x00\x4d\x03\x23\0" }, - { 0x1e43, "\x00\x6d\x03\x23\0" }, - { 0x1e44, "\x00\x4e\x03\x07\0" }, - { 0x1e45, "\x00\x6e\x03\x07\0" }, - { 0x1e46, "\x00\x4e\x03\x23\0" }, - { 0x1e47, "\x00\x6e\x03\x23\0" }, - { 0x1e48, "\x00\x4e\x03\x31\0" }, - { 0x1e49, "\x00\x6e\x03\x31\0" }, - { 0x1e4a, "\x00\x4e\x03\x2d\0" }, - { 0x1e4b, "\x00\x6e\x03\x2d\0" }, - { 0x1e4c, "\x00\x4f\x03\x03\x03\x01\0" }, - { 0x1e4d, "\x00\x6f\x03\x03\x03\x01\0" }, - { 0x1e4e, "\x00\x4f\x03\x03\x03\x08\0" }, - { 0x1e4f, "\x00\x6f\x03\x03\x03\x08\0" }, - { 0x1e50, "\x00\x4f\x03\x04\x03\x00\0" }, - { 0x1e51, "\x00\x6f\x03\x04\x03\x00\0" }, - { 0x1e52, "\x00\x4f\x03\x04\x03\x01\0" }, - { 0x1e53, "\x00\x6f\x03\x04\x03\x01\0" }, - { 0x1e54, "\x00\x50\x03\x01\0" }, - { 0x1e55, "\x00\x70\x03\x01\0" }, - { 0x1e56, "\x00\x50\x03\x07\0" }, - { 0x1e57, "\x00\x70\x03\x07\0" }, - { 0x1e58, "\x00\x52\x03\x07\0" }, - { 0x1e59, "\x00\x72\x03\x07\0" }, - { 0x1e5a, "\x00\x52\x03\x23\0" }, - { 0x1e5b, "\x00\x72\x03\x23\0" }, - { 0x1e5c, "\x00\x52\x03\x23\x03\x04\0" }, - { 0x1e5d, "\x00\x72\x03\x23\x03\x04\0" }, - { 0x1e5e, "\x00\x52\x03\x31\0" }, - { 0x1e5f, "\x00\x72\x03\x31\0" }, - { 0x1e60, "\x00\x53\x03\x07\0" }, - { 0x1e61, "\x00\x73\x03\x07\0" }, - { 0x1e62, "\x00\x53\x03\x23\0" }, - { 0x1e63, "\x00\x73\x03\x23\0" }, - { 0x1e64, "\x00\x53\x03\x01\x03\x07\0" }, - { 0x1e65, "\x00\x73\x03\x01\x03\x07\0" }, - { 0x1e66, "\x00\x53\x03\x0c\x03\x07\0" }, - { 0x1e67, "\x00\x73\x03\x0c\x03\x07\0" }, - { 0x1e68, "\x00\x53\x03\x23\x03\x07\0" }, - { 0x1e69, "\x00\x73\x03\x23\x03\x07\0" }, - { 0x1e6a, "\x00\x54\x03\x07\0" }, - { 0x1e6b, "\x00\x74\x03\x07\0" }, - { 0x1e6c, "\x00\x54\x03\x23\0" }, - { 0x1e6d, "\x00\x74\x03\x23\0" }, - { 0x1e6e, "\x00\x54\x03\x31\0" }, - { 0x1e6f, "\x00\x74\x03\x31\0" }, - { 0x1e70, "\x00\x54\x03\x2d\0" }, - { 0x1e71, "\x00\x74\x03\x2d\0" }, - { 0x1e72, "\x00\x55\x03\x24\0" }, - { 0x1e73, "\x00\x75\x03\x24\0" }, - { 0x1e74, "\x00\x55\x03\x30\0" }, - { 0x1e75, "\x00\x75\x03\x30\0" }, - { 0x1e76, "\x00\x55\x03\x2d\0" }, - { 0x1e77, "\x00\x75\x03\x2d\0" }, - { 0x1e78, "\x00\x55\x03\x03\x03\x01\0" }, - { 0x1e79, "\x00\x75\x03\x03\x03\x01\0" }, - { 0x1e7a, "\x00\x55\x03\x04\x03\x08\0" }, - { 0x1e7b, "\x00\x75\x03\x04\x03\x08\0" }, - { 0x1e7c, "\x00\x56\x03\x03\0" }, - { 0x1e7d, "\x00\x76\x03\x03\0" }, - { 0x1e7e, "\x00\x56\x03\x23\0" }, - { 0x1e7f, "\x00\x76\x03\x23\0" }, - { 0x1e80, "\x00\x57\x03\x00\0" }, - { 0x1e81, "\x00\x77\x03\x00\0" }, - { 0x1e82, "\x00\x57\x03\x01\0" }, - { 0x1e83, "\x00\x77\x03\x01\0" }, - { 0x1e84, "\x00\x57\x03\x08\0" }, - { 0x1e85, "\x00\x77\x03\x08\0" }, - { 0x1e86, "\x00\x57\x03\x07\0" }, - { 0x1e87, "\x00\x77\x03\x07\0" }, - { 0x1e88, "\x00\x57\x03\x23\0" }, - { 0x1e89, "\x00\x77\x03\x23\0" }, - { 0x1e8a, "\x00\x58\x03\x07\0" }, - { 0x1e8b, "\x00\x78\x03\x07\0" }, - { 0x1e8c, "\x00\x58\x03\x08\0" }, - { 0x1e8d, "\x00\x78\x03\x08\0" }, - { 0x1e8e, "\x00\x59\x03\x07\0" }, - { 0x1e8f, "\x00\x79\x03\x07\0" }, - { 0x1e90, "\x00\x5a\x03\x02\0" }, - { 0x1e91, "\x00\x7a\x03\x02\0" }, - { 0x1e92, "\x00\x5a\x03\x23\0" }, - { 0x1e93, "\x00\x7a\x03\x23\0" }, - { 0x1e94, "\x00\x5a\x03\x31\0" }, - { 0x1e95, "\x00\x7a\x03\x31\0" }, - { 0x1e96, "\x00\x68\x03\x31\0" }, - { 0x1e97, "\x00\x74\x03\x08\0" }, - { 0x1e98, "\x00\x77\x03\x0a\0" }, - { 0x1e99, "\x00\x79\x03\x0a\0" }, - { 0x1e9b, "\x01\x7f\x03\x07\0" }, - { 0x1ea0, "\x00\x41\x03\x23\0" }, - { 0x1ea1, "\x00\x61\x03\x23\0" }, - { 0x1ea2, "\x00\x41\x03\x09\0" }, - { 0x1ea3, "\x00\x61\x03\x09\0" }, - { 0x1ea4, "\x00\x41\x03\x02\x03\x01\0" }, - { 0x1ea5, "\x00\x61\x03\x02\x03\x01\0" }, - { 0x1ea6, "\x00\x41\x03\x02\x03\x00\0" }, - { 0x1ea7, "\x00\x61\x03\x02\x03\x00\0" }, - { 0x1ea8, "\x00\x41\x03\x02\x03\x09\0" }, - { 0x1ea9, "\x00\x61\x03\x02\x03\x09\0" }, - { 0x1eaa, "\x00\x41\x03\x02\x03\x03\0" }, - { 0x1eab, "\x00\x61\x03\x02\x03\x03\0" }, - { 0x1eac, "\x00\x41\x03\x23\x03\x02\0" }, - { 0x1ead, "\x00\x61\x03\x23\x03\x02\0" }, - { 0x1eae, "\x00\x41\x03\x06\x03\x01\0" }, - { 0x1eaf, "\x00\x61\x03\x06\x03\x01\0" }, - { 0x1eb0, "\x00\x41\x03\x06\x03\x00\0" }, - { 0x1eb1, "\x00\x61\x03\x06\x03\x00\0" }, - { 0x1eb2, "\x00\x41\x03\x06\x03\x09\0" }, - { 0x1eb3, "\x00\x61\x03\x06\x03\x09\0" }, - { 0x1eb4, "\x00\x41\x03\x06\x03\x03\0" }, - { 0x1eb5, "\x00\x61\x03\x06\x03\x03\0" }, - { 0x1eb6, "\x00\x41\x03\x23\x03\x06\0" }, - { 0x1eb7, "\x00\x61\x03\x23\x03\x06\0" }, - { 0x1eb8, "\x00\x45\x03\x23\0" }, - { 0x1eb9, "\x00\x65\x03\x23\0" }, - { 0x1eba, "\x00\x45\x03\x09\0" }, - { 0x1ebb, "\x00\x65\x03\x09\0" }, - { 0x1ebc, "\x00\x45\x03\x03\0" }, - { 0x1ebd, "\x00\x65\x03\x03\0" }, - { 0x1ebe, "\x00\x45\x03\x02\x03\x01\0" }, - { 0x1ebf, "\x00\x65\x03\x02\x03\x01\0" }, - { 0x1ec0, "\x00\x45\x03\x02\x03\x00\0" }, - { 0x1ec1, "\x00\x65\x03\x02\x03\x00\0" }, - { 0x1ec2, "\x00\x45\x03\x02\x03\x09\0" }, - { 0x1ec3, "\x00\x65\x03\x02\x03\x09\0" }, - { 0x1ec4, "\x00\x45\x03\x02\x03\x03\0" }, - { 0x1ec5, "\x00\x65\x03\x02\x03\x03\0" }, - { 0x1ec6, "\x00\x45\x03\x23\x03\x02\0" }, - { 0x1ec7, "\x00\x65\x03\x23\x03\x02\0" }, - { 0x1ec8, "\x00\x49\x03\x09\0" }, - { 0x1ec9, "\x00\x69\x03\x09\0" }, - { 0x1eca, "\x00\x49\x03\x23\0" }, - { 0x1ecb, "\x00\x69\x03\x23\0" }, - { 0x1ecc, "\x00\x4f\x03\x23\0" }, - { 0x1ecd, "\x00\x6f\x03\x23\0" }, - { 0x1ece, "\x00\x4f\x03\x09\0" }, - { 0x1ecf, "\x00\x6f\x03\x09\0" }, - { 0x1ed0, "\x00\x4f\x03\x02\x03\x01\0" }, - { 0x1ed1, "\x00\x6f\x03\x02\x03\x01\0" }, - { 0x1ed2, "\x00\x4f\x03\x02\x03\x00\0" }, - { 0x1ed3, "\x00\x6f\x03\x02\x03\x00\0" }, - { 0x1ed4, "\x00\x4f\x03\x02\x03\x09\0" }, - { 0x1ed5, "\x00\x6f\x03\x02\x03\x09\0" }, - { 0x1ed6, "\x00\x4f\x03\x02\x03\x03\0" }, - { 0x1ed7, "\x00\x6f\x03\x02\x03\x03\0" }, - { 0x1ed8, "\x00\x4f\x03\x23\x03\x02\0" }, - { 0x1ed9, "\x00\x6f\x03\x23\x03\x02\0" }, - { 0x1eda, "\x00\x4f\x03\x1b\x03\x01\0" }, - { 0x1edb, "\x00\x6f\x03\x1b\x03\x01\0" }, - { 0x1edc, "\x00\x4f\x03\x1b\x03\x00\0" }, - { 0x1edd, "\x00\x6f\x03\x1b\x03\x00\0" }, - { 0x1ede, "\x00\x4f\x03\x1b\x03\x09\0" }, - { 0x1edf, "\x00\x6f\x03\x1b\x03\x09\0" }, - { 0x1ee0, "\x00\x4f\x03\x1b\x03\x03\0" }, - { 0x1ee1, "\x00\x6f\x03\x1b\x03\x03\0" }, - { 0x1ee2, "\x00\x4f\x03\x1b\x03\x23\0" }, - { 0x1ee3, "\x00\x6f\x03\x1b\x03\x23\0" }, - { 0x1ee4, "\x00\x55\x03\x23\0" }, - { 0x1ee5, "\x00\x75\x03\x23\0" }, - { 0x1ee6, "\x00\x55\x03\x09\0" }, - { 0x1ee7, "\x00\x75\x03\x09\0" }, - { 0x1ee8, "\x00\x55\x03\x1b\x03\x01\0" }, - { 0x1ee9, "\x00\x75\x03\x1b\x03\x01\0" }, - { 0x1eea, "\x00\x55\x03\x1b\x03\x00\0" }, - { 0x1eeb, "\x00\x75\x03\x1b\x03\x00\0" }, - { 0x1eec, "\x00\x55\x03\x1b\x03\x09\0" }, - { 0x1eed, "\x00\x75\x03\x1b\x03\x09\0" }, - { 0x1eee, "\x00\x55\x03\x1b\x03\x03\0" }, - { 0x1eef, "\x00\x75\x03\x1b\x03\x03\0" }, - { 0x1ef0, "\x00\x55\x03\x1b\x03\x23\0" }, - { 0x1ef1, "\x00\x75\x03\x1b\x03\x23\0" }, - { 0x1ef2, "\x00\x59\x03\x00\0" }, - { 0x1ef3, "\x00\x79\x03\x00\0" }, - { 0x1ef4, "\x00\x59\x03\x23\0" }, - { 0x1ef5, "\x00\x79\x03\x23\0" }, - { 0x1ef6, "\x00\x59\x03\x09\0" }, - { 0x1ef7, "\x00\x79\x03\x09\0" }, - { 0x1ef8, "\x00\x59\x03\x03\0" }, - { 0x1ef9, "\x00\x79\x03\x03\0" }, - { 0x1f00, "\x03\xb1\x03\x13\0" }, - { 0x1f01, "\x03\xb1\x03\x14\0" }, - { 0x1f02, "\x03\xb1\x03\x13\x03\x00\0" }, - { 0x1f03, "\x03\xb1\x03\x14\x03\x00\0" }, - { 0x1f04, "\x03\xb1\x03\x13\x03\x01\0" }, - { 0x1f05, "\x03\xb1\x03\x14\x03\x01\0" }, - { 0x1f06, "\x03\xb1\x03\x13\x03\x42\0" }, - { 0x1f07, "\x03\xb1\x03\x14\x03\x42\0" }, - { 0x1f08, "\x03\x91\x03\x13\0" }, - { 0x1f09, "\x03\x91\x03\x14\0" }, - { 0x1f0a, "\x03\x91\x03\x13\x03\x00\0" }, - { 0x1f0b, "\x03\x91\x03\x14\x03\x00\0" }, - { 0x1f0c, "\x03\x91\x03\x13\x03\x01\0" }, - { 0x1f0d, "\x03\x91\x03\x14\x03\x01\0" }, - { 0x1f0e, "\x03\x91\x03\x13\x03\x42\0" }, - { 0x1f0f, "\x03\x91\x03\x14\x03\x42\0" }, - { 0x1f10, "\x03\xb5\x03\x13\0" }, - { 0x1f11, "\x03\xb5\x03\x14\0" }, - { 0x1f12, "\x03\xb5\x03\x13\x03\x00\0" }, - { 0x1f13, "\x03\xb5\x03\x14\x03\x00\0" }, - { 0x1f14, "\x03\xb5\x03\x13\x03\x01\0" }, - { 0x1f15, "\x03\xb5\x03\x14\x03\x01\0" }, - { 0x1f18, "\x03\x95\x03\x13\0" }, - { 0x1f19, "\x03\x95\x03\x14\0" }, - { 0x1f1a, "\x03\x95\x03\x13\x03\x00\0" }, - { 0x1f1b, "\x03\x95\x03\x14\x03\x00\0" }, - { 0x1f1c, "\x03\x95\x03\x13\x03\x01\0" }, - { 0x1f1d, "\x03\x95\x03\x14\x03\x01\0" }, - { 0x1f20, "\x03\xb7\x03\x13\0" }, - { 0x1f21, "\x03\xb7\x03\x14\0" }, - { 0x1f22, "\x03\xb7\x03\x13\x03\x00\0" }, - { 0x1f23, "\x03\xb7\x03\x14\x03\x00\0" }, - { 0x1f24, "\x03\xb7\x03\x13\x03\x01\0" }, - { 0x1f25, "\x03\xb7\x03\x14\x03\x01\0" }, - { 0x1f26, "\x03\xb7\x03\x13\x03\x42\0" }, - { 0x1f27, "\x03\xb7\x03\x14\x03\x42\0" }, - { 0x1f28, "\x03\x97\x03\x13\0" }, - { 0x1f29, "\x03\x97\x03\x14\0" }, - { 0x1f2a, "\x03\x97\x03\x13\x03\x00\0" }, - { 0x1f2b, "\x03\x97\x03\x14\x03\x00\0" }, - { 0x1f2c, "\x03\x97\x03\x13\x03\x01\0" }, - { 0x1f2d, "\x03\x97\x03\x14\x03\x01\0" }, - { 0x1f2e, "\x03\x97\x03\x13\x03\x42\0" }, - { 0x1f2f, "\x03\x97\x03\x14\x03\x42\0" }, - { 0x1f30, "\x03\xb9\x03\x13\0" }, - { 0x1f31, "\x03\xb9\x03\x14\0" }, - { 0x1f32, "\x03\xb9\x03\x13\x03\x00\0" }, - { 0x1f33, "\x03\xb9\x03\x14\x03\x00\0" }, - { 0x1f34, "\x03\xb9\x03\x13\x03\x01\0" }, - { 0x1f35, "\x03\xb9\x03\x14\x03\x01\0" }, - { 0x1f36, "\x03\xb9\x03\x13\x03\x42\0" }, - { 0x1f37, "\x03\xb9\x03\x14\x03\x42\0" }, - { 0x1f38, "\x03\x99\x03\x13\0" }, - { 0x1f39, "\x03\x99\x03\x14\0" }, - { 0x1f3a, "\x03\x99\x03\x13\x03\x00\0" }, - { 0x1f3b, "\x03\x99\x03\x14\x03\x00\0" }, - { 0x1f3c, "\x03\x99\x03\x13\x03\x01\0" }, - { 0x1f3d, "\x03\x99\x03\x14\x03\x01\0" }, - { 0x1f3e, "\x03\x99\x03\x13\x03\x42\0" }, - { 0x1f3f, "\x03\x99\x03\x14\x03\x42\0" }, - { 0x1f40, "\x03\xbf\x03\x13\0" }, - { 0x1f41, "\x03\xbf\x03\x14\0" }, - { 0x1f42, "\x03\xbf\x03\x13\x03\x00\0" }, - { 0x1f43, "\x03\xbf\x03\x14\x03\x00\0" }, - { 0x1f44, "\x03\xbf\x03\x13\x03\x01\0" }, - { 0x1f45, "\x03\xbf\x03\x14\x03\x01\0" }, - { 0x1f48, "\x03\x9f\x03\x13\0" }, - { 0x1f49, "\x03\x9f\x03\x14\0" }, - { 0x1f4a, "\x03\x9f\x03\x13\x03\x00\0" }, - { 0x1f4b, "\x03\x9f\x03\x14\x03\x00\0" }, - { 0x1f4c, "\x03\x9f\x03\x13\x03\x01\0" }, - { 0x1f4d, "\x03\x9f\x03\x14\x03\x01\0" }, - { 0x1f50, "\x03\xc5\x03\x13\0" }, - { 0x1f51, "\x03\xc5\x03\x14\0" }, - { 0x1f52, "\x03\xc5\x03\x13\x03\x00\0" }, - { 0x1f53, "\x03\xc5\x03\x14\x03\x00\0" }, - { 0x1f54, "\x03\xc5\x03\x13\x03\x01\0" }, - { 0x1f55, "\x03\xc5\x03\x14\x03\x01\0" }, - { 0x1f56, "\x03\xc5\x03\x13\x03\x42\0" }, - { 0x1f57, "\x03\xc5\x03\x14\x03\x42\0" }, - { 0x1f59, "\x03\xa5\x03\x14\0" }, - { 0x1f5b, "\x03\xa5\x03\x14\x03\x00\0" }, - { 0x1f5d, "\x03\xa5\x03\x14\x03\x01\0" }, - { 0x1f5f, "\x03\xa5\x03\x14\x03\x42\0" }, - { 0x1f60, "\x03\xc9\x03\x13\0" }, - { 0x1f61, "\x03\xc9\x03\x14\0" }, - { 0x1f62, "\x03\xc9\x03\x13\x03\x00\0" }, - { 0x1f63, "\x03\xc9\x03\x14\x03\x00\0" }, - { 0x1f64, "\x03\xc9\x03\x13\x03\x01\0" }, - { 0x1f65, "\x03\xc9\x03\x14\x03\x01\0" }, - { 0x1f66, "\x03\xc9\x03\x13\x03\x42\0" }, - { 0x1f67, "\x03\xc9\x03\x14\x03\x42\0" }, - { 0x1f68, "\x03\xa9\x03\x13\0" }, - { 0x1f69, "\x03\xa9\x03\x14\0" }, - { 0x1f6a, "\x03\xa9\x03\x13\x03\x00\0" }, - { 0x1f6b, "\x03\xa9\x03\x14\x03\x00\0" }, - { 0x1f6c, "\x03\xa9\x03\x13\x03\x01\0" }, - { 0x1f6d, "\x03\xa9\x03\x14\x03\x01\0" }, - { 0x1f6e, "\x03\xa9\x03\x13\x03\x42\0" }, - { 0x1f6f, "\x03\xa9\x03\x14\x03\x42\0" }, - { 0x1f70, "\x03\xb1\x03\x00\0" }, - { 0x1f71, "\x03\xb1\x03\x01\0" }, - { 0x1f72, "\x03\xb5\x03\x00\0" }, - { 0x1f73, "\x03\xb5\x03\x01\0" }, - { 0x1f74, "\x03\xb7\x03\x00\0" }, - { 0x1f75, "\x03\xb7\x03\x01\0" }, - { 0x1f76, "\x03\xb9\x03\x00\0" }, - { 0x1f77, "\x03\xb9\x03\x01\0" }, - { 0x1f78, "\x03\xbf\x03\x00\0" }, - { 0x1f79, "\x03\xbf\x03\x01\0" }, - { 0x1f7a, "\x03\xc5\x03\x00\0" }, - { 0x1f7b, "\x03\xc5\x03\x01\0" }, - { 0x1f7c, "\x03\xc9\x03\x00\0" }, - { 0x1f7d, "\x03\xc9\x03\x01\0" }, - { 0x1f80, "\x03\xb1\x03\x13\x03\x45\0" }, - { 0x1f81, "\x03\xb1\x03\x14\x03\x45\0" }, - { 0x1f82, "\x03\xb1\x03\x13\x03\x00\x03\x45\0" }, - { 0x1f83, "\x03\xb1\x03\x14\x03\x00\x03\x45\0" }, - { 0x1f84, "\x03\xb1\x03\x13\x03\x01\x03\x45\0" }, - { 0x1f85, "\x03\xb1\x03\x14\x03\x01\x03\x45\0" }, - { 0x1f86, "\x03\xb1\x03\x13\x03\x42\x03\x45\0" }, - { 0x1f87, "\x03\xb1\x03\x14\x03\x42\x03\x45\0" }, - { 0x1f88, "\x03\x91\x03\x13\x03\x45\0" }, - { 0x1f89, "\x03\x91\x03\x14\x03\x45\0" }, - { 0x1f8a, "\x03\x91\x03\x13\x03\x00\x03\x45\0" }, - { 0x1f8b, "\x03\x91\x03\x14\x03\x00\x03\x45\0" }, - { 0x1f8c, "\x03\x91\x03\x13\x03\x01\x03\x45\0" }, - { 0x1f8d, "\x03\x91\x03\x14\x03\x01\x03\x45\0" }, - { 0x1f8e, "\x03\x91\x03\x13\x03\x42\x03\x45\0" }, - { 0x1f8f, "\x03\x91\x03\x14\x03\x42\x03\x45\0" }, - { 0x1f90, "\x03\xb7\x03\x13\x03\x45\0" }, - { 0x1f91, "\x03\xb7\x03\x14\x03\x45\0" }, - { 0x1f92, "\x03\xb7\x03\x13\x03\x00\x03\x45\0" }, - { 0x1f93, "\x03\xb7\x03\x14\x03\x00\x03\x45\0" }, - { 0x1f94, "\x03\xb7\x03\x13\x03\x01\x03\x45\0" }, - { 0x1f95, "\x03\xb7\x03\x14\x03\x01\x03\x45\0" }, - { 0x1f96, "\x03\xb7\x03\x13\x03\x42\x03\x45\0" }, - { 0x1f97, "\x03\xb7\x03\x14\x03\x42\x03\x45\0" }, - { 0x1f98, "\x03\x97\x03\x13\x03\x45\0" }, - { 0x1f99, "\x03\x97\x03\x14\x03\x45\0" }, - { 0x1f9a, "\x03\x97\x03\x13\x03\x00\x03\x45\0" }, - { 0x1f9b, "\x03\x97\x03\x14\x03\x00\x03\x45\0" }, - { 0x1f9c, "\x03\x97\x03\x13\x03\x01\x03\x45\0" }, - { 0x1f9d, "\x03\x97\x03\x14\x03\x01\x03\x45\0" }, - { 0x1f9e, "\x03\x97\x03\x13\x03\x42\x03\x45\0" }, - { 0x1f9f, "\x03\x97\x03\x14\x03\x42\x03\x45\0" }, - { 0x1fa0, "\x03\xc9\x03\x13\x03\x45\0" }, - { 0x1fa1, "\x03\xc9\x03\x14\x03\x45\0" }, - { 0x1fa2, "\x03\xc9\x03\x13\x03\x00\x03\x45\0" }, - { 0x1fa3, "\x03\xc9\x03\x14\x03\x00\x03\x45\0" }, - { 0x1fa4, "\x03\xc9\x03\x13\x03\x01\x03\x45\0" }, - { 0x1fa5, "\x03\xc9\x03\x14\x03\x01\x03\x45\0" }, - { 0x1fa6, "\x03\xc9\x03\x13\x03\x42\x03\x45\0" }, - { 0x1fa7, "\x03\xc9\x03\x14\x03\x42\x03\x45\0" }, - { 0x1fa8, "\x03\xa9\x03\x13\x03\x45\0" }, - { 0x1fa9, "\x03\xa9\x03\x14\x03\x45\0" }, - { 0x1faa, "\x03\xa9\x03\x13\x03\x00\x03\x45\0" }, - { 0x1fab, "\x03\xa9\x03\x14\x03\x00\x03\x45\0" }, - { 0x1fac, "\x03\xa9\x03\x13\x03\x01\x03\x45\0" }, - { 0x1fad, "\x03\xa9\x03\x14\x03\x01\x03\x45\0" }, - { 0x1fae, "\x03\xa9\x03\x13\x03\x42\x03\x45\0" }, - { 0x1faf, "\x03\xa9\x03\x14\x03\x42\x03\x45\0" }, - { 0x1fb0, "\x03\xb1\x03\x06\0" }, - { 0x1fb1, "\x03\xb1\x03\x04\0" }, - { 0x1fb2, "\x03\xb1\x03\x00\x03\x45\0" }, - { 0x1fb3, "\x03\xb1\x03\x45\0" }, - { 0x1fb4, "\x03\xb1\x03\x01\x03\x45\0" }, - { 0x1fb6, "\x03\xb1\x03\x42\0" }, - { 0x1fb7, "\x03\xb1\x03\x42\x03\x45\0" }, - { 0x1fb8, "\x03\x91\x03\x06\0" }, - { 0x1fb9, "\x03\x91\x03\x04\0" }, - { 0x1fba, "\x03\x91\x03\x00\0" }, - { 0x1fbb, "\x03\x91\x03\x01\0" }, - { 0x1fbc, "\x03\x91\x03\x45\0" }, - { 0x1fbe, "\x03\xb9\0" }, - { 0x1fc1, "\x00\xa8\x03\x42\0" }, - { 0x1fc2, "\x03\xb7\x03\x00\x03\x45\0" }, - { 0x1fc3, "\x03\xb7\x03\x45\0" }, - { 0x1fc4, "\x03\xb7\x03\x01\x03\x45\0" }, - { 0x1fc6, "\x03\xb7\x03\x42\0" }, - { 0x1fc7, "\x03\xb7\x03\x42\x03\x45\0" }, - { 0x1fc8, "\x03\x95\x03\x00\0" }, - { 0x1fc9, "\x03\x95\x03\x01\0" }, - { 0x1fca, "\x03\x97\x03\x00\0" }, - { 0x1fcb, "\x03\x97\x03\x01\0" }, - { 0x1fcc, "\x03\x97\x03\x45\0" }, - { 0x1fcd, "\x1f\xbf\x03\x00\0" }, - { 0x1fce, "\x1f\xbf\x03\x01\0" }, - { 0x1fcf, "\x1f\xbf\x03\x42\0" }, - { 0x1fd0, "\x03\xb9\x03\x06\0" }, - { 0x1fd1, "\x03\xb9\x03\x04\0" }, - { 0x1fd2, "\x03\xb9\x03\x08\x03\x00\0" }, - { 0x1fd3, "\x03\xb9\x03\x08\x03\x01\0" }, - { 0x1fd6, "\x03\xb9\x03\x42\0" }, - { 0x1fd7, "\x03\xb9\x03\x08\x03\x42\0" }, - { 0x1fd8, "\x03\x99\x03\x06\0" }, - { 0x1fd9, "\x03\x99\x03\x04\0" }, - { 0x1fda, "\x03\x99\x03\x00\0" }, - { 0x1fdb, "\x03\x99\x03\x01\0" }, - { 0x1fdd, "\x1f\xfe\x03\x00\0" }, - { 0x1fde, "\x1f\xfe\x03\x01\0" }, - { 0x1fdf, "\x1f\xfe\x03\x42\0" }, - { 0x1fe0, "\x03\xc5\x03\x06\0" }, - { 0x1fe1, "\x03\xc5\x03\x04\0" }, - { 0x1fe2, "\x03\xc5\x03\x08\x03\x00\0" }, - { 0x1fe3, "\x03\xc5\x03\x08\x03\x01\0" }, - { 0x1fe4, "\x03\xc1\x03\x13\0" }, - { 0x1fe5, "\x03\xc1\x03\x14\0" }, - { 0x1fe6, "\x03\xc5\x03\x42\0" }, - { 0x1fe7, "\x03\xc5\x03\x08\x03\x42\0" }, - { 0x1fe8, "\x03\xa5\x03\x06\0" }, - { 0x1fe9, "\x03\xa5\x03\x04\0" }, - { 0x1fea, "\x03\xa5\x03\x00\0" }, - { 0x1feb, "\x03\xa5\x03\x01\0" }, - { 0x1fec, "\x03\xa1\x03\x14\0" }, - { 0x1fed, "\x00\xa8\x03\x00\0" }, - { 0x1fee, "\x00\xa8\x03\x01\0" }, - { 0x1fef, "\x00\x60\0" }, - { 0x1ff2, "\x03\xc9\x03\x00\x03\x45\0" }, - { 0x1ff3, "\x03\xc9\x03\x45\0" }, - { 0x1ff4, "\x03\xc9\x03\x01\x03\x45\0" }, - { 0x1ff6, "\x03\xc9\x03\x42\0" }, - { 0x1ff7, "\x03\xc9\x03\x42\x03\x45\0" }, - { 0x1ff8, "\x03\x9f\x03\x00\0" }, - { 0x1ff9, "\x03\x9f\x03\x01\0" }, - { 0x1ffa, "\x03\xa9\x03\x00\0" }, - { 0x1ffb, "\x03\xa9\x03\x01\0" }, - { 0x1ffc, "\x03\xa9\x03\x45\0" }, - { 0x1ffd, "\x00\xb4\0" }, - { 0x2000, "\x20\x02\0" }, - { 0x2001, "\x20\x03\0" }, - { 0x2126, "\x03\xa9\0" }, - { 0x212a, "\x00\x4b\0" }, - { 0x212b, "\x00\x41\x03\x0a\0" }, - { 0x2204, "\x22\x03\x03\x38\0" }, - { 0x2209, "\x22\x08\x03\x38\0" }, - { 0x220c, "\x22\x0b\x03\x38\0" }, - { 0x2224, "\x22\x23\x03\x38\0" }, - { 0x2226, "\x22\x25\x03\x38\0" }, - { 0x2241, "\x00\x7e\x03\x38\0" }, - { 0x2244, "\x22\x43\x03\x38\0" }, - { 0x2247, "\x22\x45\x03\x38\0" }, - { 0x2249, "\x22\x48\x03\x38\0" }, - { 0x2260, "\x00\x3d\x03\x38\0" }, - { 0x2262, "\x22\x61\x03\x38\0" }, - { 0x226d, "\x22\x4d\x03\x38\0" }, - { 0x226e, "\x00\x3c\x03\x38\0" }, - { 0x226f, "\x00\x3e\x03\x38\0" }, - { 0x2270, "\x22\x64\x03\x38\0" }, - { 0x2271, "\x22\x65\x03\x38\0" }, - { 0x2274, "\x22\x72\x03\x38\0" }, - { 0x2275, "\x22\x73\x03\x38\0" }, - { 0x2278, "\x22\x76\x03\x38\0" }, - { 0x2279, "\x22\x77\x03\x38\0" }, - { 0x2280, "\x22\x7a\x03\x38\0" }, - { 0x2281, "\x22\x7b\x03\x38\0" }, - { 0x2284, "\x22\x82\x03\x38\0" }, - { 0x2285, "\x22\x83\x03\x38\0" }, - { 0x2288, "\x22\x86\x03\x38\0" }, - { 0x2289, "\x22\x87\x03\x38\0" }, - { 0x22ac, "\x22\xa2\x03\x38\0" }, - { 0x22ad, "\x22\xa8\x03\x38\0" }, - { 0x22ae, "\x22\xa9\x03\x38\0" }, - { 0x22af, "\x22\xab\x03\x38\0" }, - { 0x22e0, "\x22\x7c\x03\x38\0" }, - { 0x22e1, "\x22\x7d\x03\x38\0" }, - { 0x22e2, "\x22\x91\x03\x38\0" }, - { 0x22e3, "\x22\x92\x03\x38\0" }, - { 0x22ea, "\x22\xb2\x03\x38\0" }, - { 0x22eb, "\x22\xb3\x03\x38\0" }, - { 0x22ec, "\x22\xb4\x03\x38\0" }, - { 0x22ed, "\x22\xb5\x03\x38\0" }, - { 0x2329, "\x30\x08\0" }, - { 0x232a, "\x30\x09\0" }, - { 0x304c, "\x30\x4b\x30\x99\0" }, - { 0x304e, "\x30\x4d\x30\x99\0" }, - { 0x3050, "\x30\x4f\x30\x99\0" }, - { 0x3052, "\x30\x51\x30\x99\0" }, - { 0x3054, "\x30\x53\x30\x99\0" }, - { 0x3056, "\x30\x55\x30\x99\0" }, - { 0x3058, "\x30\x57\x30\x99\0" }, - { 0x305a, "\x30\x59\x30\x99\0" }, - { 0x305c, "\x30\x5b\x30\x99\0" }, - { 0x305e, "\x30\x5d\x30\x99\0" }, - { 0x3060, "\x30\x5f\x30\x99\0" }, - { 0x3062, "\x30\x61\x30\x99\0" }, - { 0x3065, "\x30\x64\x30\x99\0" }, - { 0x3067, "\x30\x66\x30\x99\0" }, - { 0x3069, "\x30\x68\x30\x99\0" }, - { 0x3070, "\x30\x6f\x30\x99\0" }, - { 0x3071, "\x30\x6f\x30\x9a\0" }, - { 0x3073, "\x30\x72\x30\x99\0" }, - { 0x3074, "\x30\x72\x30\x9a\0" }, - { 0x3076, "\x30\x75\x30\x99\0" }, - { 0x3077, "\x30\x75\x30\x9a\0" }, - { 0x3079, "\x30\x78\x30\x99\0" }, - { 0x307a, "\x30\x78\x30\x9a\0" }, - { 0x307c, "\x30\x7b\x30\x99\0" }, - { 0x307d, "\x30\x7b\x30\x9a\0" }, - { 0x3094, "\x30\x46\x30\x99\0" }, - { 0x309e, "\x30\x9d\x30\x99\0" }, - { 0x30ac, "\x30\xab\x30\x99\0" }, - { 0x30ae, "\x30\xad\x30\x99\0" }, - { 0x30b0, "\x30\xaf\x30\x99\0" }, - { 0x30b2, "\x30\xb1\x30\x99\0" }, - { 0x30b4, "\x30\xb3\x30\x99\0" }, - { 0x30b6, "\x30\xb5\x30\x99\0" }, - { 0x30b8, "\x30\xb7\x30\x99\0" }, - { 0x30ba, "\x30\xb9\x30\x99\0" }, - { 0x30bc, "\x30\xbb\x30\x99\0" }, - { 0x30be, "\x30\xbd\x30\x99\0" }, - { 0x30c0, "\x30\xbf\x30\x99\0" }, - { 0x30c2, "\x30\xc1\x30\x99\0" }, - { 0x30c5, "\x30\xc4\x30\x99\0" }, - { 0x30c7, "\x30\xc6\x30\x99\0" }, - { 0x30c9, "\x30\xc8\x30\x99\0" }, - { 0x30d0, "\x30\xcf\x30\x99\0" }, - { 0x30d1, "\x30\xcf\x30\x9a\0" }, - { 0x30d3, "\x30\xd2\x30\x99\0" }, - { 0x30d4, "\x30\xd2\x30\x9a\0" }, - { 0x30d6, "\x30\xd5\x30\x99\0" }, - { 0x30d7, "\x30\xd5\x30\x9a\0" }, - { 0x30d9, "\x30\xd8\x30\x99\0" }, - { 0x30da, "\x30\xd8\x30\x9a\0" }, - { 0x30dc, "\x30\xdb\x30\x99\0" }, - { 0x30dd, "\x30\xdb\x30\x9a\0" }, - { 0x30f4, "\x30\xa6\x30\x99\0" }, - { 0x30f7, "\x30\xef\x30\x99\0" }, - { 0x30f8, "\x30\xf0\x30\x99\0" }, - { 0x30f9, "\x30\xf1\x30\x99\0" }, - { 0x30fa, "\x30\xf2\x30\x99\0" }, - { 0x30fe, "\x30\xfd\x30\x99\0" }, - { 0xf900, "\x8c\x48\0" }, - { 0xf901, "\x66\xf4\0" }, - { 0xf902, "\x8e\xca\0" }, - { 0xf903, "\x8c\xc8\0" }, - { 0xf904, "\x6e\xd1\0" }, - { 0xf905, "\x4e\x32\0" }, - { 0xf906, "\x53\xe5\0" }, - { 0xf907, "\x9f\x9c\0" }, - { 0xf908, "\x9f\x9c\0" }, - { 0xf909, "\x59\x51\0" }, - { 0xf90a, "\x91\xd1\0" }, - { 0xf90b, "\x55\x87\0" }, - { 0xf90c, "\x59\x48\0" }, - { 0xf90d, "\x61\xf6\0" }, - { 0xf90e, "\x76\x69\0" }, - { 0xf90f, "\x7f\x85\0" }, - { 0xf910, "\x86\x3f\0" }, - { 0xf911, "\x87\xba\0" }, - { 0xf912, "\x88\xf8\0" }, - { 0xf913, "\x90\x8f\0" }, - { 0xf914, "\x6a\x02\0" }, - { 0xf915, "\x6d\x1b\0" }, - { 0xf916, "\x70\xd9\0" }, - { 0xf917, "\x73\xde\0" }, - { 0xf918, "\x84\x3d\0" }, - { 0xf919, "\x91\x6a\0" }, - { 0xf91a, "\x99\xf1\0" }, - { 0xf91b, "\x4e\x82\0" }, - { 0xf91c, "\x53\x75\0" }, - { 0xf91d, "\x6b\x04\0" }, - { 0xf91e, "\x72\x1b\0" }, - { 0xf91f, "\x86\x2d\0" }, - { 0xf920, "\x9e\x1e\0" }, - { 0xf921, "\x5d\x50\0" }, - { 0xf922, "\x6f\xeb\0" }, - { 0xf923, "\x85\xcd\0" }, - { 0xf924, "\x89\x64\0" }, - { 0xf925, "\x62\xc9\0" }, - { 0xf926, "\x81\xd8\0" }, - { 0xf927, "\x88\x1f\0" }, - { 0xf928, "\x5e\xca\0" }, - { 0xf929, "\x67\x17\0" }, - { 0xf92a, "\x6d\x6a\0" }, - { 0xf92b, "\x72\xfc\0" }, - { 0xf92c, "\x90\xce\0" }, - { 0xf92d, "\x4f\x86\0" }, - { 0xf92e, "\x51\xb7\0" }, - { 0xf92f, "\x52\xde\0" }, - { 0xf930, "\x64\xc4\0" }, - { 0xf931, "\x6a\xd3\0" }, - { 0xf932, "\x72\x10\0" }, - { 0xf933, "\x76\xe7\0" }, - { 0xf934, "\x80\x01\0" }, - { 0xf935, "\x86\x06\0" }, - { 0xf936, "\x86\x5c\0" }, - { 0xf937, "\x8d\xef\0" }, - { 0xf938, "\x97\x32\0" }, - { 0xf939, "\x9b\x6f\0" }, - { 0xf93a, "\x9d\xfa\0" }, - { 0xf93b, "\x78\x8c\0" }, - { 0xf93c, "\x79\x7f\0" }, - { 0xf93d, "\x7d\xa0\0" }, - { 0xf93e, "\x83\xc9\0" }, - { 0xf93f, "\x93\x04\0" }, - { 0xf940, "\x9e\x7f\0" }, - { 0xf941, "\x8a\xd6\0" }, - { 0xf942, "\x58\xdf\0" }, - { 0xf943, "\x5f\x04\0" }, - { 0xf944, "\x7c\x60\0" }, - { 0xf945, "\x80\x7e\0" }, - { 0xf946, "\x72\x62\0" }, - { 0xf947, "\x78\xca\0" }, - { 0xf948, "\x8c\xc2\0" }, - { 0xf949, "\x96\xf7\0" }, - { 0xf94a, "\x58\xd8\0" }, - { 0xf94b, "\x5c\x62\0" }, - { 0xf94c, "\x6a\x13\0" }, - { 0xf94d, "\x6d\xda\0" }, - { 0xf94e, "\x6f\x0f\0" }, - { 0xf94f, "\x7d\x2f\0" }, - { 0xf950, "\x7e\x37\0" }, - { 0xf951, "\x96\xfb\0" }, - { 0xf952, "\x52\xd2\0" }, - { 0xf953, "\x80\x8b\0" }, - { 0xf954, "\x51\xdc\0" }, - { 0xf955, "\x51\xcc\0" }, - { 0xf956, "\x7a\x1c\0" }, - { 0xf957, "\x7d\xbe\0" }, - { 0xf958, "\x83\xf1\0" }, - { 0xf959, "\x96\x75\0" }, - { 0xf95a, "\x8b\x80\0" }, - { 0xf95b, "\x62\xcf\0" }, - { 0xf95c, "\x6a\x02\0" }, - { 0xf95d, "\x8a\xfe\0" }, - { 0xf95e, "\x4e\x39\0" }, - { 0xf95f, "\x5b\xe7\0" }, - { 0xf960, "\x60\x12\0" }, - { 0xf961, "\x73\x87\0" }, - { 0xf962, "\x75\x70\0" }, - { 0xf963, "\x53\x17\0" }, - { 0xf964, "\x78\xfb\0" }, - { 0xf965, "\x4f\xbf\0" }, - { 0xf966, "\x5f\xa9\0" }, - { 0xf967, "\x4e\x0d\0" }, - { 0xf968, "\x6c\xcc\0" }, - { 0xf969, "\x65\x78\0" }, - { 0xf96a, "\x7d\x22\0" }, - { 0xf96b, "\x53\xc3\0" }, - { 0xf96c, "\x58\x5e\0" }, - { 0xf96d, "\x77\x01\0" }, - { 0xf96e, "\x84\x49\0" }, - { 0xf96f, "\x8a\xaa\0" }, - { 0xf970, "\x6b\xba\0" }, - { 0xf971, "\x8f\xb0\0" }, - { 0xf972, "\x6c\x88\0" }, - { 0xf973, "\x62\xfe\0" }, - { 0xf974, "\x82\xe5\0" }, - { 0xf975, "\x63\xa0\0" }, - { 0xf976, "\x75\x65\0" }, - { 0xf977, "\x4e\xae\0" }, - { 0xf978, "\x51\x69\0" }, - { 0xf979, "\x51\xc9\0" }, - { 0xf97a, "\x68\x81\0" }, - { 0xf97b, "\x7c\xe7\0" }, - { 0xf97c, "\x82\x6f\0" }, - { 0xf97d, "\x8a\xd2\0" }, - { 0xf97e, "\x91\xcf\0" }, - { 0xf97f, "\x52\xf5\0" }, - { 0xf980, "\x54\x42\0" }, - { 0xf981, "\x59\x73\0" }, - { 0xf982, "\x5e\xec\0" }, - { 0xf983, "\x65\xc5\0" }, - { 0xf984, "\x6f\xfe\0" }, - { 0xf985, "\x79\x2a\0" }, - { 0xf986, "\x95\xad\0" }, - { 0xf987, "\x9a\x6a\0" }, - { 0xf988, "\x9e\x97\0" }, - { 0xf989, "\x9e\xce\0" }, - { 0xf98a, "\x52\x9b\0" }, - { 0xf98b, "\x66\xc6\0" }, - { 0xf98c, "\x6b\x77\0" }, - { 0xf98d, "\x8f\x62\0" }, - { 0xf98e, "\x5e\x74\0" }, - { 0xf98f, "\x61\x90\0" }, - { 0xf990, "\x62\x00\0" }, - { 0xf991, "\x64\x9a\0" }, - { 0xf992, "\x6f\x23\0" }, - { 0xf993, "\x71\x49\0" }, - { 0xf994, "\x74\x89\0" }, - { 0xf995, "\x79\xca\0" }, - { 0xf996, "\x7d\xf4\0" }, - { 0xf997, "\x80\x6f\0" }, - { 0xf998, "\x8f\x26\0" }, - { 0xf999, "\x84\xee\0" }, - { 0xf99a, "\x90\x23\0" }, - { 0xf99b, "\x93\x4a\0" }, - { 0xf99c, "\x52\x17\0" }, - { 0xf99d, "\x52\xa3\0" }, - { 0xf99e, "\x54\xbd\0" }, - { 0xf99f, "\x70\xc8\0" }, - { 0xf9a0, "\x88\xc2\0" }, - { 0xf9a1, "\x8a\xaa\0" }, - { 0xf9a2, "\x5e\xc9\0" }, - { 0xf9a3, "\x5f\xf5\0" }, - { 0xf9a4, "\x63\x7b\0" }, - { 0xf9a5, "\x6b\xae\0" }, - { 0xf9a6, "\x7c\x3e\0" }, - { 0xf9a7, "\x73\x75\0" }, - { 0xf9a8, "\x4e\xe4\0" }, - { 0xf9a9, "\x56\xf9\0" }, - { 0xf9aa, "\x5b\xe7\0" }, - { 0xf9ab, "\x5d\xba\0" }, - { 0xf9ac, "\x60\x1c\0" }, - { 0xf9ad, "\x73\xb2\0" }, - { 0xf9ae, "\x74\x69\0" }, - { 0xf9af, "\x7f\x9a\0" }, - { 0xf9b0, "\x80\x46\0" }, - { 0xf9b1, "\x92\x34\0" }, - { 0xf9b2, "\x96\xf6\0" }, - { 0xf9b3, "\x97\x48\0" }, - { 0xf9b4, "\x98\x18\0" }, - { 0xf9b5, "\x4f\x8b\0" }, - { 0xf9b6, "\x79\xae\0" }, - { 0xf9b7, "\x91\xb4\0" }, - { 0xf9b8, "\x96\xb8\0" }, - { 0xf9b9, "\x60\xe1\0" }, - { 0xf9ba, "\x4e\x86\0" }, - { 0xf9bb, "\x50\xda\0" }, - { 0xf9bc, "\x5b\xee\0" }, - { 0xf9bd, "\x5c\x3f\0" }, - { 0xf9be, "\x65\x99\0" }, - { 0xf9bf, "\x6a\x02\0" }, - { 0xf9c0, "\x71\xce\0" }, - { 0xf9c1, "\x76\x42\0" }, - { 0xf9c2, "\x84\xfc\0" }, - { 0xf9c3, "\x90\x7c\0" }, - { 0xf9c4, "\x9f\x8d\0" }, - { 0xf9c5, "\x66\x88\0" }, - { 0xf9c6, "\x96\x2e\0" }, - { 0xf9c7, "\x52\x89\0" }, - { 0xf9c8, "\x67\x7b\0" }, - { 0xf9c9, "\x67\xf3\0" }, - { 0xf9ca, "\x6d\x41\0" }, - { 0xf9cb, "\x6e\x9c\0" }, - { 0xf9cc, "\x74\x09\0" }, - { 0xf9cd, "\x75\x59\0" }, - { 0xf9ce, "\x78\x6b\0" }, - { 0xf9cf, "\x7d\x10\0" }, - { 0xf9d0, "\x98\x5e\0" }, - { 0xf9d1, "\x51\x6d\0" }, - { 0xf9d2, "\x62\x2e\0" }, - { 0xf9d3, "\x96\x78\0" }, - { 0xf9d4, "\x50\x2b\0" }, - { 0xf9d5, "\x5d\x19\0" }, - { 0xf9d6, "\x6d\xea\0" }, - { 0xf9d7, "\x8f\x2a\0" }, - { 0xf9d8, "\x5f\x8b\0" }, - { 0xf9d9, "\x61\x44\0" }, - { 0xf9da, "\x68\x17\0" }, - { 0xf9db, "\x73\x87\0" }, - { 0xf9dc, "\x96\x86\0" }, - { 0xf9dd, "\x52\x29\0" }, - { 0xf9de, "\x54\x0f\0" }, - { 0xf9df, "\x5c\x65\0" }, - { 0xf9e0, "\x66\x13\0" }, - { 0xf9e1, "\x67\x4e\0" }, - { 0xf9e2, "\x68\xa8\0" }, - { 0xf9e3, "\x6c\xe5\0" }, - { 0xf9e4, "\x74\x06\0" }, - { 0xf9e5, "\x75\xe2\0" }, - { 0xf9e6, "\x7f\x79\0" }, - { 0xf9e7, "\x88\xcf\0" }, - { 0xf9e8, "\x88\xe1\0" }, - { 0xf9e9, "\x91\xcc\0" }, - { 0xf9ea, "\x96\xe2\0" }, - { 0xf9eb, "\x53\x3f\0" }, - { 0xf9ec, "\x6e\xba\0" }, - { 0xf9ed, "\x54\x1d\0" }, - { 0xf9ee, "\x71\xd0\0" }, - { 0xf9ef, "\x74\x98\0" }, - { 0xf9f0, "\x85\xfa\0" }, - { 0xf9f1, "\x96\xa3\0" }, - { 0xf9f2, "\x9c\x57\0" }, - { 0xf9f3, "\x9e\x9f\0" }, - { 0xf9f4, "\x67\x97\0" }, - { 0xf9f5, "\x6d\xcb\0" }, - { 0xf9f6, "\x81\xe8\0" }, - { 0xf9f7, "\x7a\xcb\0" }, - { 0xf9f8, "\x7b\x20\0" }, - { 0xf9f9, "\x7c\x92\0" }, - { 0xf9fa, "\x72\xc0\0" }, - { 0xf9fb, "\x70\x99\0" }, - { 0xf9fc, "\x8b\x58\0" }, - { 0xf9fd, "\x4e\xc0\0" }, - { 0xf9fe, "\x83\x36\0" }, - { 0xf9ff, "\x52\x3a\0" }, - { 0xfa00, "\x52\x07\0" }, - { 0xfa01, "\x5e\xa6\0" }, - { 0xfa02, "\x62\xd3\0" }, - { 0xfa03, "\x7c\xd6\0" }, - { 0xfa04, "\x5b\x85\0" }, - { 0xfa05, "\x6d\x1e\0" }, - { 0xfa06, "\x66\xb4\0" }, - { 0xfa07, "\x8f\x3b\0" }, - { 0xfa08, "\x88\x4c\0" }, - { 0xfa09, "\x96\x4d\0" }, - { 0xfa0a, "\x89\x8b\0" }, - { 0xfa0b, "\x5e\xd3\0" }, - { 0xfa0c, "\x51\x40\0" }, - { 0xfa0d, "\x55\xc0\0" }, - { 0xfa10, "\x58\x5a\0" }, - { 0xfa12, "\x66\x74\0" }, - { 0xfa15, "\x51\xde\0" }, - { 0xfa16, "\x73\x2a\0" }, - { 0xfa17, "\x76\xca\0" }, - { 0xfa18, "\x79\x3c\0" }, - { 0xfa19, "\x79\x5e\0" }, - { 0xfa1a, "\x79\x65\0" }, - { 0xfa1b, "\x79\x8f\0" }, - { 0xfa1c, "\x97\x56\0" }, - { 0xfa1d, "\x7c\xbe\0" }, - { 0xfa1e, "\x7f\xbd\0" }, - { 0xfa20, "\x86\x12\0" }, - { 0xfa22, "\x8a\xf8\0" }, - { 0xfa25, "\x90\x38\0" }, - { 0xfa26, "\x90\xfd\0" }, - { 0xfa2a, "\x98\xef\0" }, - { 0xfa2b, "\x98\xfc\0" }, - { 0xfa2c, "\x99\x28\0" }, - { 0xfa2d, "\x9d\xb4\0" }, - { 0xfb1f, "\x05\xf2\x05\xb7\0" }, - { 0xfb2a, "\x05\xe9\x05\xc1\0" }, - { 0xfb2b, "\x05\xe9\x05\xc2\0" }, - { 0xfb2c, "\x05\xe9\x05\xbc\x05\xc1\0" }, - { 0xfb2d, "\x05\xe9\x05\xbc\x05\xc2\0" }, - { 0xfb2e, "\x05\xd0\x05\xb7\0" }, - { 0xfb2f, "\x05\xd0\x05\xb8\0" }, - { 0xfb30, "\x05\xd0\x05\xbc\0" }, - { 0xfb31, "\x05\xd1\x05\xbc\0" }, - { 0xfb32, "\x05\xd2\x05\xbc\0" }, - { 0xfb33, "\x05\xd3\x05\xbc\0" }, - { 0xfb34, "\x05\xd4\x05\xbc\0" }, - { 0xfb35, "\x05\xd5\x05\xbc\0" }, - { 0xfb36, "\x05\xd6\x05\xbc\0" }, - { 0xfb38, "\x05\xd8\x05\xbc\0" }, - { 0xfb39, "\x05\xd9\x05\xbc\0" }, - { 0xfb3a, "\x05\xda\x05\xbc\0" }, - { 0xfb3b, "\x05\xdb\x05\xbc\0" }, - { 0xfb3c, "\x05\xdc\x05\xbc\0" }, - { 0xfb3e, "\x05\xde\x05\xbc\0" }, - { 0xfb40, "\x05\xe0\x05\xbc\0" }, - { 0xfb41, "\x05\xe1\x05\xbc\0" }, - { 0xfb43, "\x05\xe3\x05\xbc\0" }, - { 0xfb44, "\x05\xe4\x05\xbc\0" }, - { 0xfb46, "\x05\xe6\x05\xbc\0" }, - { 0xfb47, "\x05\xe7\x05\xbc\0" }, - { 0xfb48, "\x05\xe8\x05\xbc\0" }, - { 0xfb49, "\x05\xe9\x05\xbc\0" }, - { 0xfb4a, "\x05\xea\x05\xbc\0" }, - { 0xfb4b, "\x05\xd5\x05\xb9\0" }, - { 0xfb4c, "\x05\xd1\x05\xbf\0" }, - { 0xfb4d, "\x05\xdb\x05\xbf\0" }, - { 0xfb4e, "\x05\xe4\x05\xbf\0" } -}; - -/* - * WARNING! - * - * NO BUFFER CHECKING AHEAD! - * - */ - -static gint -e_canonical_decomposition (gunichar ch, gunichar * buf) -{ - gint len = 0; - - if (ch <= 0xffff) - { - int start = 0; - int end = sizeof (e_decomp_table) / sizeof (e_decomp_table[0]); - while (start != end) - { - int half = (start + end) / 2; - if (ch == e_decomp_table[half].ch) { - /* Found it. */ - int i; - /* We store as a double-nul terminated string. */ - for (len = 0; (e_decomp_table[half].expansion[len] || e_decomp_table[half].expansion[len + 1]); len += 2) ; - - /* We've counted twice as many bytes as there are - characters. */ - len /= 2; - - for (i = 0; i < len; i ++) { - buf[i] = (e_decomp_table[half].expansion[2 * i] << 8) | e_decomp_table[half].expansion[2 * i + 1]; - } - break; - } else if (ch > e_decomp_table[half].ch) { - if (start == half) break; - start = half; - } else { - if (end == half) break; - end = half; - } - } - } - - if (len == 0) - { - /* Not in our table. */ - *buf = ch; - len = 1; - } - - /* Supposedly following the Unicode 2.1.9 table means that the - decompositions come out in canonical order. I haven't tested - this, but we rely on it here. */ - return len; -} - -static gunichar -e_stripped_char (gunichar ch) -{ - gunichar decomp[MAX_DECOMP]; - GUnicodeType utype; - gint dlen; - - utype = g_unichar_type (ch); - - switch (utype) { - case G_UNICODE_CONTROL: - case G_UNICODE_FORMAT: - case G_UNICODE_UNASSIGNED: - case G_UNICODE_COMBINING_MARK: - /* Ignore those */ - return 0; - default: - /* Convert to lowercase, fall through */ - ch = g_unichar_tolower (ch); - case G_UNICODE_LOWERCASE_LETTER: - dlen = e_canonical_decomposition (ch, decomp); - if (dlen > 0) return *decomp; - break; - } - - return 0; -} - -gchar * -e_xml_get_translated_utf8_string_prop_by_name (const xmlNode *parent, const xmlChar *prop_name) -{ - xmlChar *prop; - gchar *ret_val = NULL; - gchar *combined_name; - - g_return_val_if_fail (parent != NULL, NULL); - g_return_val_if_fail (prop_name != NULL, NULL); - - prop = xmlGetProp ((xmlNode *) parent, prop_name); - if (prop != NULL) { - ret_val = g_strdup ((char *)prop); - xmlFree (prop); - return ret_val; - } - - combined_name = g_strdup_printf("_%s", prop_name); - prop = xmlGetProp ((xmlNode *) parent, (unsigned char *)combined_name); - if (prop != NULL) { - ret_val = g_strdup (gettext ((char *)prop)); - xmlFree (prop); - } - g_free(combined_name); - - return ret_val; -} diff --git a/widgets/misc/e-unicode.h b/widgets/misc/e-unicode.h deleted file mode 100644 index b745876b6d..0000000000 --- a/widgets/misc/e-unicode.h +++ /dev/null @@ -1,113 +0,0 @@ -/* - * e-unicode.h - utf-8 support functions for gal - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) version 3. - * - * 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with the program; if not, see <http://www.gnu.org/licenses/> - * - * - * Authors: - * Lauris Kaplinski <lauris@ximian.com> - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#ifndef _E_UNICODE_H_ -#define _E_UNICODE_H_ - -#include <sys/types.h> -#include <glib.h> -#include <gtk/gtk.h> -#include <libxml/tree.h> -#include <iconv.h> - -G_BEGIN_DECLS - -#define G_UTF8_IN_GAL - -/* - * UTF-8 searching implementations - * - * e_utf8_strstrcase - case insensitive search - * e_utf8_strstrcasedecomp - case insensitive and decompositing search (i.e. accented - * letters are treated equal to their base letters, explicit accent marks (unicode - * not ascii/iso ones) are ignored). - */ - -const gchar *e_utf8_strstrcase (const gchar *haystack, - const gchar *needle); -const gchar *e_utf8_strstrcasedecomp (const gchar *haystack, - const gchar *needle); -gchar *e_utf8_from_gtk_event_key (GtkWidget *widget, - guint keyval, - const gchar *string); -gchar *e_utf8_from_iconv_string (iconv_t ic, - const gchar *string); -gchar *e_utf8_from_iconv_string_sized (iconv_t ic, - const gchar *string, - gint bytes); -gchar *e_utf8_to_iconv_string (iconv_t ic, - const gchar *string); -gchar *e_utf8_to_iconv_string_sized (iconv_t ic, - const gchar *string, - gint bytes); -gchar *e_utf8_from_charset_string (const gchar *charset, - const gchar *string); -gchar *e_utf8_from_charset_string_sized (const gchar *charset, - const gchar *string, - gint bytes); -gchar *e_utf8_to_charset_string (const gchar *charset, - const gchar *string); -gchar *e_utf8_to_charset_string_sized (const gchar *charset, - const gchar *string, - gint bytes); -gchar *e_utf8_from_locale_string (const gchar *string); -gchar *e_utf8_from_locale_string_sized (const gchar *string, - gint bytes); -gchar *e_utf8_to_locale_string (const gchar *string); -gchar *e_utf8_to_locale_string_sized (const gchar *string, - gint bytes); -gboolean e_utf8_is_ascii (const gchar *string); -/* - * These are simple wrappers that save us some typing - */ - -/* NB! This return newly allocated string, not const as gtk+ one */ -gchar *e_utf8_gtk_entry_get_text (GtkEntry *entry); -void e_utf8_gtk_entry_set_text (GtkEntry *entry, - const gchar *text); -gchar *e_utf8_gtk_editable_get_text (GtkEditable *editable); -void e_utf8_gtk_editable_set_text (GtkEditable *editable, - const gchar *text); -gchar *e_utf8_gtk_editable_get_chars (GtkEditable *editable, - gint start, - gint end); -void e_utf8_gtk_editable_insert_text (GtkEditable *editable, - const gchar *text, - gint length, - gint *position); -gchar *e_utf8_xml1_decode (const gchar *text); -gchar *e_utf8_xml1_encode (const gchar *text); -gint e_unichar_to_utf8 (gint c, - gchar *outbuf); -gchar *e_unicode_get_utf8 (const gchar *text, - gunichar *out); -guint32 gdk_keyval_to_unicode (guint keysym); -gchar *e_xml_get_translated_utf8_string_prop_by_name (const xmlNode *parent, - const xmlChar *prop_name); - -G_END_DECLS - -#endif - - diff --git a/widgets/table/Makefile.am b/widgets/table/Makefile.am index be43b559e4..a53b249ce4 100644 --- a/widgets/table/Makefile.am +++ b/widgets/table/Makefile.am @@ -1,9 +1,3 @@ -if OS_WIN32 -WIN32_BOOTSTRAP_LIBS = \ - $(top_builddir)/win32/libemiscwidgets.la \ - $(top_builddir)/win32/libetext.la -endif - glade_DATA = \ e-table-config.glade \ e-table-field-chooser.glade @@ -24,7 +18,9 @@ libetable_la_SOURCES = \ e-cell-checkbox.c \ e-cell-combo.c \ e-cell-date.c \ + e-cell-date-edit.c \ e-cell-number.c \ + e-cell-percent.c \ e-cell-pixbuf.c \ e-cell-popup.c \ e-cell-size.c \ @@ -76,7 +72,23 @@ libetable_la_SOURCES = \ e-tree-selection-model.c \ e-tree-sorted.c \ e-tree-table-adapter.c \ - e-tree.c + e-tree.c \ + a11y/gal-a11y-e-cell.c \ + a11y/gal-a11y-e-cell-popup.c \ + a11y/gal-a11y-e-cell-registry.c \ + a11y/gal-a11y-e-cell-text.c \ + a11y/gal-a11y-e-cell-toggle.c \ + a11y/gal-a11y-e-cell-tree.c \ + a11y/gal-a11y-e-cell-vbox.c \ + a11y/gal-a11y-e-table.c \ + a11y/gal-a11y-e-table-click-to-add.c \ + a11y/gal-a11y-e-table-click-to-add-factory.c \ + a11y/gal-a11y-e-table-column-header.c \ + a11y/gal-a11y-e-table-factory.c \ + a11y/gal-a11y-e-table-item.c \ + a11y/gal-a11y-e-table-item-factory.c \ + a11y/gal-a11y-e-tree.c \ + a11y/gal-a11y-e-tree-factory.c libetableincludedir = $(privincludedir)/table @@ -85,7 +97,9 @@ libetableinclude_HEADERS = \ e-cell-checkbox.h \ e-cell-combo.h \ e-cell-date.h \ + e-cell-date-edit.h \ e-cell-number.h \ + e-cell-percent.h \ e-cell-pixbuf.h \ e-cell-popup.h \ e-cell-size.h \ @@ -140,16 +154,34 @@ libetableinclude_HEADERS = \ e-tree-selection-model.h \ e-tree-sorted.h \ e-tree-table-adapter.h \ - e-tree.h + e-tree.h \ + a11y/gal-a11y-e-cell.h \ + a11y/gal-a11y-e-cell-popup.h \ + a11y/gal-a11y-e-cell-registry.h \ + a11y/gal-a11y-e-cell-text.h \ + a11y/gal-a11y-e-cell-toggle.h \ + a11y/gal-a11y-e-cell-tree.h \ + a11y/gal-a11y-e-cell-vbox.h \ + a11y/gal-a11y-e-table.h \ + a11y/gal-a11y-e-table-click-to-add.h \ + a11y/gal-a11y-e-table-click-to-add-factory.h \ + a11y/gal-a11y-e-table-column-header.h \ + a11y/gal-a11y-e-table-factory.h \ + a11y/gal-a11y-e-table-item.h \ + a11y/gal-a11y-e-table-item-factory.h \ + a11y/gal-a11y-e-tree.h \ + a11y/gal-a11y-e-tree-factory.h libetable_la_LDFLAGS = $(NO_UNDEFINED) libetable_la_LIBADD = \ - $(WIN32_BOOTSTRAP_LIBS) \ - $(top_builddir)/e-util/libeutil.la \ $(top_builddir)/a11y/libevolution-a11y.la \ + $(top_builddir)/e-util/libeutil.la \ + $(top_builddir)/widgets/misc/libemiscwidgets.la \ + $(top_builddir)/widgets/text/libetext.la \ $(E_UTIL_LIBS) \ $(E_WIDGETS_LIBS) \ + $(MATH_LIB) \ $(GNOME_PLATFORM_LIBS) icons = \ diff --git a/widgets/table/a11y/gal-a11y-e-cell-popup.c b/widgets/table/a11y/gal-a11y-e-cell-popup.c new file mode 100644 index 0000000000..1a40b23a21 --- /dev/null +++ b/widgets/table/a11y/gal-a11y-e-cell-popup.c @@ -0,0 +1,144 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Authors: + * Yang Wu <yang.wu@sun.com> + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include <config.h> + +#include <gdk/gdkkeysyms.h> +#include <gtk/gtk.h> + +#include "a11y/gal-a11y-util.h" +#include "table/e-cell-popup.h" +#include <glib/gi18n.h> + +#include "gal-a11y-e-cell-popup.h" +#include "gal-a11y-e-cell-registry.h" + +static AtkObjectClass *parent_class = NULL; +#define PARENT_TYPE (gal_a11y_e_cell_get_type ()) + +static void gal_a11y_e_cell_popup_class_init (GalA11yECellPopupClass *klass); +static void popup_cell_action (GalA11yECell *cell); + +/** + * gal_a11y_e_cell_popup_get_type: + * @void: + * + * Registers the &GalA11yECellPopup class if necessary, and returns the type ID + * associated to it. + * + * Return value: The type ID of the &GalA11yECellPopup class. + **/ +GType +gal_a11y_e_cell_popup_get_type (void) +{ + static GType type = 0; + + if (!type) { + GTypeInfo info = { + sizeof (GalA11yECellPopupClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) gal_a11y_e_cell_popup_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (GalA11yECellPopup), + 0, + (GInstanceInitFunc) NULL, + NULL /* value_cell_popup */ + }; + + type = g_type_register_static (PARENT_TYPE, "GalA11yECellPopup", &info, 0); + gal_a11y_e_cell_type_add_action_interface (type); + } + + return type; +} + +static void +gal_a11y_e_cell_popup_class_init (GalA11yECellPopupClass *klass) +{ + parent_class = g_type_class_ref (PARENT_TYPE); +} + +AtkObject * +gal_a11y_e_cell_popup_new (ETableItem *item, + ECellView *cell_view, + AtkObject *parent, + int model_col, + int view_col, + int row) +{ + AtkObject *a11y; + GalA11yECell *cell; + ECellPopup *popupcell; + ECellView* child_view = NULL; + + popupcell= E_CELL_POPUP(cell_view->ecell); + + if (popupcell && popupcell->popup_cell_view) + child_view = popupcell->popup_cell_view->child_view; + + if (child_view && child_view->ecell) { + a11y = gal_a11y_e_cell_registry_get_object (NULL, + item, + child_view, + parent, + model_col, + view_col, + row); + } else { + a11y = g_object_new (GAL_A11Y_TYPE_E_CELL_POPUP, NULL); + gal_a11y_e_cell_construct (a11y, + item, + cell_view, + parent, + model_col, + view_col, + row); + } + g_return_val_if_fail (a11y != NULL, NULL); + cell = GAL_A11Y_E_CELL(a11y); + gal_a11y_e_cell_add_action (cell, + _("popup"), /* action name*/ + _("popup a child"), /* action description */ + "<Alt>Down", /* action keybinding */ + popup_cell_action); + + a11y->role = ATK_ROLE_TABLE_CELL; + return a11y; +} + +static void +popup_cell_action (GalA11yECell *cell) +{ + gint finished; + GdkEvent event; + + event.key.type = GDK_KEY_PRESS; + event.key.window = GTK_LAYOUT(GNOME_CANVAS_ITEM(cell->item)->canvas)->bin_window;; + event.key.send_event = TRUE; + event.key.time = GDK_CURRENT_TIME; + event.key.state = GDK_MOD1_MASK; + event.key.keyval = GDK_Down; + + g_signal_emit_by_name (cell->item, "event", &event, &finished); +} diff --git a/widgets/table/a11y/gal-a11y-e-cell-popup.h b/widgets/table/a11y/gal-a11y-e-cell-popup.h new file mode 100644 index 0000000000..4f205c10bc --- /dev/null +++ b/widgets/table/a11y/gal-a11y-e-cell-popup.h @@ -0,0 +1,62 @@ +/* + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Authors: + * Yang Wu <yang.wu@sun.com> + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef __GAL_A11Y_E_CELL_POPUP_H__ +#define __GAL_A11Y_E_CELL_POPUP_H__ + +#include <glib-object.h> +#include <table/e-table-item.h> +#include <table/a11y/gal-a11y-e-cell.h> +#include <atk/atkgobjectaccessible.h> + +#define GAL_A11Y_TYPE_E_CELL_POPUP (gal_a11y_e_cell_popup_get_type ()) +#define GAL_A11Y_E_CELL_POPUP(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GAL_A11Y_TYPE_E_CELL_POPUP, GalA11yECellPopup)) +#define GAL_A11Y_E_CELL_POPUP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GAL_A11Y_TYPE_E_CELL_POPUP, GalA11yECellPopupClass)) +#define GAL_A11Y_IS_E_CELL_POPUP(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GAL_A11Y_TYPE_E_CELL_POPUP)) +#define GAL_A11Y_IS_E_CELL_POPUP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GAL_A11Y_TYPE_E_CELL_POPUP)) + +typedef struct _GalA11yECellPopup GalA11yECellPopup; +typedef struct _GalA11yECellPopupClass GalA11yECellPopupClass; + +/* This struct should actually be larger as this isn't what we derive from. + * The GalA11yECellPopupPrivate comes right after the parent class structure. + **/ +struct _GalA11yECellPopup { + GalA11yECell object; +}; + +struct _GalA11yECellPopupClass { + GalA11yECellClass parent_class; +}; + + +/* Standard Glib function */ +GType gal_a11y_e_cell_popup_get_type (void); +AtkObject *gal_a11y_e_cell_popup_new (ETableItem *item, + ECellView *cell_view, + AtkObject *parent, + int model_col, + int view_col, + int row); + +#endif /* ! __GAL_A11Y_E_CELL_POPUP_H__ */ diff --git a/widgets/table/a11y/gal-a11y-e-cell-registry.c b/widgets/table/a11y/gal-a11y-e-cell-registry.c new file mode 100644 index 0000000000..b88fb581fc --- /dev/null +++ b/widgets/table/a11y/gal-a11y-e-cell-registry.c @@ -0,0 +1,149 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Authors: + * Christopher James Lahey <clahey@ximian.com> + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include <config.h> + +#include "gal-a11y-e-cell.h" +#include "gal-a11y-e-cell-registry.h" + +static GObjectClass *parent_class; +static GalA11yECellRegistry *default_registry; +#define PARENT_TYPE (G_TYPE_OBJECT) + +struct _GalA11yECellRegistryPrivate { + GHashTable *table; +}; + +/* Static functions */ + +static void +gal_a11y_e_cell_registry_finalize (GObject *obj) +{ + GalA11yECellRegistry *registry = GAL_A11Y_E_CELL_REGISTRY (obj); + + g_hash_table_destroy (registry->priv->table); + g_free (registry->priv); + + G_OBJECT_CLASS (parent_class)->finalize (obj); +} + +static void +gal_a11y_e_cell_registry_class_init (GalA11yECellRegistryClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + parent_class = g_type_class_ref (PARENT_TYPE); + + object_class->finalize = gal_a11y_e_cell_registry_finalize; +} + +static void +gal_a11y_e_cell_registry_init (GalA11yECellRegistry *registry) +{ + registry->priv = g_new (GalA11yECellRegistryPrivate, 1); + registry->priv->table = g_hash_table_new (NULL, NULL); +} + +/** + * gal_a11y_e_cell_registry_get_type: + * @void: + * + * Registers the &GalA11yECellRegistry class if necessary, and returns the type ID + * associated to it. + * + * Return value: The type ID of the &GalA11yECellRegistry class. + **/ +GType +gal_a11y_e_cell_registry_get_type (void) +{ + static GType type = 0; + + if (!type) { + GTypeInfo info = { + sizeof (GalA11yECellRegistryClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) gal_a11y_e_cell_registry_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (GalA11yECellRegistry), + 0, + (GInstanceInitFunc) gal_a11y_e_cell_registry_init, + NULL /* value_cell */ + }; + + type = g_type_register_static (PARENT_TYPE, "GalA11yECellRegistry", &info, 0); + } + + return type; +} + +static void +init_default_registry (void) +{ + if (default_registry == NULL) { + default_registry = g_object_new (gal_a11y_e_cell_registry_get_type(), NULL); + } +} + + +AtkObject * +gal_a11y_e_cell_registry_get_object (GalA11yECellRegistry *registry, + ETableItem *item, + ECellView *cell_view, + AtkObject *parent, + int model_col, + int view_col, + int row) +{ + GalA11yECellRegistryFunc func = NULL; + GType type; + + if (registry == NULL) { + init_default_registry (); + registry = default_registry; + } + + type = GTK_OBJECT_TYPE (cell_view->ecell); + while (func == NULL && type != 0) { + func = g_hash_table_lookup (registry->priv->table, GINT_TO_POINTER (type)); + type = g_type_parent (type); + } + + if (func) + return func (item, cell_view, parent, model_col, view_col, row); + else + return gal_a11y_e_cell_new (item, cell_view, parent, model_col, view_col, row); +} + +void +gal_a11y_e_cell_registry_add_cell_type (GalA11yECellRegistry *registry, + GType type, + GalA11yECellRegistryFunc func) +{ + if (registry == NULL) { + init_default_registry (); + registry = default_registry; + } + + g_hash_table_insert (registry->priv->table, GINT_TO_POINTER (type), func); +} diff --git a/widgets/table/a11y/gal-a11y-e-cell-registry.h b/widgets/table/a11y/gal-a11y-e-cell-registry.h new file mode 100644 index 0000000000..f231567222 --- /dev/null +++ b/widgets/table/a11y/gal-a11y-e-cell-registry.h @@ -0,0 +1,72 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Authors: + * Christopher James Lahey <clahey@ximian.com> + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef __GAL_A11Y_E_CELL_REGISTRY_H__ +#define __GAL_A11Y_E_CELL_REGISTRY_H__ + +#include <glib-object.h> +#include <atk/atkobject.h> +#include <table/e-table-item.h> +#include <table/e-cell.h> + +#define GAL_A11Y_TYPE_E_CELL_REGISTRY (gal_a11y_e_cell_registry_get_type ()) +#define GAL_A11Y_E_CELL_REGISTRY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GAL_A11Y_TYPE_E_CELL_REGISTRY, GalA11yECellRegistry)) +#define GAL_A11Y_E_CELL_REGISTRY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GAL_A11Y_TYPE_E_CELL_REGISTRY, GalA11yECellRegistryClass)) +#define GAL_A11Y_IS_E_CELL_REGISTRY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GAL_A11Y_TYPE_E_CELL_REGISTRY)) +#define GAL_A11Y_IS_E_CELL_REGISTRY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GAL_A11Y_TYPE_E_CELL_REGISTRY)) + +typedef struct _GalA11yECellRegistry GalA11yECellRegistry; +typedef struct _GalA11yECellRegistryClass GalA11yECellRegistryClass; +typedef struct _GalA11yECellRegistryPrivate GalA11yECellRegistryPrivate; + +typedef AtkObject *(*GalA11yECellRegistryFunc) (ETableItem *item, + ECellView *cell_view, + AtkObject *parent, + int model_col, + int view_col, + int row); + +struct _GalA11yECellRegistry { + GObject object; + + GalA11yECellRegistryPrivate *priv; +}; + +struct _GalA11yECellRegistryClass { + GObjectClass parent_class; +}; + + +/* Standard Glib function */ +GType gal_a11y_e_cell_registry_get_type (void); +AtkObject *gal_a11y_e_cell_registry_get_object (GalA11yECellRegistry *registry, + ETableItem *item, + ECellView *cell_view, + AtkObject *parent, + int model_col, + int view_col, + int row); +void gal_a11y_e_cell_registry_add_cell_type (GalA11yECellRegistry *registry, + GType type, + GalA11yECellRegistryFunc func); + +#endif /* ! __GAL_A11Y_E_CELL_REGISTRY_H__ */ diff --git a/widgets/table/a11y/gal-a11y-e-cell-text.c b/widgets/table/a11y/gal-a11y-e-cell-text.c new file mode 100644 index 0000000000..e77c0739a9 --- /dev/null +++ b/widgets/table/a11y/gal-a11y-e-cell-text.c @@ -0,0 +1,737 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Authors: + * Christopher James Lahey <clahey@ximian.com> + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include <config.h> + +#include <string.h> + +#include <atk/atk.h> + +#include "a11y/gal-a11y-util.h" +#include "table/e-cell-text.h" +#include <glib/gi18n.h> + +#include "gal-a11y-e-cell-text.h" + +#define CS_CLASS(a11y) (G_TYPE_INSTANCE_GET_CLASS ((a11y), C_TYPE_STREAM, GalA11yECellTextClass)) +static AtkObjectClass *parent_class; +#define PARENT_TYPE (gal_a11y_e_cell_get_type ()) + +/* Static functions */ +static void +ect_dispose (GObject *object) +{ + GObjectClass *g_class; + GalA11yECell *gaec = GAL_A11Y_E_CELL (object); + GalA11yECellText *gaet = GAL_A11Y_E_CELL_TEXT (object); + + if (gaet->inserted_id != 0) { + ECellText *ect = E_CELL_TEXT (gaec->cell_view->ecell); + + if (ect) { + g_signal_handler_disconnect (ect, gaet->inserted_id); + g_signal_handler_disconnect (ect, gaet->deleted_id); + } + + gaet->inserted_id = 0; + gaet->deleted_id = 0; + } + + g_class = (GObjectClass *)parent_class; + if (g_class->dispose) + g_class->dispose (object); + +} + +static gboolean +ect_check (gpointer a11y) +{ + GalA11yECell *gaec = GAL_A11Y_E_CELL (a11y); + ETableItem *item = gaec->item; + + g_return_val_if_fail ((gaec->item != NULL), FALSE); + g_return_val_if_fail ((gaec->cell_view != NULL), FALSE); + g_return_val_if_fail ((gaec->cell_view->ecell != NULL), FALSE); + + if (atk_state_set_contains_state (gaec->state_set, ATK_STATE_DEFUNCT)) + return FALSE; + + if (gaec->row < 0 || gaec->row >= item->rows + || gaec->view_col <0 || gaec->view_col >= item->cols + || gaec->model_col <0 || gaec->model_col >= e_table_model_column_count (item->table_model)) + return FALSE; + + if (!E_IS_CELL_TEXT (gaec->cell_view->ecell)) + return FALSE; + + return TRUE; +} + +static G_CONST_RETURN gchar* +ect_get_name (AtkObject * a11y) +{ + GalA11yECell *gaec; + char *name; + + if (!ect_check (a11y)) + return NULL; + + gaec = GAL_A11Y_E_CELL (a11y); + name = e_cell_text_get_text_by_view (gaec->cell_view, gaec->model_col, gaec->row); + if (name != NULL) { + ATK_OBJECT_CLASS (parent_class)->set_name (a11y, name); + g_free (name); + } + + if (a11y->name != NULL && strcmp (a11y->name, "")) { + return a11y->name; + } else { + return parent_class->get_name (a11y); + } +} + +static gchar * +ect_get_text (AtkText *text, + gint start_offset, + gint end_offset) +{ + GalA11yECell *gaec = GAL_A11Y_E_CELL (text); + gchar *full_text; + gchar *ret_val; + + if (!ect_check (text)) + return NULL; + + full_text = e_cell_text_get_text_by_view (gaec->cell_view, gaec->model_col, gaec->row); + + if (end_offset == -1) + end_offset = strlen (full_text); + else + end_offset = g_utf8_offset_to_pointer (full_text, end_offset) - full_text; + + start_offset = g_utf8_offset_to_pointer (full_text, start_offset) - full_text; + + ret_val = g_strndup (full_text + start_offset, end_offset - start_offset); + + g_free (full_text); + + return ret_val; +} + +static gchar * +ect_get_text_after_offset (AtkText *text, + gint offset, + AtkTextBoundary boundary_type, + gint *start_offset, + gint *end_offset) +{ + /* Unimplemented */ + return NULL; +} + +static gchar * +ect_get_text_at_offset (AtkText *text, + gint offset, + AtkTextBoundary boundary_type, + gint *start_offset, + gint *end_offset) +{ + /* Unimplemented */ + return NULL; +} + +static gunichar +ect_get_character_at_offset (AtkText *text, + gint offset) +{ + GalA11yECell *gaec = GAL_A11Y_E_CELL (text); + gunichar ret_val; + gchar *at_offset; + gchar *full_text; + + if (!ect_check (text)) + return -1; + + full_text = e_cell_text_get_text_by_view (gaec->cell_view, gaec->model_col, gaec->row); + at_offset = g_utf8_offset_to_pointer (full_text, offset); + ret_val = g_utf8_get_char_validated (at_offset, -1); + g_free (full_text); + + return ret_val; +} + + +static gchar* +ect_get_text_before_offset (AtkText *text, + gint offset, + AtkTextBoundary boundary_type, + gint *start_offset, + gint *end_offset) +{ + /* Unimplemented */ + return NULL; +} + + +static gint +ect_get_caret_offset (AtkText *text) +{ + GalA11yECell *gaec = GAL_A11Y_E_CELL (text); + gint start, end; + + if (!ect_check (text)) + return -1; + + if (e_cell_text_get_selection (gaec->cell_view, + gaec->view_col, gaec->row, + &start, &end)) { + gchar *full_text = e_cell_text_get_text_by_view (gaec->cell_view, gaec->model_col, gaec->row); + end = g_utf8_pointer_to_offset (full_text, full_text + end); + g_free (full_text); + + return end; + } + else + return -1; +} + +static AtkAttributeSet* +ect_get_run_attributes (AtkText *text, + gint offset, + gint *start_offset, + gint *end_offset) +{ + /* Unimplemented */ + return NULL; +} + + +static AtkAttributeSet* +ect_get_default_attributes (AtkText *text) +{ + /* Unimplemented */ + return NULL; +} + + +static void +ect_get_character_extents (AtkText *text, + gint offset, + gint *x, + gint *y, + gint *width, + gint *height, + AtkCoordType coords) +{ + /* Unimplemented */ +} + + +static gint +ect_get_character_count (AtkText *text) +{ + GalA11yECell *gaec = GAL_A11Y_E_CELL (text); + gint ret_val; + gchar *full_text; + + if (!ect_check (text)) + return -1; + + full_text = e_cell_text_get_text_by_view (gaec->cell_view, gaec->model_col, gaec->row); + + ret_val = g_utf8_strlen (full_text, -1); + g_free (full_text); + return ret_val; +} + + +static gint +ect_get_offset_at_point (AtkText *text, + gint x, + gint y, + AtkCoordType coords) +{ + /* Unimplemented */ + return 0; +} + + +static gint +ect_get_n_selections (AtkText *text) +{ + GalA11yECell *gaec = GAL_A11Y_E_CELL (text); + gint selection_start, selection_end; + + if (!ect_check (text)) + return 0; + + if (e_cell_text_get_selection (gaec->cell_view, + gaec->view_col, gaec->row, + &selection_start, + &selection_end) + && selection_start != selection_end) + return 1; + return 0; +} + + +static gchar* +ect_get_selection (AtkText *text, + gint selection_num, + gint *start_offset, + gint *end_offset) +{ + GalA11yECell *gaec = GAL_A11Y_E_CELL (text); + gchar *ret_val; + gint selection_start, selection_end; + + if (selection_num == 0 + && e_cell_text_get_selection (gaec->cell_view, + gaec->view_col, gaec->row, + &selection_start, + &selection_end) + && selection_start != selection_end) { + gint real_start, real_end, len; + gchar *full_text = e_cell_text_get_text_by_view (gaec->cell_view, gaec->model_col, gaec->row); + len = strlen (full_text); + real_start = MIN (selection_start, selection_end); + real_end = MAX (selection_start, selection_end); + real_start = MIN (MAX (0, real_start), len); + real_end = MIN (MAX (0, real_end), len); + + ret_val = g_strndup (full_text + real_start, real_end - real_start); + + real_start = g_utf8_pointer_to_offset (full_text, full_text + real_start); + real_end = g_utf8_pointer_to_offset (full_text, full_text + real_end); + + if (start_offset) + *start_offset = real_start; + if (end_offset) + *end_offset = real_end; + g_free (full_text); + } else { + if (start_offset) + *start_offset = 0; + if (end_offset) + *end_offset = 0; + ret_val = NULL; + } + + return ret_val; +} + + +static gboolean +ect_add_selection (AtkText *text, + gint start_offset, + gint end_offset) +{ + GalA11yECell *gaec = GAL_A11Y_E_CELL (text); + + if (start_offset != end_offset) { + gint real_start, real_end, len; + gchar *full_text = + e_cell_text_get_text_by_view (gaec->cell_view, gaec->model_col, gaec->row); + + len = g_utf8_strlen (full_text, -1); + if (end_offset == -1) + end_offset = len; + + real_start = MIN (start_offset, end_offset); + real_end = MAX (start_offset, end_offset); + + real_start = MIN (MAX (0, real_start), len); + real_end = MIN (MAX (0, real_end), len); + + real_start = g_utf8_offset_to_pointer (full_text, real_start) - full_text; + real_end = g_utf8_offset_to_pointer (full_text, real_end) - full_text; + g_free (full_text); + + if (e_cell_text_set_selection (gaec->cell_view, + gaec->view_col, gaec->row, + real_start, real_end)) { + g_signal_emit_by_name (ATK_OBJECT(text), "text_selection_changed"); + return TRUE; + } + } + + return FALSE; +} + + +static gboolean +ect_remove_selection (AtkText *text, + gint selection_num) +{ + GalA11yECell *gaec = GAL_A11Y_E_CELL (text); + gint selection_start, selection_end; + + if (selection_num == 0 + && e_cell_text_get_selection (gaec->cell_view, + gaec->view_col, gaec->row, + &selection_start, + &selection_end) + && selection_start != selection_end + && e_cell_text_set_selection (gaec->cell_view, + gaec->view_col, gaec->row, + selection_end, selection_end)) { + g_signal_emit_by_name (ATK_OBJECT(text), "text_selection_changed"); + return TRUE; + } + else + return FALSE; +} + + +static gboolean +ect_set_selection (AtkText *text, + gint selection_num, + gint start_offset, + gint end_offset) +{ + if (selection_num == 0) { + atk_text_add_selection (text, start_offset, end_offset); + return TRUE; + } + else + return FALSE; +} + + +static gboolean +ect_set_caret_offset (AtkText *text, + gint offset) +{ + GalA11yECell *gaec = GAL_A11Y_E_CELL (text); + gchar *full_text; + gint len; + + full_text = e_cell_text_get_text_by_view (gaec->cell_view, gaec->model_col, gaec->row); + + len = g_utf8_strlen (full_text, -1); + if (offset == -1) + offset = len; + else + offset = MIN (MAX (0, offset), len); + + offset = g_utf8_offset_to_pointer (full_text, offset) - full_text; + + g_free (full_text); + + return e_cell_text_set_selection (gaec->cell_view, + gaec->view_col, gaec->row, + offset, offset); +} + +static gboolean +ect_set_run_attributes (AtkEditableText *text, + AtkAttributeSet *attrib_set, + gint start_offset, + gint end_offset) +{ + /* Unimplemented */ + return FALSE; +} + +static void +ect_set_text_contents (AtkEditableText *text, + const gchar *string) +{ + GalA11yECell *gaec = GAL_A11Y_E_CELL (text); + ECellText *ect = E_CELL_TEXT (gaec->cell_view->ecell); + + e_cell_text_set_value (ect, gaec->item->table_model, gaec->model_col, gaec->row, string); + e_table_item_enter_edit (gaec->item, gaec->view_col, gaec->row); +} + +static void +ect_insert_text (AtkEditableText *text, + const gchar *string, + gint length, + gint *position) +{ + /* Utf8 unimplemented */ + GalA11yECell *gaec = GAL_A11Y_E_CELL (text); + ECellText *ect = E_CELL_TEXT (gaec->cell_view->ecell); + + gchar *full_text = e_cell_text_get_text_by_view (gaec->cell_view, gaec->model_col, gaec->row); + gchar *result = g_strdup_printf ("%.*s%.*s%s", *position, full_text, length, string, full_text + *position); + + e_cell_text_set_value (ect, gaec->item->table_model, gaec->model_col, gaec->row, result); + + *position += length; + + g_free (result); + g_free (full_text); +} + +static void +ect_copy_text (AtkEditableText *text, + gint start_pos, + gint end_pos) +{ + GalA11yECell *gaec = GAL_A11Y_E_CELL (text); + if (start_pos != end_pos + && atk_text_set_selection (ATK_TEXT (text), 0, start_pos, end_pos)) + e_cell_text_copy_clipboard (gaec->cell_view, + gaec->view_col, gaec->row); +} + +static void +ect_delete_text (AtkEditableText *text, + gint start_pos, + gint end_pos) +{ + GalA11yECell *gaec = GAL_A11Y_E_CELL (text); + if (start_pos != end_pos + && atk_text_set_selection (ATK_TEXT (text), 0, start_pos, end_pos)) + e_cell_text_delete_selection (gaec->cell_view, + gaec->view_col, gaec->row); +} + +static void +ect_cut_text (AtkEditableText *text, + gint start_pos, + gint end_pos) +{ + ect_copy_text (text, start_pos, end_pos); + ect_delete_text (text, start_pos, end_pos); +} + +static void +ect_paste_text (AtkEditableText *text, + gint position) +{ + GalA11yECell *gaec = GAL_A11Y_E_CELL (text); + + e_table_item_enter_edit (gaec->item, gaec->view_col, gaec->row); + + if (atk_text_set_caret_offset (ATK_TEXT (text), position)) + e_cell_text_paste_clipboard (gaec->cell_view, + gaec->view_col, gaec->row); +} + +static void +ect_do_action_edit (AtkAction *action) +{ + GalA11yECell *a11y = GAL_A11Y_E_CELL (action); + ETableModel *e_table_model = a11y->item->table_model; + + if (e_table_model_is_cell_editable(e_table_model, a11y->model_col, a11y->row)) { + e_table_item_enter_edit (a11y->item, a11y->view_col, a11y->row); + } +} + +/* text signal handlers */ +static void +ect_text_inserted_cb (ECellText *text, ECellView *cell_view, int pos, int len, int row, int model_col, gpointer data) +{ + GalA11yECellText *gaet; + GalA11yECell *gaec; + + if (!ect_check (data)) + return; + gaet = GAL_A11Y_E_CELL_TEXT (data); + gaec = GAL_A11Y_E_CELL (data); + + if (cell_view == gaec->cell_view && row == gaec->row && model_col == gaec->model_col) { + g_signal_emit_by_name (gaet, "text_changed::insert", pos, len); + + } +} + +static void +ect_text_deleted_cb (ECellText *text, ECellView *cell_view, int pos, int len, int row, int model_col, gpointer data) +{ + GalA11yECellText *gaet; + GalA11yECell *gaec; + if (!ect_check (data)) + return; + gaet = GAL_A11Y_E_CELL_TEXT (data); + gaec = GAL_A11Y_E_CELL (data); + if (cell_view == gaec->cell_view && row == gaec->row && model_col == gaec->model_col) { + g_signal_emit_by_name (gaet, "text_changed::delete", pos, len); + } +} + +static void +ect_atk_text_iface_init (AtkTextIface *iface) +{ + iface->get_text = ect_get_text; + iface->get_text_after_offset = ect_get_text_after_offset; + iface->get_text_at_offset = ect_get_text_at_offset; + iface->get_character_at_offset = ect_get_character_at_offset; + iface->get_text_before_offset = ect_get_text_before_offset; + iface->get_caret_offset = ect_get_caret_offset; + iface->get_run_attributes = ect_get_run_attributes; + iface->get_default_attributes = ect_get_default_attributes; + iface->get_character_extents = ect_get_character_extents; + iface->get_character_count = ect_get_character_count; + iface->get_offset_at_point = ect_get_offset_at_point; + iface->get_n_selections = ect_get_n_selections; + iface->get_selection = ect_get_selection; + iface->add_selection = ect_add_selection; + iface->remove_selection = ect_remove_selection; + iface->set_selection = ect_set_selection; + iface->set_caret_offset = ect_set_caret_offset; +} + +static void +ect_atk_editable_text_iface_init (AtkEditableTextIface *iface) +{ + iface->set_run_attributes = ect_set_run_attributes; + iface->set_text_contents = ect_set_text_contents; + iface->insert_text = ect_insert_text; + iface->copy_text = ect_copy_text; + iface->cut_text = ect_cut_text; + iface->delete_text = ect_delete_text; + iface->paste_text = ect_paste_text; +} + +static void +ect_class_init (GalA11yECellTextClass *klass) +{ + AtkObjectClass *a11y = ATK_OBJECT_CLASS (klass); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + parent_class = g_type_class_ref (PARENT_TYPE); + a11y->get_name = ect_get_name; + object_class->dispose = ect_dispose; +} + +static void +ect_action_init (GalA11yECellText *a11y) +{ + GalA11yECell *gaec = GAL_A11Y_E_CELL (a11y); + ECellText *ect = E_CELL_TEXT (gaec->cell_view->ecell); + if (ect->editable && e_table_model_is_cell_editable (gaec->cell_view->e_table_model, gaec->model_col, gaec->row)) + gal_a11y_e_cell_add_action (gaec, + _("edit"), + _("begin editing this cell"), + NULL, + (ACTION_FUNC) ect_do_action_edit); +} + +/** + * gal_a11y_e_cell_text_get_type: + * @void: + * + * Registers the &GalA11yECellText class if necessary, and returns the type ID + * associated to it. + * + * Return value: The type ID of the &GalA11yECellText class. + **/ +GType +gal_a11y_e_cell_text_get_type (void) +{ + static GType type = 0; + + if (!type) { + GTypeInfo info = { + sizeof (GalA11yECellTextClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) ect_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (GalA11yECellText), + 0, + (GInstanceInitFunc) NULL, + NULL /* value_cell_text */ + }; + + static const GInterfaceInfo atk_text_info = { + (GInterfaceInitFunc) ect_atk_text_iface_init, + (GInterfaceFinalizeFunc) NULL, + NULL + }; + + static const GInterfaceInfo atk_editable_text_info = { + (GInterfaceInitFunc) ect_atk_editable_text_iface_init, + (GInterfaceFinalizeFunc) NULL, + NULL + }; + + type = g_type_register_static (PARENT_TYPE, "GalA11yECellText", &info, 0); + g_type_add_interface_static (type, ATK_TYPE_TEXT, &atk_text_info); + g_type_add_interface_static (type, ATK_TYPE_EDITABLE_TEXT, &atk_editable_text_info); + gal_a11y_e_cell_type_add_action_interface (type); + } + + return type; +} + +static void +cell_text_destroyed (gpointer data) +{ + g_return_if_fail (GAL_A11Y_IS_E_CELL_TEXT (data)); + + g_object_unref (data); +} + +AtkObject * +gal_a11y_e_cell_text_new (ETableItem *item, + ECellView *cell_view, + AtkObject *parent, + int model_col, + int view_col, + int row) +{ + AtkObject *a11y; + GalA11yECell *gaec; + GalA11yECellText *gaet; + ECellText *ect; + + a11y = g_object_new (gal_a11y_e_cell_text_get_type (), NULL); + + gal_a11y_e_cell_construct (a11y, + item, + cell_view, + parent, + model_col, + view_col, + row); + gaet = GAL_A11Y_E_CELL_TEXT (a11y); + + /* will be unrefed in cell_text_destroyed */ + g_object_ref (a11y); + + gaet->inserted_id = g_signal_connect (E_CELL_TEXT (((ECellView *)cell_view)->ecell), + "text_inserted", G_CALLBACK (ect_text_inserted_cb), a11y); + gaet->deleted_id = g_signal_connect (E_CELL_TEXT (((ECellView *)cell_view)->ecell), + "text_deleted", G_CALLBACK (ect_text_deleted_cb), a11y); + + g_object_weak_ref (G_OBJECT (((ECellView *)cell_view)->ecell), + (GWeakNotify) cell_text_destroyed, + a11y); + + ect_action_init (gaet); + + ect = E_CELL_TEXT (cell_view->ecell); + gaec = GAL_A11Y_E_CELL (a11y); + if (ect->editable && e_table_model_is_cell_editable (gaec->cell_view->e_table_model, gaec->model_col, gaec->row)) + gal_a11y_e_cell_add_state (gaec, ATK_STATE_EDITABLE, FALSE); + else + gal_a11y_e_cell_remove_state (gaec, ATK_STATE_EDITABLE, FALSE); + + return a11y; +} diff --git a/widgets/table/a11y/gal-a11y-e-cell-text.h b/widgets/table/a11y/gal-a11y-e-cell-text.h new file mode 100644 index 0000000000..208bc67c66 --- /dev/null +++ b/widgets/table/a11y/gal-a11y-e-cell-text.h @@ -0,0 +1,64 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Authors: + * Christopher James Lahey <clahey@ximian.com> + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef __GAL_A11Y_E_CELL_TEXT_H__ +#define __GAL_A11Y_E_CELL_TEXT_H__ + +#include <glib-object.h> +#include <table/e-table-item.h> +#include <table/e-cell-text.h> +#include <table/a11y/gal-a11y-e-cell.h> + +#define GAL_A11Y_TYPE_E_CELL_TEXT (gal_a11y_e_cell_text_get_type ()) +#define GAL_A11Y_E_CELL_TEXT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GAL_A11Y_TYPE_E_CELL_TEXT, GalA11yECellText)) +#define GAL_A11Y_E_CELL_TEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GAL_A11Y_TYPE_E_CELL_TEXT, GalA11yECellTextClass)) +#define GAL_A11Y_IS_E_CELL_TEXT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GAL_A11Y_TYPE_E_CELL_TEXT)) +#define GAL_A11Y_IS_E_CELL_TEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GAL_A11Y_TYPE_E_CELL_TEXT)) + +typedef struct _GalA11yECellText GalA11yECellText; +typedef struct _GalA11yECellTextClass GalA11yECellTextClass; +typedef struct _GalA11yECellTextPrivate GalA11yECellTextPrivate; + +/* This struct should actually be larger as this isn't what we derive from. + * The GalA11yECellTextPrivate comes right after the parent class structure. + **/ +struct _GalA11yECellText { + GalA11yECell object; + gint inserted_id; + gint deleted_id; +}; + +struct _GalA11yECellTextClass { + GalA11yECellClass parent_class; +}; + + +/* Standard Glib function */ +GType gal_a11y_e_cell_text_get_type (void); +AtkObject *gal_a11y_e_cell_text_new (ETableItem *item, + ECellView *cell_view, + AtkObject *parent, + int model_col, + int view_col, + int row); + +#endif /* ! __GAL_A11Y_E_CELL_TEXT_H__ */ diff --git a/widgets/table/a11y/gal-a11y-e-cell-toggle.c b/widgets/table/a11y/gal-a11y-e-cell-toggle.c new file mode 100644 index 0000000000..23114b0373 --- /dev/null +++ b/widgets/table/a11y/gal-a11y-e-cell-toggle.c @@ -0,0 +1,191 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Authors: + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include <gtk/gtk.h> + +#include "table/e-cell-toggle.h" +#include "table/e-table-model.h" +#include <glib/gi18n.h> + +#include "gal-a11y-e-cell-toggle.h" + +#define PARENT_TYPE (gal_a11y_e_cell_get_type ()) +static GObjectClass *parent_class; + +static void gal_a11y_e_cell_toggle_class_init (GalA11yECellToggleClass *klass); + +static void +gal_a11y_e_cell_toggle_dispose (GObject *object) +{ + GalA11yECellToggle *a11y = GAL_A11Y_E_CELL_TOGGLE (object); + + ETableModel *e_table_model = GAL_A11Y_E_CELL (a11y)->item->table_model; + + if (e_table_model && a11y->model_id > 0) { + g_signal_handler_disconnect (e_table_model, a11y->model_id); + a11y->model_id = 0; + } + + if (parent_class->dispose) + parent_class->dispose (object); +} + +GType +gal_a11y_e_cell_toggle_get_type (void) +{ + static GType type = 0; + + if (!type) + { + static const GTypeInfo tinfo = + { + sizeof (GalA11yECellToggleClass), + (GBaseInitFunc) NULL, /* base init */ + (GBaseFinalizeFunc) NULL, /* base finalize */ + (GClassInitFunc) gal_a11y_e_cell_toggle_class_init, /* class init */ + (GClassFinalizeFunc) NULL, /* class finalize */ + NULL, /* class data */ + sizeof (GalA11yECellToggle), /* instance size */ + 0, /* nb preallocs */ + NULL, /* instance init */ + NULL /* value table */ + }; + + + type = g_type_register_static (GAL_A11Y_TYPE_E_CELL, + "GalA11yECellToggle", &tinfo, 0); + gal_a11y_e_cell_type_add_action_interface (type); + + } + return type; +} + + +static void +gal_a11y_e_cell_toggle_class_init (GalA11yECellToggleClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->dispose = gal_a11y_e_cell_toggle_dispose; + parent_class = g_type_class_ref (PARENT_TYPE); +} + +static void +toggle_cell_action (GalA11yECell *cell) +{ + gint finished; + GdkEventButton event; + gint x, y, width, height; + gint row, col; + + row = cell->row; + col = cell->view_col; + + e_table_item_get_cell_geometry (cell->item, &row, &col, + &x, &y, &width, &height); + + event.x = x + width / 2 + (int)(GNOME_CANVAS_ITEM (cell->item)->x1); + event.y = y + height / 2 + (int)(GNOME_CANVAS_ITEM (cell->item)->y1); + + event.type = GDK_BUTTON_PRESS; + event.window = GTK_LAYOUT(GNOME_CANVAS_ITEM(cell->item)->canvas)->bin_window; + event.button = 1; + event.send_event = TRUE; + event.time = GDK_CURRENT_TIME; + event.axes = NULL; + + g_signal_emit_by_name (cell->item, "event", &event, &finished); +} + +static void +model_change_cb (ETableModel *etm, + gint col, + gint row, + GalA11yECell *cell) +{ + gint value; + + if (col == cell->model_col && row == cell->row) { + + value = GPOINTER_TO_INT ( + e_table_model_value_at (cell->cell_view->e_table_model, + cell->model_col, cell->row)); + /* Cheat gnopernicus, or it will ignore the state change signal */ + atk_focus_tracker_notify (ATK_OBJECT (cell)); + + if (value) + gal_a11y_e_cell_add_state (cell, ATK_STATE_CHECKED, TRUE); + else + gal_a11y_e_cell_remove_state (cell, ATK_STATE_CHECKED, TRUE); + } +} + + +AtkObject* +gal_a11y_e_cell_toggle_new (ETableItem *item, + ECellView *cell_view, + AtkObject *parent, + int model_col, + int view_col, + int row) +{ + AtkObject *a11y; + GalA11yECell *cell; + GalA11yECellToggle *toggle_cell; + gint value; + + a11y = ATK_OBJECT(g_object_new (GAL_A11Y_TYPE_E_CELL_TOGGLE, NULL)); + + g_return_val_if_fail (a11y != NULL, NULL); + + cell = GAL_A11Y_E_CELL(a11y); + toggle_cell = GAL_A11Y_E_CELL_TOGGLE(a11y); + a11y->role = ATK_ROLE_TABLE_CELL; + + gal_a11y_e_cell_construct (a11y, + item, + cell_view, + parent, + model_col, + view_col, + row); + + gal_a11y_e_cell_add_action (cell, + _("toggle"), /* action name*/ + _("toggle the cell"), /* action description */ + NULL, /* action keybinding */ + toggle_cell_action); + + toggle_cell->model_id = g_signal_connect (item->table_model, + "model_cell_changed", + (GCallback) model_change_cb, + a11y); + + value = GPOINTER_TO_INT ( + e_table_model_value_at (cell->cell_view->e_table_model, + cell->model_col, cell->row)); + if (value) + gal_a11y_e_cell_add_state (cell, ATK_STATE_CHECKED, FALSE); + else + gal_a11y_e_cell_remove_state (cell, ATK_STATE_CHECKED, FALSE); + + return a11y; +} diff --git a/widgets/table/a11y/gal-a11y-e-cell-toggle.h b/widgets/table/a11y/gal-a11y-e-cell-toggle.h new file mode 100644 index 0000000000..56483aae6b --- /dev/null +++ b/widgets/table/a11y/gal-a11y-e-cell-toggle.h @@ -0,0 +1,68 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Authors: + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef __GAL_A11Y_E_CELL_TOGGLE_H__ +#define __GAL_A11Y_E_CELL_TOGGLE_H__ + +#include <atk/atk.h> +#include "gal-a11y-e-cell.h" +#include "gal-a11y-e-cell-toggle.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#define GAL_A11Y_TYPE_E_CELL_TOGGLE (gal_a11y_e_cell_toggle_get_type ()) +#define GAL_A11Y_E_CELL_TOGGLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GAL_A11Y_TYPE_E_CELL_TOGGLE, GalA11yECellToggle)) +#define GAL_A11Y_E_CELL_TOGGLE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GAL_A11Y_E_CELL_TOGGLE, GalA11yECellToggleClass)) +#define GAL_A11Y_IS_E_CELL_TOGGLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GAL_A11Y_TYPE_E_CELL_TOGGLE)) +#define GAL_A11Y_IS_E_CELL_TOGGLE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GAL_A11Y_TYPE_E_CELL_TOGGLE)) +#define GAL_A11Y_E_CELL_TOGGLE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GAL_A11Y_TYPE_E_CELL_TOGGLE, GalA11yECellToggleClass)) + +typedef struct _GalA11yECellToggle GalA11yECellToggle; +typedef struct _GalA11yECellToggleClass GalA11yECellToggleClass; + +struct _GalA11yECellToggle +{ + GalA11yECell parent; + gint model_id; +}; + +GType gal_a11y_e_cell_toggle_get_type (void); + +struct _GalA11yECellToggleClass +{ + GalA11yECellClass parent_class; +}; + +AtkObject *gal_a11y_e_cell_toggle_new (ETableItem *item, + ECellView *cell_view, + AtkObject *parent, + int model_col, + int view_col, + int row); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + + +#endif /* __GAL_A11Y_E_CELL_TOGGLE_H__ */ diff --git a/widgets/table/a11y/gal-a11y-e-cell-tree.c b/widgets/table/a11y/gal-a11y-e-cell-tree.c new file mode 100644 index 0000000000..520a818a37 --- /dev/null +++ b/widgets/table/a11y/gal-a11y-e-cell-tree.c @@ -0,0 +1,260 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Authors: + * Tim Wo <tim.wo@sun.com> + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include <config.h> + +#include <atk/atk.h> + +#include "a11y/gal-a11y-util.h" +#include "table/e-cell-tree.h" +#include "table/e-table.h" +#include "table/e-tree-table-adapter.h" +#include <glib/gi18n.h> + +#include "gal-a11y-e-cell-tree.h" +#include "gal-a11y-e-cell-registry.h" + +#define CS_CLASS(a11y) (G_TYPE_INSTANCE_GET_CLASS ((a11y), C_TYPE_STREAM, GalA11yECellTreeClass)) +static AtkObjectClass *a11y_parent_class; +#define A11Y_PARENT_TYPE (gal_a11y_e_cell_get_type ()) + +#define d(x) + +static void +ectr_model_row_changed_cb (ETableModel *etm, + gint row, + GalA11yECell *a11y) +{ + ETreePath node; + ETreeModel *tree_model; + ETreeTableAdapter *tree_table_adapter; + + g_return_if_fail (a11y); + if (a11y->row != row) + return; + + node = e_table_model_value_at (etm, -1, a11y->row); + tree_model = e_table_model_value_at (etm, -2, a11y->row); + tree_table_adapter = e_table_model_value_at (etm, -3, a11y->row); + + if (e_tree_model_node_is_expandable (tree_model, node)) { + gboolean is_exp = e_tree_table_adapter_node_is_expanded (tree_table_adapter, node); + if (is_exp) + gal_a11y_e_cell_add_state (a11y, ATK_STATE_EXPANDED, TRUE); + else + gal_a11y_e_cell_remove_state (a11y, ATK_STATE_EXPANDED, TRUE); + } +} + +static void +kill_view_cb(ECellView *subcell_view, + gpointer psubcell_a11ies) +{ + GList *node; + GList *subcell_a11ies = (GList *) psubcell_a11ies; + GalA11yECell *subcell; + + for (node = subcell_a11ies; node != NULL; node = g_list_next (node)) + { + subcell = GAL_A11Y_E_CELL(node->data); + if (subcell && subcell->cell_view == subcell_view) + { + d(fprintf(stderr, "subcell_view %p deleted before the a11y object %p\n", subcell_view, subcell)); + subcell->cell_view = NULL; + } + } +} + +static void +ectr_subcell_weak_ref (GalA11yECellTree *a11y, + GalA11yECell *subcell_a11y) +{ + ECellView *subcell_view = subcell_a11y ? subcell_a11y->cell_view : NULL; + if (subcell_a11y && subcell_view && subcell_view->kill_view_cb_data) + subcell_view->kill_view_cb_data = g_list_remove(subcell_view->kill_view_cb_data, subcell_a11y); + + g_signal_handler_disconnect (GAL_A11Y_E_CELL (a11y)->item->table_model, + a11y->model_row_changed_id); + g_object_unref (a11y); +} + +static void +ectr_do_action_expand (AtkAction *action) +{ + GalA11yECell *a11y; + ETableModel *table_model; + ETreePath node; + ETreeModel *tree_model; + ETreeTableAdapter *tree_table_adapter; + + a11y = GAL_A11Y_E_CELL (action); + table_model = a11y->item->table_model; + node = e_table_model_value_at (table_model, -1, a11y->row); + tree_model = e_table_model_value_at (table_model, -2, a11y->row); + tree_table_adapter = e_table_model_value_at (table_model, -3, a11y->row); + + if (e_tree_model_node_is_expandable (tree_model, node)) { + e_tree_table_adapter_node_set_expanded (tree_table_adapter, + node, + TRUE); + gal_a11y_e_cell_add_state (a11y, ATK_STATE_EXPANDED, TRUE); + } +} + +static void +ectr_do_action_collapse (AtkAction *action) +{ + GalA11yECell *a11y; + ETableModel *table_model; + ETreePath node; + ETreeModel *tree_model; + ETreeTableAdapter *tree_table_adapter; + + a11y = GAL_A11Y_E_CELL (action); + table_model = a11y->item->table_model; + node = e_table_model_value_at (table_model, -1, a11y->row); + tree_model = e_table_model_value_at (table_model, -2, a11y->row); + tree_table_adapter = e_table_model_value_at (table_model, -3, a11y->row); + + if (e_tree_model_node_is_expandable (tree_model, node)) { + e_tree_table_adapter_node_set_expanded (tree_table_adapter, + node, + FALSE); + gal_a11y_e_cell_remove_state (a11y, ATK_STATE_EXPANDED, TRUE); + } +} + +static void +ectr_class_init (GalA11yECellTreeClass *klass) +{ + a11y_parent_class = g_type_class_ref (A11Y_PARENT_TYPE); +} + +static void +ectr_init (GalA11yECellTree *a11y) +{ +} + +GType +gal_a11y_e_cell_tree_get_type (void) +{ + static GType type = 0; + + if (!type) { + GTypeInfo info = { + sizeof (GalA11yECellTreeClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) ectr_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (GalA11yECellTree), + 0, + (GInstanceInitFunc) ectr_init, + NULL /* value_cell_text */ + }; + + type = g_type_register_static (A11Y_PARENT_TYPE, "GalA11yECellTree", &info, 0); + gal_a11y_e_cell_type_add_action_interface (type); + } + + return type; +} + +AtkObject * +gal_a11y_e_cell_tree_new (ETableItem *item, + ECellView *cell_view, + AtkObject *parent, + int model_col, + int view_col, + int row) +{ + AtkObject *subcell_a11y; + GalA11yECellTree *a11y; + + ETreePath node; + ETreeModel *tree_model; + ETreeTableAdapter *tree_table_adapter; + + ECellView *subcell_view; + subcell_view = e_cell_tree_view_get_subcell_view (cell_view); + + if (subcell_view->ecell) { + subcell_a11y = gal_a11y_e_cell_registry_get_object (NULL, + item, + subcell_view, + parent, + model_col, + view_col, + row); + gal_a11y_e_cell_add_action (GAL_A11Y_E_CELL (subcell_a11y), + _("expand"), + _("expands the row in the ETree containing this cell"), + NULL, + (ACTION_FUNC)ectr_do_action_expand); + + gal_a11y_e_cell_add_action (GAL_A11Y_E_CELL (subcell_a11y), + _("collapse"), + _("collapses the row in the ETree containing this cell"), + NULL, + (ACTION_FUNC)ectr_do_action_collapse); + + /* init AtkStates for the cell's a11y object */ + node = e_table_model_value_at (item->table_model, -1, row); + tree_model = e_table_model_value_at (item->table_model, -2, row); + tree_table_adapter = e_table_model_value_at (item->table_model, -3, row); + if (e_tree_model_node_is_expandable (tree_model, node)) { + gal_a11y_e_cell_add_state (GAL_A11Y_E_CELL (subcell_a11y), ATK_STATE_EXPANDABLE, FALSE); + if (e_tree_table_adapter_node_is_expanded (tree_table_adapter, node)) + gal_a11y_e_cell_add_state (GAL_A11Y_E_CELL (subcell_a11y), ATK_STATE_EXPANDED, FALSE); + } + } + else + subcell_a11y = NULL; + + /* create a companion a11y object, this object has type GalA11yECellTree + and it connects to some signals to determine whether a tree cell is + expanded or collapsed */ + a11y = g_object_new (gal_a11y_e_cell_tree_get_type (), NULL); + gal_a11y_e_cell_construct (ATK_OBJECT (a11y), + item, + cell_view, + parent, + model_col, + view_col, + row); + a11y->model_row_changed_id = + g_signal_connect (item->table_model, "model_row_changed", + G_CALLBACK (ectr_model_row_changed_cb), + subcell_a11y); + + if (subcell_a11y && subcell_view) + { + subcell_view->kill_view_cb = kill_view_cb; + if (!g_list_find(subcell_view->kill_view_cb_data, subcell_a11y)) + subcell_view->kill_view_cb_data = g_list_append(subcell_view->kill_view_cb_data, subcell_a11y); + } + + g_object_weak_ref (G_OBJECT (subcell_a11y), (GWeakNotify) ectr_subcell_weak_ref, a11y); + + return subcell_a11y; +} diff --git a/widgets/table/a11y/gal-a11y-e-cell-tree.h b/widgets/table/a11y/gal-a11y-e-cell-tree.h new file mode 100644 index 0000000000..f6f6d9dd70 --- /dev/null +++ b/widgets/table/a11y/gal-a11y-e-cell-tree.h @@ -0,0 +1,64 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Authors: + * Tim Wo <tim.wo@sun.com> + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef __GAL_A11Y_E_CELL_TREE_H__ +#define __GAL_A11Y_E_CELL_TREE_H__ + +#include <glib-object.h> +#include <table/e-table-item.h> +#include <table/e-cell-tree.h> +#include "gal-a11y-e-cell.h" + +#define GAL_A11Y_TYPE_E_CELL_TREE (gal_a11y_e_cell_tree_get_type ()) +#define GAL_A11Y_E_CELL_TREE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GAL_A11Y_TYPE_E_CELL_TREE, GalA11yECellTree)) +#define GAL_A11Y_E_CELL_TREE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GAL_A11Y_TYPE_E_CELL_TREE, GalA11yECellTreeClass)) +#define GAL_A11Y_IS_E_CELL_TREE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GAL_A11Y_TYPE_E_CELL_TREE)) +#define GAL_A11Y_IS_E_CELL_TREE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GAL_A11Y_TYPE_E_CELL_TREE)) + +typedef struct _GalA11yECellTree GalA11yECellTree; +typedef struct _GalA11yECellTreeClass GalA11yECellTreeClass; +typedef struct _GalA11yECellTreePrivate GalA11yECellTreePrivate; + +/* This struct should actually be larger as this isn't what we derive from. + * The GalA11yECellTreePrivate comes right after the parent class structure. + **/ +struct _GalA11yECellTree { + GalA11yECell object; + + int model_row_changed_id; +}; + +struct _GalA11yECellTreeClass { + GalA11yECellClass parent_class; +}; + + +/* Standard Glib function */ +GType gal_a11y_e_cell_tree_get_type (void); +AtkObject *gal_a11y_e_cell_tree_new (ETableItem *item, + ECellView *cell_view, + AtkObject *parent, + int model_col, + int view_col, + int row); + +#endif /* ! __GAL_A11Y_E_CELL_TREE_H__ */ diff --git a/widgets/table/a11y/gal-a11y-e-cell-vbox.c b/widgets/table/a11y/gal-a11y-e-cell-vbox.c new file mode 100644 index 0000000000..08859d07ef --- /dev/null +++ b/widgets/table/a11y/gal-a11y-e-cell-vbox.c @@ -0,0 +1,225 @@ +/* + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Authors: + * Eric Zhao <eric.zhao@sun.com> + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * Copyright (C) 2004 Sun Microsystem, Inc. + * + */ + +#include <config.h> + +#include <atk/atk.h> + +#include "table/e-cell-vbox.h" + +#include "gal-a11y-e-cell-registry.h" +#include "gal-a11y-e-cell-vbox.h" + +static GObjectClass *parent_class; +static AtkComponentIface *component_parent_iface; +#define PARENT_TYPE (gal_a11y_e_cell_get_type ()) + +static gint +ecv_get_n_children (AtkObject *a11y) +{ + g_return_val_if_fail (GAL_A11Y_IS_E_CELL_VBOX (a11y), 0); + + return GAL_A11Y_E_CELL_VBOX (a11y)->a11y_subcell_count; +} + +static void +subcell_destroyed (gpointer data) +{ + GalA11yECell *cell; + AtkObject *parent; + GalA11yECellVbox *gaev; + + g_return_if_fail (GAL_A11Y_IS_E_CELL (data)); + cell = GAL_A11Y_E_CELL (data); + + parent = atk_object_get_parent (ATK_OBJECT (cell)); + g_return_if_fail (GAL_A11Y_IS_E_CELL_VBOX (parent)); + gaev = GAL_A11Y_E_CELL_VBOX (parent); + + if (cell->view_col < gaev->a11y_subcell_count) + gaev->a11y_subcells[cell->view_col] = NULL; +} + +static AtkObject* +ecv_ref_child (AtkObject *a11y, gint i) +{ + GalA11yECellVbox *gaev = GAL_A11Y_E_CELL_VBOX (a11y); + GalA11yECell *gaec = GAL_A11Y_E_CELL (a11y); + ECellVboxView *ecvv = (ECellVboxView *) (gaec->cell_view); + AtkObject *ret; + if (i < gaev->a11y_subcell_count) { + if (gaev->a11y_subcells[i] == NULL) { + ECellView *subcell_view; + gint model_col, row; + row = gaec->row; + model_col = ecvv->model_cols[i]; + subcell_view = ecvv->subcell_views[i]; + ret = gal_a11y_e_cell_registry_get_object (NULL, + gaec->item, + subcell_view, + a11y, + model_col, + gaec->view_col, /* FIXME should the view column use a fake one or the same as its parent? */ + row); + gaev->a11y_subcells[i] = ret; + g_object_ref (ret); + g_object_weak_ref (G_OBJECT (ret), + (GWeakNotify) subcell_destroyed, + ret); + } else { + ret = (AtkObject *) gaev->a11y_subcells[i]; + if (ATK_IS_OBJECT (ret)) + g_object_ref (ret); + else + ret = NULL; + } + } else { + ret = NULL; + } + + return ret; +} + +static void +ecv_dispose (GObject *object) +{ + GalA11yECellVbox *gaev = GAL_A11Y_E_CELL_VBOX (object); + if (gaev->a11y_subcells) + g_free (gaev->a11y_subcells); + + if (parent_class->dispose) + parent_class->dispose (object); +} + +/* AtkComponet interface */ +static AtkObject* +ecv_ref_accessible_at_point (AtkComponent *component, + gint x, + gint y, + AtkCoordType coord_type) +{ + gint x0, y0, width, height; + int subcell_height, i; + + GalA11yECell *gaec = GAL_A11Y_E_CELL (component); + ECellVboxView *ecvv = (ECellVboxView *) (gaec->cell_view); + + atk_component_get_extents (component, &x0, &y0, &width, &height, coord_type); + x -= x0; + y -= y0; + if (x < 0 || x > width || y < 0 || y > height) + return NULL; + + for (i = 0; i < ecvv->subcell_view_count; i++) { + subcell_height = e_cell_height (ecvv->subcell_views[i], ecvv->model_cols[i], gaec->view_col, gaec->row); + if ( 0 <= y && y <= subcell_height) { + return ecv_ref_child ((AtkObject *)component, i); + } else + y -= subcell_height; + } + + return NULL; +} + +static void +ecv_class_init (GalA11yECellVboxClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + AtkObjectClass *a11y_class = ATK_OBJECT_CLASS (klass); + parent_class = g_type_class_ref (PARENT_TYPE); + + object_class->dispose = ecv_dispose; + + a11y_class->get_n_children = ecv_get_n_children; + a11y_class->ref_child = ecv_ref_child; +} + +static void +ecv_init (GalA11yECellVbox *a11y) +{ +} + +static void +ecv_atk_component_iface_init (AtkComponentIface *iface) +{ + component_parent_iface = g_type_interface_peek_parent (iface); + + iface->ref_accessible_at_point = ecv_ref_accessible_at_point; +} + +GType +gal_a11y_e_cell_vbox_get_type (void) +{ + static GType type = 0; + if (!type) { + GTypeInfo info = { + sizeof (GalA11yECellVboxClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) ecv_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (GalA11yECellVbox), + 0, + (GInstanceInitFunc) ecv_init, + NULL /* value_cell */ + }; + + static const GInterfaceInfo atk_component_info = { + (GInterfaceInitFunc) ecv_atk_component_iface_init, + (GInterfaceFinalizeFunc) NULL, + NULL + }; + + type = g_type_register_static (PARENT_TYPE, "GalA11yECellVbox", &info, 0); + gal_a11y_e_cell_type_add_action_interface (type); + g_type_add_interface_static (type, ATK_TYPE_COMPONENT, &atk_component_info); + } + + return type; +} + +AtkObject *gal_a11y_e_cell_vbox_new (ETableItem *item, + ECellView *cell_view, + AtkObject *parent, + int model_col, + int view_col, + int row) +{ + AtkObject *a11y; + GalA11yECell *gaec; + GalA11yECellVbox *gaev; + ECellVboxView *ecvv; + + a11y = g_object_new (gal_a11y_e_cell_vbox_get_type (), NULL); + + gal_a11y_e_cell_construct (a11y, item, cell_view, parent, model_col, view_col, row); + + gaec = GAL_A11Y_E_CELL (a11y); + gaev = GAL_A11Y_E_CELL_VBOX (a11y); + ecvv = (ECellVboxView *) (gaec->cell_view); + gaev->a11y_subcell_count = ecvv->subcell_view_count; + gaev->a11y_subcells = g_malloc0 (sizeof(AtkObject *)*gaev->a11y_subcell_count); + return a11y; +} diff --git a/widgets/table/a11y/gal-a11y-e-cell-vbox.h b/widgets/table/a11y/gal-a11y-e-cell-vbox.h new file mode 100644 index 0000000000..276a60177a --- /dev/null +++ b/widgets/table/a11y/gal-a11y-e-cell-vbox.h @@ -0,0 +1,67 @@ +/* + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Authors: + * Eric Zhao <eric.zhao@sun.com> + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * Copyright (C) 2004 Sun Microsystem, Inc. + * + */ + +#ifndef __GAL_A11Y_E_CELL_VBOX_H__ +#define __GAL_A11Y_E_CELL_VBOX_H__ + +#include "gal-a11y-e-cell.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#define GAL_A11Y_TYPE_E_CELL_VBOX (gal_a11y_e_cell_vbox_get_type ()) +#define GAL_A11Y_E_CELL_VBOX(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GAL_A11Y_TYPE_E_CELL_VBOX, GalA11yECellVbox)) +#define GAL_A11Y_E_CELL_VBOX_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GAL_A11Y_E_CELL_VBOX, GalA11yECellVboxClass)) +#define GAL_A11Y_IS_E_CELL_VBOX(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GAL_A11Y_TYPE_E_CELL_VBOX)) +#define GAL_A11Y_IS_E_CELL_VBOX_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GAL_A11Y_TYPE_E_CELL_VBOX)) +#define GAL_A11Y_E_CELL_VBOX_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GAL_A11Y_TYPE_E_CELL_VBOX, GalA11yECellVboxClass)) + +typedef struct _GalA11yECellVbox GalA11yECellVbox; +typedef struct _GalA11yECellVboxClass GalA11yECellVboxClass; + +struct _GalA11yECellVbox +{ + GalA11yECell object; + int a11y_subcell_count; + gpointer *a11y_subcells; +}; + +struct _GalA11yECellVboxClass +{ + GalA11yECellClass parent_class; +}; + +GType gal_a11y_e_cell_vbox_get_type (void); +AtkObject *gal_a11y_e_cell_vbox_new (ETableItem *item, + ECellView *cell_view, + AtkObject *parent, + int model_col, + int view_col, + int row); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ +#endif /* __GAL_A11Y_E_CELL_VBOX_H__ */ diff --git a/widgets/table/a11y/gal-a11y-e-cell.c b/widgets/table/a11y/gal-a11y-e-cell.c new file mode 100644 index 0000000000..6154fc0acd --- /dev/null +++ b/widgets/table/a11y/gal-a11y-e-cell.c @@ -0,0 +1,644 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Authors: + * Christopher James Lahey <clahey@ximian.com> + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include <config.h> + +#include <string.h> + +#include <gtk/gtk.h> + +#include "a11y/gal-a11y-util.h" +#include "table/e-table.h" +#include "table/e-tree.h" +#include <glib/gi18n.h> + +#include "gal-a11y-e-cell.h" +#include "gal-a11y-e-cell-vbox.h" +#include "gal-a11y-e-table-item.h" + +#define CS_CLASS(a11y) (G_TYPE_INSTANCE_GET_CLASS ((a11y), C_TYPE_STREAM, GalA11yECellClass)) +static GObjectClass *parent_class; +#define PARENT_TYPE (atk_object_get_type ()) + + +#if 0 +static void +unref_item (gpointer user_data, GObject *obj_loc) +{ + GalA11yECell *a11y = GAL_A11Y_E_CELL (user_data); + a11y->item = NULL; + g_object_unref (a11y); +} + +static void +unref_cell (gpointer user_data, GObject *obj_loc) +{ + GalA11yECell *a11y = GAL_A11Y_E_CELL (user_data); + a11y->cell_view = NULL; + g_object_unref (a11y); +} +#endif + +static gboolean +is_valid (AtkObject *cell) +{ + GalA11yECell *a11y = GAL_A11Y_E_CELL (cell); + GalA11yETableItem *a11yItem = GAL_A11Y_E_TABLE_ITEM (a11y->parent); + AtkStateSet *item_ss; + gboolean ret = TRUE; + + item_ss = atk_object_ref_state_set (ATK_OBJECT (a11yItem)); + if (atk_state_set_contains_state (item_ss, ATK_STATE_DEFUNCT)) + ret = FALSE; + + g_object_unref (item_ss); + + if (ret && atk_state_set_contains_state (a11y->state_set, ATK_STATE_DEFUNCT)) + ret = FALSE; + + return ret; +} + +static void +gal_a11y_e_cell_dispose (GObject *object) +{ + GalA11yECell *a11y = GAL_A11Y_E_CELL (object); + +#if 0 + if (a11y->item) + g_object_unref (G_OBJECT (a11y->item)); /*, unref_item, a11y); */ + if (a11y->cell_view) + g_object_unref (G_OBJECT (a11y->cell_view)); /*, unref_cell, a11y); */ + if (a11y->parent) + g_object_unref (a11y->parent); +#endif + + if (a11y->state_set) { + g_object_unref (a11y->state_set); + a11y->state_set = NULL; + } + + if (parent_class->dispose) + parent_class->dispose (object); + +} + +/* Static functions */ +static G_CONST_RETURN gchar* +gal_a11y_e_cell_get_name (AtkObject * a11y) +{ + GalA11yECell *cell = GAL_A11Y_E_CELL (a11y); + ETableCol *ecol; + + if (a11y->name != NULL && strcmp (a11y->name, "")) + return a11y->name; + + if (cell->item != NULL) { + ecol = e_table_header_get_column (cell->item->header, cell->view_col); + if (ecol != NULL) + return ecol->text; + } + + return _("Table Cell"); +} + +static AtkStateSet * +gal_a11y_e_cell_ref_state_set (AtkObject *accessible) +{ + GalA11yECell *cell = GAL_A11Y_E_CELL (accessible); + + g_return_val_if_fail (cell->state_set, NULL); + + g_object_ref(cell->state_set); + + return cell->state_set; +} + +static AtkObject* +gal_a11y_e_cell_get_parent (AtkObject *accessible) +{ + GalA11yECell *a11y = GAL_A11Y_E_CELL (accessible); + return a11y->parent; +} + +static gint +gal_a11y_e_cell_get_index_in_parent (AtkObject *accessible) +{ + GalA11yECell *a11y = GAL_A11Y_E_CELL (accessible); + + if (!is_valid (accessible)) + return -1; + + return (a11y->row + 1) * a11y->item->cols + a11y->view_col; +} + + +/* Component IFace */ +static void +gal_a11y_e_cell_get_extents (AtkComponent *component, + gint *x, + gint *y, + gint *width, + gint *height, + AtkCoordType coord_type) +{ + GalA11yECell *a11y = GAL_A11Y_E_CELL (component); + GtkWidget *tableOrTree; + int row; + int col; + int xval; + int yval; + + row = a11y->row; + col = a11y->view_col; + + tableOrTree = gtk_widget_get_parent (GTK_WIDGET (a11y->item->parent.canvas)); + if (E_IS_TREE (tableOrTree)) { + e_tree_get_cell_geometry (E_TREE (tableOrTree), + row, col, &xval, &yval, + width, height); + } else { + e_table_get_cell_geometry (E_TABLE (tableOrTree), + row, col, &xval, &yval, + width, height); + } + + atk_component_get_position (ATK_COMPONENT (a11y->parent), + x, y, coord_type); + if (x && *x != G_MININT) + *x += xval; + if (y && *y != G_MININT) + *y += yval; +} + +static gboolean +gal_a11y_e_cell_grab_focus (AtkComponent *component) +{ + GalA11yECell *a11y; + gint index; + GtkWidget *toplevel; + GalA11yETableItem *a11yTableItem; + + a11y = GAL_A11Y_E_CELL (component); + + /* for e_cell_vbox's children, we just grab the e_cell_vbox */ + if (GAL_A11Y_IS_E_CELL_VBOX (a11y->parent)) { + return atk_component_grab_focus (ATK_COMPONENT (a11y->parent)); + } + + a11yTableItem = GAL_A11Y_E_TABLE_ITEM (a11y->parent); + index = atk_object_get_index_in_parent (ATK_OBJECT (a11y)); + + atk_selection_clear_selection (ATK_SELECTION (a11yTableItem)); + atk_selection_add_selection (ATK_SELECTION (a11yTableItem), index); + + gtk_widget_grab_focus (GTK_WIDGET (GNOME_CANVAS_ITEM (a11y->item)->canvas)); + toplevel = gtk_widget_get_toplevel (GTK_WIDGET (GNOME_CANVAS_ITEM (a11y->item)->canvas)); + if (toplevel && GTK_WIDGET_TOPLEVEL (toplevel)) + gtk_window_present (GTK_WINDOW (toplevel)); + + return TRUE; +} + +/* Table IFace */ + +static void +gal_a11y_e_cell_atk_component_iface_init (AtkComponentIface *iface) +{ + iface->get_extents = gal_a11y_e_cell_get_extents; + iface->grab_focus = gal_a11y_e_cell_grab_focus; +} + +static void +gal_a11y_e_cell_class_init (GalA11yECellClass *klass) +{ + AtkObjectClass *atk_object_class = ATK_OBJECT_CLASS (klass); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + parent_class = g_type_class_ref (PARENT_TYPE); + + object_class->dispose = gal_a11y_e_cell_dispose; + + atk_object_class->get_parent = gal_a11y_e_cell_get_parent; + atk_object_class->get_index_in_parent = gal_a11y_e_cell_get_index_in_parent; + atk_object_class->ref_state_set = gal_a11y_e_cell_ref_state_set; + atk_object_class->get_name = gal_a11y_e_cell_get_name; +} + +static void +gal_a11y_e_cell_init (GalA11yECell *a11y) +{ + a11y->item = NULL; + a11y->cell_view = NULL; + a11y->parent = NULL; + a11y->model_col = -1; + a11y->view_col = -1; + a11y->row = -1; + + a11y->state_set = atk_state_set_new (); + atk_state_set_add_state (a11y->state_set, ATK_STATE_TRANSIENT); + atk_state_set_add_state (a11y->state_set, ATK_STATE_ENABLED); + atk_state_set_add_state (a11y->state_set, ATK_STATE_SENSITIVE); + atk_state_set_add_state (a11y->state_set, ATK_STATE_SELECTABLE); + atk_state_set_add_state (a11y->state_set, ATK_STATE_SHOWING); + atk_state_set_add_state (a11y->state_set, ATK_STATE_FOCUSABLE); + atk_state_set_add_state (a11y->state_set, ATK_STATE_VISIBLE); +} + + +static ActionInfo * +_gal_a11y_e_cell_get_action_info (GalA11yECell *cell, + gint index) +{ + GList *list_node; + + g_return_val_if_fail (GAL_A11Y_IS_E_CELL (cell), NULL); + if (cell->action_list == NULL) + return NULL; + list_node = g_list_nth (cell->action_list, index); + if (!list_node) + return NULL; + return (ActionInfo *) (list_node->data); +} + +static void +_gal_a11y_e_cell_destroy_action_info (gpointer action_info, + gpointer user_data) +{ + ActionInfo *info = (ActionInfo *)action_info; + + g_return_if_fail (info != NULL); + g_free (info->name); + g_free (info->description); + g_free (info->keybinding); + g_free (info); +} + + +gboolean +gal_a11y_e_cell_add_action ( GalA11yECell * cell, + const gchar *action_name, + const gchar *action_description, + const gchar *action_keybinding, + ACTION_FUNC action_func) +{ + ActionInfo *info; + g_return_val_if_fail (GAL_A11Y_IS_E_CELL (cell), FALSE); + info = g_new (ActionInfo, 1); + + if (action_name != NULL) + info->name = g_strdup (action_name); + else + info->name = NULL; + + if (action_description != NULL) + info->description = g_strdup (action_description); + else + info->description = NULL; + if (action_keybinding != NULL) + info->keybinding = g_strdup (action_keybinding); + else + info->keybinding = NULL; + info->do_action_func = action_func; + + cell->action_list = g_list_append (cell->action_list, (gpointer) info); + return TRUE; +} + +gboolean +gal_a11y_e_cell_remove_action (GalA11yECell *cell, + gint action_index) +{ + GList *list_node; + + g_return_val_if_fail (GAL_A11Y_IS_E_CELL (cell), FALSE); + list_node = g_list_nth (cell->action_list, action_index); + if (!list_node) + return FALSE; + g_return_val_if_fail (list_node->data != NULL, FALSE); + _gal_a11y_e_cell_destroy_action_info (list_node->data, NULL); + cell->action_list = g_list_remove_link (cell->action_list, list_node); + + return TRUE; +} + +gboolean +gal_a11y_e_cell_remove_action_by_name (GalA11yECell *cell, + const gchar *action_name) +{ + GList *list_node; + gboolean action_found= FALSE; + + g_return_val_if_fail (GAL_A11Y_IS_E_CELL (cell), FALSE); + for (list_node = cell->action_list; list_node && !action_found; + list_node = list_node->next) { + if (!g_ascii_strcasecmp (((ActionInfo *)(list_node->data))->name, action_name)) { + action_found = TRUE; + break; + } + } + + g_return_val_if_fail (action_found, FALSE); + _gal_a11y_e_cell_destroy_action_info (list_node->data, NULL); + cell->action_list = g_list_remove_link (cell->action_list, list_node); + + return TRUE; +} + +static gint +gal_a11y_e_cell_action_get_n_actions (AtkAction *action) +{ + GalA11yECell *cell = GAL_A11Y_E_CELL(action); + if (cell->action_list != NULL) + return g_list_length (cell->action_list); + else + return 0; +} + +static G_CONST_RETURN gchar * +gal_a11y_e_cell_action_get_name (AtkAction *action, + gint index) +{ + GalA11yECell *cell = GAL_A11Y_E_CELL(action); + ActionInfo *info = _gal_a11y_e_cell_get_action_info (cell, index); + + if (info == NULL) + return NULL; + return info->name; +} + +static G_CONST_RETURN gchar * +gal_a11y_e_cell_action_get_description (AtkAction *action, + gint index) +{ + GalA11yECell *cell = GAL_A11Y_E_CELL(action); + ActionInfo *info = _gal_a11y_e_cell_get_action_info (cell, index); + + if (info == NULL) + return NULL; + return info->description; +} + +static gboolean +gal_a11y_e_cell_action_set_description (AtkAction *action, + gint index, + const gchar *desc) +{ + GalA11yECell *cell = GAL_A11Y_E_CELL(action); + ActionInfo *info = _gal_a11y_e_cell_get_action_info (cell, index); + + if (info == NULL) + return FALSE; + g_free (info->description); + info->description = g_strdup (desc); + return TRUE; +} + +static G_CONST_RETURN gchar * +gal_a11y_e_cell_action_get_keybinding (AtkAction *action, + gint index) +{ + GalA11yECell *cell = GAL_A11Y_E_CELL(action); + ActionInfo *info = _gal_a11y_e_cell_get_action_info (cell, index); + if (info == NULL) + return NULL; + + return info->keybinding; +} + +static gboolean +idle_do_action (gpointer data) +{ + GalA11yECell *cell; + + cell = GAL_A11Y_E_CELL (data); + + if (!is_valid (ATK_OBJECT (cell))) + return FALSE; + + cell->action_idle_handler = 0; + cell->action_func (cell); + g_object_unref (cell); + + return FALSE; +} + +static gboolean +gal_a11y_e_cell_action_do_action (AtkAction *action, + gint index) +{ + GalA11yECell *cell = GAL_A11Y_E_CELL(action); + ActionInfo *info = _gal_a11y_e_cell_get_action_info (cell, index); + + if (!is_valid (ATK_OBJECT (action))) + return FALSE; + + if (info == NULL) + return FALSE; + g_return_val_if_fail (info->do_action_func, FALSE); + if (cell->action_idle_handler) + return FALSE; + cell->action_func = info->do_action_func; + g_object_ref (cell); + cell->action_idle_handler = g_idle_add (idle_do_action, cell); + + return TRUE; +} + +static void +gal_a11y_e_cell_atk_action_interface_init (AtkActionIface *iface) +{ + g_return_if_fail (iface != NULL); + + iface->get_n_actions = gal_a11y_e_cell_action_get_n_actions; + iface->do_action = gal_a11y_e_cell_action_do_action; + iface->get_name = gal_a11y_e_cell_action_get_name; + iface->get_description = gal_a11y_e_cell_action_get_description; + iface->set_description = gal_a11y_e_cell_action_set_description; + iface->get_keybinding = gal_a11y_e_cell_action_get_keybinding; +} + +void +gal_a11y_e_cell_type_add_action_interface (GType type) +{ + static const GInterfaceInfo atk_action_info = + { + (GInterfaceInitFunc) gal_a11y_e_cell_atk_action_interface_init, + (GInterfaceFinalizeFunc) NULL, + NULL + }; + + g_type_add_interface_static (type, ATK_TYPE_ACTION, + &atk_action_info); +} + +gboolean +gal_a11y_e_cell_add_state (GalA11yECell *cell, + AtkStateType state_type, + gboolean emit_signal) +{ + if (!atk_state_set_contains_state (cell->state_set, state_type)) { + gboolean rc; + + rc = atk_state_set_add_state (cell->state_set, state_type); + /* + * The signal should only be generated if the value changed, + * not when the cell is set up. So states that are set + * initially should pass FALSE as the emit_signal argument. + */ + + if (emit_signal) { + atk_object_notify_state_change (ATK_OBJECT (cell), state_type, TRUE); + /* If state_type is ATK_STATE_VISIBLE, additional + notification */ + if (state_type == ATK_STATE_VISIBLE) + g_signal_emit_by_name (cell, "visible_data_changed"); + } + + return rc; + } + else + return FALSE; +} + +gboolean +gal_a11y_e_cell_remove_state (GalA11yECell *cell, + AtkStateType state_type, + gboolean emit_signal) +{ + if (atk_state_set_contains_state (cell->state_set, state_type)) { + gboolean rc; + + rc = atk_state_set_remove_state (cell->state_set, state_type); + /* + * The signal should only be generated if the value changed, + * not when the cell is set up. So states that are set + * initially should pass FALSE as the emit_signal argument. + */ + + if (emit_signal) { + atk_object_notify_state_change (ATK_OBJECT (cell), state_type, FALSE); + /* If state_type is ATK_STATE_VISIBLE, additional notification */ + if (state_type == ATK_STATE_VISIBLE) + g_signal_emit_by_name (cell, "visible_data_changed"); + } + + return rc; + } + else + return FALSE; +} + +/** + * gal_a11y_e_cell_get_type: + * @void: + * + * Registers the &GalA11yECell class if necessary, and returns the type ID + * associated to it. + * + * Return value: The type ID of the &GalA11yECell class. + **/ +GType +gal_a11y_e_cell_get_type (void) +{ + static GType type = 0; + + if (!type) { + GTypeInfo info = { + sizeof (GalA11yECellClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) gal_a11y_e_cell_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (GalA11yECell), + 0, + (GInstanceInitFunc) gal_a11y_e_cell_init, + NULL /* value_cell */ + }; + + static const GInterfaceInfo atk_component_info = { + (GInterfaceInitFunc) gal_a11y_e_cell_atk_component_iface_init, + (GInterfaceFinalizeFunc) NULL, + NULL + }; + + type = g_type_register_static (PARENT_TYPE, "GalA11yECell", &info, 0); + g_type_add_interface_static (type, ATK_TYPE_COMPONENT, &atk_component_info); + } + + return type; +} + +AtkObject * +gal_a11y_e_cell_new (ETableItem *item, + ECellView *cell_view, + AtkObject *parent, + int model_col, + int view_col, + int row) +{ + AtkObject *a11y; + + a11y = g_object_new (gal_a11y_e_cell_get_type (), NULL); + + gal_a11y_e_cell_construct (a11y, + item, + cell_view, + parent, + model_col, + view_col, + row); + return a11y; +} + +void +gal_a11y_e_cell_construct (AtkObject *object, + ETableItem *item, + ECellView *cell_view, + AtkObject *parent, + int model_col, + int view_col, + int row) +{ + GalA11yECell *a11y = GAL_A11Y_E_CELL (object); + a11y->item = item; + a11y->cell_view = cell_view; + a11y->parent = parent; + a11y->model_col = model_col; + a11y->view_col = view_col; + a11y->row = row; + ATK_OBJECT (a11y) ->role = ATK_ROLE_TABLE_CELL; + + if (item) + g_object_ref (G_OBJECT (item)); + +#if 0 + if (parent) + g_object_ref (parent); + + if (cell_view) + g_object_ref (G_OBJECT (cell_view)); + + +#endif +} diff --git a/widgets/table/a11y/gal-a11y-e-cell.h b/widgets/table/a11y/gal-a11y-e-cell.h new file mode 100644 index 0000000000..cdae721112 --- /dev/null +++ b/widgets/table/a11y/gal-a11y-e-cell.h @@ -0,0 +1,113 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Authors: + * Christopher James Lahey <clahey@ximian.com> + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef __GAL_A11Y_E_CELL_H__ +#define __GAL_A11Y_E_CELL_H__ + +#include <glib-object.h> +#include <table/e-table-item.h> +#include <table/e-cell.h> + +#define GAL_A11Y_TYPE_E_CELL (gal_a11y_e_cell_get_type ()) +#define GAL_A11Y_E_CELL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GAL_A11Y_TYPE_E_CELL, GalA11yECell)) +#define GAL_A11Y_E_CELL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GAL_A11Y_TYPE_E_CELL, GalA11yECellClass)) +#define GAL_A11Y_IS_E_CELL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GAL_A11Y_TYPE_E_CELL)) +#define GAL_A11Y_IS_E_CELL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GAL_A11Y_TYPE_E_CELL)) + +typedef struct _GalA11yECell GalA11yECell; +typedef struct _GalA11yECellClass GalA11yECellClass; +typedef struct _GalA11yECellPrivate GalA11yECellPrivate; +typedef struct _ActionInfo ActionInfo; +typedef void (*ACTION_FUNC) (GalA11yECell *cell); + + +/* This struct should actually be larger as this isn't what we derive from. + * The GalA11yECellPrivate comes right after the parent class structure. + **/ +struct _GalA11yECell { + AtkObject object; + + ETableItem *item; + ECellView *cell_view; + AtkObject *parent; + int model_col; + int view_col; + int row; + AtkStateSet *state_set; + GList *action_list; + gint action_idle_handler; + ACTION_FUNC action_func; +}; + +struct _GalA11yECellClass { + AtkObjectClass parent_class; +}; + +struct _ActionInfo { + gchar *name; + gchar *description; + gchar *keybinding; + ACTION_FUNC do_action_func; +}; + + + +/* Standard Glib function */ +GType gal_a11y_e_cell_get_type (void); +AtkObject *gal_a11y_e_cell_new (ETableItem *item, + ECellView *cell_view, + AtkObject *parent, + int model_col, + int view_col, + int row); +void gal_a11y_e_cell_construct (AtkObject *object, + ETableItem *item, + ECellView *cell_view, + AtkObject *parent, + int model_col, + int view_col, + int row); + +void gal_a11y_e_cell_type_add_action_interface (GType type); + +gboolean gal_a11y_e_cell_add_action (GalA11yECell *cell, + const gchar *action_name, + const gchar *action_description, + const gchar *action_keybinding, + ACTION_FUNC action_func); + +gboolean gal_a11y_e_cell_remove_action (GalA11yECell *cell, + gint action_id); + +gboolean gal_a11y_e_cell_remove_action_by_name (GalA11yECell *cell, + const gchar *action_name); + +gboolean gal_a11y_e_cell_add_state (GalA11yECell *cell, + AtkStateType state_type, + gboolean emit_signal); + +gboolean gal_a11y_e_cell_remove_state (GalA11yECell *cell, + AtkStateType state_type, + gboolean emit_signal); + + +#endif /* ! __GAL_A11Y_E_CELL_H__ */ diff --git a/widgets/table/a11y/gal-a11y-e-table-click-to-add-factory.c b/widgets/table/a11y/gal-a11y-e-table-click-to-add-factory.c new file mode 100644 index 0000000000..9161b4d834 --- /dev/null +++ b/widgets/table/a11y/gal-a11y-e-table-click-to-add-factory.c @@ -0,0 +1,106 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Authors: + * Yuedong Du <yuedong.du@sun.com> + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include <config.h> + +#include <atk/atk.h> + +#include "table/e-table.h" +#include "table/e-table-click-to-add.h" + +#include "gal-a11y-e-table.h" +#include "gal-a11y-e-table-click-to-add.h" +#include "gal-a11y-e-table-click-to-add-factory.h" + +#define CS_CLASS(factory) (G_TYPE_INSTANCE_GET_CLASS ((factory), C_TYPE_STREAM, GalA11yETableClickToAddFactoryClass)) +static AtkObjectFactoryClass *parent_class; +#define PARENT_TYPE (ATK_TYPE_OBJECT_FACTORY) + +/* Static functions */ + +static GType +gal_a11y_e_table_click_to_add_factory_get_accessible_type (void) +{ + return GAL_A11Y_TYPE_E_TABLE_CLICK_TO_ADD; +} + +static AtkObject* +gal_a11y_e_table_click_to_add_factory_create_accessible (GObject *obj) +{ + AtkObject * atk_object; + + g_return_val_if_fail (E_IS_TABLE_CLICK_TO_ADD(obj), NULL); + + atk_object = gal_a11y_e_table_click_to_add_new (obj); + + return atk_object; +} + +static void +gal_a11y_e_table_click_to_add_factory_class_init (GalA11yETableClickToAddFactoryClass *klass) +{ + AtkObjectFactoryClass *factory_class = ATK_OBJECT_FACTORY_CLASS (klass); + + parent_class = g_type_class_ref (PARENT_TYPE); + + factory_class->create_accessible = gal_a11y_e_table_click_to_add_factory_create_accessible; + factory_class->get_accessible_type = gal_a11y_e_table_click_to_add_factory_get_accessible_type; +} + +static void +gal_a11y_e_table_click_to_add_factory_init (GalA11yETableClickToAddFactory *factory) +{ +} + +/** + * gal_a11y_e_table_factory_get_type: + * @void: + * + * Registers the &GalA11yETableFactory class if necessary, and returns the type ID + * associated to it. + * + * Return value: The type ID of the &GalA11yETableFactory class. + **/ +GType +gal_a11y_e_table_click_to_add_factory_get_type (void) +{ + static GType type = 0; + + if (!type) { + GTypeInfo info = { + sizeof (GalA11yETableClickToAddFactoryClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) gal_a11y_e_table_click_to_add_factory_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (GalA11yETableClickToAddFactory), + 0, + (GInstanceInitFunc) gal_a11y_e_table_click_to_add_factory_init, + NULL /* value_table */ + }; + + type = g_type_register_static (PARENT_TYPE, "GalA11yETableClickToAddFactory", &info, 0); + } + + return type; +} diff --git a/widgets/table/a11y/gal-a11y-e-table-click-to-add-factory.h b/widgets/table/a11y/gal-a11y-e-table-click-to-add-factory.h new file mode 100644 index 0000000000..0e4ac11f79 --- /dev/null +++ b/widgets/table/a11y/gal-a11y-e-table-click-to-add-factory.h @@ -0,0 +1,50 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Authors: + * Yuedong Du <yuedong.du@sun.com> + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef __GAL_A11Y_E_TABLE_CLICK_TO_ADD_FACTORY_H__ +#define __GAL_A11Y_E_TABLE_CLICK_TO_ADD_FACTORY_H__ + +#include <glib-object.h> +#include <atk/atkobjectfactory.h> + +#define GAL_A11Y_TYPE_E_TABLE_CLICK_TO_ADD_FACTORY (gal_a11y_e_table_item_factory_get_type ()) +#define GAL_A11Y_E_TABLE_CLICK_TO_ADD_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GAL_A11Y_TYPE_E_TABLE_CLICK_TO_ADD_FACTORY, GalA11yETableClickToAddFactory)) +#define GAL_A11Y_E_TABLE_CLICK_TO_ADD_FACTORY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GAL_A11Y_TYPE_E_TABLE_CLICK_TO_ADD_FACTORY, GalA11yETableClickToAddFactoryClass)) +#define GAL_A11Y_IS_E_TABLE_CLICK_TO_ADD_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GAL_A11Y_TYPE_E_TABLE_CLICK_TO_ADD_FACTORY)) +#define GAL_A11Y_IS_E_TABLE_CLICK_TO_ADD_FACTORY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GAL_A11Y_TYPE_E_TABLE_CLICK_TO_ADD_FACTORY)) + +typedef struct _GalA11yETableClickToAddFactory GalA11yETableClickToAddFactory; +typedef struct _GalA11yETableClickToAddFactoryClass GalA11yETableClickToAddFactoryClass; + +struct _GalA11yETableClickToAddFactory { + AtkObject object; +}; + +struct _GalA11yETableClickToAddFactoryClass { + AtkObjectClass parent_class; +}; + + +/* Standard Glib function */ +GType gal_a11y_e_table_click_to_add_factory_get_type (void); + +#endif diff --git a/widgets/table/a11y/gal-a11y-e-table-click-to-add.c b/widgets/table/a11y/gal-a11y-e-table-click-to-add.c new file mode 100644 index 0000000000..85c896ccf3 --- /dev/null +++ b/widgets/table/a11y/gal-a11y-e-table-click-to-add.c @@ -0,0 +1,344 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Authors: + * Yuedong Du <yuedong.du@sun.com> + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include <config.h> + +#include <atk/atk.h> + +#include "a11y/gal-a11y-util.h" +#include "table/e-table-click-to-add.h" +#include "table/e-table-group.h" +#include "table/e-table-group-leaf.h" +#include <glib/gi18n.h> + +#include "gal-a11y-e-table-click-to-add.h" +#include "gal-a11y-e-table-click-to-add-factory.h" + +static AtkObjectClass *parent_class; +static GType parent_type; +static gint priv_offset; +#define GET_PRIVATE(object) ((GalA11yETableClickToAddPrivate *) (((char *) object) + priv_offset)) +#define PARENT_TYPE (parent_type) + +struct _GalA11yETableClickToAddPrivate { + gpointer rect; + gpointer row; +}; + + +static gint +etcta_get_n_actions (AtkAction *action) +{ + return 1; +} + +static G_CONST_RETURN gchar* +etcta_get_description (AtkAction *action, + gint i) +{ + if (i == 0) + return _("click to add"); + + return NULL; +} + +static G_CONST_RETURN gchar* +etcta_action_get_name (AtkAction *action, gint i) +{ + if (i == 0) + return _("click"); + + return NULL; +} + + +static gboolean +idle_do_action (gpointer data) +{ + GdkEventButton event; + ETableClickToAdd * etcta; + gint finished; + + g_return_val_if_fail ( data!= NULL, FALSE); + + etcta = E_TABLE_CLICK_TO_ADD (atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (data))); + g_return_val_if_fail (etcta, FALSE); + + event.x = 0; + event.y = 0; + + event.type = GDK_BUTTON_PRESS; + event.window = GTK_LAYOUT(GNOME_CANVAS_ITEM(etcta)->canvas)->bin_window; + event.button = 1; + event.send_event = TRUE; + event.time = GDK_CURRENT_TIME; + event.axes = NULL; + + g_signal_emit_by_name (etcta, "event", &event, &finished); + + return FALSE; +} + +static gboolean +etcta_do_action (AtkAction * action, gint i) +{ + g_return_val_if_fail (i == 0, FALSE); + + g_idle_add (idle_do_action, action); + + return TRUE; +} + +static void +atk_action_interface_init (AtkActionIface *iface) +{ + g_return_if_fail (iface != NULL); + + iface->do_action = etcta_do_action; + iface->get_n_actions = etcta_get_n_actions; + iface->get_description = etcta_get_description; + iface->get_name = etcta_action_get_name; +} + + +static G_CONST_RETURN gchar * +etcta_get_name (AtkObject *obj) +{ + ETableClickToAdd * etcta; + + g_return_val_if_fail (GAL_A11Y_IS_E_TABLE_CLICK_TO_ADD (obj), NULL); + + etcta = E_TABLE_CLICK_TO_ADD (atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE(obj))); + if (etcta && etcta->message != NULL) + return etcta->message; + + return _("click to add"); +} + +static gint +etcta_get_n_children (AtkObject *accessible) +{ + return 1; +} + +static AtkObject* +etcta_ref_child (AtkObject *accessible, + gint i) +{ + AtkObject * atk_obj = NULL; + ETableClickToAdd * etcta; + + if ( i != 0 ) + return NULL; + + etcta = E_TABLE_CLICK_TO_ADD(atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (accessible))); + + g_return_val_if_fail (etcta, NULL); + + if (etcta->rect) { + atk_obj = atk_gobject_accessible_for_object (G_OBJECT(etcta->rect)); + } else if (etcta->row) { + atk_obj = atk_gobject_accessible_for_object (G_OBJECT(etcta->row)); + } + + g_object_ref (atk_obj); + + return atk_obj; +} + +static AtkStateSet * +etcta_ref_state_set (AtkObject *accessible) +{ + AtkStateSet * state_set = NULL; + + state_set = ATK_OBJECT_CLASS (parent_class)->ref_state_set (accessible); + if (state_set != NULL) { + atk_state_set_add_state (state_set, ATK_STATE_SENSITIVE); + atk_state_set_add_state (state_set, ATK_STATE_SHOWING); + } + + return state_set; +} + +static void +etcta_class_init (GalA11yETableClickToAddClass *klass) +{ + AtkObjectClass *atk_object_class = ATK_OBJECT_CLASS (klass); + + parent_class = g_type_class_ref (PARENT_TYPE); + + atk_object_class->get_name = etcta_get_name; + atk_object_class->get_n_children = etcta_get_n_children; + atk_object_class->ref_child = etcta_ref_child; + atk_object_class->ref_state_set = etcta_ref_state_set; +} + +static void +etcta_init (GalA11yETableClickToAdd *a11y) +{ +} + +/** + * gal_a11y_e_table_click_to_add_get_type: + * @void: + * + * Registers the &GalA11yETableClickToAdd class if necessary, and returns the type ID + * associated to it. + * + * Return value: The type ID of the &GalA11yETableClickToAdd class. + **/ +GType +gal_a11y_e_table_click_to_add_get_type (void) +{ + static GType type = 0; + + if (!type) { + AtkObjectFactory *factory; + + GTypeInfo info = { + sizeof (GalA11yETableClickToAddClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) etcta_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (GalA11yETableClickToAdd), + 0, + (GInstanceInitFunc) etcta_init, + NULL /* value_table */ + }; + + static const GInterfaceInfo atk_action_info = { + (GInterfaceInitFunc) atk_action_interface_init, + (GInterfaceFinalizeFunc) NULL, + NULL + }; + + factory = atk_registry_get_factory (atk_get_default_registry (), GNOME_TYPE_CANVAS_ITEM); + + parent_type = atk_object_factory_get_accessible_type (factory); + type = gal_a11y_type_register_static_with_private (PARENT_TYPE, + "GalA11yETableClickToAdd", &info, 0, + sizeof(GalA11yETableClickToAddPrivate), &priv_offset); + + g_type_add_interface_static (type, ATK_TYPE_ACTION, &atk_action_info); + + } + + return type; +} + +static gboolean +etcta_event (GnomeCanvasItem *item, GdkEvent *e, gpointer data) +{ + ETableClickToAdd *etcta = E_TABLE_CLICK_TO_ADD (item); + GalA11yETableClickToAdd *a11y; + GalA11yETableClickToAddPrivate *priv; + + g_return_val_if_fail (item, TRUE); + + g_return_val_if_fail (GAL_A11Y_IS_E_TABLE_CLICK_TO_ADD(data), FALSE); + a11y = GAL_A11Y_E_TABLE_CLICK_TO_ADD (data); + + priv = GET_PRIVATE (a11y); + + /* rect replaced by row. */ + if (etcta->rect == NULL && priv->rect != NULL) { + g_signal_emit_by_name (a11y, "children_changed::remove", 0, NULL, NULL); + + } + /* row inserted, and/or replaced by a new row. */ + if (etcta->row != NULL && priv->row == NULL) { + g_signal_emit_by_name (a11y, "children_changed::add", 0, NULL, NULL); + } else if (etcta->row != NULL && priv->row != NULL && etcta->row != priv->row) { + g_signal_emit_by_name (a11y, "children_changed::remove", 0, NULL, NULL); + g_signal_emit_by_name (a11y, "children_changed::add", 0, NULL, NULL); + } + + + priv->rect = etcta->rect; + priv->row = etcta->row; + + return FALSE; +} + +static void +etcta_selection_cursor_changed (ESelectionModel *esm, gint row, gint col, + GalA11yETableClickToAdd *a11y) +{ + ETableClickToAdd *etcta; + AtkObject *row_a11y; + + etcta = E_TABLE_CLICK_TO_ADD (atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE(a11y))); + + if (etcta == NULL || etcta->row == NULL) + return; + + row_a11y = atk_gobject_accessible_for_object (G_OBJECT(etcta->row)); + if (row_a11y) { + AtkObject *cell_a11y = g_object_get_data (G_OBJECT(row_a11y), "gail-focus-object"); + if (cell_a11y) { + atk_focus_tracker_notify (cell_a11y); + } + } +} + +AtkObject * +gal_a11y_e_table_click_to_add_new (GObject *widget) +{ + GalA11yETableClickToAdd *a11y; + ETableClickToAdd * etcta; + GalA11yETableClickToAddPrivate *priv; + + g_return_val_if_fail (widget != NULL, NULL); + + a11y = g_object_new (gal_a11y_e_table_click_to_add_get_type (), NULL); + priv = GET_PRIVATE (a11y); + + etcta = E_TABLE_CLICK_TO_ADD(widget); + + + atk_object_initialize (ATK_OBJECT (a11y), etcta); + + priv->rect = etcta->rect; + priv->row = etcta->row; + + + g_signal_connect_after (G_OBJECT(widget), "event", + G_CALLBACK (etcta_event), a11y); + + g_signal_connect (etcta->selection, "cursor_changed", + G_CALLBACK (etcta_selection_cursor_changed), a11y); + + return ATK_OBJECT (a11y); +} + +void +gal_a11y_e_table_click_to_add_init (void) +{ + if (atk_get_root ()) + atk_registry_set_factory_type (atk_get_default_registry (), + E_TABLE_CLICK_TO_ADD_TYPE, + gal_a11y_e_table_click_to_add_factory_get_type ()); + +} + diff --git a/widgets/table/a11y/gal-a11y-e-table-click-to-add.h b/widgets/table/a11y/gal-a11y-e-table-click-to-add.h new file mode 100644 index 0000000000..ccefc7a9b8 --- /dev/null +++ b/widgets/table/a11y/gal-a11y-e-table-click-to-add.h @@ -0,0 +1,55 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Authors: + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef __GAL_A11Y_E_TABLE_CLICK_TO_ADD_H__ +#define __GAL_A11Y_E_TABLE_CLICK_TO_ADD_H__ + +#include <glib-object.h> +#include <table/e-table-item.h> +#include <atk/atkgobjectaccessible.h> + +#define GAL_A11Y_TYPE_E_TABLE_CLICK_TO_ADD (gal_a11y_e_table_click_to_add_get_type ()) +#define GAL_A11Y_E_TABLE_CLICK_TO_ADD(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GAL_A11Y_TYPE_E_TABLE_CLICK_TO_ADD, GalA11yETableClickToAdd)) +#define GAL_A11Y_E_TABLE_CLICK_TO_ADD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GAL_A11Y_TYPE_E_TABLE_CLICK_TO_ADD, GalA11yETableClickToAddClass)) +#define GAL_A11Y_IS_E_TABLE_CLICK_TO_ADD(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GAL_A11Y_TYPE_E_TABLE_CLICK_TO_ADD)) +#define GAL_A11Y_IS_E_TABLE_CLICK_TO_ADD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GAL_A11Y_TYPE_E_TABLE_CLICK_TO_ADD)) + +typedef struct _GalA11yETableClickToAdd GalA11yETableClickToAdd; +typedef struct _GalA11yETableClickToAddClass GalA11yETableClickToAddClass; +typedef struct _GalA11yETableClickToAddPrivate GalA11yETableClickToAddPrivate; + +/* This struct should actually be larger as this isn't what we derive from. + * The GalA11yETableClickToAddPrivate comes right after the parent class structure. + **/ +struct _GalA11yETableClickToAdd { + AtkGObjectAccessible parent; +}; + +struct _GalA11yETableClickToAddClass { + AtkGObjectAccessibleClass parent_class; +}; + +/* Standard Glib function */ +GType gal_a11y_e_table_click_to_add_get_type (void); +AtkObject *gal_a11y_e_table_click_to_add_new (GObject *widget); + +void gal_a11y_e_table_click_to_add_init (void); +#endif /* ! __GAL_A11Y_E_TABLE_CLICK_TO_ADD_H__ */ diff --git a/widgets/table/a11y/gal-a11y-e-table-column-header.c b/widgets/table/a11y/gal-a11y-e-table-column-header.c new file mode 100644 index 0000000000..a50a286940 --- /dev/null +++ b/widgets/table/a11y/gal-a11y-e-table-column-header.c @@ -0,0 +1,229 @@ +/* + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Authors: + * Li Yuan <li.yuan@sun.com> + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include <config.h> +#include <glib/gi18n.h> +#include <atk/atkobject.h> +#include <atk/atkregistry.h> +#include "table/e-table-header-item.h" +#include "a11y/gal-a11y-util.h" +#include "gal-a11y-e-table-column-header.h" + +static GObjectClass *parent_class; +static gint priv_offset; + +#define GET_PRIVATE(object) ((GalA11yETableColumnHeaderPrivate *) (((char *) object) + priv_offset)) +#define PARENT_TYPE (atk_gobject_accessible_get_type ()) + +struct _GalA11yETableColumnHeaderPrivate { + ETableItem *item; + AtkObject *parent; + AtkStateSet *state_set; +}; + +static void +etch_init (GalA11yETableColumnHeader *a11y) +{ + GET_PRIVATE (a11y)->item = NULL; + GET_PRIVATE (a11y)->parent = NULL; + GET_PRIVATE (a11y)->state_set = NULL; +} + +static AtkStateSet * +gal_a11y_e_table_column_header_ref_state_set (AtkObject *accessible) +{ + GalA11yETableColumnHeaderPrivate *priv = GET_PRIVATE (accessible); + + g_return_val_if_fail (priv->state_set, NULL); + + g_object_ref(priv->state_set); + + return priv->state_set; +} + +static void +gal_a11y_e_table_column_header_real_initialize (AtkObject *obj, gpointer data) +{ + ATK_OBJECT_CLASS (parent_class)->initialize (obj, data); +} + +static void +gal_a11y_e_table_column_header_dispose (GObject *object) +{ + GalA11yETableColumnHeader *a11y = GAL_A11Y_E_TABLE_COLUMN_HEADER (object); + GalA11yETableColumnHeaderPrivate *priv = GET_PRIVATE (a11y); + + if (priv->state_set) { + g_object_unref (priv->state_set); + priv->state_set = NULL; + } + + if (parent_class->dispose) + parent_class->dispose (object); + +} + +static void +etch_class_init (GalA11yETableColumnHeaderClass *klass) +{ + AtkObjectClass *class = ATK_OBJECT_CLASS (klass); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + parent_class = g_type_class_ref (PARENT_TYPE); + + object_class->dispose = gal_a11y_e_table_column_header_dispose; + + class->ref_state_set = gal_a11y_e_table_column_header_ref_state_set; + class->initialize = gal_a11y_e_table_column_header_real_initialize; +} + +inline static GObject * +etch_a11y_get_gobject (AtkGObjectAccessible *accessible) +{ + return atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (accessible)); +} + +static gboolean +gal_a11y_e_table_column_header_do_action (AtkAction *action, + gint i) +{ + gboolean return_value = TRUE; + GtkWidget *widget; + GalA11yETableColumnHeader *a11y; + ETableHeaderItem *ethi; + ETableItem *item; + ETableCol *col; + + switch (i) { + case 0: + a11y = GAL_A11Y_E_TABLE_COLUMN_HEADER (action); + col = E_TABLE_COL (etch_a11y_get_gobject (ATK_GOBJECT_ACCESSIBLE (a11y))); + item = GET_PRIVATE (a11y)->item; + widget = gtk_widget_get_parent (GTK_WIDGET (item->parent.canvas)); + if (E_IS_TREE (widget)) { + ethi = E_TABLE_HEADER_ITEM (e_tree_get_header_item (E_TREE (widget))); + } + else if (E_IS_TABLE (widget)) + ethi = E_TABLE_HEADER_ITEM (E_TABLE (widget)->header_item); + else + break; + ethi_change_sort_state (ethi, col); + default: + return_value = FALSE; + break; + } + return return_value; +} + +static gint +gal_a11y_e_table_column_header_get_n_actions (AtkAction *action) +{ + return 1; +} + +static G_CONST_RETURN gchar* +gal_a11y_e_table_column_header_action_get_name (AtkAction *action, + gint i) +{ + G_CONST_RETURN gchar *return_value; + + switch (i) { + case 0: + return_value = _("sort"); + break; + default: + return_value = NULL; + break; + } + return return_value; +} + +static void +atk_action_interface_init (AtkActionIface *iface) +{ + g_return_if_fail (iface != NULL); + + iface->do_action = gal_a11y_e_table_column_header_do_action; + iface->get_n_actions = gal_a11y_e_table_column_header_get_n_actions; + iface->get_name = gal_a11y_e_table_column_header_action_get_name; +} + +GType +gal_a11y_e_table_column_header_get_type (void) +{ + static GType type = 0; + + if (!type) { + GTypeInfo info = { + sizeof (GalA11yETableColumnHeaderClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) etch_class_init, + (GClassFinalizeFunc) NULL, + NULL, + sizeof (GalA11yETableColumnHeader), + 0, + (GInstanceInitFunc) etch_init, + NULL + }; + static const GInterfaceInfo atk_action_info = { + (GInterfaceInitFunc) atk_action_interface_init, + (GInterfaceFinalizeFunc) NULL, + NULL + }; + + type = gal_a11y_type_register_static_with_private (PARENT_TYPE, "GalA11yETableColumnHeader", &info, 0, + sizeof (GalA11yETableColumnHeaderPrivate), &priv_offset); + + g_type_add_interface_static (type, ATK_TYPE_ACTION, &atk_action_info); + } + + return type; +} + +AtkObject * +gal_a11y_e_table_column_header_new (ETableCol *ecol, ETableItem *item) +{ + GalA11yETableColumnHeader *a11y; + AtkObject *accessible; + + g_return_val_if_fail (E_IS_TABLE_COL (ecol), NULL); + + a11y = g_object_new (gal_a11y_e_table_column_header_get_type(), NULL); + accessible = ATK_OBJECT (a11y); + atk_object_initialize (accessible, ecol); + + GET_PRIVATE (a11y)->item = item; + GET_PRIVATE (a11y)->state_set = atk_state_set_new (); + + atk_state_set_add_state (GET_PRIVATE(a11y)->state_set, ATK_STATE_VISIBLE); + atk_state_set_add_state (GET_PRIVATE(a11y)->state_set, ATK_STATE_SHOWING); + atk_state_set_add_state (GET_PRIVATE(a11y)->state_set, ATK_STATE_SENSITIVE); + atk_state_set_add_state (GET_PRIVATE(a11y)->state_set, ATK_STATE_ENABLED); + + if (ecol->text) + atk_object_set_name (accessible, ecol->text); + atk_object_set_role (accessible, ATK_ROLE_TABLE_COLUMN_HEADER); + + return ATK_OBJECT (a11y); +} diff --git a/widgets/table/a11y/gal-a11y-e-table-column-header.h b/widgets/table/a11y/gal-a11y-e-table-column-header.h new file mode 100644 index 0000000000..083f0af3de --- /dev/null +++ b/widgets/table/a11y/gal-a11y-e-table-column-header.h @@ -0,0 +1,55 @@ +/* + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Authors: + * Li Yuan <li.yuan@sun.com> + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + + +#ifndef __GAL_A11Y_E_TABLE_COLUMN_HEADER_H__ +#define __GAL_A11Y_E_TABLE_COLUMN_HEADER_H__ + +#include <glib-object.h> +#include <atk/atkgobjectaccessible.h> + +#define GAL_A11Y_TYPE_E_TABLE_COLUMN_HEADER (gal_a11y_e_table_column_header_get_type ()) +#define GAL_A11Y_E_TABLE_COLUMN_HEADER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GAL_A11Y_TYPE_E_TABLE_COLUMN_HEADER, GalA11yETableColumnHeader)) +#define GAL_A11Y_E_TABLE_COLUMN_HEADER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GAL_A11Y_TYPE_E_TABLE_COLUMN_HEADER, GalA11yETableColumnHeaderClass)) +#define GAL_A11Y_IS_E_TABLE_COLUMN_HEADER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GAL_A11Y_TYPE_E_TABLE_COLUMN_HEADER)) +#define GAL_A11Y_IS_E_TABLE_COLUMN_HEADER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GAL_A11Y_TYPE_E_TABLE_COLUMN_HEADER)) + +typedef struct _GalA11yETableColumnHeader GalA11yETableColumnHeader; +typedef struct _GalA11yETableColumnHeaderClass GalA11yETableColumnHeaderClass; +typedef struct _GalA11yETableColumnHeaderPrivate GalA11yETableColumnHeaderPrivate; + +struct _GalA11yETableColumnHeader { + AtkGObjectAccessible parent; +}; + +struct _GalA11yETableColumnHeaderClass { + AtkGObjectAccessibleClass parent_class; +}; + + +/* Standard Glib function */ +GType gal_a11y_e_table_column_header_get_type (void); +AtkObject *gal_a11y_e_table_column_header_new (ETableCol *etc, ETableItem *item); +void gal_a11y_e_table_column_header_init (void); + +#endif /* ! __GAL_A11Y_E_TABLE_COLUMN_HEADER_H__ */ diff --git a/widgets/table/a11y/gal-a11y-e-table-factory.c b/widgets/table/a11y/gal-a11y-e-table-factory.c new file mode 100644 index 0000000000..37c396aba8 --- /dev/null +++ b/widgets/table/a11y/gal-a11y-e-table-factory.c @@ -0,0 +1,99 @@ +/* + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Authors: + * Christopher James Lahey <clahey@ximian.com> + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include <config.h> + +#include "gal-a11y-e-table.h" +#include "gal-a11y-e-table-factory.h" + +#define CS_CLASS(factory) (G_TYPE_INSTANCE_GET_CLASS ((factory), C_TYPE_STREAM, GalA11yETableFactoryClass)) +static AtkObjectFactoryClass *parent_class; +#define PARENT_TYPE (ATK_TYPE_OBJECT_FACTORY) + +/* Static functions */ + +static GType +gal_a11y_e_table_factory_get_accessible_type (void) +{ + return GAL_A11Y_TYPE_E_TABLE; +} + +static AtkObject* +gal_a11y_e_table_factory_create_accessible (GObject *obj) +{ + AtkObject *accessible; + + accessible = gal_a11y_e_table_new (obj); + + return accessible; +} + +static void +gal_a11y_e_table_factory_class_init (GalA11yETableFactoryClass *klass) +{ + AtkObjectFactoryClass *factory_class = ATK_OBJECT_FACTORY_CLASS (klass); + + parent_class = g_type_class_ref (PARENT_TYPE); + + factory_class->create_accessible = gal_a11y_e_table_factory_create_accessible; + factory_class->get_accessible_type = gal_a11y_e_table_factory_get_accessible_type; +} + +static void +gal_a11y_e_table_factory_init (GalA11yETableFactory *factory) +{ +} + +/** + * gal_a11y_e_table_factory_get_type: + * @void: + * + * Registers the &GalA11yETableFactory class if necessary, and returns the type ID + * associated to it. + * + * Return value: The type ID of the &GalA11yETableFactory class. + **/ +GType +gal_a11y_e_table_factory_get_type (void) +{ + static GType type = 0; + + if (!type) { + GTypeInfo info = { + sizeof (GalA11yETableFactoryClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) gal_a11y_e_table_factory_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (GalA11yETableFactory), + 0, + (GInstanceInitFunc) gal_a11y_e_table_factory_init, + NULL /* value_table */ + }; + + type = g_type_register_static (PARENT_TYPE, "GalA11yETableFactory", &info, 0); + } + + return type; +} diff --git a/widgets/table/a11y/gal-a11y-e-table-factory.h b/widgets/table/a11y/gal-a11y-e-table-factory.h new file mode 100644 index 0000000000..e3ef52c872 --- /dev/null +++ b/widgets/table/a11y/gal-a11y-e-table-factory.h @@ -0,0 +1,51 @@ +/* + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Authors: + * Christopher James Lahey <clahey@ximian.com> + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef __GAL_A11Y_E_TABLE_FACTORY_H__ +#define __GAL_A11Y_E_TABLE_FACTORY_H__ + +#include <glib-object.h> +#include <atk/atkobjectfactory.h> + +#define GAL_A11Y_TYPE_E_TABLE_FACTORY (gal_a11y_e_table_factory_get_type ()) +#define GAL_A11Y_E_TABLE_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GAL_A11Y_TYPE_E_TABLE_FACTORY, GalA11yETableFactory)) +#define GAL_A11Y_E_TABLE_FACTORY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GAL_A11Y_TYPE_E_TABLE_FACTORY, GalA11yETableFactoryClass)) +#define GAL_A11Y_IS_E_TABLE_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GAL_A11Y_TYPE_E_TABLE_FACTORY)) +#define GAL_A11Y_IS_E_TABLE_FACTORY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GAL_A11Y_TYPE_E_TABLE_FACTORY)) + +typedef struct _GalA11yETableFactory GalA11yETableFactory; +typedef struct _GalA11yETableFactoryClass GalA11yETableFactoryClass; + +struct _GalA11yETableFactory { + AtkObject object; +}; + +struct _GalA11yETableFactoryClass { + AtkObjectClass parent_class; +}; + + +/* Standard Glib function */ +GType gal_a11y_e_table_factory_get_type (void); + +#endif /* ! __GAL_A11Y_E_TABLE_FACTORY_H__ */ diff --git a/widgets/table/a11y/gal-a11y-e-table-item-factory.c b/widgets/table/a11y/gal-a11y-e-table-item-factory.c new file mode 100644 index 0000000000..43508e4796 --- /dev/null +++ b/widgets/table/a11y/gal-a11y-e-table-item-factory.c @@ -0,0 +1,105 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Authors: + * Yuedong Du <yuedong.du@sun.com> + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include <config.h> + +#include <atk/atk.h> + +#include "table/e-table.h" +#include "table/e-tree.h" + +#include "gal-a11y-e-table.h" +#include "gal-a11y-e-table-item.h" +#include "gal-a11y-e-table-item-factory.h" + +#define CS_CLASS(factory) (G_TYPE_INSTANCE_GET_CLASS ((factory), C_TYPE_STREAM, GalA11yETableItemFactoryClass)) +static AtkObjectFactoryClass *parent_class; +#define PARENT_TYPE (ATK_TYPE_OBJECT_FACTORY) + +/* Static functions */ + +static GType +gal_a11y_e_table_item_factory_get_accessible_type (void) +{ + return GAL_A11Y_TYPE_E_TABLE_ITEM; +} + +static AtkObject* +gal_a11y_e_table_item_factory_create_accessible (GObject *obj) +{ + AtkObject *accessible; + + g_return_val_if_fail (E_IS_TABLE_ITEM(obj), NULL); + accessible = gal_a11y_e_table_item_new (E_TABLE_ITEM (obj)); + + return accessible; +} + +static void +gal_a11y_e_table_item_factory_class_init (GalA11yETableItemFactoryClass *klass) +{ + AtkObjectFactoryClass *factory_class = ATK_OBJECT_FACTORY_CLASS (klass); + + parent_class = g_type_class_ref (PARENT_TYPE); + + factory_class->create_accessible = gal_a11y_e_table_item_factory_create_accessible; + factory_class->get_accessible_type = gal_a11y_e_table_item_factory_get_accessible_type; +} + +static void +gal_a11y_e_table_item_factory_init (GalA11yETableItemFactory *factory) +{ +} + +/** + * gal_a11y_e_table_factory_get_type: + * @void: + * + * Registers the &GalA11yETableFactory class if necessary, and returns the type ID + * associated to it. + * + * Return value: The type ID of the &GalA11yETableFactory class. + **/ +GType +gal_a11y_e_table_item_factory_get_type (void) +{ + static GType type = 0; + + if (!type) { + GTypeInfo info = { + sizeof (GalA11yETableItemFactoryClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) gal_a11y_e_table_item_factory_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (GalA11yETableItemFactory), + 0, + (GInstanceInitFunc) gal_a11y_e_table_item_factory_init, + NULL /* value_table */ + }; + + type = g_type_register_static (PARENT_TYPE, "GalA11yETableItemFactory", &info, 0); + } + + return type; +} diff --git a/widgets/table/a11y/gal-a11y-e-table-item-factory.h b/widgets/table/a11y/gal-a11y-e-table-item-factory.h new file mode 100644 index 0000000000..a85c9e894f --- /dev/null +++ b/widgets/table/a11y/gal-a11y-e-table-item-factory.h @@ -0,0 +1,50 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Authors: + * Yuedong Du <yuedong.du@sun.com> + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef __GAL_A11Y_E_TABLE_ITEM_FACTORY_H__ +#define __GAL_A11Y_E_TABLE_ITEM_FACTORY_H__ + +#include <glib-object.h> +#include <atk/atkobjectfactory.h> + +#define GAL_A11Y_TYPE_E_TABLE_ITEM_FACTORY (gal_a11y_e_table_item_factory_get_type ()) +#define GAL_A11Y_E_TABLE_ITEM_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GAL_A11Y_TYPE_E_TABLE_ITEM_FACTORY, GalA11yETableItemFactory)) +#define GAL_A11Y_E_TABLE_ITEM_FACTORY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GAL_A11Y_TYPE_E_TABLE_ITEM_FACTORY, GalA11yETableItemFactoryClass)) +#define GAL_A11Y_IS_E_TABLE_ITEM_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GAL_A11Y_TYPE_E_TABLE_ITEM_FACTORY)) +#define GAL_A11Y_IS_E_TABLE_ITEM_FACTORY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GAL_A11Y_TYPE_E_TABLE_ITEM_FACTORY)) + +typedef struct _GalA11yETableItemFactory GalA11yETableItemFactory; +typedef struct _GalA11yETableItemFactoryClass GalA11yETableItemFactoryClass; + +struct _GalA11yETableItemFactory { + AtkObject object; +}; + +struct _GalA11yETableItemFactoryClass { + AtkObjectClass parent_class; +}; + + +/* Standard Glib function */ +GType gal_a11y_e_table_item_factory_get_type (void); + +#endif /* ! __GAL_A11Y_E_TABLE_FACTORY_H__ */ diff --git a/widgets/table/a11y/gal-a11y-e-table-item.c b/widgets/table/a11y/gal-a11y-e-table-item.c new file mode 100644 index 0000000000..16d50df9b0 --- /dev/null +++ b/widgets/table/a11y/gal-a11y-e-table-item.c @@ -0,0 +1,1327 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Authors: + * Christopher James Lahey <clahey@ximian.com> + * Bolian Yin <bolian.yin@sun.com> + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include <config.h> + +#include <string.h> + +#include <atk/atk.h> + +#include "a11y/gal-a11y-util.h" +#include "table/e-table-click-to-add.h" +#include "table/e-table-subset.h" +#include "table/e-table.h" +#include "table/e-tree.h" +#include "misc/e-canvas.h" +#include "misc/e-selection-model.h" + +#include "gal-a11y-e-table-item.h" +#include "gal-a11y-e-table-item-factory.h" +#include "gal-a11y-e-table-click-to-add.h" +#include "gal-a11y-e-cell-registry.h" +#include "gal-a11y-e-cell.h" +#include "gal-a11y-e-table-column-header.h" + +#define CS_CLASS(a11y) (G_TYPE_INSTANCE_GET_CLASS ((a11y), C_TYPE_STREAM, GalA11yETableItemClass)) +static GObjectClass *parent_class; +static AtkComponentIface *component_parent_iface; +static GType parent_type; +static gint priv_offset; +static GQuark quark_accessible_object = 0; +#define GET_PRIVATE(object) ((GalA11yETableItemPrivate *) (((char *) object) + priv_offset)) +#define PARENT_TYPE (parent_type) + +struct _GalA11yETableItemPrivate { + gint cols; + gint rows; + int selection_change_id; + int cursor_change_id; + ETableCol ** columns; + ESelectionModel *selection; + AtkStateSet *state_set; + GtkWidget *widget; +}; + +static gboolean gal_a11y_e_table_item_ref_selection (GalA11yETableItem *a11y, + ESelectionModel *selection); +static gboolean gal_a11y_e_table_item_unref_selection (GalA11yETableItem *a11y); + +static AtkObject* eti_ref_at (AtkTable *table, gint row, gint column); + +static void +item_destroyed (GtkObject *item, gpointer user_data) +{ + GalA11yETableItem *a11y = GAL_A11Y_E_TABLE_ITEM (user_data); + GalA11yETableItemPrivate *priv = GET_PRIVATE (a11y); + + atk_state_set_add_state (priv->state_set, ATK_STATE_DEFUNCT); + atk_object_notify_state_change (ATK_OBJECT (a11y), ATK_STATE_DEFUNCT, TRUE); + + if (priv->selection) + gal_a11y_e_table_item_unref_selection (a11y); + +} + +static AtkStateSet * +eti_ref_state_set (AtkObject *accessible) +{ + GalA11yETableItemPrivate *priv = GET_PRIVATE (accessible); + + g_object_ref(priv->state_set); + + return priv->state_set; +} + +inline static gint +view_to_model_row(ETableItem *eti, int row) +{ + if (eti->uses_source_model) { + ETableSubset *etss = E_TABLE_SUBSET(eti->table_model); + if (row >= 0 && row < etss->n_map) { + eti->row_guess = row; + return etss->map_table[row]; + } else + return -1; + } else + return row; +} + +inline static gint +view_to_model_col(ETableItem *eti, int col) +{ + ETableCol *ecol = e_table_header_get_column (eti->header, col); + return ecol ? ecol->col_idx : -1; +} + +inline static gint +model_to_view_row(ETableItem *eti, int row) +{ + int i; + if (row == -1) + return -1; + if (eti->uses_source_model) { + ETableSubset *etss = E_TABLE_SUBSET(eti->table_model); + if (eti->row_guess >= 0 && eti->row_guess < etss->n_map) { + if (etss->map_table[eti->row_guess] == row) { + return eti->row_guess; + } + } + for (i = 0; i < etss->n_map; i++) { + if (etss->map_table[i] == row) + return i; + } + return -1; + } else + return row; +} + +inline static gint +model_to_view_col(ETableItem *eti, int col) +{ + int i; + if (col == -1) + return -1; + for (i = 0; i < eti->cols; i++) { + ETableCol *ecol = e_table_header_get_column (eti->header, i); + if (ecol->col_idx == col) + return i; + } + return -1; +} + +inline static GObject * +eti_a11y_get_gobject (AtkObject *accessible) +{ + return atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (accessible)); +} + +static void +eti_a11y_reset_focus_object (GalA11yETableItem *a11y, ETableItem *item, gboolean notify) +{ + ESelectionModel * esm; + int cursor_row, cursor_col, view_row, view_col; + AtkObject *cell, *old_cell; + + esm = item->selection; + g_return_if_fail (esm); + + cursor_row = e_selection_model_cursor_row (esm); + cursor_col = e_selection_model_cursor_col (esm); + + view_row = model_to_view_row (item, cursor_row); + view_col = model_to_view_col (item, cursor_col); + + if (view_row == -1) + view_row = 0; + if (view_col == -1) + view_col = 0; + + old_cell = (AtkObject *)g_object_get_data (G_OBJECT (a11y), "gail-focus-object"); + if (old_cell && GAL_A11Y_IS_E_CELL (old_cell)) + gal_a11y_e_cell_remove_state (GAL_A11Y_E_CELL (old_cell), ATK_STATE_FOCUSED, FALSE); + if (old_cell) + g_object_unref (old_cell); + + cell = eti_ref_at (ATK_TABLE (a11y), view_row, view_col); + + if (cell != NULL) { + g_object_set_data (G_OBJECT (a11y), "gail-focus-object", cell); + gal_a11y_e_cell_add_state (GAL_A11Y_E_CELL (cell), ATK_STATE_FOCUSED, FALSE); + } else + g_object_set_data (G_OBJECT (a11y), "gail-focus-object", NULL); + + if (notify && cell) + atk_focus_tracker_notify (cell); +} + +static void +eti_dispose (GObject *object) +{ + GalA11yETableItem *a11y = GAL_A11Y_E_TABLE_ITEM (object); + GalA11yETableItemPrivate *priv = GET_PRIVATE (a11y); + + if (priv->columns) { + g_free(priv->columns); + priv->columns = NULL; + } + + if (parent_class->dispose) + parent_class->dispose (object); +} + +/* Static functions */ +static gint +eti_get_n_children (AtkObject *accessible) +{ + g_return_val_if_fail (GAL_A11Y_IS_E_TABLE_ITEM (accessible), 0); + if (!eti_a11y_get_gobject (accessible)) + return 0; + + return atk_table_get_n_columns (ATK_TABLE (accessible)) * + (atk_table_get_n_rows (ATK_TABLE (accessible)) + 1); +} + +static AtkObject* +eti_ref_child (AtkObject *accessible, gint index) +{ + ETableItem *item; + gint col, row; + + g_return_val_if_fail (GAL_A11Y_IS_E_TABLE_ITEM (accessible), NULL); + item = E_TABLE_ITEM (eti_a11y_get_gobject (accessible)); + if (!item) + return NULL; + + if (index < item->cols) { + ETableCol *ecol; + AtkObject *child; + + ecol = e_table_header_get_column (item->header, index); + child = gal_a11y_e_table_column_header_new (ecol, item); + return child; + } + index -= item->cols; + + col = index % item->cols; + row = index / item->cols; + + return eti_ref_at (ATK_TABLE (accessible), row, col); +} + +static void +eti_get_extents (AtkComponent *component, + gint *x, + gint *y, + gint *width, + gint *height, + AtkCoordType coord_type) +{ + ETableItem *item; + AtkObject *parent; + + item = E_TABLE_ITEM (eti_a11y_get_gobject (ATK_OBJECT (component))); + if (!item) + return; + + parent = ATK_OBJECT (component)->accessible_parent; + if (parent && ATK_IS_COMPONENT (parent)) + atk_component_get_extents (ATK_COMPONENT (parent), x, y, + width, height, + coord_type); + + if (parent && GAL_A11Y_IS_E_TABLE_CLICK_TO_ADD (parent)) { + ETableClickToAdd *etcta = E_TABLE_CLICK_TO_ADD (atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (parent))); + if (etcta) { + *width = etcta->width; + *height = etcta->height; + } + } +} + +static AtkObject* +eti_ref_accessible_at_point (AtkComponent *component, + gint x, + gint y, + AtkCoordType coord_type) +{ + int row = -1; + int col = -1; + int x_origin, y_origin; + ETableItem *item; + GtkWidget *tableOrTree; + + item = E_TABLE_ITEM (eti_a11y_get_gobject (ATK_OBJECT (component))); + if (!item) + return NULL; + + atk_component_get_position (component, + &x_origin, + &y_origin, + coord_type); + x -= x_origin; + y -= y_origin; + + tableOrTree = gtk_widget_get_parent (GTK_WIDGET (item->parent.canvas)); + + if (E_IS_TREE(tableOrTree)) + e_tree_get_cell_at (E_TREE (tableOrTree), x, y, &row, &col); + else + e_table_get_cell_at (E_TABLE (tableOrTree), x, y, &row, &col); + + if (row != -1 && col != -1) { + return eti_ref_at (ATK_TABLE (component), row, col); + } else { + return NULL; + } +} + + +static void +cell_destroyed (gpointer data) +{ + GalA11yECell * cell; + + g_return_if_fail (GAL_A11Y_IS_E_CELL (data)); + cell = GAL_A11Y_E_CELL (data); + + g_return_if_fail (cell->item && G_IS_OBJECT (cell->item)); + + if (cell->item) { + g_object_unref (cell->item); + cell->item = NULL; + } + +} + +/* atk table */ +static AtkObject* +eti_ref_at (AtkTable *table, gint row, gint column) +{ + ETableItem *item; + AtkObject* ret; + GalA11yETableItemPrivate *priv = GET_PRIVATE (table); + + if (atk_state_set_contains_state (priv->state_set, ATK_STATE_DEFUNCT)) + return NULL; + + + item = E_TABLE_ITEM (eti_a11y_get_gobject (ATK_OBJECT (table))); + if (!item) + return NULL; + + if (column >= 0 && + column < item->cols && + row >= 0 && + row < item->rows && + item->cell_views_realized) { + ECellView *cell_view = item->cell_views[column]; + ETableCol *ecol = e_table_header_get_column (item->header, column); + ret = gal_a11y_e_cell_registry_get_object (NULL, + item, + cell_view, + ATK_OBJECT (table), + ecol->col_idx, + column, + row); + if (ATK_IS_OBJECT (ret)) { + g_object_weak_ref (G_OBJECT (ret), + (GWeakNotify) cell_destroyed, + ret); + /* if current cell is focused, add FOCUSED state */ + if (e_selection_model_cursor_row (item->selection) == GAL_A11Y_E_CELL (ret)->row && + e_selection_model_cursor_col (item->selection) == GAL_A11Y_E_CELL (ret)->model_col) + gal_a11y_e_cell_add_state (GAL_A11Y_E_CELL (ret), ATK_STATE_FOCUSED, FALSE); + } else + ret = NULL; + + return ret; + } + + return NULL; +} + +static gint +eti_get_index_at (AtkTable *table, gint row, gint column) +{ + ETableItem *item; + + item = E_TABLE_ITEM (eti_a11y_get_gobject (ATK_OBJECT (table))); + if (!item) + return -1; + + return column + (row + 1) * item->cols; +} + +static gint +eti_get_column_at_index (AtkTable *table, gint index) +{ + ETableItem *item; + + item = E_TABLE_ITEM (eti_a11y_get_gobject (ATK_OBJECT (table))); + if (!item) + return -1; + + return index % item->cols; +} + +static gint +eti_get_row_at_index (AtkTable *table, gint index) +{ + ETableItem *item; + + item = E_TABLE_ITEM (eti_a11y_get_gobject (ATK_OBJECT (table))); + if (!item) + return -1; + + return index / item->cols - 1; +} + +static gint +eti_get_n_columns (AtkTable *table) +{ + ETableItem *item; + + item = E_TABLE_ITEM (eti_a11y_get_gobject (ATK_OBJECT (table))); + if (!item) + return -1; + + return item->cols; +} + +static gint +eti_get_n_rows (AtkTable *table) +{ + ETableItem *item; + + item = E_TABLE_ITEM (eti_a11y_get_gobject (ATK_OBJECT (table))); + if (!item) + return -1; + + return item->rows; +} + +static gint +eti_get_column_extent_at (AtkTable *table, + gint row, + gint column) +{ + ETableItem *item; + int width; + + item = E_TABLE_ITEM (eti_a11y_get_gobject (ATK_OBJECT (table))); + if (!item) + return -1; + + e_table_item_get_cell_geometry (item, + &row, + &column, + NULL, + NULL, + &width, + NULL); + + return width; +} + +static gint +eti_get_row_extent_at (AtkTable *table, + gint row, + gint column) +{ + ETableItem *item; + int height; + + item = E_TABLE_ITEM (eti_a11y_get_gobject (ATK_OBJECT (table))); + if (!item) + return -1; + + e_table_item_get_cell_geometry (item, + &row, + &column, + NULL, + NULL, + NULL, + &height); + + return height; +} + +static AtkObject * +eti_get_caption (AtkTable *table) +{ + /* Unimplemented */ + return NULL; +} + +static G_CONST_RETURN gchar * +eti_get_column_description (AtkTable *table, + gint column) +{ + ETableItem *item; + ETableCol *ecol; + + item = E_TABLE_ITEM (eti_a11y_get_gobject (ATK_OBJECT (table))); + if (!item) + return NULL; + + ecol = e_table_header_get_column (item->header, column); + + return ecol->text; +} + +static AtkObject * +eti_get_column_header (AtkTable *table, gint column) +{ + ETableItem *item; + ETableCol *ecol; + AtkObject *atk_obj = NULL; + + item = E_TABLE_ITEM (eti_a11y_get_gobject (ATK_OBJECT (table))); + if (!item) + return NULL; + + ecol = e_table_header_get_column (item->header, column); + if (ecol) { + atk_obj = gal_a11y_e_table_column_header_new (ecol, item); + } + + return atk_obj; +} + +static G_CONST_RETURN gchar * +eti_get_row_description (AtkTable *table, + gint row) +{ + /* Unimplemented */ + return NULL; +} + +static AtkObject * +eti_get_row_header (AtkTable *table, + gint row) +{ + /* Unimplemented */ + return NULL; +} + +static AtkObject * +eti_get_summary (AtkTable *table) +{ + /* Unimplemented */ + return NULL; +} + +static gboolean +table_is_row_selected (AtkTable *table, gint row) +{ + ETableItem *item; + GalA11yETableItemPrivate *priv = GET_PRIVATE (table); + + if (row < 0) + return FALSE; + + if (atk_state_set_contains_state (priv->state_set, ATK_STATE_DEFUNCT)) + return FALSE; + + item = E_TABLE_ITEM (eti_a11y_get_gobject (ATK_OBJECT (table))); + if (!item) + return FALSE; + + return e_selection_model_is_row_selected(item->selection, view_to_model_row (item, row)); +} + +static gboolean +table_is_selected (AtkTable *table, gint row, gint column) +{ + return table_is_row_selected (table, row); +} + +static gint +table_get_selected_rows (AtkTable *table, gint **rows_selected) +{ + ETableItem *item; + gint n_selected, row, index_selected; + GalA11yETableItemPrivate *priv = GET_PRIVATE (table); + + if (atk_state_set_contains_state (priv->state_set, ATK_STATE_DEFUNCT)) + return 0; + + item = E_TABLE_ITEM (eti_a11y_get_gobject (ATK_OBJECT (table))); + if (!item) + return 0; + + n_selected = e_selection_model_selected_count (item->selection); + if (rows_selected) { + *rows_selected = (gint *) g_malloc (n_selected * sizeof (gint)); + + index_selected = 0; + for (row = 0; row < item->rows && index_selected < n_selected; ++row) { + if (atk_table_is_row_selected (table, row)) { + (*rows_selected)[index_selected] = row; + ++index_selected; + } + } + } + return n_selected; +} + +static gboolean +table_add_row_selection (AtkTable *table, gint row) +{ + ETableItem *item; + + item = E_TABLE_ITEM (eti_a11y_get_gobject (ATK_OBJECT (table))); + if (!item) + return FALSE; + + if (table_is_row_selected (table, row)) + return TRUE; + e_selection_model_toggle_single_row (item->selection, + view_to_model_row (item, row)); + + return TRUE; +} + +static gboolean +table_remove_row_selection (AtkTable *table, gint row) +{ + ETableItem *item; + GalA11yETableItemPrivate *priv = GET_PRIVATE (table); + + if (atk_state_set_contains_state (priv->state_set, ATK_STATE_DEFUNCT)) + return FALSE; + + item = E_TABLE_ITEM (eti_a11y_get_gobject (ATK_OBJECT (table))); + if (!item) + return FALSE; + + if (!atk_table_is_row_selected (table, row)) + return TRUE; + e_selection_model_toggle_single_row (item->selection, view_to_model_row (item, row)); + return TRUE; +} + +static void +eti_atk_table_iface_init (AtkTableIface *iface) +{ + iface->ref_at = eti_ref_at; + iface->get_index_at = eti_get_index_at; + iface->get_column_at_index = eti_get_column_at_index; + iface->get_row_at_index = eti_get_row_at_index; + iface->get_n_columns = eti_get_n_columns; + iface->get_n_rows = eti_get_n_rows; + iface->get_column_extent_at = eti_get_column_extent_at; + iface->get_row_extent_at = eti_get_row_extent_at; + iface->get_caption = eti_get_caption; + iface->get_column_description = eti_get_column_description; + iface->get_column_header = eti_get_column_header; + iface->get_row_description = eti_get_row_description; + iface->get_row_header = eti_get_row_header; + iface->get_summary = eti_get_summary; + + iface->is_row_selected = table_is_row_selected; + iface->is_selected = table_is_selected; + iface->get_selected_rows = table_get_selected_rows; + iface->add_row_selection = table_add_row_selection; + iface->remove_row_selection = table_remove_row_selection; +} + +static void +eti_atk_component_iface_init (AtkComponentIface *iface) +{ + component_parent_iface = g_type_interface_peek_parent (iface); + + iface->ref_accessible_at_point = eti_ref_accessible_at_point; + iface->get_extents = eti_get_extents; +} + +static void +eti_rows_inserted (ETableModel * model, int row, int count, + AtkObject * table_item) +{ + gint n_cols,n_rows,i,j; + GalA11yETableItem * item_a11y; + gint old_nrows; + + g_return_if_fail (table_item); + item_a11y = GAL_A11Y_E_TABLE_ITEM (table_item); + + n_cols = atk_table_get_n_columns (ATK_TABLE(table_item)); + n_rows = atk_table_get_n_rows (ATK_TABLE(table_item)); + + old_nrows = GET_PRIVATE(item_a11y)->rows; + + g_return_if_fail (n_cols > 0 && n_rows > 0); + g_return_if_fail (old_nrows == n_rows - count); + + GET_PRIVATE(table_item)->rows = n_rows; + + g_signal_emit_by_name (table_item, "row-inserted", row, + count, NULL); + + for (i = row; i < (row + count); i ++) { + for (j = 0; j < n_cols; j ++) { + g_signal_emit_by_name (table_item, + "children_changed::add", + ( ((i + 1)*n_cols) + j), NULL, NULL); + } + } + + g_signal_emit_by_name (table_item, "visible-data-changed"); +} + +static void +eti_rows_deleted (ETableModel * model, int row, int count, + AtkObject * table_item) +{ + gint i,j, n_rows, n_cols, old_nrows; + ETableItem *item = E_TABLE_ITEM (atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (table_item))); + + n_rows = atk_table_get_n_rows (ATK_TABLE(table_item)); + n_cols = atk_table_get_n_columns (ATK_TABLE(table_item)); + + old_nrows = GET_PRIVATE(table_item)->rows; + + g_return_if_fail ( row+count <= old_nrows); + g_return_if_fail (old_nrows == n_rows + count); + GET_PRIVATE(table_item)->rows = n_rows; + + g_signal_emit_by_name (table_item, "row-deleted", row, + count, NULL); + + for (i = row; i < (row + count); i ++) { + for (j = 0; j < n_cols; j ++) { + g_signal_emit_by_name (table_item, + "children_changed::remove", + ( ((i + 1)*n_cols) + j), NULL, NULL); + } + } + g_signal_emit_by_name (table_item, "visible-data-changed"); + eti_a11y_reset_focus_object ((GalA11yETableItem *)table_item, item, TRUE); +} + +static void +eti_tree_model_node_changed_cb (ETreeModel *model, ETreePath node, ETableItem *eti) +{ + AtkObject *atk_obj; + GalA11yETableItem *a11y; + + g_return_if_fail (E_IS_TABLE_ITEM (eti)); + + atk_obj = atk_gobject_accessible_for_object (G_OBJECT (eti)); + a11y = GAL_A11Y_E_TABLE_ITEM (atk_obj); + + /* we can't figure out which rows are changed, so just send out a signal ... */ + if (GET_PRIVATE (a11y)->rows > 0) + g_signal_emit_by_name (a11y, "visible-data-changed"); +} + +enum { + ETI_HEADER_UNCHANGED = 0, + ETI_HEADER_REORDERED, + ETI_HEADER_NEW_ADDED, + ETI_HEADER_REMOVED, +}; + +/* + * 1. Check what actually happened: column reorder, remove or add + * 2. Update cache + * 3. Emit signals + */ +static void +eti_header_structure_changed (ETableHeader *eth, AtkObject *a11y) +{ + + gboolean reorder_found=FALSE, added_found=FALSE, removed_found=FALSE; + GalA11yETableItem * a11y_item; + ETableCol ** cols, **prev_cols; + GalA11yETableItemPrivate *priv; + gint *state = NULL, *prev_state = NULL, *reorder = NULL; + gint i,j,n_rows,n_cols, prev_n_cols; + + a11y_item = GAL_A11Y_E_TABLE_ITEM (a11y); + priv = GET_PRIVATE (a11y_item); + + /* Assume rows do not changed. */ + n_rows = priv->rows; + + prev_n_cols = priv->cols; + prev_cols = priv->columns; + + cols = e_table_header_get_columns (eth); + n_cols = eth->col_count; + + g_return_if_fail (cols && prev_cols && n_cols > 0); + + /* Init to ETI_HEADER_UNCHANGED. */ + state = g_malloc0 (sizeof (gint) * n_cols); + prev_state = g_malloc0 (sizeof (gint) * prev_n_cols); + reorder = g_malloc0 (sizeof (gint) * n_cols); + + /* Compare with previously saved column headers. */ + for ( i = 0 ; i < n_cols && cols[i]; i ++ ) { + for ( j = 0 ; j < prev_n_cols && prev_cols[j]; j ++ ) { + if ( prev_cols [j] == cols[i] && i != j ) { + + reorder_found = TRUE; + state [i] = ETI_HEADER_REORDERED; + reorder [i] = j; + + break; + } else if (prev_cols[j] == cols[i]) { + /* OK, this column is not changed. */ + break; + } + } + + /* cols[i] is new added column. */ + if ( j == prev_n_cols ) { + added_found = TRUE; + state[i] = ETI_HEADER_NEW_ADDED; + } + } + + /* Now try to find if there are removed columns. */ + for (i = 0 ; i < prev_n_cols && prev_cols[i]; i ++) { + for (j = 0 ; j < n_cols && cols[j]; j ++) + if ( prev_cols [j] == cols[i] ) + break; + + /* Removed columns found. */ + if ( j == n_cols ) { + removed_found = TRUE; + prev_state[j] = ETI_HEADER_REMOVED; + } + } + + /* If nothing interesting just return. */ + if (!reorder_found && !added_found && !removed_found) + return; + + /* Emit signals */ + if (reorder_found) + g_signal_emit_by_name (G_OBJECT(a11y_item), "column_reordered"); + + + if (removed_found) { + for (i = 0; i < prev_n_cols; i ++ ) { + if (prev_state[i] == ETI_HEADER_REMOVED) { + g_signal_emit_by_name (G_OBJECT(a11y_item), "column-deleted", i, 1); + for (j = 0 ; j < n_rows; j ++) + g_signal_emit_by_name (G_OBJECT(a11y_item), "children_changed::remove", ((j+1)*prev_n_cols+i), NULL, NULL); + } + } + } + + if (added_found) { + for ( i = 0; i < n_cols; i ++ ) { + if (state[i] == ETI_HEADER_NEW_ADDED) { + g_signal_emit_by_name (G_OBJECT(a11y_item), "column-inserted", i, 1); + for (j = 0 ; j < n_rows; j ++) + g_signal_emit_by_name (G_OBJECT(a11y_item), "children_changed::add", ((j+1)*n_cols+i), NULL, NULL); + } + } + } + + priv->cols = n_cols; + + g_free (state); + g_free (reorder); + g_free (prev_state); + + g_free (priv->columns); + priv->columns = cols; +} + + +static void +eti_real_initialize (AtkObject *obj, + gpointer data) +{ + ETableItem * eti; + ETableModel * model; + + ATK_OBJECT_CLASS (parent_class)->initialize (obj, data); + eti = E_TABLE_ITEM (data); + + model = eti->table_model; + + g_signal_connect (model, "model-rows-inserted", + G_CALLBACK (eti_rows_inserted), + obj); + g_signal_connect (model, "model-rows-deleted", + G_CALLBACK (eti_rows_deleted), + obj); + g_signal_connect (G_OBJECT (eti->header), "structure_change", + G_CALLBACK (eti_header_structure_changed), obj); + +} + +static void +eti_class_init (GalA11yETableItemClass *klass) +{ + AtkObjectClass *atk_object_class = ATK_OBJECT_CLASS (klass); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + quark_accessible_object = g_quark_from_static_string ("gtk-accessible-object"); + + parent_class = g_type_class_ref (PARENT_TYPE); + + object_class->dispose = eti_dispose; + + atk_object_class->get_n_children = eti_get_n_children; + atk_object_class->ref_child = eti_ref_child; + atk_object_class->initialize = eti_real_initialize; + atk_object_class->ref_state_set = eti_ref_state_set; +} + +static void +eti_init (GalA11yETableItem *a11y) +{ + GalA11yETableItemPrivate *priv; + + priv = GET_PRIVATE (a11y); + + priv->selection_change_id = 0; + priv->cursor_change_id = 0; + priv->selection = NULL; +} + +/* atk selection */ + +static void atk_selection_interface_init (AtkSelectionIface *iface); +static gboolean selection_add_selection (AtkSelection *selection, + gint i); +static gboolean selection_clear_selection (AtkSelection *selection); +static AtkObject* selection_ref_selection (AtkSelection *selection, + gint i); +static gint selection_get_selection_count (AtkSelection *selection); +static gboolean selection_is_child_selected (AtkSelection *selection, + gint i); + +/* callbacks */ +static void eti_a11y_selection_model_removed_cb (ETableItem *eti, + ESelectionModel *selection, + gpointer data); +static void eti_a11y_selection_model_added_cb (ETableItem *eti, + ESelectionModel *selection, + gpointer data); +static void eti_a11y_selection_changed_cb (ESelectionModel *selection, + GalA11yETableItem *a11y); +static void eti_a11y_cursor_changed_cb (ESelectionModel *selection, + int row, int col, + GalA11yETableItem *a11y); + +/** + * gal_a11y_e_table_item_get_type: + * @void: + * + * Registers the &GalA11yETableItem class if necessary, and returns the type ID + * associated to it. + * + * Return value: The type ID of the &GalA11yETableItem class. + **/ +GType +gal_a11y_e_table_item_get_type (void) +{ + static GType type = 0; + + if (!type) { + AtkObjectFactory *factory; + + GTypeInfo info = { + sizeof (GalA11yETableItemClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) eti_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (GalA11yETableItem), + 0, + (GInstanceInitFunc) eti_init, + NULL /* value_table_item */ + }; + + static const GInterfaceInfo atk_component_info = { + (GInterfaceInitFunc) eti_atk_component_iface_init, + (GInterfaceFinalizeFunc) NULL, + NULL + }; + static const GInterfaceInfo atk_table_info = { + (GInterfaceInitFunc) eti_atk_table_iface_init, + (GInterfaceFinalizeFunc) NULL, + NULL + }; + + static const GInterfaceInfo atk_selection_info = { + (GInterfaceInitFunc) atk_selection_interface_init, + (GInterfaceFinalizeFunc) NULL, + NULL + }; + + + factory = atk_registry_get_factory (atk_get_default_registry (), GNOME_TYPE_CANVAS_ITEM); + parent_type = atk_object_factory_get_accessible_type (factory); + + type = gal_a11y_type_register_static_with_private (PARENT_TYPE, "GalA11yETableItem", &info, 0, + sizeof (GalA11yETableItemPrivate), &priv_offset); + + g_type_add_interface_static (type, ATK_TYPE_COMPONENT, &atk_component_info); + g_type_add_interface_static (type, ATK_TYPE_TABLE, &atk_table_info); + g_type_add_interface_static (type, ATK_TYPE_SELECTION, &atk_selection_info); + } + + return type; +} + +AtkObject * +gal_a11y_e_table_item_new (ETableItem *item) +{ + GalA11yETableItem *a11y; + AtkObject *accessible; + ESelectionModel * esm; + AtkObject *parent; + const char *name; + + g_return_val_if_fail (item && item->cols >= 0 && item->rows >= 0, NULL); + a11y = g_object_new (gal_a11y_e_table_item_get_type (), NULL); + + atk_object_initialize (ATK_OBJECT (a11y), item); + + GET_PRIVATE (a11y)->state_set = atk_state_set_new (); + + atk_state_set_add_state (GET_PRIVATE(a11y)->state_set, ATK_STATE_TRANSIENT); + atk_state_set_add_state (GET_PRIVATE(a11y)->state_set, ATK_STATE_ENABLED); + atk_state_set_add_state (GET_PRIVATE(a11y)->state_set, ATK_STATE_SENSITIVE); + atk_state_set_add_state (GET_PRIVATE(a11y)->state_set, ATK_STATE_SHOWING); + atk_state_set_add_state (GET_PRIVATE(a11y)->state_set, ATK_STATE_VISIBLE); + + + accessible = ATK_OBJECT(a11y); + + /* Initialize cell data. */ + GET_PRIVATE (a11y)->cols = item->cols; + GET_PRIVATE (a11y)->rows = item->rows; + + GET_PRIVATE (a11y)->columns = e_table_header_get_columns (item->header); + if ( GET_PRIVATE (a11y)->columns == NULL) + return NULL; + + if (item) { + g_signal_connect (G_OBJECT(item), "selection_model_removed", + G_CALLBACK (eti_a11y_selection_model_removed_cb), NULL); + g_signal_connect (G_OBJECT(item), "selection_model_added", + G_CALLBACK (eti_a11y_selection_model_added_cb), NULL); + if (item->selection) + gal_a11y_e_table_item_ref_selection (a11y, + item->selection); + + /* find the TableItem's parent: table or tree */ + GET_PRIVATE (a11y)->widget = gtk_widget_get_parent (GTK_WIDGET (item->parent.canvas)); + parent = gtk_widget_get_accessible (GET_PRIVATE (a11y)->widget); + name = atk_object_get_name (parent); + if (name) + atk_object_set_name (accessible, name); + atk_object_set_parent (accessible, parent); + + if (E_IS_TREE (GET_PRIVATE (a11y)->widget)) { + ETreeModel *model; + model = e_tree_get_model (E_TREE (GET_PRIVATE (a11y)->widget)); + g_signal_connect (G_OBJECT(model), "node_changed", + G_CALLBACK (eti_tree_model_node_changed_cb), item); + accessible->role = ATK_ROLE_TREE_TABLE; + } else if (E_IS_TABLE (GET_PRIVATE (a11y)->widget)) { + accessible->role = ATK_ROLE_TABLE; + } + } + + if (item) + g_signal_connect (G_OBJECT (item), "destroy", + G_CALLBACK (item_destroyed), + a11y); + esm = item->selection; + + if (esm != NULL) { + eti_a11y_reset_focus_object (a11y, item, FALSE); + } + + return ATK_OBJECT (a11y); +} + +static gboolean +gal_a11y_e_table_item_ref_selection (GalA11yETableItem *a11y, + ESelectionModel *selection) +{ + GalA11yETableItemPrivate *priv; + + g_return_val_if_fail (a11y && selection, FALSE); + + priv = GET_PRIVATE (a11y); + priv->selection_change_id = g_signal_connect ( + G_OBJECT(selection), "selection_changed", + G_CALLBACK (eti_a11y_selection_changed_cb), a11y); + priv->cursor_change_id = g_signal_connect ( + G_OBJECT(selection), "cursor_changed", + G_CALLBACK (eti_a11y_cursor_changed_cb), a11y); + + priv->selection = selection; + g_object_ref (selection); + + return TRUE; +} + +static gboolean +gal_a11y_e_table_item_unref_selection (GalA11yETableItem *a11y) +{ + GalA11yETableItemPrivate *priv; + + g_return_val_if_fail (a11y, FALSE); + + priv = GET_PRIVATE (a11y); + + g_return_val_if_fail (priv->selection_change_id != 0, FALSE); + g_return_val_if_fail (priv->cursor_change_id != 0, FALSE); + + + g_signal_handler_disconnect (priv->selection, + priv->selection_change_id); + g_signal_handler_disconnect (priv->selection, + priv->cursor_change_id); + priv->cursor_change_id = 0; + priv->selection_change_id = 0; + + g_object_unref (priv->selection); + priv->selection = NULL; + + return TRUE; +} + +/* callbacks */ + +static void +eti_a11y_selection_model_removed_cb (ETableItem *eti, ESelectionModel *selection, + gpointer data) +{ + AtkObject *atk_obj; + GalA11yETableItem *a11y; + + g_return_if_fail (E_IS_TABLE_ITEM (eti)); + g_return_if_fail (E_IS_SELECTION_MODEL (selection)); + + atk_obj = atk_gobject_accessible_for_object (G_OBJECT (eti)); + a11y = GAL_A11Y_E_TABLE_ITEM (atk_obj); + + if (selection == GET_PRIVATE (a11y)->selection) + gal_a11y_e_table_item_unref_selection (a11y); +} + +static void +eti_a11y_selection_model_added_cb (ETableItem *eti, ESelectionModel *selection, + gpointer data) +{ + AtkObject *atk_obj; + GalA11yETableItem *a11y; + + g_return_if_fail (E_IS_TABLE_ITEM (eti)); + g_return_if_fail (E_IS_SELECTION_MODEL (selection)); + + atk_obj = atk_gobject_accessible_for_object (G_OBJECT (eti)); + a11y = GAL_A11Y_E_TABLE_ITEM (atk_obj); + + if (GET_PRIVATE (a11y)->selection) + gal_a11y_e_table_item_unref_selection (a11y); + gal_a11y_e_table_item_ref_selection (a11y, selection); +} + +static void +eti_a11y_selection_changed_cb (ESelectionModel *selection, GalA11yETableItem *a11y) +{ + GalA11yETableItemPrivate *priv = GET_PRIVATE (a11y); + + if (atk_state_set_contains_state (priv->state_set, ATK_STATE_DEFUNCT)) + return; + + g_return_if_fail (GAL_A11Y_IS_E_TABLE_ITEM (a11y)); + + g_signal_emit_by_name (a11y, "selection_changed"); +} + +static void +eti_a11y_cursor_changed_cb (ESelectionModel *selection, + int row, int col, GalA11yETableItem *a11y) +{ + ETableItem *item; + GalA11yETableItemPrivate *priv = GET_PRIVATE (a11y); + + g_return_if_fail (GAL_A11Y_IS_E_TABLE_ITEM (a11y)); + + if (atk_state_set_contains_state (priv->state_set, ATK_STATE_DEFUNCT)) + return; + + item = E_TABLE_ITEM (eti_a11y_get_gobject (ATK_OBJECT (a11y))); + + g_return_if_fail (item); + + if (row == -1 && col == -1) + return; + eti_a11y_reset_focus_object (a11y, item, TRUE); +} + +/* atk selection */ + +static void atk_selection_interface_init (AtkSelectionIface *iface) +{ + g_return_if_fail (iface != NULL); + iface->add_selection = selection_add_selection; + iface->clear_selection = selection_clear_selection; + iface->ref_selection = selection_ref_selection; + iface->get_selection_count = selection_get_selection_count; + iface->is_child_selected = selection_is_child_selected; +} + +static gboolean +selection_add_selection (AtkSelection *selection, gint index) +{ + AtkTable *table; + gint row, col, cursor_row, cursor_col, model_row, model_col; + ETableItem *item; + + item = E_TABLE_ITEM (eti_a11y_get_gobject (ATK_OBJECT (selection))); + if (!item) + return FALSE; + + table = ATK_TABLE (selection); + + row = atk_table_get_row_at_index (table, index); + col = atk_table_get_column_at_index (table, index); + + model_row = view_to_model_row (item, row); + model_col = view_to_model_col (item, col); + + cursor_row = e_selection_model_cursor_row (item->selection); + cursor_col = e_selection_model_cursor_col (item->selection); + + /* check whether is selected already */ + if (model_row == cursor_row && model_col == cursor_col) + return TRUE; + + if (model_row != cursor_row) { + /* we need to make the item get focus */ + e_canvas_item_grab_focus (GNOME_CANVAS_ITEM (item), TRUE); + + /* FIXME, currently we only support single row selection */ + atk_selection_clear_selection (selection); + atk_table_add_row_selection (table, row); + } + + e_selection_model_change_cursor (item->selection, + model_row, + model_col); + e_selection_model_cursor_changed (item->selection, + model_row, + model_col); + e_selection_model_cursor_activated (item->selection, + model_row, + model_col); + return TRUE; +} + +static gboolean +selection_clear_selection (AtkSelection *selection) +{ + ETableItem *item; + + item = E_TABLE_ITEM (eti_a11y_get_gobject (ATK_OBJECT (selection))); + if (!item) + return FALSE; + + e_selection_model_clear (item->selection); + return TRUE; +} + +static AtkObject * +selection_ref_selection (AtkSelection *selection, gint index) +{ + AtkTable *table; + gint row, col; + + table = ATK_TABLE (selection); + row = atk_table_get_row_at_index (table, index); + col = atk_table_get_column_at_index (table, index); + if (!atk_table_is_row_selected (table, row)) + return NULL; + + return eti_ref_at (table, row, col); +} + +static gint +selection_get_selection_count (AtkSelection *selection) +{ + AtkTable *table; + gint n_selected; + + table = ATK_TABLE (selection); + n_selected = atk_table_get_selected_rows (table, NULL); + if (n_selected > 0) + n_selected *= atk_table_get_n_columns (table); + return n_selected; +} + +static gboolean +selection_is_child_selected (AtkSelection *selection, gint i) +{ + gint row; + + row = atk_table_get_row_at_index (ATK_TABLE (selection), i); + return atk_table_is_row_selected (ATK_TABLE (selection), row); +} + +void +gal_a11y_e_table_item_init (void) +{ + if (atk_get_root ()) + atk_registry_set_factory_type (atk_get_default_registry (), + E_TABLE_ITEM_TYPE, + gal_a11y_e_table_item_factory_get_type ()); +} + diff --git a/widgets/table/a11y/gal-a11y-e-table-item.h b/widgets/table/a11y/gal-a11y-e-table-item.h new file mode 100644 index 0000000000..e89f0824b3 --- /dev/null +++ b/widgets/table/a11y/gal-a11y-e-table-item.h @@ -0,0 +1,59 @@ +/* + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Authors: + * Christopher James Lahey <clahey@ximian.com> + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef __GAL_A11Y_E_TABLE_ITEM_H__ +#define __GAL_A11Y_E_TABLE_ITEM_H__ + +#include <glib-object.h> +#include <table/e-table-item.h> +#include <atk/atkgobjectaccessible.h> + +#define GAL_A11Y_TYPE_E_TABLE_ITEM (gal_a11y_e_table_item_get_type ()) +#define GAL_A11Y_E_TABLE_ITEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GAL_A11Y_TYPE_E_TABLE_ITEM, GalA11yETableItem)) +#define GAL_A11Y_E_TABLE_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GAL_A11Y_TYPE_E_TABLE_ITEM, GalA11yETableItemClass)) +#define GAL_A11Y_IS_E_TABLE_ITEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GAL_A11Y_TYPE_E_TABLE_ITEM)) +#define GAL_A11Y_IS_E_TABLE_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GAL_A11Y_TYPE_E_TABLE_ITEM)) + +typedef struct _GalA11yETableItem GalA11yETableItem; +typedef struct _GalA11yETableItemClass GalA11yETableItemClass; +typedef struct _GalA11yETableItemPrivate GalA11yETableItemPrivate; + +/* This struct should actually be larger as this isn't what we derive from. + * The GalA11yETableItemPrivate comes right after the parent class structure. + **/ +struct _GalA11yETableItem { + AtkGObjectAccessible parent; +}; + +struct _GalA11yETableItemClass { + AtkGObjectAccessibleClass parent_class; +}; + + +/* Standard Glib function */ +GType gal_a11y_e_table_item_get_type (void); +AtkObject *gal_a11y_e_table_item_new (ETableItem *item); + +void gal_a11y_e_table_item_init (void); + +#endif /* ! __GAL_A11Y_E_TABLE_ITEM_H__ */ diff --git a/widgets/table/a11y/gal-a11y-e-table.c b/widgets/table/a11y/gal-a11y-e-table.c new file mode 100644 index 0000000000..20261d4eab --- /dev/null +++ b/widgets/table/a11y/gal-a11y-e-table.c @@ -0,0 +1,308 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Authors: + * Christopher James Lahey <clahey@ximian.com> + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include <config.h> + +#include "a11y/gal-a11y-util.h" +#include "table/e-table.h" +#include "table/e-table-click-to-add.h" +#include "table/e-table-group.h" +#include "table/e-table-group-container.h" +#include "table/e-table-group-leaf.h" + +#include "gal-a11y-e-table.h" +#include "gal-a11y-e-table-factory.h" +#include "gal-a11y-e-table-item.h" + +#define CS_CLASS(a11y) (G_TYPE_INSTANCE_GET_CLASS ((a11y), C_TYPE_STREAM, GalA11yETableClass)) +static AtkObjectClass *parent_class; +static GType parent_type; +static gint priv_offset; +#define GET_PRIVATE(object) ((GalA11yETablePrivate *) (((char *) object) + priv_offset)) +#define PARENT_TYPE (parent_type) + +struct _GalA11yETablePrivate { + AtkObject *child_item; +}; + +/* Static functions */ +static ETableItem * +find_first_table_item (ETableGroup *group) +{ + GnomeCanvasGroup *cgroup; + GList *l; + + cgroup = GNOME_CANVAS_GROUP (group); + + for (l = cgroup->item_list; l; l = l->next) { + GnomeCanvasItem *i; + + i = GNOME_CANVAS_ITEM (l->data); + + if (E_IS_TABLE_GROUP (i)) + return find_first_table_item (E_TABLE_GROUP (i)); + else if (E_IS_TABLE_ITEM (i)) { + return E_TABLE_ITEM (i); + } + } + + return NULL; +} + +static AtkObject* +eti_get_accessible (ETableItem *eti, AtkObject *parent) +{ + AtkObject *a11y = NULL; + + g_return_val_if_fail (eti, NULL); + + a11y = atk_gobject_accessible_for_object (G_OBJECT (eti)); + g_return_val_if_fail (a11y, NULL); + + return a11y; +} + +static gboolean +init_child_item (GalA11yETable *a11y) +{ + ETable *table; + + if (!a11y || !GTK_IS_ACCESSIBLE (a11y)) + return FALSE; + + table = E_TABLE (GTK_ACCESSIBLE (a11y)->widget); + if (table && GTK_WIDGET_MAPPED (GTK_WIDGET (table)) && table->group && E_IS_TABLE_GROUP_CONTAINER(table->group)) { + ETableGroupContainer *etgc = (ETableGroupContainer *)table->group; + GList *list; + + for (list = etgc->children; list; list = g_list_next (list)) { + ETableGroupContainerChildNode *child_node = list->data; + ETableGroup *child = child_node->child; + ETableItem *eti = find_first_table_item (child); + + eti_get_accessible (eti, ATK_OBJECT (a11y)); + } + } + g_object_unref (a11y); + g_object_unref (table); + + return FALSE; +} + +static AtkObject* +et_ref_accessible_at_point (AtkComponent *component, + gint x, + gint y, + AtkCoordType coord_type) +{ + GalA11yETable *a11y = GAL_A11Y_E_TABLE (component); + if (GET_PRIVATE (a11y)->child_item) + g_object_ref (GET_PRIVATE (a11y)->child_item); + return GET_PRIVATE (a11y)->child_item; +} + +static gint +et_get_n_children (AtkObject *accessible) +{ + GalA11yETable *a11y = GAL_A11Y_E_TABLE (accessible); + ETable * et; + int n = 0; + + et = E_TABLE(GTK_ACCESSIBLE (a11y)->widget); + + if (et->group) { + if (E_IS_TABLE_GROUP_LEAF (et->group)) + n = 1; + else if (E_IS_TABLE_GROUP_CONTAINER (et->group)) { + ETableGroupContainer *etgc = (ETableGroupContainer *)et->group; + n = g_list_length (etgc->children); + } + } + + if (et && et->use_click_to_add && et->click_to_add) { + n++; + } + return n; +} + +static AtkObject* +et_ref_child (AtkObject *accessible, + gint i) +{ + GalA11yETable *a11y = GAL_A11Y_E_TABLE (accessible); + ETable * et; + gint child_no; + + et = E_TABLE(GTK_ACCESSIBLE (a11y)->widget); + + child_no = et_get_n_children (accessible); + if (i == 0 || i < child_no - 1) { + if (E_IS_TABLE_GROUP_LEAF (et->group)) { + ETableItem *eti = find_first_table_item (et->group); + AtkObject *aeti = eti_get_accessible (eti, accessible); + if (aeti) + g_object_ref (aeti); + return aeti; + + } else if (E_IS_TABLE_GROUP_CONTAINER (et->group)) { + ETableGroupContainer *etgc = (ETableGroupContainer *) et->group; + ETableGroupContainerChildNode *child_node = g_list_nth_data (etgc->children, i); + if (child_node) { + ETableGroup *child = child_node->child; + ETableItem * eti = find_first_table_item (child); + AtkObject *aeti = eti_get_accessible (eti, accessible); + if (aeti) + g_object_ref (aeti); + return aeti; + } + } + } else if (i == child_no -1) { + ETableClickToAdd * etcta; + + if (et && et->use_click_to_add && et->click_to_add) { + etcta = E_TABLE_CLICK_TO_ADD(et->click_to_add); + accessible = atk_gobject_accessible_for_object (G_OBJECT(etcta)); + if (accessible) + g_object_ref (accessible); + return accessible; + } + } + + return NULL; +} + +static AtkLayer +et_get_layer (AtkComponent *component) +{ + return ATK_LAYER_WIDGET; +} + +static void +et_class_init (GalA11yETableClass *klass) +{ + AtkObjectClass *atk_object_class = ATK_OBJECT_CLASS (klass); + + parent_class = g_type_class_ref (PARENT_TYPE); + + atk_object_class->get_n_children = et_get_n_children; + atk_object_class->ref_child = et_ref_child; +} + +static void +et_atk_component_iface_init (AtkComponentIface *iface) +{ + iface->ref_accessible_at_point = et_ref_accessible_at_point; + iface->get_layer = et_get_layer; +} + +static void +et_init (GalA11yETable *a11y) +{ + GalA11yETablePrivate *priv; + + priv = GET_PRIVATE (a11y); + + priv->child_item = NULL; +} + +/** + * gal_a11y_e_table_get_type: + * @void: + * + * Registers the &GalA11yETable class if necessary, and returns the type ID + * associated to it. + * + * Return value: The type ID of the &GalA11yETable class. + **/ +GType +gal_a11y_e_table_get_type (void) +{ + static GType type = 0; + + if (!type) { + AtkObjectFactory *factory; + + GTypeInfo info = { + sizeof (GalA11yETableClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) et_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (GalA11yETable), + 0, + (GInstanceInitFunc) et_init, + NULL /* value_table */ + }; + + static const GInterfaceInfo atk_component_info = { + (GInterfaceInitFunc) et_atk_component_iface_init, + (GInterfaceFinalizeFunc) NULL, + NULL + }; + + factory = atk_registry_get_factory (atk_get_default_registry (), GTK_TYPE_WIDGET); + parent_type = atk_object_factory_get_accessible_type (factory); + + type = gal_a11y_type_register_static_with_private (PARENT_TYPE, "GalA11yETable", &info, 0, + sizeof (GalA11yETablePrivate), &priv_offset); + g_type_add_interface_static (type, ATK_TYPE_COMPONENT, &atk_component_info); + } + + return type; +} + +AtkObject * +gal_a11y_e_table_new (GObject *widget) +{ + GalA11yETable *a11y; + ETable *table; + + table = E_TABLE (widget); + + a11y = g_object_new (gal_a11y_e_table_get_type (), NULL); + + GTK_ACCESSIBLE (a11y)->widget = GTK_WIDGET (widget); + + /* we need to init all the children for multiple table items */ + if (table && GTK_WIDGET_MAPPED (GTK_WIDGET (table)) && table->group && E_IS_TABLE_GROUP_CONTAINER (table->group)) { + /* Ref it here so that it is still valid in the idle function */ + /* It will be unrefed in the idle function */ + g_object_ref (a11y); + g_object_ref (widget); + + g_idle_add ((GSourceFunc)init_child_item, a11y); + } + + return ATK_OBJECT (a11y); +} + +void +gal_a11y_e_table_init (void) +{ + if (atk_get_root ()) + atk_registry_set_factory_type (atk_get_default_registry (), + E_TABLE_TYPE, + gal_a11y_e_table_factory_get_type ()); + +} + diff --git a/widgets/table/a11y/gal-a11y-e-table.h b/widgets/table/a11y/gal-a11y-e-table.h new file mode 100644 index 0000000000..ab133f5c71 --- /dev/null +++ b/widgets/table/a11y/gal-a11y-e-table.h @@ -0,0 +1,59 @@ +/* + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Authors: + * Christopher James Lahey <clahey@ximian.com> + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef __GAL_A11Y_E_TABLE_H__ +#define __GAL_A11Y_E_TABLE_H__ + +#include <gtk/gtk.h> +#include <atk/atkobject.h> +#include <atk/atkcomponent.h> + +#define GAL_A11Y_TYPE_E_TABLE (gal_a11y_e_table_get_type ()) +#define GAL_A11Y_E_TABLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GAL_A11Y_TYPE_E_TABLE, GalA11yETable)) +#define GAL_A11Y_E_TABLE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GAL_A11Y_TYPE_E_TABLE, GalA11yETableClass)) +#define GAL_A11Y_IS_E_TABLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GAL_A11Y_TYPE_E_TABLE)) +#define GAL_A11Y_IS_E_TABLE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GAL_A11Y_TYPE_E_TABLE)) + +typedef struct _GalA11yETable GalA11yETable; +typedef struct _GalA11yETableClass GalA11yETableClass; +typedef struct _GalA11yETablePrivate GalA11yETablePrivate; + +/* This struct should actually be larger as this isn't what we derive from. + * The GalA11yETablePrivate comes right after the parent class structure. + **/ +struct _GalA11yETable { + GtkAccessible object; +}; + +struct _GalA11yETableClass { + GtkAccessibleClass parent_class; +}; + + +/* Standard Glib function */ +GType gal_a11y_e_table_get_type (void); +AtkObject *gal_a11y_e_table_new (GObject *table); + +void gal_a11y_e_table_init (void); + +#endif /* ! __GAL_A11Y_E_TABLE_H__ */ diff --git a/widgets/table/a11y/gal-a11y-e-tree-factory.c b/widgets/table/a11y/gal-a11y-e-tree-factory.c new file mode 100644 index 0000000000..cacb3fe082 --- /dev/null +++ b/widgets/table/a11y/gal-a11y-e-tree-factory.c @@ -0,0 +1,98 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Authors: + * Yuedong Du <yuedong.du@sun.com> + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include <config.h> + +#include "gal-a11y-e-tree.h" +#include "gal-a11y-e-tree-factory.h" + +#define CS_CLASS(factory) (G_TYPE_INSTANCE_GET_CLASS ((factory), C_TYPE_STREAM, GalA11yETreeFactoryClass)) +static AtkObjectFactoryClass *parent_class; +#define PARENT_TYPE (ATK_TYPE_OBJECT_FACTORY) + +/* Static functions */ + +static GType +gal_a11y_e_tree_factory_get_accessible_type (void) +{ + return GAL_A11Y_TYPE_E_TREE; +} + +static AtkObject* +gal_a11y_e_tree_factory_create_accessible (GObject *obj) +{ + AtkObject *accessible; + + accessible = gal_a11y_e_tree_new (obj); + + return accessible; +} + +static void +gal_a11y_e_tree_factory_class_init (GalA11yETreeFactoryClass *klass) +{ + AtkObjectFactoryClass *factory_class = ATK_OBJECT_FACTORY_CLASS (klass); + + parent_class = g_type_class_ref (PARENT_TYPE); + + factory_class->create_accessible = gal_a11y_e_tree_factory_create_accessible; + factory_class->get_accessible_type = gal_a11y_e_tree_factory_get_accessible_type; +} + +static void +gal_a11y_e_tree_factory_init (GalA11yETreeFactory *factory) +{ +} + +/** + * gal_a11y_e_tree_factory_get_type: + * @void: + * + * Registers the &GalA11yETreeFactory class if necessary, and returns the type ID + * associated to it. + * + * Return value: The type ID of the &GalA11yETreeFactory class. + **/ +GType +gal_a11y_e_tree_factory_get_type (void) +{ + static GType type = 0; + + if (!type) { + GTypeInfo info = { + sizeof (GalA11yETreeFactoryClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) gal_a11y_e_tree_factory_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (GalA11yETreeFactory), + 0, + (GInstanceInitFunc) gal_a11y_e_tree_factory_init, + NULL /* value_tree */ + }; + + type = g_type_register_static (PARENT_TYPE, "GalA11yETreeFactory", &info, 0); + } + + return type; +} diff --git a/widgets/table/a11y/gal-a11y-e-tree-factory.h b/widgets/table/a11y/gal-a11y-e-tree-factory.h new file mode 100644 index 0000000000..621d256c48 --- /dev/null +++ b/widgets/table/a11y/gal-a11y-e-tree-factory.h @@ -0,0 +1,50 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Authors: + * Yuedong Du <yuedong.du@ximian.com> + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef __GAL_A11Y_E_TREE_FACTORY_H__ +#define __GAL_A11Y_E_TREE_FACTORY_H__ + +#include <glib-object.h> +#include <atk/atkobjectfactory.h> + +#define GAL_A11Y_TYPE_E_TREE_FACTORY (gal_a11y_e_table_factory_get_type ()) +#define GAL_A11Y_E_TREE_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GAL_A11Y_TYPE_E_TREE_FACTORY, GalA11yETreeFactory)) +#define GAL_A11Y_E_TREE_FACTORY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GAL_A11Y_TYPE_E_TREE_FACTORY, GalA11yETreeFactoryClass)) +#define GAL_A11Y_IS_E_TREE_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GAL_A11Y_TYPE_E_TREE_FACTORY)) +#define GAL_A11Y_IS_E_TREE_FACTORY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GAL_A11Y_TYPE_E_TREE_FACTORY)) + +typedef struct _GalA11yETreeFactory GalA11yETreeFactory; +typedef struct _GalA11yETreeFactoryClass GalA11yETreeFactoryClass; + +struct _GalA11yETreeFactory { + AtkObject object; +}; + +struct _GalA11yETreeFactoryClass { + AtkObjectClass parent_class; +}; + + +/* Standard Glib function */ +GType gal_a11y_e_tree_factory_get_type (void); + +#endif /* ! __GAL_A11Y_E_TREE_FACTORY_H__ */ diff --git a/widgets/table/a11y/gal-a11y-e-tree.c b/widgets/table/a11y/gal-a11y-e-tree.c new file mode 100644 index 0000000000..6fde32b8e7 --- /dev/null +++ b/widgets/table/a11y/gal-a11y-e-tree.c @@ -0,0 +1,191 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Authors: + * Yuedong Du <yuedong.du@sun.com> + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include <config.h> + +#include "a11y/gal-a11y-util.h" +#include "table/e-table-item.h" +#include "table/e-tree.h" + +#include "gal-a11y-e-table-item.h" +#include "gal-a11y-e-tree.h" +#include "gal-a11y-e-tree-factory.h" + +#define CS_CLASS(a11y) (G_TYPE_INSTANCE_GET_CLASS ((a11y), C_TYPE_STREAM, GalA11yETreeClass)) +static AtkObjectClass *parent_class; +static GType parent_type; +static gint priv_offset; +#define GET_PRIVATE(object) ((GalA11yETreePrivate *) (((char *) object) + priv_offset)) +#define PARENT_TYPE (parent_type) + +struct _GalA11yETreePrivate { + AtkObject *child_item; +}; + +/* Static functions */ + +static void +init_child_item (GalA11yETree *a11y) +{ + GalA11yETreePrivate *priv = GET_PRIVATE (a11y); + ETree *tree = E_TREE (GTK_ACCESSIBLE (a11y)->widget); + ETableItem * eti; + + g_return_if_fail (tree); + eti = e_tree_get_item (tree); + if (priv->child_item == NULL) { + priv->child_item = atk_gobject_accessible_for_object (G_OBJECT (eti)); + } +} + +static AtkObject* +et_ref_accessible_at_point (AtkComponent *component, + gint x, + gint y, + AtkCoordType coord_type) +{ + GalA11yETree *a11y = GAL_A11Y_E_TREE (component); + init_child_item (a11y); + return GET_PRIVATE (a11y)->child_item; +} + +static gint +et_get_n_children (AtkObject *accessible) +{ + return 1; +} + +static AtkObject* +et_ref_child (AtkObject *accessible, + gint i) +{ + GalA11yETree *a11y = GAL_A11Y_E_TREE (accessible); + if (i != 0) + return NULL; + init_child_item (a11y); + g_object_ref (GET_PRIVATE (a11y)->child_item); + return GET_PRIVATE (a11y)->child_item; +} + +static AtkLayer +et_get_layer (AtkComponent *component) +{ + return ATK_LAYER_WIDGET; +} + +static void +et_class_init (GalA11yETreeClass *klass) +{ + AtkObjectClass *atk_object_class = ATK_OBJECT_CLASS (klass); + + parent_class = g_type_class_ref (PARENT_TYPE); + + atk_object_class->get_n_children = et_get_n_children; + atk_object_class->ref_child = et_ref_child; +} + +static void +et_atk_component_iface_init (AtkComponentIface *iface) +{ + iface->ref_accessible_at_point = et_ref_accessible_at_point; + iface->get_layer = et_get_layer; +} + +static void +et_init (GalA11yETree *a11y) +{ + GalA11yETreePrivate *priv; + + priv = GET_PRIVATE (a11y); + + priv->child_item = NULL; +} + +/** + * gal_a11y_e_tree_get_type: + * @void: + * + * Registers the &GalA11yETree class if necessary, and returns the type ID + * associated to it. + * + * Return value: The type ID of the &GalA11yETree class. + **/ +GType +gal_a11y_e_tree_get_type (void) +{ + static GType type = 0; + + if (!type) { + AtkObjectFactory *factory; + + GTypeInfo info = { + sizeof (GalA11yETreeClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) et_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (GalA11yETree), + 0, + (GInstanceInitFunc) et_init, + NULL /* value_tree */ + }; + + static const GInterfaceInfo atk_component_info = { + (GInterfaceInitFunc) et_atk_component_iface_init, + (GInterfaceFinalizeFunc) NULL, + NULL + }; + + factory = atk_registry_get_factory (atk_get_default_registry (), GTK_TYPE_WIDGET); + parent_type = atk_object_factory_get_accessible_type (factory); + + type = gal_a11y_type_register_static_with_private (PARENT_TYPE, "GalA11yETree", &info, 0, + sizeof (GalA11yETreePrivate), &priv_offset); + g_type_add_interface_static (type, ATK_TYPE_COMPONENT, &atk_component_info); + } + + return type; +} + +AtkObject * +gal_a11y_e_tree_new (GObject *widget) +{ + GalA11yETree *a11y; + + a11y = g_object_new (gal_a11y_e_tree_get_type (), NULL); + + GTK_ACCESSIBLE (a11y)->widget = GTK_WIDGET (widget); + + return ATK_OBJECT (a11y); +} + +void +gal_a11y_e_tree_init (void) +{ + if (atk_get_root ()) + atk_registry_set_factory_type (atk_get_default_registry (), + E_TREE_TYPE, + gal_a11y_e_tree_factory_get_type ()); + +} + diff --git a/widgets/table/a11y/gal-a11y-e-tree.h b/widgets/table/a11y/gal-a11y-e-tree.h new file mode 100644 index 0000000000..9fe482e1f8 --- /dev/null +++ b/widgets/table/a11y/gal-a11y-e-tree.h @@ -0,0 +1,58 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Authors: + * Yuedong Du <yuedong.du@sun.com> + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef __GAL_A11Y_E_TREE_H__ +#define __GAL_A11Y_E_TREE_H__ + +#include <gtk/gtk.h> +#include <atk/atkobject.h> +#include <atk/atkcomponent.h> + +#define GAL_A11Y_TYPE_E_TREE (gal_a11y_e_tree_get_type ()) +#define GAL_A11Y_E_TREE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GAL_A11Y_TYPE_E_TREE, GalA11yETree)) +#define GAL_A11Y_E_TREE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GAL_A11Y_TYPE_E_TREE, GalA11yETreeClass)) +#define GAL_A11Y_IS_E_TREE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GAL_A11Y_TYPE_E_TREE)) +#define GAL_A11Y_IS_E_TREE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GAL_A11Y_TYPE_E_TREE)) + +typedef struct _GalA11yETree GalA11yETree; +typedef struct _GalA11yETreeClass GalA11yETreeClass; +typedef struct _GalA11yETreePrivate GalA11yETreePrivate; + +/* This struct should actually be larger as this isn't what we derive from. + * The GalA11yETablePrivate comes right after the parent class structure. + **/ +struct _GalA11yETree { + GtkAccessible object; +}; + +struct _GalA11yETreeClass { + GtkAccessibleClass parent_class; +}; + + +/* Standard Glib function */ +GType gal_a11y_e_tree_get_type (void); +AtkObject *gal_a11y_e_tree_new (GObject *tree); + +void gal_a11y_e_tree_init (void); + +#endif /* ! __GAL_A11Y_E_TREE_H__ */ diff --git a/widgets/table/e-cell-combo.c b/widgets/table/e-cell-combo.c index 84d58200d2..4b75881104 100644 --- a/widgets/table/e-cell-combo.c +++ b/widgets/table/e-cell-combo.c @@ -62,7 +62,7 @@ #include <glib/gi18n.h> #include "e-util/e-util.h" -#include "misc/e-unicode.h" +#include "e-util/e-unicode.h" #include "e-table-item.h" #include "e-cell-combo.h" diff --git a/widgets/misc/e-cell-date-edit.c b/widgets/table/e-cell-date-edit.c index 97947980d9..1cf3838c91 100644 --- a/widgets/misc/e-cell-date-edit.c +++ b/widgets/table/e-cell-date-edit.c @@ -39,15 +39,15 @@ #include <gdk/gdkkeysyms.h> #include <gtk/gtk.h> -#include <table/e-table-item.h> -#include <table/e-cell-text.h> +#include "e-table-item.h" +#include "e-cell-text.h" #include <glib/gi18n.h> #include <libedataserver/e-time-utils.h> /* This depends on ECalendar which is why I didn't put it in gal. */ -#include "e-calendar.h" +#include <misc/e-calendar.h> static void e_cell_date_edit_destroy (GtkObject *object); static void e_cell_date_edit_get_property (GObject *object, diff --git a/widgets/misc/e-cell-date-edit.h b/widgets/table/e-cell-date-edit.h index 30dee535e8..30dee535e8 100644 --- a/widgets/misc/e-cell-date-edit.h +++ b/widgets/table/e-cell-date-edit.h diff --git a/widgets/table/e-cell-date.c b/widgets/table/e-cell-date.c index ac0274f183..9199d5715b 100644 --- a/widgets/table/e-cell-date.c +++ b/widgets/table/e-cell-date.c @@ -29,7 +29,7 @@ #include <glib/gi18n.h> #include "e-util/e-util.h" -#include "misc/e-unicode.h" +#include "e-util/e-unicode.h" #include "e-cell-date.h" diff --git a/widgets/table/e-cell-hbox.c b/widgets/table/e-cell-hbox.c index b9a8544f57..6c0bded852 100644 --- a/widgets/table/e-cell-hbox.c +++ b/widgets/table/e-cell-hbox.c @@ -32,8 +32,8 @@ #include <gtk/gtk.h> -/* #include "a11y/e-table/gal-a11y-e-cell-registry.h" */ -/* #include "a11y/e-table/gal-a11y-e-cell-vbox.h" */ +/* #include "a11y/gal-a11y-e-cell-registry.h" */ +/* #include "a11y/gal-a11y-e-cell-vbox.h" */ #include "e-util/e-util.h" #include "e-cell-hbox.h" diff --git a/widgets/misc/e-cell-percent.c b/widgets/table/e-cell-percent.c index 94e33489e5..94e33489e5 100644 --- a/widgets/misc/e-cell-percent.c +++ b/widgets/table/e-cell-percent.c diff --git a/widgets/misc/e-cell-percent.h b/widgets/table/e-cell-percent.h index 46a7ddc3e3..46a7ddc3e3 100644 --- a/widgets/misc/e-cell-percent.h +++ b/widgets/table/e-cell-percent.h diff --git a/widgets/table/e-cell-popup.c b/widgets/table/e-cell-popup.c index 92e03d79a1..e7203c5550 100644 --- a/widgets/table/e-cell-popup.c +++ b/widgets/table/e-cell-popup.c @@ -33,8 +33,8 @@ #include <gdk/gdkkeysyms.h> -#include "a11y/e-table/gal-a11y-e-cell-popup.h" -#include "a11y/e-table/gal-a11y-e-cell-registry.h" +#include "a11y/gal-a11y-e-cell-popup.h" +#include "a11y/gal-a11y-e-cell-registry.h" #include "e-util/e-util.h" #include "e-cell-popup.h" diff --git a/widgets/table/e-cell-text.c b/widgets/table/e-cell-text.c index e50d3d7ae7..55ec753c2a 100644 --- a/widgets/table/e-cell-text.c +++ b/widgets/table/e-cell-text.c @@ -45,15 +45,15 @@ #include <libgnomecanvas/gnome-canvas.h> #include <libgnomecanvas/gnome-canvas-rect-ellipse.h> -#include "a11y/e-table/gal-a11y-e-cell-registry.h" -#include "a11y/e-table/gal-a11y-e-cell-text.h" +#include "a11y/gal-a11y-e-cell-registry.h" +#include "a11y/gal-a11y-e-cell-text.h" #include "text/e-text.h" #include <glib/gi18n.h> #include "e-util/e-text-event-processor.h" #include "e-util/e-text-event-processor-emacs-like.h" #include "e-util/e-util.h" #include "misc/e-canvas.h" -#include "misc/e-unicode.h" +#include "e-util/e-unicode.h" #include "e-cell-text.h" #include "e-table-item.h" diff --git a/widgets/table/e-cell-toggle.c b/widgets/table/e-cell-toggle.c index 4fc6aca107..38562f58a8 100644 --- a/widgets/table/e-cell-toggle.c +++ b/widgets/table/e-cell-toggle.c @@ -28,8 +28,8 @@ #include <gtk/gtk.h> #include <libgnomecanvas/gnome-canvas.h> -#include "a11y/e-table/gal-a11y-e-cell-toggle.h" -#include "a11y/e-table/gal-a11y-e-cell-registry.h" +#include "a11y/gal-a11y-e-cell-toggle.h" +#include "a11y/gal-a11y-e-cell-registry.h" #include "e-util/e-util.h" #include "misc/e-hsv-utils.h" diff --git a/widgets/table/e-cell-tree.c b/widgets/table/e-cell-tree.c index eb7e428fb9..e9cb30bb23 100644 --- a/widgets/table/e-cell-tree.c +++ b/widgets/table/e-cell-tree.c @@ -38,8 +38,8 @@ #include <gtk/gtk.h> #include <libgnomecanvas/gnome-canvas.h> -#include "a11y/e-table/gal-a11y-e-cell-registry.h" -#include "a11y/e-table/gal-a11y-e-cell-tree.h" +#include "a11y/gal-a11y-e-cell-registry.h" +#include "a11y/gal-a11y-e-cell-tree.h" #include "e-util/e-util.h" #include "e-cell-tree.h" diff --git a/widgets/table/e-cell-vbox.c b/widgets/table/e-cell-vbox.c index af398ae872..46da90eea4 100644 --- a/widgets/table/e-cell-vbox.c +++ b/widgets/table/e-cell-vbox.c @@ -29,8 +29,8 @@ #include <gtk/gtk.h> -#include "a11y/e-table/gal-a11y-e-cell-registry.h" -#include "a11y/e-table/gal-a11y-e-cell-vbox.h" +#include "a11y/gal-a11y-e-cell-registry.h" +#include "a11y/gal-a11y-e-cell-vbox.h" #include "e-util/e-util.h" #include "e-cell-vbox.h" diff --git a/widgets/table/e-table-click-to-add.c b/widgets/table/e-table-click-to-add.c index 4871b055eb..dedf8e1c53 100644 --- a/widgets/table/e-table-click-to-add.c +++ b/widgets/table/e-table-click-to-add.c @@ -29,7 +29,7 @@ #include <libgnomecanvas/gnome-canvas-util.h> #include <gdk-pixbuf/gdk-pixbuf.h> -#include "a11y/e-table/gal-a11y-e-table-click-to-add.h" +#include "a11y/gal-a11y-e-table-click-to-add.h" #include "text/e-text.h" #include <glib/gi18n.h> #include "e-util/e-util.h" diff --git a/widgets/table/e-table-config.c b/widgets/table/e-table-config.c index 5becaa30f2..5f93c32a72 100644 --- a/widgets/table/e-table-config.c +++ b/widgets/table/e-table-config.c @@ -38,7 +38,7 @@ #include <glib/gi18n.h> #include "e-util/e-util-private.h" #include "e-util/e-util.h" -#include "misc/e-unicode.h" +#include "e-util/e-unicode.h" #include "e-table-config.h" #include "e-table-memory-store.h" diff --git a/widgets/table/e-table-group-container.c b/widgets/table/e-table-group-container.c index c342c6ca7e..f6758025ab 100644 --- a/widgets/table/e-table-group-container.c +++ b/widgets/table/e-table-group-container.c @@ -31,7 +31,7 @@ #include "e-util/e-util.h" #include "misc/e-canvas-utils.h" #include "misc/e-canvas.h" -#include "misc/e-unicode.h" +#include "e-util/e-unicode.h" #include "e-table-defines.h" #include "e-table-group-container.h" diff --git a/widgets/table/e-table-header-utils.c b/widgets/table/e-table-header-utils.c index afcc0720e1..80b5be42ce 100644 --- a/widgets/table/e-table-header-utils.c +++ b/widgets/table/e-table-header-utils.c @@ -29,7 +29,7 @@ #include <gtk/gtk.h> -#include "misc/e-unicode.h" +#include "e-util/e-unicode.h" #include "e-table-defines.h" #include "e-table-header-utils.h" diff --git a/widgets/table/e-table-item.c b/widgets/table/e-table-item.c index 58d6c65f03..394679e6ef 100644 --- a/widgets/table/e-table-item.c +++ b/widgets/table/e-table-item.c @@ -36,8 +36,8 @@ #include <gtk/gtk.h> #include <gdk/gdkkeysyms.h> -#include "a11y/e-table/gal-a11y-e-table-item-factory.h" -#include "a11y/e-table/gal-a11y-e-table-item.h" +#include "a11y/gal-a11y-e-table-item-factory.h" +#include "a11y/gal-a11y-e-table-item.h" #include <glib/gi18n.h> #include "e-util/e-util.h" #include "misc/e-canvas.h" diff --git a/widgets/table/e-table-utils.c b/widgets/table/e-table-utils.c index d01d94ae28..96b6004c41 100644 --- a/widgets/table/e-table-utils.c +++ b/widgets/table/e-table-utils.c @@ -27,7 +27,7 @@ #include <string.h> #include "e-util/e-util.h" -#include "misc/e-unicode.h" +#include "e-util/e-unicode.h" #include "e-table-utils.h" #include "e-table-header-utils.h" diff --git a/widgets/table/e-table.c b/widgets/table/e-table.c index 69a300d950..754607c376 100644 --- a/widgets/table/e-table.c +++ b/widgets/table/e-table.c @@ -36,13 +36,13 @@ #include <libgnomecanvas/gnome-canvas.h> #include <libgnomecanvas/gnome-canvas-rect-ellipse.h> -#include "a11y/e-table/gal-a11y-e-table.h" +#include "a11y/gal-a11y-e-table.h" #include <glib/gi18n.h> #include "e-util/e-util.h" #include "misc/e-canvas.h" #include "misc/e-canvas-background.h" #include "misc/e-canvas-vbox.h" -#include "misc/e-unicode.h" +#include "e-util/e-unicode.h" #include "e-table.h" #include "e-table-click-to-add.h" diff --git a/widgets/table/e-tree.c b/widgets/table/e-tree.c index 0963229c94..08399609a0 100644 --- a/widgets/table/e-tree.c +++ b/widgets/table/e-tree.c @@ -30,7 +30,7 @@ #include <gtk/gtk.h> #include <libgnomecanvas/gnome-canvas-rect-ellipse.h> -#include "a11y/e-table/gal-a11y-e-tree.h" +#include "a11y/gal-a11y-e-tree.h" #include <glib/gi18n.h> #include "e-util/e-util.h" #include "misc/e-canvas.h" diff --git a/widgets/text/Makefile.am b/widgets/text/Makefile.am index fbe03c828f..e035d8714d 100644 --- a/widgets/text/Makefile.am +++ b/widgets/text/Makefile.am @@ -1,7 +1,3 @@ -if OS_WIN32 -WIN32_BOOTSTRAP_LIBS = $(top_builddir)/win32/libemiscwidgets.la -endif - INCLUDES = \ -I$(top_srcdir) \ -I$(top_srcdir)/widgets \ @@ -15,22 +11,29 @@ privsolib_LTLIBRARIES = libetext.la libetext_la_SOURCES = \ e-text-model-repos.c \ e-text-model.c \ - e-text.c + e-text.c \ + e-reflow.c \ + e-reflow-model.c \ + a11y/gal-a11y-e-text-factory.c \ + a11y/gal-a11y-e-text.c libetextincludedir = $(privincludedir)/text libetextinclude_HEADERS = \ e-text-model-repos.h \ e-text-model.h \ - e-text.h + e-text.h \ + e-reflow.h \ + e-reflow-model.h \ + a11y/gal-a11y-e-text-factory.h \ + a11y/gal-a11y-e-text.h libetext_la_LDFLAGS = $(NO_UNDEFINED) libetext_la_LIBADD = \ - $(WIN32_BOOTSTRAP_LIBS) \ - $(top_builddir)/e-util/libeutil.la \ $(top_builddir)/a11y/libevolution-a11y.la \ - $(top_builddir)/widgets/table/libetable.la \ + $(top_builddir)/e-util/libeutil.la \ + $(top_builddir)/widgets/misc/libemiscwidgets.la \ $(E_UTIL_LIBS) \ $(GNOME_PLATFORM_LIBS) \ $(REGEX_LIBS) diff --git a/widgets/text/a11y/gal-a11y-e-text-factory.c b/widgets/text/a11y/gal-a11y-e-text-factory.c new file mode 100644 index 0000000000..e1f835e912 --- /dev/null +++ b/widgets/text/a11y/gal-a11y-e-text-factory.c @@ -0,0 +1,101 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Authors: + * Christopher James Lahey <clahey@ximian.com> + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include <config.h> +#include "text/e-text.h" +#include "gal-a11y-e-text-factory.h" +#include "gal-a11y-e-text.h" + +#define CS_CLASS(factory) (G_TYPE_INSTANCE_GET_CLASS ((factory), C_TYPE_STREAM, GalA11yETextFactoryClass)) +static AtkObjectFactoryClass *parent_class; +#define PARENT_TYPE (ATK_TYPE_OBJECT_FACTORY) + +/* Static functions */ + +static GType +gal_a11y_e_text_factory_get_accessible_type (void) +{ + return GAL_A11Y_TYPE_E_TEXT; +} + +static AtkObject* +gal_a11y_e_text_factory_create_accessible (GObject *obj) +{ + AtkObject *atk_object; + + g_return_val_if_fail (E_IS_TEXT (obj), NULL); + + atk_object = g_object_new (GAL_A11Y_TYPE_E_TEXT, NULL); + atk_object_initialize (atk_object, obj); + + return atk_object; +} + +static void +gal_a11y_e_text_factory_class_init (GalA11yETextFactoryClass *klass) +{ + AtkObjectFactoryClass *factory_class = ATK_OBJECT_FACTORY_CLASS (klass); + + parent_class = g_type_class_ref (PARENT_TYPE); + + factory_class->create_accessible = gal_a11y_e_text_factory_create_accessible; + factory_class->get_accessible_type = gal_a11y_e_text_factory_get_accessible_type; +} + +static void +gal_a11y_e_text_factory_init (GalA11yETextFactory *factory) +{ +} + +/** + * gal_a11y_e_text_factory_get_type: + * @void: + * + * Registers the &GalA11yETextFactory class if necessary, and returns the type ID + * associated to it. + * + * Return value: The type ID of the &GalA11yETextFactory class. + **/ +GType +gal_a11y_e_text_factory_get_type (void) +{ + static GType type = 0; + + if (!type) { + GTypeInfo info = { + sizeof (GalA11yETextFactoryClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) gal_a11y_e_text_factory_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (GalA11yETextFactory), + 0, + (GInstanceInitFunc) gal_a11y_e_text_factory_init, + NULL /* value_text */ + }; + + type = g_type_register_static (PARENT_TYPE, "GalA11yETextFactory", &info, 0); + } + + return type; +} diff --git a/widgets/text/a11y/gal-a11y-e-text-factory.h b/widgets/text/a11y/gal-a11y-e-text-factory.h new file mode 100644 index 0000000000..ce4d4d0a65 --- /dev/null +++ b/widgets/text/a11y/gal-a11y-e-text-factory.h @@ -0,0 +1,50 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Authors: + * Christopher James Lahey <clahey@ximian.com> + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef __GAL_A11Y_E_TEXT_FACTORY_H__ +#define __GAL_A11Y_E_TEXT_FACTORY_H__ + +#include <glib-object.h> +#include <atk/atkobjectfactory.h> + +#define GAL_A11Y_TYPE_E_TEXT_FACTORY (gal_a11y_e_text_factory_get_type ()) +#define GAL_A11Y_E_TEXT_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GAL_A11Y_TYPE_E_TEXT_FACTORY, GalA11yETextFactory)) +#define GAL_A11Y_E_TEXT_FACTORY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GAL_A11Y_TYPE_E_TEXT_FACTORY, GalA11yETextFactoryClass)) +#define GAL_A11Y_IS_E_TEXT_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GAL_A11Y_TYPE_E_TEXT_FACTORY)) +#define GAL_A11Y_IS_E_TEXT_FACTORY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GAL_A11Y_TYPE_E_TEXT_FACTORY)) + +typedef struct _GalA11yETextFactory GalA11yETextFactory; +typedef struct _GalA11yETextFactoryClass GalA11yETextFactoryClass; + +struct _GalA11yETextFactory { + AtkObjectFactory object; +}; + +struct _GalA11yETextFactoryClass { + AtkObjectFactoryClass parent_class; +}; + + +/* Standard Glib function */ +GType gal_a11y_e_text_factory_get_type (void); + +#endif /* ! __GAL_A11Y_E_TEXT_FACTORY_H__ */ diff --git a/widgets/text/a11y/gal-a11y-e-text.c b/widgets/text/a11y/gal-a11y-e-text.c new file mode 100644 index 0000000000..4eeb7811fc --- /dev/null +++ b/widgets/text/a11y/gal-a11y-e-text.c @@ -0,0 +1,1134 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Authors: + * Christopher James Lahey <clahey@ximian.com> + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#include <config.h> + +#include <string.h> + +#include <gtk/gtk.h> + +#include "a11y/gal-a11y-util.h" +#include "text/e-text.h" +#include "text/e-text-model-repos.h" + +#include "gal-a11y-e-text.h" +#include "gal-a11y-e-text-factory.h" + +#define CS_CLASS(a11y) (G_TYPE_INSTANCE_GET_CLASS ((a11y), C_TYPE_STREAM, GalA11yETextClass)) +static GObjectClass *parent_class; +static AtkComponentIface *component_parent_iface; +static GType parent_type; +static gint priv_offset; +static GQuark quark_accessible_object = 0; +#define GET_PRIVATE(object) ((GalA11yETextPrivate *) (((char *) object) + priv_offset)) +#define PARENT_TYPE (parent_type) + +struct _GalA11yETextPrivate { + int dummy; +}; + +static void +et_dispose (GObject *object) +{ + if (parent_class->dispose) + parent_class->dispose (object); +} + +/* Static functions */ + +static void +et_get_extents (AtkComponent *component, + gint *x, + gint *y, + gint *width, + gint *height, + AtkCoordType coord_type) +{ + EText *item = E_TEXT (atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (component))); + double real_width; + double real_height; + int fake_width; + int fake_height; + + if (component_parent_iface && + component_parent_iface->get_extents) + component_parent_iface->get_extents (component, + x, + y, + &fake_width, + &fake_height, + coord_type); + + g_object_get (item, + "text_width", &real_width, + "text_height", &real_height, + NULL); + + if (width) + *width = real_width; + if (height) + *height = real_height; +} + +static const gchar * +et_get_full_text (AtkText *text) +{ + EText *etext = E_TEXT (atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (text))); + ETextModel *model; + const char *full_text; + + g_object_get (etext, "model", &model, NULL); + + full_text = e_text_model_get_text (model); + + return full_text; +} + +static void +et_set_full_text (AtkEditableText *text, + const char *full_text) +{ + EText *etext = E_TEXT (atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (text))); + ETextModel *model; + + g_object_get (etext, "model", &model, NULL); + + e_text_model_set_text (model, full_text); +} + +static gchar * +et_get_text (AtkText *text, + gint start_offset, + gint end_offset) +{ + gint start, end, real_start, real_end, len; + const char *full_text = et_get_full_text (text); + if (full_text == NULL) + return NULL; + len = g_utf8_strlen (full_text, -1); + + start = MIN (MAX (0, start_offset), len); + end = MIN (MAX (-1, end_offset), len); + + if (end_offset == -1) + end = strlen (full_text); + else + end = g_utf8_offset_to_pointer (full_text, end) - full_text; + + start = g_utf8_offset_to_pointer (full_text, start) - full_text; + + real_start = MIN (start, end); + real_end = MAX (start, end); + + return g_strndup (full_text + real_start, real_end - real_start); +} + +static gboolean +is_a_seperator (gunichar c) +{ + return g_unichar_ispunct(c) || g_unichar_isspace(c); +} + +static gint +find_word_start (const char *text, + gint begin_offset, + gint step) +{ + gint offset; + char *at_offset; + gunichar current, previous; + gint len; + + offset = begin_offset; + len = g_utf8_strlen (text, -1); + + while (offset > 0 && offset < len) { + at_offset = g_utf8_offset_to_pointer (text, offset); + current = g_utf8_get_char_validated (at_offset, -1); + at_offset = g_utf8_offset_to_pointer (text, offset-1); + previous = g_utf8_get_char_validated (at_offset, -1); + if ((! is_a_seperator (current)) && is_a_seperator (previous)) + break; + offset += step; + } + + return offset; +} + +static gint +find_word_end (const char *text, + gint begin_offset, + gint step) +{ + gint offset; + char *at_offset; + gunichar current, previous; + gint len; + + offset = begin_offset; + len = g_utf8_strlen (text, -1); + + while (offset > 0 && offset < len) { + at_offset = g_utf8_offset_to_pointer (text, offset); + current = g_utf8_get_char_validated (at_offset, -1); + at_offset = g_utf8_offset_to_pointer (text, offset-1); + previous = g_utf8_get_char_validated (at_offset, -1); + if (is_a_seperator (current) && (! is_a_seperator (previous))) + break; + offset += step; + } + + return offset; +} + +static gint +find_sentence_start (const char *text, + gint begin_offset, + gint step) +{ + gint offset, last_word_end, len; + char *at_offset; + gunichar ch; + int i; + + offset = find_word_start (text, begin_offset, step); + len = g_utf8_strlen (text, -1); + + while (offset>0 && offset <len) { + last_word_end = find_word_end (text, offset - 1, -1); + if (last_word_end == 0) + break; + for (i = last_word_end; i < offset; i++) { + at_offset = g_utf8_offset_to_pointer (text, i); + ch = g_utf8_get_char_validated (at_offset, -1); + if (ch == '.' || ch == '!' || ch == '?') + return offset; + } + + offset = find_word_start (text, offset + step, step); + } + + return offset; +} + +static gint +find_sentence_end (const char *text, + gint begin_offset, + gint step) +{ + gint offset; + char *at_offset; + gunichar previous; + gint len; + + offset = begin_offset; + len = g_utf8_strlen (text, -1); + + while (offset > 0 && offset < len) { + at_offset = g_utf8_offset_to_pointer (text, offset - 1); + previous = g_utf8_get_char_validated (at_offset, -1); + if (previous == '.' || previous == '!' || previous == '?') + break; + offset += step; + } + + return offset; +} + +static gint +find_line_start (const char *text, + gint begin_offset, + gint step) +{ + gint offset; + char *at_offset; + gunichar previous; + gint len; + + offset = begin_offset; + len = g_utf8_strlen (text, -1); + + while (offset > 0 && offset < len) { + at_offset = g_utf8_offset_to_pointer (text, offset - 1); + previous = g_utf8_get_char_validated (at_offset, -1); + if (previous == '\n' || previous == '\r') + break; + offset += step; + } + + return offset; +} + +static gint +find_line_end (const char *text, + gint begin_offset, + gint step) +{ + gint offset; + char *at_offset; + gunichar current; + gint len; + + offset = begin_offset; + len = g_utf8_strlen (text, -1); + + while (offset >= 0 && offset < len) { + at_offset = g_utf8_offset_to_pointer (text, offset); + current = g_utf8_get_char_validated (at_offset, -1); + if (current == '\n' || current == '\r') + break; + offset += step; + } + + return offset; +} + +static gchar * +et_get_text_after_offset (AtkText *text, + gint offset, + AtkTextBoundary boundary_type, + gint *start_offset, + gint *end_offset) +{ + gint start, end, len; + const char *full_text = et_get_full_text (text); + g_return_val_if_fail (full_text, NULL); + + switch (boundary_type) + { + case ATK_TEXT_BOUNDARY_CHAR: + start = offset + 1; + end = offset + 2; + break; + case ATK_TEXT_BOUNDARY_WORD_START: + start = find_word_start (full_text, offset + 1, 1); + end = find_word_start (full_text, start + 1, 1); + break; + case ATK_TEXT_BOUNDARY_WORD_END: + start = find_word_end (full_text, offset + 1, 1); + end = find_word_end (full_text, start + 1, 1); + break; + case ATK_TEXT_BOUNDARY_SENTENCE_START: + start = find_sentence_start (full_text, offset + 1, 1); + end = find_sentence_start (full_text, start + 1, 1); + break; + case ATK_TEXT_BOUNDARY_SENTENCE_END: + start = find_sentence_end (full_text, offset + 1, 1); + end = find_sentence_end (full_text, start + 1, 1); + break; + case ATK_TEXT_BOUNDARY_LINE_START: + start = find_line_start (full_text, offset + 1, 1); + end = find_line_start (full_text, start + 1, 1); + break; + case ATK_TEXT_BOUNDARY_LINE_END: + start = find_line_end (full_text, offset + 1, 1); + end = find_line_end (full_text, start + 1, 1); + break; + default: + return NULL; + } + + len = g_utf8_strlen (full_text, -1); + if (start_offset) + *start_offset = MIN (MAX (0, start), len); + if (end_offset) + *end_offset = MIN (MAX (0, end), len); + return et_get_text (text, start, end); +} + +static gchar * +et_get_text_at_offset (AtkText *text, + gint offset, + AtkTextBoundary boundary_type, + gint *start_offset, + gint *end_offset) +{ + gint start, end, len; + const char *full_text = et_get_full_text (text); + g_return_val_if_fail (full_text, NULL); + + switch (boundary_type) + { + case ATK_TEXT_BOUNDARY_CHAR: + start = offset; + end = offset + 1; + break; + case ATK_TEXT_BOUNDARY_WORD_START: + start = find_word_start (full_text, offset - 1, -1); + end = find_word_start (full_text, offset, 1); + break; + case ATK_TEXT_BOUNDARY_WORD_END: + start = find_word_end (full_text, offset, -1); + end = find_word_end (full_text, offset + 1, 1); + break; + case ATK_TEXT_BOUNDARY_SENTENCE_START: + start = find_sentence_start (full_text, offset - 1, -1); + end = find_sentence_start (full_text, offset, 1); + break; + case ATK_TEXT_BOUNDARY_SENTENCE_END: + start = find_sentence_end (full_text, offset, -1); + end = find_sentence_end (full_text, offset + 1, 1); + break; + case ATK_TEXT_BOUNDARY_LINE_START: + start = find_line_start (full_text, offset - 1, -1); + end = find_line_start (full_text, offset, 1); + break; + case ATK_TEXT_BOUNDARY_LINE_END: + start = find_line_end (full_text, offset, -1); + end = find_line_end (full_text, offset + 1, 1); + break; + default: + return NULL; + } + + len = g_utf8_strlen (full_text, -1); + if (start_offset) + *start_offset = MIN (MAX (0, start), len); + if (end_offset) + *end_offset = MIN (MAX (0, end), len); + return et_get_text (text, start, end); +} + +static gunichar +et_get_character_at_offset (AtkText *text, + gint offset) +{ + const char *full_text = et_get_full_text (text); + char *at_offset; + + at_offset = g_utf8_offset_to_pointer (full_text, offset); + return g_utf8_get_char_validated (at_offset, -1); +} + + +static gchar* +et_get_text_before_offset (AtkText *text, + gint offset, + AtkTextBoundary boundary_type, + gint *start_offset, + gint *end_offset) +{ + gint start, end, len; + const char *full_text = et_get_full_text (text); + g_return_val_if_fail (full_text, NULL); + + switch (boundary_type) + { + case ATK_TEXT_BOUNDARY_CHAR: + start = offset - 1; + end = offset; + break; + case ATK_TEXT_BOUNDARY_WORD_START: + end = find_word_start (full_text, offset - 1, -1); + start = find_word_start (full_text, end - 1, -1) ; + break; + case ATK_TEXT_BOUNDARY_WORD_END: + end = find_word_end (full_text, offset, -1); + start = find_word_end (full_text, end - 1, -1); + break; + case ATK_TEXT_BOUNDARY_SENTENCE_START: + end = find_sentence_start (full_text, offset, -1); + start = find_sentence_start (full_text, end - 1, -1); + break; + case ATK_TEXT_BOUNDARY_SENTENCE_END: + end = find_sentence_end (full_text, offset, -1); + start = find_sentence_end (full_text, end - 1, -1); + break; + case ATK_TEXT_BOUNDARY_LINE_START: + end = find_line_start (full_text, offset, -1); + start = find_line_start (full_text, end - 1, -1); + break; + case ATK_TEXT_BOUNDARY_LINE_END: + end = find_line_end (full_text, offset, -1); + start = find_line_end (full_text, end - 1, -1); + break; + default: + return NULL; + } + + len = g_utf8_strlen (full_text, -1); + if (start_offset) + *start_offset = MIN (MAX (0, start), len); + if (end_offset) + *end_offset = MIN (MAX (0, end), len); + return et_get_text (text, start, end); +} + +static gint +et_get_caret_offset (AtkText *text) +{ + GObject *obj; + EText *etext; + int offset; + + g_return_val_if_fail (ATK_IS_GOBJECT_ACCESSIBLE(text), -1); + obj = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (text)); + if (obj == NULL) + return -1; + + g_return_val_if_fail (E_IS_TEXT (obj), -1); + etext = E_TEXT (obj); + + g_object_get (etext, "cursor_pos", &offset, NULL); + return offset; +} + + +static AtkAttributeSet* +et_get_run_attributes (AtkText *text, + gint offset, + gint *start_offset, + gint *end_offset) +{ + /* Unimplemented */ + return NULL; +} + + +static AtkAttributeSet* +et_get_default_attributes (AtkText *text) +{ + /* Unimplemented */ + return NULL; +} + + +static void +et_get_character_extents (AtkText *text, + gint offset, + gint *x, + gint *y, + gint *width, + gint *height, + AtkCoordType coords) +{ + GObject *obj; + EText *etext; + GnomeCanvas *canvas; + gint x_widget, y_widget, x_window, y_window; + GdkWindow *window; + GtkWidget *widget; + PangoRectangle pango_pos; + + g_return_if_fail (ATK_IS_GOBJECT_ACCESSIBLE(text)); + obj = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (text)); + if (obj == NULL) + return; + g_return_if_fail (E_IS_TEXT (obj)); + etext = E_TEXT(obj); + canvas = GNOME_CANVAS_ITEM(etext)->canvas; + widget = GTK_WIDGET(canvas); + window = widget->window; + gdk_window_get_origin (window, &x_widget, &y_widget); + + pango_layout_index_to_pos (etext->layout, offset, &pango_pos); + pango_pos.x = PANGO_PIXELS (pango_pos.x); + pango_pos.y = PANGO_PIXELS (pango_pos.y); + pango_pos.width = (pango_pos.width + PANGO_SCALE / 2) / PANGO_SCALE; + pango_pos.height = (pango_pos.height + PANGO_SCALE / 2) / PANGO_SCALE; + + *x = pango_pos.x + x_widget; + *y = pango_pos.y + y_widget; + + *width = pango_pos.width; + *height = pango_pos.height; + + if (etext->draw_borders) { + *x += 3; /*BORDER_INDENT;*/ + *y += 3; /*BORDER_INDENT;*/ + } + + *x += etext->xofs; + *y += etext->yofs; + + if (etext->editing) { + *x -= etext->xofs_edit; + *y -= etext->yofs_edit; + } + + *x += etext->cx; + *y += etext->cy; + + if (coords == ATK_XY_WINDOW) { + window = gdk_window_get_toplevel (window); + gdk_window_get_origin (window, &x_window, &y_window); + *x -= x_window; + *y -= y_window; + } + else if (coords == ATK_XY_SCREEN) { + } + else { + *x = 0; + *y = 0; + *height = 0; + *width = 0; + } +} + + +static gint +et_get_character_count (AtkText *text) +{ + const char *full_text = et_get_full_text (text); + + return g_utf8_strlen (full_text, -1); +} + + +static gint +et_get_offset_at_point (AtkText *text, + gint x, + gint y, + AtkCoordType coords) +{ + GObject *obj; + EText *etext; + GnomeCanvas *canvas; + gint x_widget, y_widget, x_window, y_window; + GdkWindow *window; + GtkWidget *widget; + int index; + int trailing; + + g_return_val_if_fail (ATK_IS_GOBJECT_ACCESSIBLE(text), -1); + obj = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (text)); + if (obj == NULL) + return -1; + g_return_val_if_fail (E_IS_TEXT (obj), -1); + etext = E_TEXT(obj); + canvas = GNOME_CANVAS_ITEM(etext)->canvas; + widget = GTK_WIDGET(canvas); + window = widget->window; + gdk_window_get_origin (window, &x_widget, &y_widget); + + if (coords == ATK_XY_SCREEN) { + x = x - x_widget; + y = y - y_widget; + } + else if (coords == ATK_XY_WINDOW) { + window = gdk_window_get_toplevel (window); + gdk_window_get_origin (window, &x_window, &y_window); + x = x - x_widget + x_window; + y = y - y_widget + y_window; + } + else + return -1; + + if (etext->draw_borders) { + x -= 3; /*BORDER_INDENT;*/ + y -= 3; /*BORDER_INDENT;*/ + } + + x -= etext->xofs; + y -= etext->yofs; + + if (etext->editing) { + x += etext->xofs_edit; + y += etext->yofs_edit; + } + + x -= etext->cx; + y -= etext->cy; + + pango_layout_xy_to_index (etext->layout, + x * PANGO_SCALE - PANGO_SCALE / 2, + y * PANGO_SCALE - PANGO_SCALE / 2, + &index, + &trailing); + + return g_utf8_pointer_to_offset (etext->text, etext->text + index + trailing); +} + + +static gint +et_get_n_selections (AtkText *text) +{ + EText *etext = E_TEXT (atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (text))); + if (etext->selection_start != + etext->selection_end) + return 1; + return 0; +} + + +static gchar* +et_get_selection (AtkText *text, + gint selection_num, + gint *start_offset, + gint *end_offset) +{ + gint start, end, real_start, real_end, len; + EText *etext; + if (selection_num == 0) { + const char *full_text = et_get_full_text (text); + if (full_text == NULL) + return NULL; + len = g_utf8_strlen (full_text, -1); + etext = E_TEXT (atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (text))); + start = MIN (etext->selection_start, etext->selection_end); + end = MAX (etext->selection_start, etext->selection_end); + start = MIN (MAX (0, start), len); + end = MIN (MAX (0, end), len); + if (start != end) { + if (start_offset) + *start_offset = start; + if (end_offset) + *end_offset = end; + real_start = g_utf8_offset_to_pointer (full_text, start) - full_text; + real_end = g_utf8_offset_to_pointer (full_text, end) - full_text; + return g_strndup (full_text + real_start, real_end - real_start); + } + } + + return NULL; +} + + +static gboolean +et_add_selection (AtkText *text, + gint start_offset, + gint end_offset) +{ + GObject *obj; + EText *etext; + + g_return_val_if_fail (ATK_IS_GOBJECT_ACCESSIBLE (text), FALSE); + obj = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (text)); + if (obj == NULL) + return FALSE; + g_return_val_if_fail (E_IS_TEXT (obj), FALSE); + etext = E_TEXT (obj); + + g_return_val_if_fail (start_offset >= 0, FALSE); + g_return_val_if_fail (start_offset >= -1, FALSE); + if (end_offset == -1) + end_offset = et_get_character_count (text); + + if (start_offset != end_offset) { + gint real_start, real_end; + real_start = MIN (start_offset, end_offset); + real_end = MAX (start_offset, end_offset); + etext->selection_start = real_start; + etext->selection_end = real_end; + + gnome_canvas_item_grab_focus (GNOME_CANVAS_ITEM (etext)); + gnome_canvas_item_request_update (GNOME_CANVAS_ITEM (etext)); + + g_signal_emit_by_name (ATK_OBJECT (text), "text_selection_changed"); + + return TRUE; + } + + return FALSE; +} + + +static gboolean +et_remove_selection (AtkText *text, + gint selection_num) +{ + GObject *obj; + EText *etext; + + g_return_val_if_fail (ATK_IS_GOBJECT_ACCESSIBLE (text), FALSE); + obj = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (text)); + if (obj == NULL) + return FALSE; + g_return_val_if_fail (E_IS_TEXT (obj), FALSE); + etext = E_TEXT (obj); + + if (selection_num == 0 + && etext->selection_start != etext->selection_end) { + etext->selection_end = etext->selection_start; + g_signal_emit_by_name (ATK_OBJECT(text), "text_selection_changed"); + return TRUE; + } + + return FALSE; +} + + +static gboolean +et_set_selection (AtkText *text, + gint selection_num, + gint start_offset, + gint end_offset) +{ + GObject *obj; + + g_return_val_if_fail (ATK_IS_GOBJECT_ACCESSIBLE (text), FALSE); + obj = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (text)); + if (obj == NULL) + return FALSE; + g_return_val_if_fail (E_IS_TEXT (obj), FALSE); + if (selection_num == 0) + return et_add_selection (text, start_offset, end_offset); + return FALSE; +} + + +static gboolean +et_set_caret_offset (AtkText *text, + gint offset) +{ + GObject *obj; + EText *etext; + + g_return_val_if_fail (ATK_IS_GOBJECT_ACCESSIBLE (text), FALSE); + obj = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (text)); + if (obj == NULL) + return FALSE; + + g_return_val_if_fail (E_IS_TEXT (obj), FALSE); + etext = E_TEXT (obj); + + if (offset < -1) + return FALSE; + else { + ETextEventProcessorCommand command; + + if (offset == -1) + offset = et_get_character_count (text); + + command.action = E_TEP_MOVE; + command.position = E_TEP_VALUE; + command.value = offset; + command.time = GDK_CURRENT_TIME; + g_signal_emit_by_name (etext->tep, "command", &command); + return TRUE; + } +} + +static gboolean +et_set_run_attributes (AtkEditableText *text, + AtkAttributeSet *attrib_set, + gint start_offset, + gint end_offset) +{ + /* Unimplemented */ + return FALSE; +} + +static void +et_set_text_contents (AtkEditableText *text, + const gchar *string) +{ + et_set_full_text (text, string); +} + +static void +et_insert_text (AtkEditableText *text, + const gchar *string, + gint length, + gint *position) +{ + /* Utf8 unimplemented */ + char *result; + + const char *full_text = et_get_full_text (ATK_TEXT (text)); + if (full_text == NULL) + return; + + result = g_strdup_printf ("%.*s%.*s%s", *position, full_text, length, string, full_text + *position); + + et_set_full_text (text, result); + + *position += length; + + g_free (result); +} + +static void +et_copy_text (AtkEditableText *text, + gint start_pos, + gint end_pos) +{ + GObject *obj; + EText *etext; + + g_return_if_fail (ATK_IS_GOBJECT_ACCESSIBLE (text)); + obj = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (text)); + if (obj == NULL) + return; + + g_return_if_fail (E_IS_TEXT (obj)); + etext = E_TEXT (obj); + + if (start_pos != end_pos) { + etext->selection_start = start_pos; + etext->selection_end = end_pos; + e_text_copy_clipboard (etext); + } +} + +static void +et_delete_text (AtkEditableText *text, + gint start_pos, + gint end_pos) +{ + GObject *obj; + EText *etext; + + g_return_if_fail (ATK_IS_GOBJECT_ACCESSIBLE(text)); + obj = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (text)); + if (obj == NULL) + return; + + g_return_if_fail (E_IS_TEXT (obj)); + etext = E_TEXT (obj); + + etext->selection_start = start_pos; + etext->selection_end = end_pos; + + e_text_delete_selection (etext); +} + +static void +et_cut_text (AtkEditableText *text, + gint start_pos, + gint end_pos) +{ + et_copy_text (text, start_pos, end_pos); + et_delete_text (text, start_pos, end_pos); +} + +static void +et_paste_text (AtkEditableText *text, + gint position) +{ + GObject *obj; + EText *etext; + + g_return_if_fail (ATK_IS_GOBJECT_ACCESSIBLE (text)); + obj = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (text)); + if (obj == NULL) + return; + + g_return_if_fail (E_IS_TEXT (obj)); + etext = E_TEXT (obj); + + g_object_set (etext, "cursor_pos", position, NULL); + e_text_paste_clipboard (etext); +} + +static void +et_atk_component_iface_init (AtkComponentIface *iface) +{ + iface->get_extents = et_get_extents; +} + +static void +et_atk_text_iface_init (AtkTextIface *iface) +{ + iface->get_text = et_get_text; + iface->get_text_after_offset = et_get_text_after_offset; + iface->get_text_at_offset = et_get_text_at_offset; + iface->get_character_at_offset = et_get_character_at_offset; + iface->get_text_before_offset = et_get_text_before_offset; + iface->get_caret_offset = et_get_caret_offset; + iface->get_run_attributes = et_get_run_attributes; + iface->get_default_attributes = et_get_default_attributes; + iface->get_character_extents = et_get_character_extents; + iface->get_character_count = et_get_character_count; + iface->get_offset_at_point = et_get_offset_at_point; + iface->get_n_selections = et_get_n_selections; + iface->get_selection = et_get_selection; + iface->add_selection = et_add_selection; + iface->remove_selection = et_remove_selection; + iface->set_selection = et_set_selection; + iface->set_caret_offset = et_set_caret_offset; +} + +static void +et_atk_editable_text_iface_init (AtkEditableTextIface *iface) +{ + iface->set_run_attributes = et_set_run_attributes; + iface->set_text_contents = et_set_text_contents; + iface->insert_text = et_insert_text; + iface->copy_text = et_copy_text; + iface->cut_text = et_cut_text; + iface->delete_text = et_delete_text; + iface->paste_text = et_paste_text; +} + +static void +_et_reposition_cb (ETextModel *model, + ETextModelReposFn fn, + gpointer repos_data, + gpointer user_data) +{ + AtkObject *accessible; + AtkText *text; + + accessible = ATK_OBJECT (user_data); + text = ATK_TEXT (accessible); + + if (fn == e_repos_delete_shift) { + EReposDeleteShift *info = (EReposDeleteShift *) repos_data; + g_signal_emit_by_name (text, "text-changed::delete", info->pos, info->len); + } + else if (fn == e_repos_insert_shift) { + EReposInsertShift *info = (EReposInsertShift *) repos_data; + g_signal_emit_by_name (text, "text-changed::insert", info->pos, info->len); + } +} + +static void +_et_command_cb (ETextEventProcessor *tep, + ETextEventProcessorCommand *command, + gpointer user_data) +{ + AtkObject *accessible; + AtkText *text; + + accessible = ATK_OBJECT (user_data); + text = ATK_TEXT (accessible); + + switch (command->action) { + case E_TEP_MOVE: + g_signal_emit_by_name (text, "text-caret-moved", et_get_caret_offset (text)); + break; + case E_TEP_SELECT: + g_signal_emit_by_name (text, "text-selection-changed"); + break; + default: + break; + } +} + +static void +et_real_initialize (AtkObject *obj, + gpointer data) +{ + EText *etext; + + ATK_OBJECT_CLASS (parent_class)->initialize (obj, data); + + g_return_if_fail (GAL_A11Y_IS_E_TEXT (obj)); + g_return_if_fail (E_IS_TEXT (data)); + + etext = E_TEXT (data); + + /* Set up signal callbacks */ + g_signal_connect (etext->model, "reposition", + G_CALLBACK (_et_reposition_cb), obj); + + if (etext->tep) + g_signal_connect_after (etext->tep, "command", + (GCallback) _et_command_cb, obj); + + obj->role = ATK_ROLE_TEXT; +} + +static void +et_class_init (GalA11yETextClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + AtkObjectClass *atk_class = ATK_OBJECT_CLASS (klass); + + quark_accessible_object = g_quark_from_static_string ("gtk-accessible-object"); + parent_class = g_type_class_ref (PARENT_TYPE); + component_parent_iface = g_type_interface_peek(parent_class, ATK_TYPE_COMPONENT); + object_class->dispose = et_dispose; + atk_class->initialize = et_real_initialize; +} + +static void +et_init (GalA11yEText *a11y) +{ +#if 0 + GalA11yETextPrivate *priv; + + priv = GET_PRIVATE (a11y); +#endif +} + +/** + * gal_a11y_e_text_get_type: + * @void: + * + * Registers the &GalA11yEText class if necessary, and returns the type ID + * associated to it. + * + * Return value: The type ID of the &GalA11yEText class. + **/ +GType +gal_a11y_e_text_get_type (void) +{ + static GType type = 0; + + if (!type) { + AtkObjectFactory *factory; + + GTypeInfo info = { + sizeof (GalA11yETextClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) et_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (GalA11yEText), + 0, + (GInstanceInitFunc) et_init, + NULL /* value_text */ + }; + + static const GInterfaceInfo atk_component_info = { + (GInterfaceInitFunc) et_atk_component_iface_init, + (GInterfaceFinalizeFunc) NULL, + NULL + }; + static const GInterfaceInfo atk_text_info = { + (GInterfaceInitFunc) et_atk_text_iface_init, + (GInterfaceFinalizeFunc) NULL, + NULL + }; + static const GInterfaceInfo atk_editable_text_info = { + (GInterfaceInitFunc) et_atk_editable_text_iface_init, + (GInterfaceFinalizeFunc) NULL, + NULL + }; + + factory = atk_registry_get_factory (atk_get_default_registry (), GNOME_TYPE_CANVAS_ITEM); + parent_type = atk_object_factory_get_accessible_type (factory); + + type = gal_a11y_type_register_static_with_private (PARENT_TYPE, "GalA11yEText", &info, 0, + sizeof (GalA11yETextPrivate), &priv_offset); + + g_type_add_interface_static (type, ATK_TYPE_COMPONENT, &atk_component_info); + g_type_add_interface_static (type, ATK_TYPE_TEXT, &atk_text_info); + g_type_add_interface_static (type, ATK_TYPE_EDITABLE_TEXT, &atk_editable_text_info); + } + + return type; +} + +void +gal_a11y_e_text_init (void) +{ + if (atk_get_root ()) + atk_registry_set_factory_type (atk_get_default_registry (), + E_TYPE_TEXT, + gal_a11y_e_text_factory_get_type ()); + +} + diff --git a/widgets/text/a11y/gal-a11y-e-text.h b/widgets/text/a11y/gal-a11y-e-text.h new file mode 100644 index 0000000000..5cebd0ff83 --- /dev/null +++ b/widgets/text/a11y/gal-a11y-e-text.h @@ -0,0 +1,57 @@ +/* + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Authors: + * Christopher James Lahey <clahey@ximian.com> + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifndef __GAL_A11Y_E_TEXT_H__ +#define __GAL_A11Y_E_TEXT_H__ + +#include <glib-object.h> +#include <table/e-table-item.h> + +#define GAL_A11Y_TYPE_E_TEXT (gal_a11y_e_text_get_type ()) +#define GAL_A11Y_E_TEXT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GAL_A11Y_TYPE_E_TEXT, GalA11yEText)) +#define GAL_A11Y_E_TEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GAL_A11Y_TYPE_E_TEXT, GalA11yETextClass)) +#define GAL_A11Y_IS_E_TEXT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GAL_A11Y_TYPE_E_TEXT)) +#define GAL_A11Y_IS_E_TEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GAL_A11Y_TYPE_E_TEXT)) + +typedef struct _GalA11yEText GalA11yEText; +typedef struct _GalA11yETextClass GalA11yETextClass; +typedef struct _GalA11yETextPrivate GalA11yETextPrivate; + +/* This struct should actually be larger as this isn't what we derive from. + * The GalA11yETextPrivate comes right after the parent class structure. + **/ +struct _GalA11yEText { + AtkObject object; +}; + +struct _GalA11yETextClass { + AtkObject parent_class; +}; + + +/* Standard Glib function */ +GType gal_a11y_e_text_get_type (void); + +void gal_a11y_e_text_init (void); + +#endif /* ! __GAL_A11Y_E_TEXT_H__ */ diff --git a/widgets/misc/e-reflow-model.c b/widgets/text/e-reflow-model.c index eae3d43324..eae3d43324 100644 --- a/widgets/misc/e-reflow-model.c +++ b/widgets/text/e-reflow-model.c diff --git a/widgets/misc/e-reflow-model.h b/widgets/text/e-reflow-model.h index 7482e5079f..7482e5079f 100644 --- a/widgets/misc/e-reflow-model.h +++ b/widgets/text/e-reflow-model.h diff --git a/widgets/misc/e-reflow.c b/widgets/text/e-reflow.c index f51a502a83..c17b970a23 100644 --- a/widgets/misc/e-reflow.c +++ b/widgets/text/e-reflow.c @@ -30,12 +30,12 @@ #include "text/e-text.h" #include <glib/gi18n.h> #include "e-util/e-util.h" -#include "misc/e-unicode.h" +#include "e-util/e-unicode.h" -#include "e-canvas.h" -#include "e-canvas-utils.h" +#include "misc/e-canvas.h" +#include "misc/e-canvas-utils.h" #include "e-reflow.h" -#include "e-selection-model-simple.h" +#include "misc/e-selection-model-simple.h" static gboolean e_reflow_event (GnomeCanvasItem *item, GdkEvent *event); static void e_reflow_realize (GnomeCanvasItem *item); diff --git a/widgets/misc/e-reflow.h b/widgets/text/e-reflow.h index 6d67369209..afdc9edb67 100644 --- a/widgets/misc/e-reflow.h +++ b/widgets/text/e-reflow.h @@ -24,7 +24,7 @@ #define __E_REFLOW_H__ #include <libgnomecanvas/gnome-canvas.h> -#include <misc/e-reflow-model.h> +#include <text/e-reflow-model.h> #include <misc/e-selection-model.h> #include <e-util/e-sorter-array.h> diff --git a/widgets/text/e-text.c b/widgets/text/e-text.c index 0890b46243..3ce0065210 100644 --- a/widgets/text/e-text.c +++ b/widgets/text/e-text.c @@ -46,10 +46,10 @@ #include <gtk/gtk.h> #include <libgnomecanvas/gnome-canvas-rect-ellipse.h> -#include "a11y/e-text/gal-a11y-e-text.h" +#include "a11y/gal-a11y-e-text.h" #include "misc/e-canvas.h" #include "misc/e-canvas-utils.h" -#include "misc/e-unicode.h" +#include "e-util/e-unicode.h" #include <glib/gi18n.h> #include "e-util/e-text-event-processor-emacs-like.h" #include "e-util/e-util.h" |