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 <data/dictionary.h>
37 #include <language/lexer/lexer.h>
38 #include <language/command.h>
39 #include <data/procedure.h>
40 #include "syntax-editor.h"
41 #include "syntax-editor-source.h"
43 extern struct source_stream *the_source_stream ;
44 extern struct dataset *the_dataset;
46 static gboolean save_editor_to_file (struct syntax_editor *se,
47 const gchar *filename,
50 /* Append ".sps" to FILENAME if necessary.
51 The returned result must be freed when no longer required.
54 append_suffix (const gchar *filename)
56 if ( ! g_str_has_suffix (filename, ".sps" ) &&
57 ! g_str_has_suffix (filename, ".SPS" ) )
59 return g_strdup_printf ("%s.sps", filename);
62 return strdup (filename);
65 /* If the buffer's modified flag is set, then save it, and close the window.
66 Otherwise just close the window.
69 save_if_modified (struct syntax_editor *se)
71 struct editor_window *e = (struct editor_window *) se;
72 if ( TRUE == gtk_text_buffer_get_modified (se->buffer))
76 gtk_message_dialog_new (GTK_WINDOW (e->window),
80 _("Save contents of syntax editor to %s?"),
84 gtk_dialog_add_button (GTK_DIALOG (dialog),
87 gtk_dialog_add_button (GTK_DIALOG (dialog),
90 gtk_dialog_add_button (GTK_DIALOG (dialog),
95 response = gtk_dialog_run (GTK_DIALOG (dialog));
97 gtk_widget_destroy (dialog);
99 if ( response == GTK_RESPONSE_ACCEPT )
103 if ( ! save_editor_to_file (se, e->name, &err) )
105 msg (ME, err->message);
110 if ( response == GTK_RESPONSE_CANCEL )
114 gtk_widget_destroy (GTK_WIDGET (e->window));
117 /* Callback for the File->SaveAs menuitem */
119 on_syntax_save_as (GtkMenuItem *menuitem, gpointer user_data)
121 GtkFileFilter *filter;
123 struct syntax_editor *se = user_data;
124 struct editor_window *e = user_data;
127 gtk_file_chooser_dialog_new (_("Save Syntax"),
128 GTK_WINDOW (e->window),
129 GTK_FILE_CHOOSER_ACTION_SAVE,
130 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
131 GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
134 filter = gtk_file_filter_new ();
135 gtk_file_filter_set_name (filter, _("Syntax Files (*.sps) "));
136 gtk_file_filter_add_pattern (filter, "*.sps");
137 gtk_file_filter_add_pattern (filter, "*.SPS");
138 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
140 filter = gtk_file_filter_new ();
141 gtk_file_filter_set_name (filter, _("All Files"));
142 gtk_file_filter_add_pattern (filter, "*");
143 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
145 gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dialog),
147 response = gtk_dialog_run (GTK_DIALOG (dialog));
149 if ( response == GTK_RESPONSE_ACCEPT )
153 gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog) );
155 if ( save_editor_to_file (se, filename, &err) )
158 e->name = g_strdup (filename);
162 msg ( ME, err->message );
169 gtk_widget_destroy ( dialog );
172 /* Callback for the File->Save menuitem */
174 on_syntax_save (GtkMenuItem *menuitem, gpointer user_data)
176 struct syntax_editor *se = user_data;
177 struct editor_window *e = user_data;
179 if ( e->name == NULL )
180 on_syntax_save_as (menuitem, user_data);
184 save_editor_to_file (se, e->name, &err);
187 msg (ME, err->message);
194 /* Callback for the "delete" action (clicking the x on the top right
195 hand corner of the window) */
197 on_delete (GtkWidget *w, GdkEvent *event, gpointer user_data)
199 struct syntax_editor *se = user_data;
200 save_if_modified (se);
205 /* Callback for the File->Quit menuitem */
207 on_quit (GtkMenuItem *menuitem, gpointer user_data)
209 struct syntax_editor *se = user_data;
210 save_if_modified (se);
215 execute_syntax (const struct syntax_editor *se, GtkTextIter start,
218 g_return_if_fail (proc_has_source (the_dataset));
220 getl_append_source (the_source_stream,
221 create_syntax_editor_source (se, start, stop));
224 const struct dictionary *dict = dataset_dict (the_dataset);
225 int result = cmd_parse (se->lexer, the_dataset,
226 dict_get_var_cnt (dict) > 0 ?
227 CMD_STATE_DATA : CMD_STATE_INITIAL);
228 if (result == CMD_EOF || result == CMD_FINISH)
233 /* Parse and execute all the text in the buffer */
235 on_run_all (GtkMenuItem *menuitem, gpointer user_data)
237 GtkTextIter begin, end;
238 struct syntax_editor *se = user_data;
240 gtk_text_buffer_get_iter_at_line (se->buffer, &begin, 0);
241 gtk_text_buffer_get_iter_at_line (se->buffer, &end, -1);
244 execute_syntax (se, begin, end);
247 /* Parse and execute the currently selected text */
249 on_run_selection (GtkMenuItem *menuitem, gpointer user_data)
251 GtkTextIter begin, end;
252 struct syntax_editor *se = user_data;
254 if ( gtk_text_buffer_get_selection_bounds (se->buffer, &begin, &end) )
255 execute_syntax (se, begin, end);
259 /* Parse and execute the current line */
261 on_run_current_line (GtkMenuItem *menuitem, gpointer user_data)
263 GtkTextIter begin, end;
267 struct syntax_editor *se = user_data;
269 /* Get the current line */
270 gtk_text_buffer_get_iter_at_mark (se->buffer,
272 gtk_text_buffer_get_insert (se->buffer)
275 line = gtk_text_iter_get_line (&here) ;
277 /* Now set begin and end to the start of this line, and start of
278 following line respectively */
279 gtk_text_buffer_get_iter_at_line (se->buffer, &begin, line);
280 gtk_text_buffer_get_iter_at_line (se->buffer, &end, line + 1);
282 execute_syntax (se, begin, end);
287 /* Parse and execute the from the current line, to the end of the
290 on_run_to_end (GtkMenuItem *menuitem, gpointer user_data)
292 GtkTextIter begin, end;
296 struct syntax_editor *se = user_data;
298 /* Get the current line */
299 gtk_text_buffer_get_iter_at_mark (se->buffer,
301 gtk_text_buffer_get_insert (se->buffer)
304 line = gtk_text_iter_get_line (&here) ;
306 /* Now set begin and end to the start of this line, and end of buffer
308 gtk_text_buffer_get_iter_at_line (se->buffer, &begin, line);
309 gtk_text_buffer_get_iter_at_line (se->buffer, &end, -1);
311 execute_syntax (se, begin, end);
318 Create a new syntax editor with NAME.
319 If NAME is NULL, a name will be automatically assigned
321 struct syntax_editor *
322 new_syntax_editor (void)
325 glade_xml_new (PKGDATADIR "/syntax-editor.glade", NULL, NULL);
327 GtkWidget *text_view;
328 struct syntax_editor *se ;
329 struct editor_window *e;
333 se = g_malloc (sizeof (*se));
335 e = (struct editor_window *)se;
337 e->window = GTK_WINDOW (get_widget_assert (xml, "syntax_editor"));
338 text_view = get_widget_assert (xml, "syntax_text_view");
339 se->buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (text_view));
340 se->lexer = lex_create (the_source_stream);
342 g_signal_connect (get_widget_assert (xml,"file_new_syntax"),
344 G_CALLBACK (new_syntax_window),
347 g_signal_connect (get_widget_assert (xml,"file_open_syntax"),
349 G_CALLBACK (open_syntax_window),
352 g_signal_connect (get_widget_assert (xml,"file_new_data"),
354 G_CALLBACK (new_data_window),
357 g_signal_connect (get_widget_assert (xml,"file_open_data"),
359 G_CALLBACK (open_data_window),
363 g_signal_connect (get_widget_assert (xml,"help_about"),
365 G_CALLBACK (about_new),
368 g_signal_connect (get_widget_assert (xml,"help_reference"),
370 G_CALLBACK (reference_manual),
374 g_signal_connect (get_widget_assert (xml, "file_save"),
376 G_CALLBACK (on_syntax_save),
379 g_signal_connect (get_widget_assert (xml, "file_save_as"),
381 G_CALLBACK (on_syntax_save_as),
385 g_signal_connect (get_widget_assert (xml,"file_quit"),
387 G_CALLBACK (on_quit),
391 g_signal_connect (get_widget_assert (xml,"run_all"),
393 G_CALLBACK (on_run_all),
397 g_signal_connect (get_widget_assert (xml,"run_selection"),
399 G_CALLBACK (on_run_selection),
402 g_signal_connect (get_widget_assert (xml,"run_current_line"),
404 G_CALLBACK (on_run_current_line),
408 g_signal_connect (get_widget_assert (xml,"run_to_end"),
410 G_CALLBACK (on_run_to_end),
414 g_signal_connect (get_widget_assert (xml,"windows_minimise_all"),
416 G_CALLBACK (minimise_all_windows),
421 g_object_unref (xml);
423 g_signal_connect (e->window, "delete-event",
424 G_CALLBACK (on_delete), se);
432 Callback for the File->New->Syntax menuitem
435 new_syntax_window (GtkMenuItem *menuitem,
438 window_create (WINDOW_SYNTAX, NULL);
443 Save BUFFER to the file called FILENAME.
444 If successful, clears the buffer's modified flag
447 save_editor_to_file (struct syntax_editor *se,
448 const gchar *filename,
451 GtkTextBuffer *buffer = se->buffer;
453 GtkTextIter start, stop;
460 suffixedname = append_suffix (filename);
462 glibfilename = g_filename_from_utf8 (suffixedname, -1, 0, 0, err);
464 g_free ( suffixedname);
466 if ( ! glibfilename )
469 gtk_text_buffer_get_iter_at_line (buffer, &start, 0);
470 gtk_text_buffer_get_iter_at_offset (buffer, &stop, -1);
472 text = gtk_text_buffer_get_text (buffer, &start, &stop, FALSE);
474 result = g_file_set_contents (glibfilename, text, -1, err);
478 window_set_name_from_filename ((struct editor_window *) se, filename);
479 gtk_text_buffer_set_modified (buffer, FALSE);
487 Loads the buffer from the file called FILENAME
490 load_editor_from_file (struct syntax_editor *se,
491 const gchar *filename,
494 GtkTextBuffer *buffer = se->buffer;
498 gchar *glibfilename = g_filename_from_utf8 (filename, -1, 0, 0, err);
500 if ( ! glibfilename )
503 /* FIXME: What if it's a very big file ? */
504 if ( ! g_file_get_contents (glibfilename, &text, NULL, err) )
506 g_free (glibfilename);
509 g_free (glibfilename);
511 gtk_text_buffer_get_iter_at_line (buffer, &iter, 0);
513 gtk_text_buffer_insert (buffer, &iter, text, -1);
515 window_set_name_from_filename ((struct editor_window *)se, filename);
516 gtk_text_buffer_set_modified (buffer, FALSE);
522 /* Callback for the File->Open->Syntax menuitem */
524 open_syntax_window (GtkMenuItem *menuitem, gpointer parent)
526 GtkFileFilter *filter;
530 gtk_file_chooser_dialog_new (_("Open Syntax"),
532 GTK_FILE_CHOOSER_ACTION_OPEN,
533 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
534 GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
537 filter = gtk_file_filter_new ();
538 gtk_file_filter_set_name (filter, _("Syntax Files (*.sps) "));
539 gtk_file_filter_add_pattern (filter, "*.sps");
540 gtk_file_filter_add_pattern (filter, "*.SPS");
541 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
543 filter = gtk_file_filter_new ();
544 gtk_file_filter_set_name (filter, _("All Files"));
545 gtk_file_filter_add_pattern (filter, "*");
546 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
548 response = gtk_dialog_run (GTK_DIALOG (dialog));
550 if (response == GTK_RESPONSE_ACCEPT)
552 const char *file_name = gtk_file_chooser_get_filename
553 (GTK_FILE_CHOOSER (dialog));
555 struct syntax_editor *se = (struct syntax_editor *)
556 window_create (WINDOW_SYNTAX, file_name);
558 load_editor_from_file (se, file_name, NULL);
561 gtk_widget_destroy (dialog);