Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBruno Coudoin <bruno.coudoin@free.fr>2009-10-16 20:09:33 (GMT)
committer Bruno Coudoin <bruno.coudoin@free.fr>2009-10-25 20:49:32 (GMT)
commitb21e3513cd4aa51b402429da99e1673e9516c9eb (patch)
tree07fa38a965b755b646237453e3be2aa644ee16ab
parent5bbcc313789989c8d32ab05ac15007de9c6a1547 (diff)
Now wordprocessor activity has the focus into the editing part by default.
-rw-r--r--src/boards/wordprocessor.c1151
-rw-r--r--src/wordprocessor-activity/wordprocessor.c4
2 files changed, 1154 insertions, 1 deletions
diff --git a/src/boards/wordprocessor.c b/src/boards/wordprocessor.c
new file mode 100644
index 0000000..c6b1d28
--- /dev/null
+++ b/src/boards/wordprocessor.c
@@ -0,0 +1,1151 @@
+/* gcompris - wordprocessor.c
+ *
+ * Copyright (C) 2006-2007 Bruno Coudoin
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <string.h>
+#include <glib/gstdio.h>
+#include <libxml/HTMLparser.h>
+
+#include "gcompris/gcompris.h"
+
+/*
+ * Predefined styles
+ * -----------------
+ */
+typedef struct {
+ gchar *name;
+ gchar *font;
+ PangoWeight weight;
+ GtkJustification justification;
+ gint left_margin;
+ gint pixels_above_lines;
+ gint pixels_below_lines;
+} style_t;
+
+#define NUMBER_OF_STYLE 4 /* h1 h2 h3 p */
+
+static GtkTextTag *tag_list[NUMBER_OF_STYLE];
+
+
+/*
+ * The document styles
+ */
+typedef struct {
+ gchar *name;
+ style_t style[NUMBER_OF_STYLE];
+} doctype_t;
+
+doctype_t type_normal =
+ {
+ .name = N_("Research"),
+ .style = {
+ { "h1", "Serif 30", PANGO_WEIGHT_ULTRABOLD, GTK_JUSTIFY_CENTER, 0, 40, 20 },
+ { "h2", "Serif 26", PANGO_WEIGHT_BOLD, GTK_JUSTIFY_LEFT, 0, 30, 15 },
+ { "h3", "Serif 20", PANGO_WEIGHT_SEMIBOLD, GTK_JUSTIFY_LEFT, 15, 20, 12 },
+ { "p", "Serif 16", PANGO_WEIGHT_NORMAL, GTK_JUSTIFY_LEFT, 30, 3, 3 }
+ }
+ };
+
+doctype_t type_letter =
+ {
+ .name = N_("Sentimental"),
+ .style = {
+ { "h1", "Serif 26", PANGO_WEIGHT_ULTRABOLD, GTK_JUSTIFY_CENTER, 0, 40, 20 },
+ { "h2", "Serif 20", PANGO_WEIGHT_BOLD, GTK_JUSTIFY_LEFT, 0, 30, 15 },
+ { "h3", "Serif 16", PANGO_WEIGHT_SEMIBOLD, GTK_JUSTIFY_LEFT, 10, 20, 12 },
+ { "p", "Serif 14", PANGO_WEIGHT_NORMAL, GTK_JUSTIFY_LEFT, 30, 3, 3 }
+ },
+ };
+
+doctype_t type_small =
+ {
+ .name = N_("Official"),
+ .style = {
+ { "h1", "Serif 18", PANGO_WEIGHT_ULTRABOLD, GTK_JUSTIFY_CENTER, 0, 40, 20 },
+ { "h2", "Serif 16", PANGO_WEIGHT_BOLD, GTK_JUSTIFY_LEFT, 0, 30, 15 },
+ { "h3", "Serif 14", PANGO_WEIGHT_SEMIBOLD, GTK_JUSTIFY_LEFT, 10, 20, 12 },
+ { "p", "Serif 12", PANGO_WEIGHT_NORMAL, GTK_JUSTIFY_LEFT, 30, 3, 3 }
+ },
+ };
+
+doctype_t type_text =
+ {
+ .name = N_("Text"),
+ .style = {
+ { "h1", "Serif 12", PANGO_WEIGHT_ULTRABOLD, GTK_JUSTIFY_CENTER, 0, 40, 20 },
+ { "h2", "Serif 12", PANGO_WEIGHT_BOLD, GTK_JUSTIFY_LEFT, 0, 30, 15 },
+ { "h3", "Serif 12", PANGO_WEIGHT_SEMIBOLD, GTK_JUSTIFY_LEFT, 15, 20, 12 },
+ { "p", "Serif 12", PANGO_WEIGHT_NORMAL, GTK_JUSTIFY_LEFT, 30, 3, 3 }
+ },
+ };
+
+doctype_t type_big =
+ {
+ .name = N_("Flyer"),
+ .style = {
+ { "h1", "Serif 34", PANGO_WEIGHT_ULTRABOLD, GTK_JUSTIFY_CENTER, 0, 40, 20 },
+ { "h2", "Serif 30", PANGO_WEIGHT_BOLD, GTK_JUSTIFY_LEFT, 0, 30, 15 },
+ { "h3", "Serif 26", PANGO_WEIGHT_SEMIBOLD, GTK_JUSTIFY_LEFT, 15, 20, 12 },
+ { "p", "Serif 18", PANGO_WEIGHT_NORMAL, GTK_JUSTIFY_LEFT, 30, 3, 3 }
+ },
+ };
+#define NUMBER_OF_DOCTYPE 5
+static doctype_t *doctype_list[NUMBER_OF_DOCTYPE];
+
+/*
+ * The color styles
+ */
+#define NUMBER_OF_COLOR_STYLE 4
+static gchar *color_style_list[NUMBER_OF_COLOR_STYLE][NUMBER_OF_STYLE+1] =
+{
+ {N_("Spring"), "red", "blue", "lightblue", "black"},
+ {N_("Summer"), "DeepPink", "HotPink", "MediumOrchid", "black"},
+ {N_("Autumn"), "blue", "red", "lightblue", "black"},
+ {N_("Winter"), "black", "black", "black", "black"},
+};
+
+static GcomprisBoard *gcomprisBoard = NULL;
+static gboolean board_paused = TRUE;
+static GtkWidget *gtk_combo_styles = NULL;
+static GtkWidget *gtk_combo_colors = NULL;
+static GtkWidget *gtk_button_style[NUMBER_OF_STYLE];
+static GtkWidget *sw = NULL;
+
+static void start_board (GcomprisBoard *agcomprisBoard);
+static void pause_board (gboolean pause);
+static void end_board (void);
+static gboolean is_our_board (GcomprisBoard *gcomprisBoard);
+static void set_level (guint level);
+static gboolean key_release_event (GtkWidget *text_view,
+ GdkEventKey *event);
+
+static GnomeCanvasGroup *boardRootItem = NULL;
+
+static GnomeCanvasItem *wordprocessor_create(void);
+static void wordprocessor_destroy_all_items(void);
+static void item_event(GtkWidget *item, gchar *data);
+static int display_style_buttons(GnomeCanvasGroup *boardRootItem,
+ int x,
+ int y);
+static void create_tags (GtkTextBuffer *buffer, doctype_t *doctype);
+static void set_default_tag (GtkTextBuffer *buffer, GtkTextTag *tag);
+static void display_style_selector(GnomeCanvasGroup *boardRootItem, double y);
+static void display_color_style_selector(GnomeCanvasGroup *boardRootItem, double y);
+static void item_event_style_selection (GtkComboBox *widget, void *data);
+static void item_event_color_style_selection (GtkComboBox *widget, void *data);
+static gint save_event(GnomeCanvasItem *item, GdkEvent *event,
+ void *unused);
+static gint load_event(GnomeCanvasItem *item, GdkEvent *event,
+ void *unused);
+static int get_style_index(gchar *style);
+static int get_style_current_index();
+static gint get_color_style_index(gchar *color_style);
+static gint get_color_style_current_index();
+static GtkTextTag *get_tag_from_name(gchar *name);
+static void apply_style(int style_index);
+static void apply_color_style(int style_index);
+
+#define word_area_x1 120
+#define word_area_y1 20
+#define word_area_width 650
+#define word_area_height 480
+
+#define combo_style_x1 5
+#define combo_style_width 105
+
+static GtkTextBuffer *buffer;
+static GtkWidget *view;
+GtkTextTag *selected_tag;
+
+/* Description of this plugin */
+static BoardPlugin menu_bp =
+ {
+ NULL,
+ NULL,
+ "Wordprocessor",
+ "A basic word processor",
+ "Bruno Coudoin <bruno.coudoin@free.fr>",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ start_board,
+ pause_board,
+ end_board,
+ is_our_board,
+ NULL,
+ NULL,
+ set_level,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ };
+
+/*
+ * Main entry point mandatory for each Gcompris's game
+ * ---------------------------------------------------
+ *
+ */
+
+GET_BPLUGIN_INFO(wordprocessor)
+
+/*
+ * in : boolean TRUE = PAUSE : FALSE = CONTINUE
+ *
+ */
+static void pause_board (gboolean pause)
+{
+ int i;
+
+ if(gcomprisBoard==NULL)
+ return;
+
+ /* Widgets don't like being overlapped */
+ if(pause)
+ {
+ gtk_widget_hide(GTK_WIDGET(sw));
+ gtk_widget_hide(GTK_WIDGET(gtk_combo_styles));
+ gtk_widget_hide(GTK_WIDGET(gtk_combo_colors));
+ for(i=0; i<NUMBER_OF_STYLE; i++)
+ gtk_widget_hide(gtk_button_style[i]);
+ }
+ else
+ {
+ gtk_widget_show(GTK_WIDGET(sw));
+ gtk_widget_show(GTK_WIDGET(gtk_combo_styles));
+ gtk_widget_show(GTK_WIDGET(gtk_combo_colors));
+ for(i=0; i<NUMBER_OF_STYLE; i++)
+ gtk_widget_show(gtk_button_style[i]);
+ }
+
+ board_paused = pause;
+}
+
+/*
+ */
+static void start_board (GcomprisBoard *agcomprisBoard)
+{
+
+ if(agcomprisBoard!=NULL)
+ {
+ gchar *img;
+
+ gcomprisBoard=agcomprisBoard;
+ gcomprisBoard->level=1;
+ gcomprisBoard->maxlevel=1;
+ gcomprisBoard->sublevel=1;
+ gcomprisBoard->number_of_sublevel=1; /* Go to next level after this number of 'play' */
+ gc_bar_set(0);
+
+ img = gc_skin_image_get("gcompris-shapebg.jpg");
+ gc_set_background(gnome_canvas_root(gcomprisBoard->canvas),
+ img);
+ g_free(img);
+
+ wordprocessor_create();
+
+ pause_board(FALSE);
+
+ }
+}
+/* ======================================= */
+static void end_board ()
+{
+ if(gcomprisBoard!=NULL)
+ {
+ pause_board(TRUE);
+ wordprocessor_destroy_all_items();
+ }
+ gcomprisBoard = NULL;
+}
+
+/* ======================================= */
+static void set_level (guint level)
+{
+}
+/* ======================================= */
+static gboolean is_our_board (GcomprisBoard *gcomprisBoard)
+{
+ if (gcomprisBoard)
+ {
+ if(g_strcasecmp(gcomprisBoard->type, "wordprocessor")==0)
+ {
+ /* Set the plugin entry */
+ gcomprisBoard->plugin=&menu_bp;
+
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+/*-------------------------------------------------------------------------------*/
+/*-------------------------------------------------------------------------------*/
+/* ==================================== */
+/* Destroy all the items */
+static void wordprocessor_destroy_all_items()
+{
+ if(boardRootItem!=NULL)
+ gtk_object_destroy (GTK_OBJECT(boardRootItem));
+
+ boardRootItem = NULL;
+}
+/* ==================================== */
+static GnomeCanvasItem *wordprocessor_create()
+{
+ GnomeCanvasItem *item = NULL;
+ GdkPixbuf *pixmap;
+ double y;
+
+ boardRootItem = GNOME_CANVAS_GROUP(
+ gnome_canvas_item_new (gnome_canvas_root(gcomprisBoard->canvas),
+ gnome_canvas_group_get_type (),
+ "x", (double) 0,
+ "y", (double) 0,
+ NULL));
+
+ selected_tag = NULL;
+ view = gtk_text_view_new ();
+ gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (view), GTK_WRAP_WORD);
+ /* Change left margin throughout the widget */
+ gtk_text_view_set_left_margin (GTK_TEXT_VIEW (view), 1);
+ g_signal_connect (view, "key-release-event",
+ G_CALLBACK (key_release_event), NULL);
+
+ buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
+
+
+ sw = gtk_scrolled_window_new (NULL, NULL);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
+ GTK_POLICY_AUTOMATIC,
+ GTK_POLICY_ALWAYS);
+ gtk_container_add (GTK_CONTAINER (sw), view);
+
+ item = gnome_canvas_item_new (GNOME_CANVAS_GROUP(boardRootItem),
+ gnome_canvas_widget_get_type (),
+ "widget", GTK_WIDGET(sw),
+ "x", (double) word_area_x1,
+ "y", (double) word_area_y1,
+ "width", (double) word_area_width,
+ "height", (double) word_area_height,
+ "anchor", GTK_ANCHOR_NW,
+ "size_pixels", FALSE,
+ NULL);
+ gtk_widget_show(GTK_WIDGET(view));
+ gtk_widget_show(GTK_WIDGET(sw));
+
+ /*
+ * Create the default style tags
+ */
+ doctype_list[0] = &type_text;
+ doctype_list[1] = &type_normal;
+ doctype_list[2] = &type_letter;
+ doctype_list[3] = &type_small;
+ doctype_list[4] = &type_big;
+
+ y = 20.0;
+ /*
+ * The save button
+ */
+ pixmap = gc_skin_pixmap_load("draw/tool-save.png");
+ item = \
+ gnome_canvas_item_new (boardRootItem,
+ gnome_canvas_pixbuf_get_type(),
+ "pixbuf", pixmap,
+ "x", 17.0,
+ "y", y,
+ "anchor", GTK_ANCHOR_NW,
+ NULL);
+ gdk_pixbuf_unref(pixmap);
+ gtk_signal_connect(GTK_OBJECT(item), "event",
+ (GtkSignalFunc) save_event, buffer);
+ gtk_signal_connect(GTK_OBJECT(item), "event",
+ (GtkSignalFunc) gc_item_focus_event,
+ NULL);
+
+ /*
+ * The load button
+ */
+ pixmap = gc_skin_pixmap_load("draw/tool-load.png");
+ item = \
+ gnome_canvas_item_new (boardRootItem,
+ gnome_canvas_pixbuf_get_type(),
+ "pixbuf", pixmap,
+ "x", 60.0,
+ "y", y,
+ "anchor", GTK_ANCHOR_NW,
+ NULL);
+ gdk_pixbuf_unref(pixmap);
+ gtk_signal_connect(GTK_OBJECT(item), "event",
+ (GtkSignalFunc) load_event, buffer);
+ gtk_signal_connect(GTK_OBJECT(item), "event",
+ (GtkSignalFunc) gc_item_focus_event,
+ NULL);
+
+ y += 45;
+ /*
+ * Display the style buttons
+ */
+ y = display_style_buttons(boardRootItem,
+ 20.0,
+ y);
+
+ y += 20;
+ display_style_selector(boardRootItem, y);
+
+ y += 40;
+ display_color_style_selector(boardRootItem, y);
+
+ /* Now we can create the tags */
+ create_tags(buffer, doctype_list[0]);
+
+ gtk_widget_grab_focus(view);
+
+ return NULL;
+}
+
+/*
+ * Display the style buttons
+ *
+ * \return the new y coordinate
+ */
+static int
+display_style_buttons(GnomeCanvasGroup *boardRootItem,
+ int x,
+ int y)
+{
+ int offset_y = 40;
+ int i = 0;
+ static gchar *styles_tab[] = { N_("Title"), "h1",
+ N_("Heading 1"), "h2",
+ N_("Heading 2"), "h3",
+ N_("Text"), "p",
+ NULL, NULL };
+
+ while(styles_tab[i*2])
+ {
+ gtk_button_style[i] = gtk_button_new_with_label(gettext(styles_tab[i*2]));
+
+ gnome_canvas_item_new (boardRootItem,
+ gnome_canvas_widget_get_type (),
+ "widget", GTK_WIDGET(gtk_button_style[i]),
+ "x", (double) combo_style_x1,
+ "y", (double) y,
+ "width", (double) combo_style_width,
+ "height", 35.0,
+ "anchor", GTK_ANCHOR_NW,
+ "size_pixels", FALSE,
+ NULL);
+
+ gtk_signal_connect(GTK_OBJECT(gtk_button_style[i]), "pressed",
+ (GtkSignalFunc)item_event, styles_tab[i*2+1] );
+
+ y += offset_y;
+
+ i++;
+ }
+
+ return(y);
+}
+
+/* \brief callback on a style button (h1, h2, h3, p)
+ *
+ *
+ */
+static void
+item_event(GtkWidget *button, gchar *data)
+{
+ GtkTextIter iter_start, iter_end;
+ gchar *current_style_name;
+
+ if(board_paused)
+ return;
+
+ current_style_name = (char *)data;
+
+ selected_tag = get_tag_from_name(current_style_name);
+ set_default_tag(buffer, selected_tag);
+
+ gtk_text_buffer_get_iter_at_mark(buffer,
+ &iter_start,
+ gtk_text_buffer_get_insert (buffer));
+ gtk_text_iter_set_line_offset(&iter_start, 0);
+
+ iter_end = iter_start;
+ gtk_text_iter_forward_to_line_end(&iter_end);
+
+ gtk_text_buffer_remove_all_tags(buffer,
+ &iter_start,
+ &iter_end);
+
+ gtk_text_buffer_apply_tag_by_name(buffer,
+ current_style_name,
+ &iter_start,
+ &iter_end);
+
+ gtk_widget_grab_focus(view);
+
+ return;
+}
+
+/* Create a bunch of tags. Note that it's also possible to
+ * create tags with gtk_text_tag_new() then add them to the
+ * tag table for the buffer, gtk_text_buffer_create_tag() is
+ * just a convenience function. Also note that you don't have
+ * to give tags a name; pass NULL for the name to create an
+ * anonymous tag.
+ *
+ * In any real app, another useful optimization would be to create
+ * a GtkTextTagTable in advance, and reuse the same tag table for
+ * all the buffers with the same tag set, instead of creating
+ * new copies of the same tags for every buffer.
+ *
+ * Tags are assigned default priorities in order of addition to the
+ * tag table. That is, tags created later that affect the same text
+ * property affected by an earlier tag will override the earlier
+ * tag. You can modify tag priorities with
+ * gtk_text_tag_set_priority().
+ */
+
+static void
+create_tags (GtkTextBuffer *buffer, doctype_t *doctype)
+{
+ gint i;
+ gint c = get_color_style_current_index();
+
+ for(i=0; i<NUMBER_OF_STYLE; i++)
+ {
+ GtkTextTag *tag;
+
+ tag = gtk_text_buffer_create_tag (buffer, doctype->style[i].name,
+ "weight", doctype->style[i].weight,
+ "font", doctype->style[i].font,
+ "justification", doctype->style[i].justification,
+ "left-margin", doctype->style[i].left_margin,
+ "pixels-above-lines", doctype->style[i].pixels_above_lines,
+ "pixels-below-lines", doctype->style[i].pixels_below_lines,
+ "foreground",color_style_list[c][i+1],
+ NULL);
+ tag_list[i] = tag;
+ g_object_set_data (G_OBJECT (tag), "style", &doctype->style[i]);
+ }
+
+ /* Point to the last style */
+ i--;
+
+ set_default_tag(buffer, tag_list[i]);
+}
+
+/*
+ * Set the default style
+ */
+static void
+set_default_tag (GtkTextBuffer *buffer, GtkTextTag *tag)
+{
+ PangoFontDescription *font_desc;
+ GdkColor *color = (GdkColor *)g_malloc(sizeof(GdkColor));
+ int val;
+ GtkJustification justification;
+
+ if(!tag)
+ return;
+
+ g_object_get (G_OBJECT (tag), "foreground-gdk", &color, NULL);
+ g_object_get (G_OBJECT (tag), "font-desc", &font_desc, NULL);
+
+ gtk_widget_modify_font (view, font_desc);
+ gtk_widget_modify_text (view, GTK_STATE_NORMAL, color);
+
+ g_object_get (G_OBJECT (tag), "left-margin", &val, NULL);
+ gtk_text_view_set_left_margin (GTK_TEXT_VIEW (view), val);
+
+ g_object_get (G_OBJECT (tag), "justification", &justification, NULL);
+ gtk_text_view_set_justification(GTK_TEXT_VIEW (view), justification);
+
+ g_object_get (G_OBJECT (tag), "pixels-below-lines", &val, NULL);
+ gtk_text_view_set_pixels_below_lines(GTK_TEXT_VIEW (view), val);
+
+ g_object_get (G_OBJECT (tag), "pixels-above-lines", &val, NULL);
+ gtk_text_view_set_pixels_above_lines(GTK_TEXT_VIEW (view), val);
+}
+
+static GtkTextTag *
+get_tag_from_name(gchar *tag_name)
+{
+ gint i;
+
+ for(i=0; i<NUMBER_OF_STYLE; i++)
+ {
+ gchar *name;
+ g_object_get(G_OBJECT (tag_list[i]), "name", &name, NULL);
+ if(strcmp(name, tag_name)==0)
+ return(tag_list[i]);
+
+ }
+ return(tag_list[i-1]);
+}
+
+/*
+ * Create the combo with the styles
+ * --------------------------------
+ */
+static void
+display_style_selector(GnomeCanvasGroup *boardRootItem, double y)
+{
+ int i = 0;
+
+ gtk_combo_styles = gtk_combo_box_new_text();
+
+ while (i < NUMBER_OF_DOCTYPE)
+ gtk_combo_box_append_text(GTK_COMBO_BOX(gtk_combo_styles),
+ gettext(doctype_list[i++]->name));
+
+ gnome_canvas_item_new (GNOME_CANVAS_GROUP(boardRootItem),
+ gnome_canvas_widget_get_type (),
+ "widget", GTK_WIDGET(gtk_combo_styles),
+ "x", (double) combo_style_x1,
+ "y", y,
+ "width", (double) combo_style_width,
+ "height", 35.0,
+ "anchor", GTK_ANCHOR_NW,
+ "size_pixels", FALSE,
+ NULL);
+
+ gtk_widget_show(GTK_WIDGET(gtk_combo_styles));
+ gtk_combo_box_set_active(GTK_COMBO_BOX(gtk_combo_styles), 0);
+
+ g_signal_connect(G_OBJECT(gtk_combo_styles),
+ "changed",
+ G_CALLBACK(item_event_style_selection),
+ NULL);
+}
+
+/*
+ * Create the combo with the color styles
+ * --------------------------------------
+ */
+static void
+display_color_style_selector(GnomeCanvasGroup *boardRootItem, double y)
+{
+ int i = 0;
+
+ gtk_combo_colors = gtk_combo_box_new_text();
+
+ while (i < NUMBER_OF_COLOR_STYLE)
+ gtk_combo_box_append_text(GTK_COMBO_BOX(gtk_combo_colors),
+ gettext(color_style_list[i++][0]));
+
+ gnome_canvas_item_new (GNOME_CANVAS_GROUP(boardRootItem),
+ gnome_canvas_widget_get_type (),
+ "widget", GTK_WIDGET(gtk_combo_colors),
+ "x", (double) combo_style_x1,
+ "y", y,
+ "width", (double) combo_style_width,
+ "height", 35.0,
+ "anchor", GTK_ANCHOR_NW,
+ "size_pixels", FALSE,
+ NULL);
+
+ gtk_widget_show(GTK_WIDGET(gtk_combo_colors));
+ gtk_combo_box_set_active(GTK_COMBO_BOX(gtk_combo_colors), 0);
+
+ g_signal_connect(G_OBJECT(gtk_combo_colors),
+ "changed",
+ G_CALLBACK(item_event_color_style_selection),
+ NULL);
+}
+
+static int
+get_style_index(gchar *style)
+{
+ int i;
+
+ /* Search the doctype */
+ for(i=0; i<NUMBER_OF_DOCTYPE; i++)
+ if(strcmp(gettext(doctype_list[i]->name), style)==0)
+ return(i);
+
+ return(0);
+}
+
+static int
+get_style_current_index()
+{
+ return( get_style_index(gtk_combo_box_get_active_text(GTK_COMBO_BOX(gtk_combo_styles))) );
+}
+
+static void
+apply_style(int style_index)
+{
+ int i = style_index;
+ int j;
+
+ for(j=0; j<NUMBER_OF_STYLE; j++)
+ {
+ g_object_set(tag_list[j],
+ "weight", doctype_list[i]->style[j].weight,
+ "font", doctype_list[i]->style[j].font,
+ "justification", doctype_list[i]->style[j].justification,
+ "left-margin", doctype_list[i]->style[j].left_margin,
+ "pixels-above-lines", doctype_list[i]->style[j].pixels_above_lines,
+ "pixels-below-lines", doctype_list[i]->style[j].pixels_below_lines,
+ NULL);
+ }
+}
+
+/* Set a new style from the combo box selection
+ *
+ */
+static void
+item_event_style_selection (GtkComboBox *widget,
+ void *data)
+{
+
+ apply_style(get_style_current_index());
+
+ gtk_widget_grab_focus(view);
+}
+
+static gint
+get_color_style_index(gchar *color_style)
+{
+ int i;
+
+ /* Search the color style */
+ for(i=0; i<NUMBER_OF_COLOR_STYLE; i++)
+ if(strcmp(gettext(color_style_list[i][0]), color_style)==0)
+ return(i);
+
+ return(0);
+}
+
+static gint
+get_color_style_current_index()
+{
+ return( get_color_style_index(gtk_combo_box_get_active_text(GTK_COMBO_BOX(gtk_combo_colors))) );
+}
+
+static void
+apply_color_style(int color_style_index)
+{
+ int i = color_style_index;
+ int j;
+
+ /* Change the color */
+ for(j=0; j<NUMBER_OF_STYLE; j++)
+ g_object_set(tag_list[j],
+ "foreground",color_style_list[i][j+1],
+ NULL);
+}
+
+/* Set a new color style from the combo box selection
+ *
+ */
+static void
+item_event_color_style_selection (GtkComboBox *widget,
+ void *data)
+{
+ apply_color_style(get_color_style_current_index());
+ gtk_widget_grab_focus(view);
+}
+
+
+/* Catch all typing events to apply the proper tags
+ *
+ */
+static gboolean
+key_release_event (GtkWidget *text_view,
+ GdkEventKey *event)
+{
+ GtkTextIter iter_start, iter_end;
+ GtkTextBuffer *buffer;
+
+ {
+ GSList *tags = NULL, *tagp = NULL;
+
+ buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (text_view));
+
+ gtk_text_buffer_get_iter_at_mark(buffer,
+ &iter_start,
+ gtk_text_buffer_get_insert (buffer));
+ gtk_text_iter_set_line_offset(&iter_start, 0);
+
+ iter_end = iter_start;
+ gtk_text_iter_forward_to_line_end(&iter_end);
+
+ tags = gtk_text_iter_get_tags (&iter_start);
+
+ if(g_slist_length(tags) == 0)
+ {
+ gtk_text_iter_backward_char (&iter_end);
+ tags = gtk_text_iter_get_tags (&iter_end);
+ gtk_text_iter_forward_char (&iter_end);
+ }
+
+ for (tagp = tags; tagp != NULL; tagp = tagp->next)
+ {
+ GtkTextTag *tag = tagp->data;
+ gchar *name;
+ g_object_get (G_OBJECT (tag), "name", &name, NULL);
+
+ set_default_tag(buffer, tag);
+ gtk_text_buffer_apply_tag_by_name(buffer,
+ name,
+ &iter_start,
+ &iter_end);
+ g_free(name);
+ selected_tag = NULL;
+ }
+
+ if (tags)
+ g_slist_free (tags);
+ else
+ {
+ /* Set the default style */
+ if(selected_tag)
+ {
+ set_default_tag(buffer, selected_tag);
+
+ gtk_text_buffer_apply_tag(buffer,
+ selected_tag,
+ &iter_start,
+ &iter_end);
+ }
+ else
+ {
+ set_default_tag(buffer, tag_list[NUMBER_OF_STYLE-1]);
+
+ gtk_text_buffer_apply_tag(buffer,
+ tag_list[NUMBER_OF_STYLE-1],
+ &iter_start,
+ &iter_end);
+ }
+ }
+ }
+
+ return FALSE;
+}
+
+// assumes UTF-8 or UTF-16 as encoding,
+static char *
+escape(char *input)
+{
+ gsize size = strlen(input)*6; /* 6 is the most increase we can get */
+ gchar *result = g_malloc(size);
+ int i;
+ int o = 0;
+
+ result[0] = '\0';
+
+ for(i = 0; i < strlen(input); i++)
+ {
+ char c = input[i];
+ if(c == '<')
+ o = g_strlcat(result, "&lt;", size);
+ else if(c == '>')
+ o = g_strlcat(result, "&gt;", size);
+ else if(c == '&')
+ o = g_strlcat(result, "&amp;", size);
+ else if(c == '"')
+ o = g_strlcat(result, "&quot;", size);
+ else if(c == '\'')
+ o = g_strlcat(result, "&apos;", size);
+ else
+ {
+ result[o++] = c;
+ result[o+1] = '\0';
+ }
+ }
+ g_free(input);
+ return result;
+}
+
+static void
+save_buffer(gchar *file, gchar *file_type)
+{
+ GtkTextIter iter_start, iter_end;
+ GSList *tags = NULL, *tagp = NULL;
+ gchar *tag_name;
+ FILE *filefd;
+ int style_index = get_style_current_index();
+ int color_index = get_color_style_current_index();
+
+ filefd = g_fopen(file, "w+");
+
+ /*
+ * XHTML Header
+ */
+ fprintf(filefd,
+ "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
+ "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n"
+ "<html xmlns=\"http://www.w3.org/1999/xhtml\">\n"
+ "<head>\n"
+ "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />\n"
+ "<meta http-equiv=\"GCompris-doctype\" content=\"%s\" />\n"
+ "<meta http-equiv=\"GCompris-color-style\" content=\"%s\" />\n"
+ "<title>GCompris</title>\n",
+ doctype_list[style_index]->name,
+ color_style_list[color_index][0]);
+
+ /*
+ * HTML Style
+ */
+ fprintf(filefd,
+ "<style type=\"text/css\">\n");
+
+ {
+ int i;
+ int font_size[NUMBER_OF_STYLE] = { 28, 22, 16, 12 };
+ char *align[NUMBER_OF_STYLE] = { "center", "left", "left", "justify" };
+ int left_margin[NUMBER_OF_STYLE] = { 0, 10, 20, 30 };
+
+ for(i=0; i<NUMBER_OF_STYLE; i++)
+ {
+ style_t style = doctype_list[style_index]->style[i];
+ fprintf(filefd,
+ "%s {\n"
+ " color : %s;\n"
+ " font-size : %dpx;\n"
+ " text-align : %s;\n"
+ " margin-left : %dpx;\n"
+ "}\n",
+ style.name,
+ color_style_list[color_index][i+1],
+ font_size[i],
+ align[i],
+ left_margin[i]);
+ }
+
+ }
+ fprintf(filefd,
+ "</style>\n"
+ "</head>\n");
+
+ /*
+ * Header end
+ */
+ fprintf(filefd,
+ "<body>\n");
+
+ gtk_text_buffer_get_iter_at_offset(buffer,
+ &iter_start,
+ 0);
+
+ do
+ {
+ iter_end = iter_start;
+ gtk_text_iter_forward_to_line_end(&iter_end);
+
+ if(gtk_text_iter_ends_line(&iter_start))
+ continue;
+
+ tags = gtk_text_iter_get_tags (&iter_start);
+ if(g_slist_length(tags) == 0)
+ {
+ gtk_text_iter_backward_char (&iter_end);
+ tags = gtk_text_iter_get_tags (&iter_end);
+ gtk_text_iter_forward_char (&iter_end);
+ }
+
+ tag_name = "p";
+ for (tagp = tags; tagp != NULL; tagp = tagp->next)
+ {
+ GtkTextTag *tag = tagp->data;
+ g_object_get (G_OBJECT (tag), "name", &tag_name, NULL);
+
+ }
+ fprintf(filefd, "<%s>", tag_name);
+
+ char *result = escape(gtk_text_buffer_get_text(buffer,
+ &iter_start,
+ &iter_end,
+ 0));
+
+ for (tagp = tags; tagp != NULL; tagp = tagp->next)
+ {
+ GtkTextTag *tag = tagp->data;
+ g_object_get (G_OBJECT (tag), "name", &tag_name, NULL);
+
+ }
+ fprintf(filefd, "%s</%s>\n", result, tag_name);
+ g_free(result);
+
+ if (tags)
+ g_slist_free (tags);
+
+ } while(gtk_text_iter_forward_line(&iter_start));
+
+ /*
+ * HTML Footer
+ */
+ fprintf(filefd, ""
+ "</body>\n"
+ "</html>\n");
+
+ fclose(filefd);
+
+ pause_board(FALSE);
+
+}
+
+static gint
+save_event(GnomeCanvasItem *item, GdkEvent *event, void *unused)
+{
+ if (event->type != GDK_BUTTON_PRESS || event->button.button != 1)
+ return FALSE;
+
+ pause_board(TRUE);
+
+ gc_selector_file_save(gcomprisBoard,
+ "wordprocessor",
+ "wordprocessor/xhtml",
+ save_buffer);
+
+ return FALSE;
+}
+
+static void
+load_buffer(gchar *file, gchar *file_type)
+{
+ GtkTextBuffer *buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
+ xmlDocPtr doc;
+ xmlNodePtr node;
+ GtkTextIter iter_start, iter_end;
+
+ /* parse the new file and put the result into newdoc */
+ doc = xmlParseFile(file);
+
+ /* in case something went wrong */
+ if(!doc)
+ return;
+
+ /* Get the root element node */
+ node = xmlDocGetRootElement(doc);
+
+ for(node = node; node != NULL; node = node->next)
+ if ( g_strcasecmp((char *)node->name, "html") == 0 &&
+ node->children )
+ break;
+
+ if(!node)
+ goto done;
+
+ for(node = node->children; node != NULL; node = node->next)
+ {
+ if ( g_strcasecmp((char *)node->name, "head") == 0 &&
+ node->children )
+ {
+ /* Search and apply the saved style in the META */
+ xmlNodePtr snode;
+ for(snode = node->children; snode != NULL; snode = snode->next)
+ {
+ if ( ( g_strcasecmp((char *)snode->name, "meta") == 0 ) &&
+ xmlHasProp(snode, BAD_CAST "http-equiv") )
+ {
+ xmlChar *key = xmlGetProp(snode, BAD_CAST "http-equiv");
+ xmlChar *content = xmlGetProp(snode, BAD_CAST "content");
+
+ if(g_strcasecmp((char *)key, "GCompris-doctype") == 0)
+ {
+ int style_index = get_style_index(gettext((char *)content));
+ apply_style(style_index);
+ gtk_combo_box_set_active(GTK_COMBO_BOX(gtk_combo_styles),
+ style_index);
+ }
+
+ if(g_strcasecmp((char *)key, "GCompris-color-style") == 0)
+ {
+ int cstyle_index = get_color_style_index(gettext((char *)content));
+ apply_color_style(cstyle_index);
+ gtk_combo_box_set_active(GTK_COMBO_BOX(gtk_combo_colors),
+ cstyle_index);
+ }
+
+ xmlFree(key);
+ xmlFree(content);
+ }
+ }
+ }
+
+ if ( g_strcasecmp((char *)node->name, "body") == 0 &&
+ node->children )
+ break;
+ }
+
+ if(!node)
+ goto done;
+
+ gtk_text_buffer_get_start_iter(buffer,
+ &iter_start);
+ gtk_text_buffer_get_end_iter(buffer,
+ &iter_end);
+ gtk_text_buffer_delete(buffer,
+ &iter_start,
+ &iter_end);
+
+ gtk_text_buffer_get_start_iter(buffer,
+ &iter_start);
+
+ for(node = node->children; node != NULL; node = node->next)
+ {
+
+ if ( g_strcasecmp((char *)node->name, "h1") == 0 ||
+ g_strcasecmp((char *)node->name, "h2") == 0 ||
+ g_strcasecmp((char *)node->name, "h3") == 0 ||
+ g_strcasecmp((char *)node->name, "p") == 0 )
+ {
+ xmlChar *content;
+ content = xmlNodeGetContent(node);
+ gtk_text_buffer_insert_with_tags_by_name(buffer,
+ &iter_start,
+ (char *)content,
+ strlen((char *)content),
+ (char *)node->name,
+ NULL);
+ xmlFree(content);
+ gtk_text_buffer_get_end_iter(buffer,
+ &iter_start);
+ gtk_text_buffer_insert(buffer,&iter_start, "\n", 1);
+
+ gtk_text_buffer_get_end_iter(buffer,
+ &iter_start);
+
+ }
+
+ }
+
+ done:
+ xmlFreeDoc(doc);
+}
+
+static gint
+load_event(GnomeCanvasItem *item, GdkEvent *event, void *unused)
+{
+ if (event->type != GDK_BUTTON_PRESS || event->button.button != 1)
+ return FALSE;
+
+ pause_board(TRUE);
+
+ gc_selector_file_load(gcomprisBoard,
+ "wordprocessor",
+ "wordprocessor/xhtml",
+ load_buffer);
+
+ return FALSE;
+}
+
diff --git a/src/wordprocessor-activity/wordprocessor.c b/src/wordprocessor-activity/wordprocessor.c
index 2264c1e..621db66 100644
--- a/src/wordprocessor-activity/wordprocessor.c
+++ b/src/wordprocessor-activity/wordprocessor.c
@@ -403,7 +403,9 @@ static GooCanvasItem *wordprocessor_create()
/* Now we can create the tags */
create_tags(buffer, doctype_list[0]);
- return NULL;
+ gtk_widget_grab_focus(view);
+
+ return NULL;
}
/*