Removed my authorship lines.
[pspp-builds.git] / src / ui / gui / syntax-editor.c
1 /*
2     PSPPIRE --- A Graphical User Interface for PSPP
3     Copyright (C) 2006  Free Software Foundation
4
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.
9
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.
14
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
18     02110-1301, USA. */
19
20 #include <config.h>
21 #include <stdlib.h>
22 #include <gettext.h>
23 #define _(msgid) gettext (msgid)
24 #define N_(msgid) msgid
25
26 #include <glade/glade.h>
27 #include <gtk/gtk.h>
28 #include <libpspp/message.h>
29
30 #include "helper.h"
31
32 extern GladeXML *xml;
33
34 struct syntax_editor
35 {
36   GtkWidget *window;      /* The top level window of the editor */
37   GtkTextBuffer *buffer;  /* The buffer which contains the text */
38   gchar *name;            /* The name of this syntax buffer/editor */
39 };
40
41 static gboolean save_editor_to_file (struct syntax_editor *se,
42                                      const gchar *filename,
43                                      GError **err);
44
45 /* If the buffer's modified flag is set, then save it, and close the window.
46    Otherwise just close the window.
47 */
48 static void
49 save_if_modified (struct syntax_editor *se)
50 {
51   if ( TRUE == gtk_text_buffer_get_modified (se->buffer))
52     {
53       gint response;
54       GtkWidget *dialog =
55         gtk_message_dialog_new (GTK_WINDOW(se->window),
56                                 GTK_DIALOG_MODAL,
57                                 GTK_MESSAGE_QUESTION,
58                                 GTK_BUTTONS_NONE,
59                                 _("Save contents of syntax editor to %s?"),
60                                 se->name ? se->name : _("Untitled")
61                                 );
62
63       gtk_dialog_add_button  (GTK_DIALOG(dialog),
64                               GTK_STOCK_YES,
65                               GTK_RESPONSE_ACCEPT);
66       gtk_dialog_add_button  (GTK_DIALOG(dialog),
67                               GTK_STOCK_NO,
68                               GTK_RESPONSE_REJECT);
69       gtk_dialog_add_button  (GTK_DIALOG(dialog),
70                               GTK_STOCK_CANCEL,
71                               GTK_RESPONSE_CANCEL);
72
73
74       response = gtk_dialog_run (GTK_DIALOG(dialog));
75
76       gtk_widget_destroy (dialog);
77
78       if ( response == GTK_RESPONSE_ACCEPT )
79         {
80           GError *err = NULL;
81
82           if ( ! save_editor_to_file (se, se->name ? se->name : _("Untitled"),
83                                       &err) )
84             {
85               msg (ME, err->message);
86               g_error_free (err);
87             }
88         }
89
90       if ( response == GTK_RESPONSE_CANCEL )
91         return ;
92     }
93
94   gtk_widget_destroy (se->window);
95 }
96
97 /* Callback for the File->SaveAs menuitem */
98 static void
99 on_syntax_save_as   (GtkMenuItem     *menuitem,
100                   gpointer         user_data)
101 {
102   GtkFileFilter *filter;
103   gint response;
104   struct syntax_editor *se = user_data;
105
106   GtkWidget *dialog =
107     gtk_file_chooser_dialog_new (_("Save Syntax"),
108                                  GTK_WINDOW(se->window),
109                                  GTK_FILE_CHOOSER_ACTION_SAVE,
110                                  GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
111                                  GTK_STOCK_SAVE,   GTK_RESPONSE_ACCEPT,
112                                  NULL);
113
114   filter = gtk_file_filter_new ();
115   gtk_file_filter_set_name (filter, _("Syntax Files (*.sps) "));
116   gtk_file_filter_add_pattern (filter, "*.sps");
117   gtk_file_filter_add_pattern (filter, "*.SPS");
118   gtk_file_chooser_add_filter (GTK_FILE_CHOOSER(dialog), filter);
119
120   filter = gtk_file_filter_new ();
121   gtk_file_filter_set_name (filter, _("All Files"));
122   gtk_file_filter_add_pattern (filter, "*");
123   gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
124
125   gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER(dialog),
126                                                   TRUE);
127   response = gtk_dialog_run (GTK_DIALOG (dialog));
128
129   if ( response == GTK_RESPONSE_ACCEPT )
130     {
131       GError *err = NULL;
132       char *filename =
133         gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog) );
134
135       if ( save_editor_to_file (se, filename, &err) )
136         {
137           g_free (se->name);
138           se->name = g_strdup (filename);
139         }
140       else
141         {
142           msg ( ME, err->message );
143           g_error_free (err);
144         }
145
146       free (filename);
147     }
148
149   gtk_widget_destroy ( dialog );
150 }
151
152 /* Callback for the File->Save menuitem */
153 void
154 on_syntax_save   (GtkMenuItem     *menuitem,
155                   gpointer         user_data)
156 {
157   struct syntax_editor *se = user_data;
158
159   if ( se->name == NULL )
160     on_syntax_save_as (menuitem, user_data);
161   else
162     {
163       GError *err;
164       save_editor_to_file (se, se->name, &err);
165       msg (ME, err->message);
166       g_error_free (err);
167     }
168 }
169
170
171 /* Callback for the "delete" action (clicking the x on the top right
172    hand corner of the window) */
173 static gboolean
174 on_delete (GtkWidget *w, GdkEvent *event, gpointer user_data)
175 {
176   struct syntax_editor *se = user_data;
177   save_if_modified (se);
178   return TRUE;
179 }
180
181
182 /* Callback for the File->Quit menuitem */
183 static gboolean
184 on_quit (GtkMenuItem *menuitem, gpointer    user_data)
185 {
186   struct syntax_editor *se = user_data;
187   save_if_modified (se);
188   return FALSE;
189 }
190
191 void
192 new_syntax_window (GtkMenuItem     *menuitem,
193                    gpointer         user_data);
194
195
196
197 static void open_syntax_window (GtkMenuItem *menuitem,
198                                 gpointer user_data);
199
200
201 /* Create a new syntax editor with NAME.
202    If NAME is NULL, a name will be automatically assigned
203 */
204 static struct syntax_editor *
205 new_syntax_editor (const gchar *name)
206 {
207   GladeXML *new_xml ;
208   GtkWidget *text_view;
209   struct syntax_editor *se ;
210
211   new_xml = glade_xml_new  (xml->filename, "syntax_editor", NULL);
212
213   se = g_malloc (sizeof (*se));
214
215   se->window = get_widget_assert (new_xml, "syntax_editor");
216   text_view = get_widget_assert (new_xml, "syntax_text_view");
217   se->buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW(text_view));
218   if ( name )
219     se->name = g_strdup (name);
220   else
221     se->name = NULL;
222
223   g_signal_connect (get_widget_assert (new_xml,"file_new_syntax"),
224                     "activate",
225                     G_CALLBACK(new_syntax_window),
226                     se->window);
227
228   g_signal_connect (get_widget_assert (new_xml,"file_open_syntax"),
229                     "activate",
230                     G_CALLBACK(open_syntax_window),
231                     se->window);
232
233   g_signal_connect (get_widget_assert (new_xml,"file_quit"),
234                     "activate",
235                     G_CALLBACK(on_quit),
236                     se);
237
238   g_signal_connect (get_widget_assert (new_xml,"file_save"),
239                     "activate",
240                     G_CALLBACK(on_syntax_save),
241                     se);
242
243   g_signal_connect (get_widget_assert (new_xml,"file_save_as"),
244                     "activate",
245                     G_CALLBACK(on_syntax_save_as),
246                     se);
247
248   g_object_unref (new_xml);
249
250   g_signal_connect (se->window, "delete-event",
251                     G_CALLBACK(on_delete), se);
252
253   return se;
254 }
255
256 /* Callback for the File->New->Syntax menuitem */
257 void
258 new_syntax_window (GtkMenuItem     *menuitem,
259                    gpointer         user_data)
260 {
261   struct syntax_editor *se =   new_syntax_editor (NULL);
262   gtk_widget_show (se->window);
263 }
264
265
266 static void
267 set_window_title_from_filename (struct syntax_editor *se,
268                                 const gchar *filename)
269 {
270   gchar *title;
271   gchar *basename ;
272   g_free (se->name);
273   se->name = strdup (filename);
274   basename = g_path_get_basename (filename);
275   title =
276     g_strdup_printf (_("%s --- PSPP Syntax Editor"), basename);
277   g_free (basename);
278   gtk_window_set_title (GTK_WINDOW(se->window), title);
279   g_free (title);
280 }
281
282
283 /* Save BUFFER to the file called FILENAME.
284    If successful, clears the buffer's modified flag */
285 static gboolean
286 save_editor_to_file (struct syntax_editor *se,
287                      const gchar *filename,
288                      GError **err)
289 {
290   GtkTextBuffer *buffer = se->buffer;
291   gboolean result ;
292   GtkTextIter start, stop;
293   gchar *text;
294
295   gchar *glibfilename;
296   g_assert (filename);
297
298   glibfilename = g_filename_from_utf8 (filename, -1, 0, 0, err);
299
300   if ( ! glibfilename )
301     return FALSE;
302
303   gtk_text_buffer_get_iter_at_line (buffer, &start, 0);
304   gtk_text_buffer_get_iter_at_offset (buffer, &stop, -1);
305
306   text = gtk_text_buffer_get_text (buffer, &start, &stop, FALSE);
307
308   result =  g_file_set_contents (glibfilename, text, -1, err);
309
310   if ( result )
311     {
312       set_window_title_from_filename (se, filename);
313       gtk_text_buffer_set_modified (buffer, FALSE);
314     }
315
316   return result;
317 }
318
319
320 /* Loads the buffer from the file called FILENAME
321 */
322 static gboolean
323 load_editor_from_file (struct syntax_editor *se,
324                        const gchar *filename,
325                        GError **err)
326 {
327   GtkTextBuffer *buffer = se->buffer;
328   gchar *text;
329   GtkTextIter iter;
330
331   gchar *glibfilename = g_filename_from_utf8 (filename, -1, 0, 0, err);
332
333   if ( ! glibfilename )
334     return FALSE;
335
336   /* FIXME: What if it's a very big file ? */
337   if ( ! g_file_get_contents (glibfilename, &text, NULL, err) )
338     {
339       g_free (glibfilename);
340       return FALSE;
341     }
342   g_free (glibfilename);
343
344   gtk_text_buffer_get_iter_at_line (buffer, &iter, 0);
345
346   gtk_text_buffer_insert (buffer, &iter, text, -1);
347
348   set_window_title_from_filename (se, filename);
349   gtk_text_buffer_set_modified (buffer, FALSE);
350
351   return TRUE;
352 }
353
354
355 /* Callback for the File->Open->Syntax menuitem */
356 static void
357 open_syntax_window (GtkMenuItem *menuitem, gpointer parent)
358 {
359   GtkFileFilter *filter;
360   gint response;
361
362   GtkWidget *dialog =
363     gtk_file_chooser_dialog_new (_("Open Syntax"),
364                                  GTK_WINDOW(parent),
365                                  GTK_FILE_CHOOSER_ACTION_OPEN,
366                                  GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
367                                  GTK_STOCK_OPEN,   GTK_RESPONSE_ACCEPT,
368                                  NULL);
369
370   filter = gtk_file_filter_new ();
371   gtk_file_filter_set_name (filter, _("Syntax Files (*.sps) "));
372   gtk_file_filter_add_pattern (filter, "*.sps");
373   gtk_file_filter_add_pattern (filter, "*.SPS");
374   gtk_file_chooser_add_filter (GTK_FILE_CHOOSER(dialog), filter);
375
376   filter = gtk_file_filter_new ();
377   gtk_file_filter_set_name (filter, _("All Files"));
378   gtk_file_filter_add_pattern (filter, "*");
379   gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
380
381   response = gtk_dialog_run (GTK_DIALOG (dialog));
382
383   if (response == GTK_RESPONSE_ACCEPT)
384     {
385       const char *file_name = gtk_file_chooser_get_filename
386         (GTK_FILE_CHOOSER (dialog));
387
388       struct syntax_editor *se = new_syntax_editor (file_name);
389
390       load_editor_from_file (se, file_name, NULL);
391
392       gtk_widget_show (se->window);
393     }
394
395   gtk_widget_destroy (dialog);
396 }
397
398
399 #if 1
400 /* FIXME: get rid of these functions */
401 void
402 on_syntax4_activate   (GtkMenuItem     *menuitem,
403                        gpointer         user_data)
404 {
405   g_print ("%s\n", __FUNCTION__);
406 }
407
408
409
410 void
411 on_syntax2_activate   (GtkMenuItem     *menuitem,
412                        gpointer         user_data)
413 {
414   g_print ("%s\n", __FUNCTION__);
415 }
416
417 void
418 on_syntax1_activate   (GtkMenuItem     *menuitem,
419                        gpointer         user_data)
420 {
421   g_print ("%s\n", __FUNCTION__);
422   new_syntax_window (menuitem, user_data);
423 }
424 #endif
425