/* Glimmer - gdseditor.c * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This library 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 Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "gdseditor.h" #define EXTRA_PARSE 80 static void gds_editor_init (GdsEditor * gds_editor); static void gds_editor_class_init (GdsEditorClass * klass); GtkWidget *gds_editor_new (); static void gds_editor_destroy (GtkObject * object); static gint key_press_cb (GtkWidget * widget, GdkEventKey * event, GdsEditor * gds_editor); static void gds_editor_dnd_drop (GdsEditor * editor, GdkDragContext * context, gint x, gint y, GtkSelectionData * selection_data, guint info, guint time, gpointer data); enum { TARGET_COLOR }; static GtkTargetEntry drop_types[] = { {"application/x-color", 0, TARGET_COLOR} }; static gint n_drop_types = sizeof (drop_types) / sizeof (drop_types[0]); static GtkWidgetClass *parent_class = NULL; GtkType gds_editor_get_type (void) { static GtkType gds_editor_type = 0; if (!gds_editor_type) { static const GtkTypeInfo gds_editor_info = { "GdsEditor", sizeof (GdsEditor), sizeof (GdsEditorClass), (GtkClassInitFunc) gds_editor_class_init, (GtkObjectInitFunc) gds_editor_init, NULL, NULL, (GtkClassInitFunc) NULL, }; gds_editor_type = gtk_type_unique (GTK_TYPE_EXTEXT, &gds_editor_info); } return (gds_editor_type); } static void gds_editor_class_init (GdsEditorClass * klass) { GtkObjectClass *object_class; object_class = (GtkObjectClass *) klass; parent_class = gtk_type_class (GTK_TYPE_EXTEXT); object_class->destroy = gds_editor_destroy; } static void gds_editor_init (GdsEditor * gds_editor) { gds_editor->changed = FALSE; } GtkWidget * gds_editor_new () { GdsEditor *gds_editor; gds_editor = (GdsEditor *) gtk_widget_new (GDS_TYPE_EDITOR, NULL); gtk_signal_connect (GTK_OBJECT (gds_editor), "key_press_event", GTK_SIGNAL_FUNC (key_press_cb), gds_editor); gtk_signal_connect (GTK_OBJECT (gds_editor), "changed", GTK_SIGNAL_FUNC (gds_editor_set_changed), 0); gtk_drag_dest_set (GTK_WIDGET (gds_editor), (GtkDestDefaults) (GTK_DEST_DEFAULT_MOTION | GTK_DEST_DEFAULT_HIGHLIGHT | GTK_DEST_DEFAULT_DROP), drop_types, n_drop_types, GDK_ACTION_COPY); gtk_signal_connect (GTK_OBJECT (gds_editor), "drag_data_received", GTK_SIGNAL_FUNC (gds_editor_dnd_drop), gds_editor); return GTK_WIDGET (gds_editor); } static void gds_editor_destroy (GtkObject * object) { GdsEditor *gds_editor; g_return_if_fail (object != NULL); g_return_if_fail (GDS_IS_EDITOR (object)); gds_editor = GDS_EDITOR (object); GTK_OBJECT_CLASS (parent_class)->destroy (object); } void gds_editor_set_changed (GdsEditor * gds_editor, gpointer data) { g_return_if_fail (gds_editor != NULL); g_return_if_fail (GDS_IS_EDITOR (gds_editor)); if (GTK_EXTEXT (gds_editor)->editable) gds_editor->changed++; gtk_signal_emit_by_name (GTK_OBJECT (gds_editor), "move_to_column", 0, NULL); } gboolean gds_editor_changed (GdsEditor * gds_editor) { g_return_val_if_fail (gds_editor != NULL, FALSE); g_return_val_if_fail (GDS_IS_EDITOR (gds_editor), FALSE); if (gds_editor->changed) return (TRUE); return (FALSE); } void gds_editor_set_style (GdsEditor * gds_editor, GtkStyle * style) { g_return_if_fail (gds_editor != NULL); g_return_if_fail (GDS_IS_EDITOR (gds_editor)); GTK_WIDGET (gds_editor)->style = style; gtk_extext_style_set (GTK_WIDGET (gds_editor), NULL); gtk_extext_style_insert (GTK_EXTEXT (gds_editor), "Default", NULL, &style->text[GTK_STATE_NORMAL], NULL, 0); } static gint key_press_cb (GtkWidget * widget, GdkEventKey * event, GdsEditor * gds_editor) { GtkExText *text; gint curpos; gboolean handled = FALSE; gboolean shift_state; gboolean control_state; gint key; shift_state = event->state & GDK_SHIFT_MASK; control_state = event->state & GDK_CONTROL_MASK; key = event->keyval; text = (GtkExText *) widget; curpos = gtk_extext_get_position (text); if (event->keyval == 'x' && control_state && gtk_extext_get_editable (text)) { gtk_extext_cut_clipboard (text); text->has_selection = FALSE; text->selection_start_pos = -1; text->selection_end_pos = -1; handled = TRUE; } else if (event->keyval == 'z' && control_state && gtk_extext_get_editable (text)) { text->has_selection = FALSE; text->selection_start_pos = -1; text->selection_end_pos = -1; if (!gtk_extext_undo_is_empty (text)) { gtk_extext_undo (text); gds_editor->changed -= 2; gtk_signal_emit_by_name (GTK_OBJECT (gds_editor), "move_to_column", 0, NULL); } handled = TRUE; } else if (event->keyval == 'r' && control_state && gtk_extext_get_editable (text)) { text->has_selection = FALSE; text->selection_start_pos = -1; text->selection_end_pos = -1; if (!gtk_extext_redo_is_empty (text)) { gtk_extext_redo (text); gtk_signal_emit_by_name (GTK_OBJECT (gds_editor), "move_to_column", 0, NULL); } handled = TRUE; } if (handled) gtk_signal_emit_stop_by_name (GTK_OBJECT (widget), "key_press_event"); return (handled); } void gds_editor_insert_text (GdsEditor * editor, const gchar * new_text, gint new_text_length, gint * position) { GtkExText *text; g_return_if_fail (editor != NULL); g_return_if_fail (GTK_IS_EXTEXT (editor)); text = GTK_EXTEXT (editor); if (!text->editable) return; gtk_extext_insert_text (text, new_text, new_text_length, position); } void gds_editor_delete_text (GdsEditor * editor, gint start_pos, gint end_pos) { GtkExText *text; g_return_if_fail (editor != NULL); g_return_if_fail (GTK_IS_EXTEXT (editor)); text = GTK_EXTEXT (editor); if (!text->editable) return; gtk_extext_delete_text (text, start_pos, end_pos); } gchar * gds_editor_get_chars (GdsEditor * editor, gint start_pos, gint end_pos) { GtkExText *text; gchar *chars; g_return_val_if_fail (editor != NULL, NULL); g_return_val_if_fail (GTK_IS_EXTEXT (editor), NULL); text = GTK_EXTEXT (editor); chars = gtk_extext_get_chars (text, start_pos, end_pos); return (chars); } void gds_editor_set_editable (GdsEditor * editor, gboolean editable) { g_return_if_fail (editor != NULL); g_return_if_fail (GTK_IS_EXTEXT (editor)); gtk_extext_set_editable (GTK_EXTEXT (editor), editable); } static void gds_editor_dnd_drop (GdsEditor * editor, GdkDragContext * context, gint x, gint y, GtkSelectionData * selection_data, guint info, guint time, gpointer data) { GtkExTextLineData *linedata; gint offset = 0; if (info == TARGET_COLOR) { guint16 *vals; gchar string[] = "#000000"; if (selection_data->length < 0) return; if ((selection_data->format != 16) || (selection_data->length != 8)) { g_warning ("Received invalid color data\n"); return; } vals = (guint16 *) selection_data->data; vals[0] /= 256; vals[1] /= 256; vals[2] /= 256; g_snprintf (string, sizeof (string), "#%02X%02X%02X", vals[0], vals[1], vals[2]); linedata = gtk_extext_get_line_by_offset (GTK_EXTEXT (editor), y, NULL); offset = gtk_extext_get_column_by_offset (GTK_EXTEXT (editor), linedata, x, NULL); if (offset < 0) offset = 0; offset += linedata->startpos; gtk_extext_insert_text (GTK_EXTEXT (editor), string, strlen (string), &offset); } }