2 PSPPIRE --- A Graphical User Interface for PSPP
3 Copyright (C) 2006 Free Software Foundation
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23 #define _(msgid) gettext (msgid)
24 #define N_(msgid) msgid
26 #include <glade/glade.h>
28 #include <libpspp/message.h>
29 #include <libpspp/getl.h>
31 #include "data-editor.h"
34 #include "window-manager.h"
36 #include <language/lexer/lexer.h>
37 #include <language/command.h>
38 #include <data/procedure.h>
39 #include "syntax-editor.h"
40 #include "syntax-editor-source.h"
42 extern struct source_stream *the_source_stream ;
43 extern struct dataset *the_dataset;
45 static gboolean save_editor_to_file (struct syntax_editor *se,
46 const gchar *filename,
49 /* Append ".sps" to FILENAME if necessary.
50 The returned result must be freed when no longer required.
53 append_suffix (const gchar *filename)
55 if ( ! g_str_has_suffix (filename, ".sps" ) &&
56 ! g_str_has_suffix (filename, ".SPS" ) )
58 return g_strdup_printf ("%s.sps", filename);
61 return strdup (filename);
64 /* If the buffer's modified flag is set, then save it, and close the window.
65 Otherwise just close the window.
68 save_if_modified (struct syntax_editor *se)
70 struct editor_window *e = (struct editor_window *) se;
71 if ( TRUE == gtk_text_buffer_get_modified (se->buffer))
75 gtk_message_dialog_new (GTK_WINDOW (e->window),
79 _("Save contents of syntax editor to %s?"),
83 gtk_dialog_add_button (GTK_DIALOG (dialog),
86 gtk_dialog_add_button (GTK_DIALOG (dialog),
89 gtk_dialog_add_button (GTK_DIALOG (dialog),
94 response = gtk_dialog_run (GTK_DIALOG (dialog));
96 gtk_widget_destroy (dialog);
98 if ( response == GTK_RESPONSE_ACCEPT )
102 if ( ! save_editor_to_file (se, e->name, &err) )
104 msg (ME, err->message);
109 if ( response == GTK_RESPONSE_CANCEL )
113 gtk_widget_destroy (GTK_WIDGET (e->window));
116 /* Callback for the File->SaveAs menuitem */
118 on_syntax_save_as (GtkMenuItem *menuitem, gpointer user_data)
120 GtkFileFilter *filter;
122 struct syntax_editor *se = user_data;
123 struct editor_window *e = user_data;
126 gtk_file_chooser_dialog_new (_("Save Syntax"),
127 GTK_WINDOW (e->window),
128 GTK_FILE_CHOOSER_ACTION_SAVE,
129 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
130 GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
133 filter = gtk_file_filter_new ();
134 gtk_file_filter_set_name (filter, _("Syntax Files (*.sps) "));
135 gtk_file_filter_add_pattern (filter, "*.sps");
136 gtk_file_filter_add_pattern (filter, "*.SPS");
137 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
139 filter = gtk_file_filter_new ();
140 gtk_file_filter_set_name (filter, _("All Files"));
141 gtk_file_filter_add_pattern (filter, "*");
142 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
144 gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dialog),
146 response = gtk_dialog_run (GTK_DIALOG (dialog));
148 if ( response == GTK_RESPONSE_ACCEPT )
152 gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog) );
154 if ( save_editor_to_file (se, filename, &err) )
157 e->name = g_strdup (filename);
161 msg ( ME, err->message );
168 gtk_widget_destroy ( dialog );
171 /* Callback for the File->Save menuitem */
173 on_syntax_save (GtkMenuItem *menuitem, gpointer user_data)
175 struct syntax_editor *se = user_data;
176 struct editor_window *e = user_data;
178 if ( e->name == NULL )
179 on_syntax_save_as (menuitem, user_data);
183 save_editor_to_file (se, e->name, &err);
186 msg (ME, err->message);
193 /* Callback for the "delete" action (clicking the x on the top right
194 hand corner of the window) */
196 on_delete (GtkWidget *w, GdkEvent *event, gpointer user_data)
198 struct syntax_editor *se = user_data;
199 save_if_modified (se);
204 /* Callback for the File->Quit menuitem */
206 on_quit (GtkMenuItem *menuitem, gpointer user_data)
208 struct syntax_editor *se = user_data;
209 save_if_modified (se);
214 execute_syntax (const struct syntax_editor *se, GtkTextIter start,
217 getl_append_source (the_source_stream,
218 create_syntax_editor_source (se, start, stop));
221 int result = cmd_parse (se->lexer, the_dataset,
222 proc_has_source (the_dataset)
223 ? CMD_STATE_DATA : CMD_STATE_INITIAL);
225 if (result == CMD_EOF || result == CMD_FINISH)
230 /* Parse and execute all the text in the buffer */
232 on_run_all (GtkMenuItem *menuitem, gpointer user_data)
234 GtkTextIter begin, end;
235 struct syntax_editor *se = user_data;
237 gtk_text_buffer_get_iter_at_line (se->buffer, &begin, 0);
238 gtk_text_buffer_get_iter_at_line (se->buffer, &end, -1);
241 execute_syntax (se, begin, end);
244 /* Parse and execute the currently selected text */
246 on_run_selection (GtkMenuItem *menuitem, gpointer user_data)
248 GtkTextIter begin, end;
249 struct syntax_editor *se = user_data;
251 if ( gtk_text_buffer_get_selection_bounds (se->buffer, &begin, &end) )
252 execute_syntax (se, begin, end);
256 /* Parse and execute the current line */
258 on_run_current_line (GtkMenuItem *menuitem, gpointer user_data)
260 GtkTextIter begin, end;
264 struct syntax_editor *se = user_data;
266 /* Get the current line */
267 gtk_text_buffer_get_iter_at_mark (se->buffer,
269 gtk_text_buffer_get_insert (se->buffer)
272 line = gtk_text_iter_get_line (&here) ;
274 /* Now set begin and end to the start of this line, and start of
275 following line respectively */
276 gtk_text_buffer_get_iter_at_line (se->buffer, &begin, line);
277 gtk_text_buffer_get_iter_at_line (se->buffer, &end, line + 1);
279 execute_syntax (se, begin, end);
284 /* Parse and execute the from the current line, to the end of the
287 on_run_to_end (GtkMenuItem *menuitem, gpointer user_data)
289 GtkTextIter begin, end;
293 struct syntax_editor *se = user_data;
295 /* Get the current line */
296 gtk_text_buffer_get_iter_at_mark (se->buffer,
298 gtk_text_buffer_get_insert (se->buffer)
301 line = gtk_text_iter_get_line (&here) ;
303 /* Now set begin and end to the start of this line, and end of buffer
305 gtk_text_buffer_get_iter_at_line (se->buffer, &begin, line);
306 gtk_text_buffer_get_iter_at_line (se->buffer, &end, -1);
308 execute_syntax (se, begin, end);
315 Create a new syntax editor with NAME.
316 If NAME is NULL, a name will be automatically assigned
318 struct syntax_editor *
319 new_syntax_editor (void)
322 glade_xml_new (PKGDATADIR "/syntax-editor.glade", NULL, NULL);
324 GtkWidget *text_view;
325 struct syntax_editor *se ;
326 struct editor_window *e;
330 se = g_malloc (sizeof (*se));
332 e = (struct editor_window *)se;
334 e->window = GTK_WINDOW (get_widget_assert (xml, "syntax_editor"));
335 text_view = get_widget_assert (xml, "syntax_text_view");
336 se->buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (text_view));
337 se->lexer = lex_create (the_source_stream);
339 g_signal_connect (get_widget_assert (xml,"file_new_syntax"),
341 G_CALLBACK (new_syntax_window),
344 g_signal_connect (get_widget_assert (xml,"file_open_syntax"),
346 G_CALLBACK (open_syntax_window),
349 g_signal_connect (get_widget_assert (xml,"file_new_data"),
351 G_CALLBACK (new_data_window),
354 g_signal_connect (get_widget_assert (xml,"file_open_data"),
356 G_CALLBACK (open_data_window),
360 g_signal_connect (get_widget_assert (xml,"help_about"),
362 G_CALLBACK (about_new),
365 g_signal_connect (get_widget_assert (xml,"help_reference"),
367 G_CALLBACK (reference_manual),
371 g_signal_connect (get_widget_assert (xml, "file_save"),
373 G_CALLBACK (on_syntax_save),
376 g_signal_connect (get_widget_assert (xml, "file_save_as"),
378 G_CALLBACK (on_syntax_save_as),
382 g_signal_connect (get_widget_assert (xml,"file_quit"),
384 G_CALLBACK (on_quit),
388 g_signal_connect (get_widget_assert (xml,"run_all"),
390 G_CALLBACK (on_run_all),
394 g_signal_connect (get_widget_assert (xml,"run_selection"),
396 G_CALLBACK (on_run_selection),
399 g_signal_connect (get_widget_assert (xml,"run_current_line"),
401 G_CALLBACK (on_run_current_line),
405 g_signal_connect (get_widget_assert (xml,"run_to_end"),
407 G_CALLBACK (on_run_to_end),
411 g_signal_connect (get_widget_assert (xml,"windows_minimise_all"),
413 G_CALLBACK (minimise_all_windows),
418 g_object_unref (xml);
420 g_signal_connect (e->window, "delete-event",
421 G_CALLBACK (on_delete), se);
429 Callback for the File->New->Syntax menuitem
432 new_syntax_window (GtkMenuItem *menuitem,
435 window_create (WINDOW_SYNTAX, NULL);
440 Save BUFFER to the file called FILENAME.
441 If successful, clears the buffer's modified flag
444 save_editor_to_file (struct syntax_editor *se,
445 const gchar *filename,
448 GtkTextBuffer *buffer = se->buffer;
450 GtkTextIter start, stop;
457 suffixedname = append_suffix (filename);
459 glibfilename = g_filename_from_utf8 (suffixedname, -1, 0, 0, err);
461 g_free ( suffixedname);
463 if ( ! glibfilename )
466 gtk_text_buffer_get_iter_at_line (buffer, &start, 0);
467 gtk_text_buffer_get_iter_at_offset (buffer, &stop, -1);
469 text = gtk_text_buffer_get_text (buffer, &start, &stop, FALSE);
471 result = g_file_set_contents (glibfilename, text, -1, err);
475 window_set_name_from_filename ((struct editor_window *) se, filename);
476 gtk_text_buffer_set_modified (buffer, FALSE);
484 Loads the buffer from the file called FILENAME
487 load_editor_from_file (struct syntax_editor *se,
488 const gchar *filename,
491 GtkTextBuffer *buffer = se->buffer;
495 gchar *glibfilename = g_filename_from_utf8 (filename, -1, 0, 0, err);
497 if ( ! glibfilename )
500 /* FIXME: What if it's a very big file ? */
501 if ( ! g_file_get_contents (glibfilename, &text, NULL, err) )
503 g_free (glibfilename);
506 g_free (glibfilename);
508 gtk_text_buffer_get_iter_at_line (buffer, &iter, 0);
510 gtk_text_buffer_insert (buffer, &iter, text, -1);
512 window_set_name_from_filename ((struct editor_window *)se, filename);
513 gtk_text_buffer_set_modified (buffer, FALSE);
519 /* Callback for the File->Open->Syntax menuitem */
521 open_syntax_window (GtkMenuItem *menuitem, gpointer parent)
523 GtkFileFilter *filter;
527 gtk_file_chooser_dialog_new (_("Open Syntax"),
529 GTK_FILE_CHOOSER_ACTION_OPEN,
530 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
531 GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
534 filter = gtk_file_filter_new ();
535 gtk_file_filter_set_name (filter, _("Syntax Files (*.sps) "));
536 gtk_file_filter_add_pattern (filter, "*.sps");
537 gtk_file_filter_add_pattern (filter, "*.SPS");
538 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
540 filter = gtk_file_filter_new ();
541 gtk_file_filter_set_name (filter, _("All Files"));
542 gtk_file_filter_add_pattern (filter, "*");
543 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
545 response = gtk_dialog_run (GTK_DIALOG (dialog));
547 if (response == GTK_RESPONSE_ACCEPT)
549 const char *file_name = gtk_file_chooser_get_filename
550 (GTK_FILE_CHOOSER (dialog));
552 struct syntax_editor *se = (struct syntax_editor *)
553 window_create (WINDOW_SYNTAX, file_name);
555 load_editor_from_file (se, file_name, NULL);
558 gtk_widget_destroy (dialog);