From 4995d165117c78231d7c6512b9ffc0bbb60b198e Mon Sep 17 00:00:00 2001 From: John Darrington Date: Thu, 7 Dec 2006 11:10:23 +0000 Subject: [PATCH] Added a syntax editor to the GUI. It doesn't do anything yet --- it's just an editor. --- src/ui/gui/automake.mk | 1 + src/ui/gui/menu-actions.c | 156 +++++++------- src/ui/gui/psppire.glade | 365 +++++++++++++++++++++++++++++-- src/ui/gui/syntax-editor.c | 426 +++++++++++++++++++++++++++++++++++++ 4 files changed, 863 insertions(+), 85 deletions(-) create mode 100644 src/ui/gui/syntax-editor.c diff --git a/src/ui/gui/automake.mk b/src/ui/gui/automake.mk index be59fed5..e198b7e3 100644 --- a/src/ui/gui/automake.mk +++ b/src/ui/gui/automake.mk @@ -61,6 +61,7 @@ src_ui_gui_psppire_SOURCES = \ src/ui/gui/psppire-var-store.h \ src/ui/gui/sort-cases-dialog.c \ src/ui/gui/sort-cases-dialog.h \ + src/ui/gui/syntax-editor.c \ src/ui/gui/val-labs-dialog.c \ src/ui/gui/val-labs-dialog.h \ src/ui/gui/var-sheet.c \ diff --git a/src/ui/gui/menu-actions.c b/src/ui/gui/menu-actions.c index fb62f8a5..ce973282 100644 --- a/src/ui/gui/menu-actions.c +++ b/src/ui/gui/menu-actions.c @@ -1,4 +1,4 @@ -/* +/* PSPPIRE --- A Graphical User Interface for PSPP Copyright (C) 2004, 2005, 2006 Free Software Foundation Written by John Darrington @@ -70,7 +70,7 @@ static void psppire_set_window_title(const gchar *text) { GtkWidget *data_editor = get_widget_assert(xml, "data_editor"); - + gchar *title = g_strdup_printf("%s --- %s", text, gettext(window_title)); gtk_window_set_title(GTK_WINDOW(data_editor), title); @@ -78,7 +78,7 @@ psppire_set_window_title(const gchar *text) g_free(title); } -/* Clear the active file and set the data and var sheets to +/* Clear the active file and set the data and var sheets to reflect this. */ gboolean @@ -134,7 +134,7 @@ load_system_file(const gchar *file_name) PsppireDataStore *data_store ; struct dictionary *new_dict; struct sfm_read_info ri; - struct sfm_reader *reader ; + struct sfm_reader *reader ; GtkWidget *data_sheet = get_widget_assert(xml, "data_sheet"); GtkWidget *var_sheet = get_widget_assert(xml, "variable_sheet"); @@ -144,40 +144,40 @@ load_system_file(const gchar *file_name) clear_file(); - psppire_handle = + psppire_handle = fh_create_file (handle_name, file_name, fh_default_properties()); - if ( !psppire_handle ) + if ( !psppire_handle ) { - g_warning("Cannot read handle for reading system file \"%s\"\n", + g_warning("Cannot read handle for reading system file \"%s\"\n", file_name); return FALSE; } reader = sfm_open_reader (psppire_handle, &new_dict, &ri); - - if ( ! reader ) + + if ( ! reader ) return FALSE; /* FIXME: We need a better way of updating a dictionary than this */ the_dictionary = psppire_dict_new_from_dict(new_dict); - var_store = + var_store = PSPPIRE_VAR_STORE(gtk_sheet_get_model(GTK_SHEET(var_sheet))); - + psppire_var_store_set_dictionary(var_store, the_dictionary); - data_store = + data_store = PSPPIRE_DATA_STORE(gtk_sheet_get_model(GTK_SHEET(data_sheet))); - + psppire_data_store_set_dictionary(data_store, the_dictionary); psppire_set_window_title(basename(file_name)); var_cnt = dict_get_next_value_idx(the_dictionary->dict); - if ( var_cnt == 0 ) + if ( var_cnt == 0 ) return FALSE; @@ -191,32 +191,31 @@ load_system_file(const gchar *file_name) break; } - if ( !psppire_case_file_append_case(data_store->case_file, &c) ) + if ( !psppire_case_file_append_case(data_store->case_file, &c) ) { g_warning("Cannot write case to casefile\n"); break; } case_destroy(&c); } - - sfm_close_reader(reader); + + sfm_close_reader(reader); psppire_case_file_get_case_count(data_store->case_file); return TRUE; } - void -on_open1_activate (GtkMenuItem *menuitem, - gpointer user_data) +open_data (GtkMenuItem *menuitem, + gpointer user_data) { bool finished = FALSE; GtkWidget *dialog; GtkWidget *data_editor = get_widget_assert(xml, "data_editor"); GtkFileFilter *filter ; - + dialog = gtk_file_chooser_dialog_new (_("Open"), GTK_WINDOW(data_editor), GTK_FILE_CHOOSER_ACTION_OPEN, @@ -245,9 +244,9 @@ on_open1_activate (GtkMenuItem *menuitem, if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) { - gchar *file_name = + gchar *file_name = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER (dialog)); - + finished = load_system_file(file_name) ; g_free(file_name); @@ -261,6 +260,21 @@ on_open1_activate (GtkMenuItem *menuitem, } +void +on_data3_activate (GtkMenuItem *menuitem, + gpointer user_data) +{ + open_data(menuitem, user_data); +} + +void +on_data5_activate (GtkMenuItem *menuitem, + gpointer user_data) +{ + open_data(menuitem, user_data); +} + + /* Re initialise HANDLE, by interrogating the user for a new file name */ static gboolean recreate_save_handle(struct file_handle **handle) @@ -285,10 +299,10 @@ recreate_save_handle(struct file_handle **handle) (GTK_FILE_CHOOSER (dialog)); - if ( *handle ) + if ( *handle ) fh_free(*handle); - *handle = fh_create_file (handle_name, file_name, + *handle = fh_create_file (handle_name, file_name, fh_default_properties()); psppire_set_window_title(basename(file_name)); @@ -308,16 +322,16 @@ on_save1_activate (GtkMenuItem *menuitem, GtkSheet *data_sheet ; PsppireDataStore *data_store ; - if ( ! psppire_handle ) + if ( ! psppire_handle ) { - if ( ! recreate_save_handle(&psppire_handle) ) + if ( ! recreate_save_handle(&psppire_handle) ) return; } - + data_sheet = GTK_SHEET(get_widget_assert(xml, "data_sheet")); data_store = PSPPIRE_DATA_STORE(gtk_sheet_get_model(data_sheet)); - - if ( psppire_handle ) + + if ( psppire_handle ) psppire_data_store_create_system_file(data_store, psppire_handle); } @@ -330,16 +344,16 @@ on_save_as1_activate (GtkMenuItem *menuitem, GtkSheet *data_sheet ; PsppireDataStore *data_store ; - if ( ! recreate_save_handle(&psppire_handle) ) + if ( ! recreate_save_handle(&psppire_handle) ) return ; - if ( ! psppire_handle ) + if ( ! psppire_handle ) return ; data_sheet = GTK_SHEET(get_widget_assert(xml, "data_sheet")); data_store = PSPPIRE_DATA_STORE(gtk_sheet_get_model(data_sheet)); - if ( psppire_handle ) + if ( psppire_handle ) psppire_data_store_create_system_file(data_store, psppire_handle); } @@ -362,44 +376,44 @@ on_clear_activate (GtkMenuItem *menuitem, page = gtk_notebook_get_current_page(notebook); - switch (page) + switch (page) { case PAGE_VAR_SHEET: break; case PAGE_DATA_SHEET: { GtkSheet *data_sheet = GTK_SHEET(get_widget_assert(xml, "data_sheet")); - PsppireDataStore *data_store = + PsppireDataStore *data_store = PSPPIRE_DATA_STORE(gtk_sheet_get_model(data_sheet)); - - switch ( data_sheet->state ) + + switch ( data_sheet->state ) { case GTK_SHEET_ROW_SELECTED: psppire_case_file_delete_cases(data_store->case_file, - data_sheet->range.rowi + data_sheet->range.rowi - data_sheet->range.row0 + 1, data_sheet->range.row0); break; case GTK_SHEET_COLUMN_SELECTED: { gint fv; - struct PsppireVariable *pv = - psppire_dict_get_variable(the_dictionary, + struct PsppireVariable *pv = + psppire_dict_get_variable(the_dictionary, data_sheet->range.col0); fv = psppire_variable_get_fv(pv); - - - psppire_dict_delete_variables(the_dictionary, + + + psppire_dict_delete_variables(the_dictionary, data_sheet->range.col0, 1); - psppire_case_file_insert_values(data_store->case_file, + psppire_case_file_insert_values(data_store->case_file, -1, fv); } break; default: - gtk_sheet_cell_clear(data_sheet, + gtk_sheet_cell_clear(data_sheet, data_sheet->active_cell.row, data_sheet->active_cell.col); break; @@ -416,15 +430,15 @@ on_about1_activate(GtkMenuItem *menuitem, gpointer user_data) { GtkWidget *about = get_widget_assert(xml, "aboutdialog1"); - - + + GdkPixbuf *pb = gdk_pixbuf_new_from_file_at_size( "pspplogo.png", 64, 64, 0); gtk_about_dialog_set_logo(GTK_ABOUT_DIALOG(about), pb); gtk_widget_show(about); - gtk_window_set_transient_for(GTK_WINDOW(about), + gtk_window_set_transient_for(GTK_WINDOW(about), GTK_WINDOW(get_widget_assert(xml, "data_editor"))); } @@ -435,13 +449,13 @@ on_togglebutton_value_labels_toggled(GtkToggleToolButton *toggle_tool_button, gpointer user_data) { GtkSheet *data_sheet = GTK_SHEET(get_widget_assert(xml, "data_sheet")); - GtkCheckMenuItem *item = + GtkCheckMenuItem *item = GTK_CHECK_MENU_ITEM(get_widget_assert(xml, "menuitem-value-labels")); PsppireDataStore *ds = PSPPIRE_DATA_STORE(gtk_sheet_get_model(data_sheet)); gboolean show_value_labels = gtk_toggle_tool_button_get_active(toggle_tool_button); - + gtk_check_menu_item_set_active(item, show_value_labels); psppire_data_store_show_labels(ds, show_value_labels); @@ -453,7 +467,7 @@ on_value_labels_activate(GtkCheckMenuItem *menuitem, gpointer user_data) { GtkSheet *data_sheet = GTK_SHEET(get_widget_assert(xml, "data_sheet")); - GtkToggleToolButton *tb = + GtkToggleToolButton *tb = GTK_TOGGLE_TOOL_BUTTON(get_widget_assert(xml, "togglebutton-value-labels")); PsppireDataStore *ds = PSPPIRE_DATA_STORE(gtk_sheet_get_model(data_sheet)); @@ -470,7 +484,7 @@ on_status_bar1_activate(GtkCheckMenuItem *menuitem, gpointer user_data) { - if ( gtk_check_menu_item_get_active(menuitem) ) + if ( gtk_check_menu_item_get_active(menuitem) ) gtk_widget_show(get_widget_assert(xml, "statusbar1")); else gtk_widget_hide(get_widget_assert(xml, "statusbar1")); @@ -481,7 +495,7 @@ on_grid_lines1_activate(GtkCheckMenuItem *menuitem, gpointer user_data) { - const bool grid_visible = gtk_check_menu_item_get_active(menuitem); + const bool grid_visible = gtk_check_menu_item_get_active(menuitem); gtk_sheet_show_grid(GTK_SHEET(get_widget_assert(xml, "variable_sheet")), grid_visible); @@ -495,35 +509,35 @@ void on_fonts1_activate(GtkMenuItem *menuitem, gpointer user_data) { - static GtkWidget *dialog = 0 ; - if ( !dialog ) + static GtkWidget *dialog = 0 ; + if ( !dialog ) dialog = gtk_font_selection_dialog_new(_("Font Selection")); - gtk_window_set_transient_for(GTK_WINDOW(dialog), + gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW(get_widget_assert(xml, "data_editor"))); - if ( GTK_RESPONSE_OK == gtk_dialog_run(GTK_DIALOG(dialog)) ) + if ( GTK_RESPONSE_OK == gtk_dialog_run(GTK_DIALOG(dialog)) ) { - GtkSheet *data_sheet = + GtkSheet *data_sheet = GTK_SHEET(get_widget_assert(xml, "data_sheet")); - GtkSheet *var_sheet = + GtkSheet *var_sheet = GTK_SHEET(get_widget_assert(xml, "variable_sheet")); PsppireDataStore *ds = PSPPIRE_DATA_STORE(gtk_sheet_get_model(data_sheet)); PsppireVarStore *vs = PSPPIRE_VAR_STORE(gtk_sheet_get_model(var_sheet)); - const gchar *font = gtk_font_selection_dialog_get_font_name + const gchar *font = gtk_font_selection_dialog_get_font_name (GTK_FONT_SELECTION_DIALOG(dialog)); - PangoFontDescription* font_desc = + PangoFontDescription* font_desc = pango_font_description_from_string(font); psppire_var_store_set_font(vs, font_desc); psppire_data_store_set_font(ds, font_desc); } - + gtk_widget_hide(dialog); } @@ -538,7 +552,7 @@ switch_menus(gint page) GtkWidget *insert_variable = get_widget_assert(xml, "insert-variable"); GtkWidget *insert_cases = get_widget_assert(xml, "insert-cases"); - switch (page) + switch (page) { case PAGE_VAR_SHEET: gtk_widget_hide(menuitems[PAGE_VAR_SHEET]); @@ -621,11 +635,11 @@ on_go_to_case_activate(GtkMenuItem *menuitem, GtkWidget *dialog = get_widget_assert(xml, "go_to_case_dialog"); GtkEntry *entry = GTK_ENTRY(get_widget_assert(xml, "entry_go_to_case")); GtkSheet *data_sheet = GTK_SHEET(get_widget_assert(xml, "data_sheet")); - + gint result = gtk_dialog_run(GTK_DIALOG(dialog)); - - + + switch (result) { case GTK_RESPONSE_OK: @@ -637,7 +651,7 @@ on_go_to_case_activate(GtkMenuItem *menuitem, gtk_sheet_get_active_cell(data_sheet, &row, &column); if ( column < 0 ) column = 0; if ( row < 0 ) row = 0; - + gtk_sheet_set_active_cell(data_sheet, casenum, column); } break; @@ -665,12 +679,12 @@ on_sort_cases_activate (GtkMenuItem *menuitem, data_store = PSPPIRE_DATA_STORE(gtk_sheet_get_model(data_sheet)); - if ( NULL == dialog) + if ( NULL == dialog) dialog = sort_cases_dialog_create(xml); response = sort_cases_dialog_run(dialog, the_dictionary, &criteria); - switch ( response) + switch ( response) { case GTK_RESPONSE_OK: psppire_case_file_sort(data_store->case_file, &criteria); @@ -679,7 +693,7 @@ on_sort_cases_activate (GtkMenuItem *menuitem, } -static void +static void insert_case(void) { gint row, col; @@ -694,7 +708,7 @@ insert_case(void) } void -on_insert_case_clicked (GtkButton *button, gpointer user_data) +on_insert_case_clicked (GtkButton *button, gpointer user_data) { insert_case(); } diff --git a/src/ui/gui/psppire.glade b/src/ui/gui/psppire.glade index 5b17aa1d..b7a49bee 100644 --- a/src/ui/gui/psppire.glade +++ b/src/ui/gui/psppire.glade @@ -5,7 +5,7 @@ True - Psppire + Psppire Data Editor GTK_WINDOW_TOPLEVEL GTK_WIN_POS_NONE False @@ -47,7 +47,28 @@ True gtk-new True - + + + + + + + True + _Syntax + True + + + + + + + True + _Data + True + + + + @@ -56,7 +77,29 @@ True gtk-open True - + + + + + + + True + _Syntax + True + + + + + + + True + _Data + True + + + + + @@ -166,7 +209,7 @@ True - + True gtk-find 1 @@ -287,7 +330,7 @@ False Insert Variable True - + @@ -308,7 +351,7 @@ - + True gtk-jump-to 1 @@ -461,7 +504,6 @@ True True False - False @@ -576,7 +618,6 @@ True Variables - pspp-goto-variable True True @@ -634,7 +675,6 @@ True Insert Case - pspp-insert-case True True @@ -652,7 +692,6 @@ True Insert Variable - pspp-insert-variable True True @@ -682,7 +721,6 @@ True Split File - pspp-split-file True True @@ -699,7 +737,6 @@ True Weight Cases - pspp-weight-cases True True @@ -716,7 +753,6 @@ True Select Cases - pspp-select-cases True True @@ -746,7 +782,6 @@ True Value Labels - pspp-value-labels True True @@ -2915,4 +2950,306 @@ + + 640 + 480 + True + Psppire Syntax Editor + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_NONE + False + True + False + True + False + False + GDK_WINDOW_TYPE_HINT_NORMAL + GDK_GRAVITY_NORTH_WEST + True + False + + + + True + False + 0 + + + + True + GTK_PACK_DIRECTION_LTR + GTK_PACK_DIRECTION_LTR + + + + True + _File + True + + + + + + + True + gtk-new + True + + + + + + + True + _Syntax + True + + + + + + True + _Data + True + + + + + + + + + + True + gtk-open + True + + + + + + + True + _Syntax + True + + + + + + + True + _Data + True + + + + + + + + + + + True + gtk-save + True + + + + + + True + gtk-save-as + True + + + + + + True + + + + + + True + gtk-quit + True + + + + + + + + + + True + _Edit + True + + + + + + + True + gtk-cut + True + + + + + + True + gtk-copy + True + + + + + + True + gtk-paste + True + + + + + + True + gtk-delete + True + + + + + + + + + + True + _Run + True + + + + + + + True + All + True + + + + + + True + Selection + True + + + + + + True + Current Line + True + + + + + + True + To End + True + + + + + + + + + + True + _Help + True + + + + + + + True + _About + True + + + + + + + + + 0 + False + False + + + + + + True + True + GTK_POLICY_ALWAYS + GTK_POLICY_ALWAYS + GTK_SHADOW_IN + GTK_CORNER_TOP_LEFT + + + + True + True + True + False + True + GTK_JUSTIFY_LEFT + GTK_WRAP_NONE + True + 0 + 0 + 0 + 0 + 0 + 0 + + + + + + 0 + True + True + + + + + + True + True + + + 0 + False + False + + + + + + diff --git a/src/ui/gui/syntax-editor.c b/src/ui/gui/syntax-editor.c new file mode 100644 index 00000000..4efbd98c --- /dev/null +++ b/src/ui/gui/syntax-editor.c @@ -0,0 +1,426 @@ +/* + PSPPIRE --- A Graphical User Interface for PSPP + Copyright (C) 2006 Free Software Foundation + Written by John Darrington + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. */ + +#include +#include +#include +#define _(msgid) gettext (msgid) +#define N_(msgid) msgid + +#include +#include +#include + +#include "helper.h" + +extern GladeXML *xml; + +struct syntax_editor +{ + GtkWidget *window; /* The top level window of the editor */ + GtkTextBuffer *buffer; /* The buffer which contains the text */ + gchar *name; /* The name of this syntax buffer/editor */ +}; + +static gboolean save_editor_to_file (struct syntax_editor *se, + const gchar *filename, + GError **err); + +/* If the buffer's modified flag is set, then save it, and close the window. + Otherwise just close the window. +*/ +static void +save_if_modified (struct syntax_editor *se) +{ + if ( TRUE == gtk_text_buffer_get_modified (se->buffer)) + { + gint response; + GtkWidget *dialog = + gtk_message_dialog_new (GTK_WINDOW(se->window), + GTK_DIALOG_MODAL, + GTK_MESSAGE_QUESTION, + GTK_BUTTONS_NONE, + _("Save contents of syntax editor to %s?"), + se->name ? se->name : _("Untitled") + ); + + gtk_dialog_add_button (GTK_DIALOG(dialog), + GTK_STOCK_YES, + GTK_RESPONSE_ACCEPT); + gtk_dialog_add_button (GTK_DIALOG(dialog), + GTK_STOCK_NO, + GTK_RESPONSE_REJECT); + gtk_dialog_add_button (GTK_DIALOG(dialog), + GTK_STOCK_CANCEL, + GTK_RESPONSE_CANCEL); + + + response = gtk_dialog_run (GTK_DIALOG(dialog)); + + gtk_widget_destroy (dialog); + + if ( response == GTK_RESPONSE_ACCEPT ) + { + GError *err = NULL; + + if ( ! save_editor_to_file (se, se->name ? se->name : _("Untitled"), + err) ) + { + msg (ME, err->message); + g_error_free (err); + } + } + + if ( response == GTK_RESPONSE_CANCEL ) + return ; + } + + gtk_widget_destroy (se->window); +} + +/* Callback for the File->SaveAs menuitem */ +static void +on_syntax_save_as (GtkMenuItem *menuitem, + gpointer user_data) +{ + GtkFileFilter *filter; + gint response; + struct syntax_editor *se = user_data; + + GtkWidget *dialog = + gtk_file_chooser_dialog_new (_("Save Syntax"), + GTK_WINDOW(se->window), + GTK_FILE_CHOOSER_ACTION_SAVE, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, + NULL); + + filter = gtk_file_filter_new (); + gtk_file_filter_set_name (filter, _("Syntax Files (*.sps) ")); + gtk_file_filter_add_pattern (filter, "*.sps"); + gtk_file_filter_add_pattern (filter, "*.SPS"); + gtk_file_chooser_add_filter (GTK_FILE_CHOOSER(dialog), filter); + + filter = gtk_file_filter_new (); + gtk_file_filter_set_name (filter, _("All Files")); + gtk_file_filter_add_pattern (filter, "*"); + gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter); + + gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER(dialog), + TRUE); + response = gtk_dialog_run (GTK_DIALOG (dialog)); + + if ( response == GTK_RESPONSE_ACCEPT ) + { + GError *err = NULL; + char *filename = + gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog) ); + + if ( save_editor_to_file (se, filename, &err) ) + { + g_free (se->name); + se->name = g_strdup (filename); + } + else + { + msg ( ME, err->message ); + g_error_free (err); + } + + free (filename); + } + + gtk_widget_destroy ( dialog ); +} + +/* Callback for the File->Save menuitem */ +void +on_syntax_save (GtkMenuItem *menuitem, + gpointer user_data) +{ + struct syntax_editor *se = user_data; + + if ( se->name == NULL ) + on_syntax_save_as (menuitem, user_data); + else + { + GError *err; + save_editor_to_file (se, se->name, &err); + msg (ME, err->message); + g_error_free (err); + } +} + + +/* Callback for the "delete" action (clicking the x on the top right + hand corner of the window) */ +static gboolean +on_delete (GtkWidget *w, GdkEvent *event, gpointer user_data) +{ + struct syntax_editor *se = user_data; + save_if_modified (se); + return TRUE; +} + + +/* Callback for the File->Quit menuitem */ +static gboolean +on_quit (GtkMenuItem *menuitem, gpointer user_data) +{ + struct syntax_editor *se = user_data; + save_if_modified (se); + return FALSE; +} + +void +new_syntax_window (GtkMenuItem *menuitem, + gpointer user_data); + + + +static void open_syntax_window (GtkMenuItem *menuitem, + gpointer user_data); + + +/* Create a new syntax editor with NAME. + If NAME is NULL, a name will be automatically assigned +*/ +static struct syntax_editor * +new_syntax_editor (const gchar *name) +{ + GladeXML *new_xml ; + GtkWidget *text_view; + struct syntax_editor *se ; + + new_xml = glade_xml_new (xml->filename, "syntax_editor", NULL); + + se = g_malloc (sizeof (*se)); + + se->window = get_widget_assert (new_xml, "syntax_editor"); + text_view = get_widget_assert (new_xml, "syntax_text_view"); + se->buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW(text_view)); + if ( name ) + se->name = g_strdup (name); + else + se->name = NULL; + + g_signal_connect (get_widget_assert (new_xml,"file_new_syntax"), + "activate", + G_CALLBACK(new_syntax_window), + se->window); + + g_signal_connect (get_widget_assert (new_xml,"file_open_syntax"), + "activate", + G_CALLBACK(open_syntax_window), + se->window); + + g_signal_connect (get_widget_assert (new_xml,"file_quit"), + "activate", + G_CALLBACK(on_quit), + se); + + g_signal_connect (get_widget_assert (new_xml,"file_save"), + "activate", + G_CALLBACK(on_syntax_save), + se); + + g_signal_connect (get_widget_assert (new_xml,"file_save_as"), + "activate", + G_CALLBACK(on_syntax_save_as), + se); + + g_object_unref (new_xml); + + g_signal_connect (se->window, "delete-event", + G_CALLBACK(on_delete), se); + + return se; +} + +/* Callback for the File->New->Syntax menuitem */ +void +new_syntax_window (GtkMenuItem *menuitem, + gpointer user_data) +{ + struct syntax_editor *se = new_syntax_editor (NULL); + gtk_widget_show (se->window); +} + + +static void +set_window_title_from_filename (struct syntax_editor *se, + const gchar *filename) +{ + gchar *title; + gchar *basename ; + g_free (se->name); + se->name = strdup (filename); + basename = g_path_get_basename (filename); + title = + g_strdup_printf (_("%s --- PSPP Syntax Editor"), basename); + g_free (basename); + gtk_window_set_title (GTK_WINDOW(se->window), title); + g_free (title); +} + + +/* Save BUFFER to the file called FILENAME. + If successful, clears the buffer's modified flag */ +static gboolean +save_editor_to_file (struct syntax_editor *se, + const gchar *filename, + GError **err) +{ + GtkTextBuffer *buffer = se->buffer; + gboolean result ; + GtkTextIter start, stop; + gchar *text; + + gchar *glibfilename; + g_assert (filename); + + glibfilename = g_filename_from_utf8 (filename, -1, 0, 0, err); + + if ( ! glibfilename ) + return FALSE; + + gtk_text_buffer_get_iter_at_line (buffer, &start, 0); + gtk_text_buffer_get_iter_at_offset (buffer, &stop, -1); + + text = gtk_text_buffer_get_text (buffer, &start, &stop, FALSE); + + result = g_file_set_contents (glibfilename, text, -1, err); + + if ( result ) + { + set_window_title_from_filename (se, filename); + gtk_text_buffer_set_modified (buffer, FALSE); + } + + return result; +} + + +/* Loads the buffer from the file called FILENAME +*/ +static gboolean +load_editor_from_file (struct syntax_editor *se, + const gchar *filename, + GError **err) +{ + GtkTextBuffer *buffer = se->buffer; + gchar *text; + GtkTextIter iter; + + gchar *glibfilename = g_filename_from_utf8 (filename, -1, 0, 0, err); + + if ( ! glibfilename ) + return FALSE; + + /* FIXME: What if it's a very big file ? */ + if ( ! g_file_get_contents (glibfilename, &text, NULL, err) ) + { + g_free (glibfilename); + return FALSE; + } + g_free (glibfilename); + + gtk_text_buffer_get_iter_at_line (buffer, &iter, 0); + + gtk_text_buffer_insert (buffer, &iter, text, -1); + + set_window_title_from_filename (se, filename); + gtk_text_buffer_set_modified (buffer, FALSE); + + return TRUE; +} + + +/* Callback for the File->Open->Syntax menuitem */ +static void +open_syntax_window (GtkMenuItem *menuitem, gpointer parent) +{ + GtkFileFilter *filter; + gint response; + + GtkWidget *dialog = + gtk_file_chooser_dialog_new (_("Open Syntax"), + GTK_WINDOW(parent), + GTK_FILE_CHOOSER_ACTION_OPEN, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, + NULL); + + filter = gtk_file_filter_new (); + gtk_file_filter_set_name (filter, _("Syntax Files (*.sps) ")); + gtk_file_filter_add_pattern (filter, "*.sps"); + gtk_file_filter_add_pattern (filter, "*.SPS"); + gtk_file_chooser_add_filter (GTK_FILE_CHOOSER(dialog), filter); + + filter = gtk_file_filter_new (); + gtk_file_filter_set_name (filter, _("All Files")); + gtk_file_filter_add_pattern (filter, "*"); + gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter); + + response = gtk_dialog_run (GTK_DIALOG (dialog)); + + if (response == GTK_RESPONSE_ACCEPT) + { + const char *file_name = gtk_file_chooser_get_filename + (GTK_FILE_CHOOSER (dialog)); + + struct syntax_editor *se = new_syntax_editor (file_name); + + load_editor_from_file (se, file_name, NULL); + + gtk_widget_show (se->window); + } + + gtk_widget_destroy (dialog); +} + + +#if 1 +/* FIXME: get rid of these functions */ +void +on_syntax4_activate (GtkMenuItem *menuitem, + gpointer user_data) +{ + g_print ("%s\n", __FUNCTION__); +} + + + +void +on_syntax2_activate (GtkMenuItem *menuitem, + gpointer user_data) +{ + g_print ("%s\n", __FUNCTION__); +} + +void +on_syntax1_activate (GtkMenuItem *menuitem, + gpointer user_data) +{ + g_print ("%s\n", __FUNCTION__); + new_syntax_window (menuitem, user_data); +} +#endif + -- 2.30.2