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)
232 getl_abort_noninteractive (the_source_stream);
235 /* Parse and execute all the text in the buffer */
237 on_run_all (GtkMenuItem *menuitem, gpointer user_data)
239 GtkTextIter begin, end;
240 struct syntax_editor *se = user_data;
242 gtk_text_buffer_get_iter_at_line (se->buffer, &begin, 0);
243 gtk_text_buffer_get_iter_at_line (se->buffer, &end, -1);
246 execute_syntax (se, begin, end);
249 /* Parse and execute the currently selected text */
251 on_run_selection (GtkMenuItem *menuitem, gpointer user_data)
253 GtkTextIter begin, end;
254 struct syntax_editor *se = user_data;
256 if ( gtk_text_buffer_get_selection_bounds (se->buffer, &begin, &end) )
257 execute_syntax (se, begin, end);
261 /* Parse and execute the current line */
263 on_run_current_line (GtkMenuItem *menuitem, gpointer user_data)
265 GtkTextIter begin, end;
269 struct syntax_editor *se = user_data;
271 /* Get the current line */
272 gtk_text_buffer_get_iter_at_mark (se->buffer,
274 gtk_text_buffer_get_insert (se->buffer)
277 line = gtk_text_iter_get_line (&here) ;
279 /* Now set begin and end to the start of this line, and start of
280 following line respectively */
281 gtk_text_buffer_get_iter_at_line (se->buffer, &begin, line);
282 gtk_text_buffer_get_iter_at_line (se->buffer, &end, line + 1);
284 execute_syntax (se, begin, end);
289 /* Parse and execute the from the current line, to the end of the
292 on_run_to_end (GtkMenuItem *menuitem, gpointer user_data)
294 GtkTextIter begin, end;
298 struct syntax_editor *se = user_data;
300 /* Get the current line */
301 gtk_text_buffer_get_iter_at_mark (se->buffer,
303 gtk_text_buffer_get_insert (se->buffer)
306 line = gtk_text_iter_get_line (&here) ;
308 /* Now set begin and end to the start of this line, and end of buffer
310 gtk_text_buffer_get_iter_at_line (se->buffer, &begin, line);
311 gtk_text_buffer_get_iter_at_line (se->buffer, &end, -1);
313 execute_syntax (se, begin, end);
320 Create a new syntax editor with NAME.
321 If NAME is NULL, a name will be automatically assigned
323 struct syntax_editor *
324 new_syntax_editor (void)
327 glade_xml_new (PKGDATADIR "/syntax-editor.glade", NULL, NULL);
329 GtkWidget *text_view;
330 struct syntax_editor *se ;
331 struct editor_window *e;
335 se = g_malloc (sizeof (*se));
337 e = (struct editor_window *)se;
339 e->window = GTK_WINDOW (get_widget_assert (xml, "syntax_editor"));
340 text_view = get_widget_assert (xml, "syntax_text_view");
341 se->buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (text_view));
342 se->lexer = lex_create (the_source_stream);
344 g_signal_connect (get_widget_assert (xml,"file_new_syntax"),
346 G_CALLBACK (new_syntax_window),
349 g_signal_connect (get_widget_assert (xml,"file_open_syntax"),
351 G_CALLBACK (open_syntax_window),
354 g_signal_connect (get_widget_assert (xml,"file_new_data"),
356 G_CALLBACK (new_data_window),
359 g_signal_connect (get_widget_assert (xml,"file_open_data"),
361 G_CALLBACK (open_data_window),
365 g_signal_connect (get_widget_assert (xml,"help_about"),
367 G_CALLBACK (about_new),
370 g_signal_connect (get_widget_assert (xml,"help_reference"),
372 G_CALLBACK (reference_manual),
376 g_signal_connect (get_widget_assert (xml, "file_save"),
378 G_CALLBACK (on_syntax_save),
381 g_signal_connect (get_widget_assert (xml, "file_save_as"),
383 G_CALLBACK (on_syntax_save_as),
387 g_signal_connect (get_widget_assert (xml,"file_quit"),
389 G_CALLBACK (on_quit),
393 g_signal_connect (get_widget_assert (xml,"run_all"),
395 G_CALLBACK (on_run_all),
399 g_signal_connect (get_widget_assert (xml,"run_selection"),
401 G_CALLBACK (on_run_selection),
404 g_signal_connect (get_widget_assert (xml,"run_current_line"),
406 G_CALLBACK (on_run_current_line),
410 g_signal_connect (get_widget_assert (xml,"run_to_end"),
412 G_CALLBACK (on_run_to_end),
416 g_signal_connect (get_widget_assert (xml,"windows_minimise_all"),
418 G_CALLBACK (minimise_all_windows),
423 g_object_unref (xml);
425 g_signal_connect (e->window, "delete-event",
426 G_CALLBACK (on_delete), se);
434 Callback for the File->New->Syntax menuitem
437 new_syntax_window (GtkMenuItem *menuitem,
440 window_create (WINDOW_SYNTAX, NULL);
445 Save BUFFER to the file called FILENAME.
446 If successful, clears the buffer's modified flag
449 save_editor_to_file (struct syntax_editor *se,
450 const gchar *filename,
453 GtkTextBuffer *buffer = se->buffer;
455 GtkTextIter start, stop;
462 suffixedname = append_suffix (filename);
464 glibfilename = g_filename_from_utf8 (suffixedname, -1, 0, 0, err);
466 g_free ( suffixedname);
468 if ( ! glibfilename )
471 gtk_text_buffer_get_iter_at_line (buffer, &start, 0);
472 gtk_text_buffer_get_iter_at_offset (buffer, &stop, -1);
474 text = gtk_text_buffer_get_text (buffer, &start, &stop, FALSE);
476 result = g_file_set_contents (glibfilename, text, -1, err);
480 window_set_name_from_filename ((struct editor_window *) se, filename);
481 gtk_text_buffer_set_modified (buffer, FALSE);
489 Loads the buffer from the file called FILENAME
492 load_editor_from_file (struct syntax_editor *se,
493 const gchar *filename,
496 GtkTextBuffer *buffer = se->buffer;
500 gchar *glibfilename = g_filename_from_utf8 (filename, -1, 0, 0, err);
502 if ( ! glibfilename )
505 /* FIXME: What if it's a very big file ? */
506 if ( ! g_file_get_contents (glibfilename, &text, NULL, err) )
508 g_free (glibfilename);
511 g_free (glibfilename);
513 gtk_text_buffer_get_iter_at_line (buffer, &iter, 0);
515 gtk_text_buffer_insert (buffer, &iter, text, -1);
517 window_set_name_from_filename ((struct editor_window *)se, filename);
518 gtk_text_buffer_set_modified (buffer, FALSE);
524 /* Callback for the File->Open->Syntax menuitem */
526 open_syntax_window (GtkMenuItem *menuitem, gpointer parent)
528 GtkFileFilter *filter;
532 gtk_file_chooser_dialog_new (_("Open Syntax"),
534 GTK_FILE_CHOOSER_ACTION_OPEN,
535 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
536 GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
539 filter = gtk_file_filter_new ();
540 gtk_file_filter_set_name (filter, _("Syntax Files (*.sps) "));
541 gtk_file_filter_add_pattern (filter, "*.sps");
542 gtk_file_filter_add_pattern (filter, "*.SPS");
543 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
545 filter = gtk_file_filter_new ();
546 gtk_file_filter_set_name (filter, _("All Files"));
547 gtk_file_filter_add_pattern (filter, "*");
548 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
550 response = gtk_dialog_run (GTK_DIALOG (dialog));
552 if (response == GTK_RESPONSE_ACCEPT)
554 const char *file_name = gtk_file_chooser_get_filename
555 (GTK_FILE_CHOOSER (dialog));
557 struct syntax_editor *se = (struct syntax_editor *)
558 window_create (WINDOW_SYNTAX, file_name);
560 load_editor_from_file (se, file_name, NULL);
563 gtk_widget_destroy (dialog);