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 (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;
328 se = g_malloc (sizeof (*se));
330 e = (struct editor_window *)se;
332 e->window = get_widget_assert (xml, "syntax_editor");
333 text_view = get_widget_assert (xml, "syntax_text_view");
334 se->buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (text_view));
335 se->lexer = lex_create (the_source_stream);
337 g_signal_connect (get_widget_assert (xml,"file_new_syntax"),
339 G_CALLBACK (new_syntax_window),
342 g_signal_connect (get_widget_assert (xml,"file_open_syntax"),
344 G_CALLBACK (open_syntax_window),
347 g_signal_connect (get_widget_assert (xml,"file_new_data"),
349 G_CALLBACK (new_data_window),
352 g_signal_connect (get_widget_assert (xml,"file_open_data"),
354 G_CALLBACK (open_data_window),
358 g_signal_connect (get_widget_assert (xml,"help_about"),
360 G_CALLBACK (about_new),
364 g_signal_connect (get_widget_assert (xml, "file_save"),
366 G_CALLBACK (on_syntax_save),
369 g_signal_connect (get_widget_assert (xml, "file_save_as"),
371 G_CALLBACK (on_syntax_save_as),
375 g_signal_connect (get_widget_assert (xml,"file_quit"),
377 G_CALLBACK (on_quit),
381 g_signal_connect (get_widget_assert (xml,"run_all"),
383 G_CALLBACK (on_run_all),
387 g_signal_connect (get_widget_assert (xml,"run_selection"),
389 G_CALLBACK (on_run_selection),
392 g_signal_connect (get_widget_assert (xml,"run_current_line"),
394 G_CALLBACK (on_run_current_line),
398 g_signal_connect (get_widget_assert (xml,"run_to_end"),
400 G_CALLBACK (on_run_to_end),
404 g_object_unref (xml);
406 g_signal_connect (e->window, "delete-event",
407 G_CALLBACK (on_delete), se);
415 Callback for the File->New->Syntax menuitem
418 new_syntax_window (GtkMenuItem *menuitem,
421 window_create (WINDOW_SYNTAX, NULL);
426 Save BUFFER to the file called FILENAME.
427 If successful, clears the buffer's modified flag
430 save_editor_to_file (struct syntax_editor *se,
431 const gchar *filename,
434 GtkTextBuffer *buffer = se->buffer;
436 GtkTextIter start, stop;
443 suffixedname = append_suffix (filename);
445 glibfilename = g_filename_from_utf8 (suffixedname, -1, 0, 0, err);
447 g_free ( suffixedname);
449 if ( ! glibfilename )
452 gtk_text_buffer_get_iter_at_line (buffer, &start, 0);
453 gtk_text_buffer_get_iter_at_offset (buffer, &stop, -1);
455 text = gtk_text_buffer_get_text (buffer, &start, &stop, FALSE);
457 result = g_file_set_contents (glibfilename, text, -1, err);
461 window_set_name_from_filename ((struct editor_window *) se, filename);
462 gtk_text_buffer_set_modified (buffer, FALSE);
470 Loads the buffer from the file called FILENAME
473 load_editor_from_file (struct syntax_editor *se,
474 const gchar *filename,
477 GtkTextBuffer *buffer = se->buffer;
481 gchar *glibfilename = g_filename_from_utf8 (filename, -1, 0, 0, err);
483 if ( ! glibfilename )
486 /* FIXME: What if it's a very big file ? */
487 if ( ! g_file_get_contents (glibfilename, &text, NULL, err) )
489 g_free (glibfilename);
492 g_free (glibfilename);
494 gtk_text_buffer_get_iter_at_line (buffer, &iter, 0);
496 gtk_text_buffer_insert (buffer, &iter, text, -1);
498 window_set_name_from_filename ((struct editor_window *)se, filename);
499 gtk_text_buffer_set_modified (buffer, FALSE);
505 /* Callback for the File->Open->Syntax menuitem */
507 open_syntax_window (GtkMenuItem *menuitem, gpointer parent)
509 GtkFileFilter *filter;
513 gtk_file_chooser_dialog_new (_("Open Syntax"),
515 GTK_FILE_CHOOSER_ACTION_OPEN,
516 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
517 GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
520 filter = gtk_file_filter_new ();
521 gtk_file_filter_set_name (filter, _("Syntax Files (*.sps) "));
522 gtk_file_filter_add_pattern (filter, "*.sps");
523 gtk_file_filter_add_pattern (filter, "*.SPS");
524 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
526 filter = gtk_file_filter_new ();
527 gtk_file_filter_set_name (filter, _("All Files"));
528 gtk_file_filter_add_pattern (filter, "*");
529 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
531 response = gtk_dialog_run (GTK_DIALOG (dialog));
533 if (response == GTK_RESPONSE_ACCEPT)
535 const char *file_name = gtk_file_chooser_get_filename
536 (GTK_FILE_CHOOSER (dialog));
538 struct syntax_editor *se = (struct syntax_editor *)
539 window_create (WINDOW_SYNTAX, file_name);
541 load_editor_from_file (se, file_name, NULL);
544 gtk_widget_destroy (dialog);