Relocate the directory in which the lang file is installed
[pspp-builds.git] / src / ui / gui / psppire-syntax-window.c
1 /* PSPPIRE - a graphical user interface for PSPP.
2    Copyright (C) 2008, 2009, 2010  Free Software Foundation
3
4    This program is free software: you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation, either version 3 of the License, or
7    (at your option) any later version.
8
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13
14    You should have received a copy of the GNU General Public License
15    along with this program.  If not, see <http://www.gnu.org/licenses/>. */
16
17 #include <config.h>
18
19 #include "relocatable.h"
20
21 #include <gtk/gtksignal.h>
22 #include <gtk/gtkbox.h>
23 #include "executor.h"
24 #include "helper.h"
25
26 #include <gtksourceview/gtksourcebuffer.h>
27 #include <gtksourceview/gtksourcelanguage.h>
28 #include <gtksourceview/gtksourcelanguagemanager.h>
29 #include <gtksourceview/gtksourceprintcompositor.h>
30
31 #include <libpspp/message.h>
32 #include <stdlib.h>
33
34 #include "psppire.h"
35
36 #include "psppire-data-window.h"
37 #include "psppire-window-register.h"
38 #include "psppire.h"
39 #include "help-menu.h"
40 #include "psppire-syntax-window.h"
41 #include "syntax-editor-source.h"
42 #include <language/lexer/lexer.h>
43
44 #include "xalloc.h"
45
46 #include <gettext.h>
47 #define _(msgid) gettext (msgid)
48 #define N_(msgid) msgid
49
50 static void psppire_syntax_window_base_finalize (PsppireSyntaxWindowClass *, gpointer);
51 static void psppire_syntax_window_base_init     (PsppireSyntaxWindowClass *class);
52 static void psppire_syntax_window_class_init    (PsppireSyntaxWindowClass *class);
53 static void psppire_syntax_window_init          (PsppireSyntaxWindow      *syntax_editor);
54
55
56 static void psppire_syntax_window_iface_init (PsppireWindowIface *iface);
57
58
59 GType
60 psppire_syntax_window_get_type (void)
61 {
62   static GType psppire_syntax_window_type = 0;
63
64   if (!psppire_syntax_window_type)
65     {
66       static const GTypeInfo psppire_syntax_window_info =
67       {
68         sizeof (PsppireSyntaxWindowClass),
69         (GBaseInitFunc) psppire_syntax_window_base_init,
70         (GBaseFinalizeFunc) psppire_syntax_window_base_finalize,
71         (GClassInitFunc)psppire_syntax_window_class_init,
72         (GClassFinalizeFunc) NULL,
73         NULL,
74         sizeof (PsppireSyntaxWindow),
75         0,
76         (GInstanceInitFunc) psppire_syntax_window_init,
77       };
78
79       static const GInterfaceInfo window_interface_info =
80         {
81           (GInterfaceInitFunc) psppire_syntax_window_iface_init,
82           NULL,
83           NULL
84         };
85
86       psppire_syntax_window_type =
87         g_type_register_static (PSPPIRE_TYPE_WINDOW, "PsppireSyntaxWindow",
88                                 &psppire_syntax_window_info, 0);
89
90       g_type_add_interface_static (psppire_syntax_window_type,
91                                    PSPPIRE_TYPE_WINDOW_MODEL,
92                                    &window_interface_info);
93     }
94
95   return psppire_syntax_window_type;
96 }
97
98 static GObjectClass *parent_class ;
99
100 static void
101 psppire_syntax_window_finalize (GObject *object)
102 {
103   if (G_OBJECT_CLASS (parent_class)->finalize)
104     (*G_OBJECT_CLASS (parent_class)->finalize) (object);
105 }
106
107
108 static void
109 psppire_syntax_window_class_init (PsppireSyntaxWindowClass *class)
110 {
111   GtkSourceLanguageManager *lm = gtk_source_language_manager_get_default ();
112
113   const gchar * const *existing_paths =  gtk_source_language_manager_get_search_path (lm);
114
115   const gchar **new_paths = g_strdupv (existing_paths);
116
117   int n = g_strv_length (existing_paths);
118
119   new_paths = g_realloc (new_paths, (n+1) * sizeof (*new_paths));
120
121   new_paths[n] = g_strdup (relocate (PKGDATADIR));
122   new_paths[n+1] = NULL;
123
124   lm = gtk_source_language_manager_new ();
125   gtk_source_language_manager_set_search_path (lm, new_paths);
126
127   class->lan = gtk_source_language_manager_get_language (lm, "pspp");
128
129   if (class->lan == NULL)
130     g_warning ("pspp.lang file not found.  Syntax highlighting will not be available.");
131
132   parent_class = g_type_class_peek_parent (class);
133 }
134
135
136 static void
137 psppire_syntax_window_base_init (PsppireSyntaxWindowClass *class)
138 {
139   GObjectClass *object_class = G_OBJECT_CLASS (class);
140   object_class->finalize = psppire_syntax_window_finalize;
141 }
142
143
144
145 static void
146 psppire_syntax_window_base_finalize (PsppireSyntaxWindowClass *class,
147                                      gpointer class_data)
148 {
149 }
150
151
152 static void
153 editor_execute_syntax (const PsppireSyntaxWindow *sw, GtkTextIter start,
154                        GtkTextIter stop)
155 {
156   PsppireWindow *win = PSPPIRE_WINDOW (sw);
157   const gchar *name = psppire_window_get_filename (win);
158   execute_syntax (create_syntax_editor_source (GTK_TEXT_BUFFER (sw->buffer), start, stop, name));
159 }
160
161
162 /* Parse and execute all the text in the buffer */
163 static void
164 on_run_all (GtkMenuItem *menuitem, gpointer user_data)
165 {
166   GtkTextIter begin, end;
167   PsppireSyntaxWindow *se = PSPPIRE_SYNTAX_WINDOW (user_data);
168
169   gtk_text_buffer_get_iter_at_offset (GTK_TEXT_BUFFER (se->buffer), &begin, 0);
170   gtk_text_buffer_get_iter_at_offset (GTK_TEXT_BUFFER (se->buffer), &end, -1);
171
172   editor_execute_syntax (se, begin, end);
173 }
174
175 /* Parse and execute the currently selected text */
176 static void
177 on_run_selection (GtkMenuItem *menuitem, gpointer user_data)
178 {
179   GtkTextIter begin, end;
180   PsppireSyntaxWindow *se = PSPPIRE_SYNTAX_WINDOW (user_data);
181
182   if ( gtk_text_buffer_get_selection_bounds (GTK_TEXT_BUFFER (se->buffer), &begin, &end) )
183     editor_execute_syntax (se, begin, end);
184 }
185
186
187 /* Parse and execute the from the current line, to the end of the
188    buffer */
189 static void
190 on_run_to_end (GtkMenuItem *menuitem, gpointer user_data)
191 {
192   GtkTextIter begin, end;
193   GtkTextIter here;
194   gint line;
195
196   PsppireSyntaxWindow *se = PSPPIRE_SYNTAX_WINDOW (user_data);
197
198   /* Get the current line */
199   gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (se->buffer),
200                                     &here,
201                                     gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (se->buffer))
202                                     );
203
204   line = gtk_text_iter_get_line (&here) ;
205
206   /* Now set begin and end to the start of this line, and end of buffer
207      respectively */
208   gtk_text_buffer_get_iter_at_line (GTK_TEXT_BUFFER (se->buffer), &begin, line);
209   gtk_text_buffer_get_iter_at_line (GTK_TEXT_BUFFER (se->buffer), &end, -1);
210
211   editor_execute_syntax (se, begin, end);
212 }
213
214
215
216 /* Parse and execute the current line */
217 static void
218 on_run_current_line (GtkMenuItem *menuitem, gpointer user_data)
219 {
220   GtkTextIter begin, end;
221   GtkTextIter here;
222   gint line;
223
224   PsppireSyntaxWindow *se = PSPPIRE_SYNTAX_WINDOW (user_data);
225
226   /* Get the current line */
227   gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (se->buffer),
228                                     &here,
229                                     gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (se->buffer))
230                                     );
231
232   line = gtk_text_iter_get_line (&here) ;
233
234   /* Now set begin and end to the start of this line, and start of
235      following line respectively */
236   gtk_text_buffer_get_iter_at_line (GTK_TEXT_BUFFER (se->buffer), &begin, line);
237   gtk_text_buffer_get_iter_at_line (GTK_TEXT_BUFFER (se->buffer), &end, line + 1);
238
239   editor_execute_syntax (se, begin, end);
240 }
241
242
243
244 /* Append ".sps" to FILENAME if necessary.
245    The returned result must be freed when no longer required.
246  */
247 static gchar *
248 append_suffix (const gchar *filename)
249 {
250   if ( ! g_str_has_suffix (filename, ".sps" ) &&
251        ! g_str_has_suffix (filename, ".SPS" ) )
252     {
253       return g_strdup_printf ("%s.sps", filename);
254     }
255
256   return xstrdup (filename);
257 }
258
259 /*
260   Save BUFFER to the file called FILENAME.
261   FILENAME must be encoded in Glib filename encoding.
262   If successful, clears the buffer's modified flag.
263 */
264 static gboolean
265 save_editor_to_file (PsppireSyntaxWindow *se,
266                      const gchar *filename,
267                      GError **err)
268 {
269   GtkTextBuffer *buffer = GTK_TEXT_BUFFER (se->buffer);
270   gboolean result ;
271   GtkTextIter start, stop;
272   gchar *text;
273
274   gchar *suffixedname;
275   g_assert (filename);
276
277   suffixedname = append_suffix (filename);
278
279   gtk_text_buffer_get_iter_at_line (buffer, &start, 0);
280   gtk_text_buffer_get_iter_at_offset (buffer, &stop, -1);
281
282   text = gtk_text_buffer_get_text (buffer, &start, &stop, FALSE);
283
284   result =  g_file_set_contents (suffixedname, text, -1, err);
285
286   g_free (suffixedname);
287
288   if ( result )
289     {
290       char *fn = g_filename_display_name (filename);
291       gchar *msg = g_strdup_printf (_("Saved file \"%s\""), fn);
292       g_free (fn);
293       gtk_statusbar_push (GTK_STATUSBAR (se->sb), se->text_context, msg);
294       gtk_text_buffer_set_modified (buffer, FALSE);
295       g_free (msg);
296     }
297
298   return result;
299 }
300
301
302 /* Callback for the File->SaveAs menuitem */
303 static void
304 syntax_save_as (PsppireWindow *se)
305 {
306   GtkFileFilter *filter;
307   gint response;
308
309   GtkWidget *dialog =
310     gtk_file_chooser_dialog_new (_("Save Syntax"),
311                                  GTK_WINDOW (se),
312                                  GTK_FILE_CHOOSER_ACTION_SAVE,
313                                  GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
314                                  GTK_STOCK_SAVE,   GTK_RESPONSE_ACCEPT,
315                                  NULL);
316
317   filter = gtk_file_filter_new ();
318   gtk_file_filter_set_name (filter, _("Syntax Files (*.sps) "));
319   gtk_file_filter_add_pattern (filter, "*.sps");
320   gtk_file_filter_add_pattern (filter, "*.SPS");
321   gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
322
323   filter = gtk_file_filter_new ();
324   gtk_file_filter_set_name (filter, _("All Files"));
325   gtk_file_filter_add_pattern (filter, "*");
326   gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
327
328   gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dialog),
329                                                   TRUE);
330   response = gtk_dialog_run (GTK_DIALOG (dialog));
331
332   if ( response == GTK_RESPONSE_ACCEPT )
333     {
334       GError *err = NULL;
335       char *filename =
336         gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog) );
337
338       if ( ! save_editor_to_file (PSPPIRE_SYNTAX_WINDOW (se), filename, &err) )
339         {
340           msg ( ME, "%s", err->message );
341           g_error_free (err);
342         }
343
344       free (filename);
345     }
346
347   gtk_widget_destroy (dialog);
348 }
349
350
351 /* Callback for the File->Save menuitem */
352 static void
353 syntax_save (PsppireWindow *se)
354 {
355   const gchar *filename = psppire_window_get_filename (se);
356
357   if ( filename == NULL )
358     syntax_save_as (se);
359   else
360     {
361       GError *err = NULL;
362       save_editor_to_file (PSPPIRE_SYNTAX_WINDOW (se), filename, &err);
363       if ( err )
364         {
365           msg (ME, "%s", err->message);
366           g_error_free (err);
367         }
368     }
369 }
370
371
372 /* Callback for the File->Quit menuitem */
373 static gboolean
374 on_quit (GtkMenuItem *menuitem, gpointer    user_data)
375 {
376   psppire_quit ();
377
378   return FALSE;
379 }
380
381
382 static void
383 load_and_show_syntax_window (GtkWidget *se, const gchar *filename)
384 {
385   gboolean ok;
386
387   gtk_source_buffer_begin_not_undoable_action (PSPPIRE_SYNTAX_WINDOW (se)->buffer);
388   ok = psppire_window_load (PSPPIRE_WINDOW (se), filename);
389   gtk_source_buffer_end_not_undoable_action (PSPPIRE_SYNTAX_WINDOW (se)->buffer);
390
391   if (ok )
392     gtk_widget_show (se);
393   else
394     gtk_widget_destroy (se);
395 }
396
397 void
398 create_syntax_window (void)
399 {
400   GtkWidget *w = psppire_syntax_window_new ();
401   gtk_widget_show (w);
402 }
403
404 void
405 open_new_syntax_window (const char *file_name)
406 {
407   GtkWidget *se = psppire_syntax_window_new ();
408
409   if ( file_name)
410     load_and_show_syntax_window (se, file_name);
411 }
412
413
414
415 static void psppire_syntax_window_print (PsppireSyntaxWindow *window);
416
417 static void
418 on_modified_changed (GtkTextBuffer *buffer, PsppireWindow *window)
419 {
420   if (gtk_text_buffer_get_modified (buffer))
421     psppire_window_set_unsaved (window);
422 }
423
424 extern struct source_stream *the_source_stream ;
425
426 static void undo_redo_update (PsppireSyntaxWindow *window);
427 static void undo_last_edit (PsppireSyntaxWindow *window);
428 static void redo_last_edit (PsppireSyntaxWindow *window);
429
430 static void
431 on_text_changed (GtkTextBuffer *buffer, PsppireSyntaxWindow *window)
432 {
433   gtk_statusbar_pop (GTK_STATUSBAR (window->sb), window->text_context);
434   undo_redo_update (window);
435 }
436
437 static void
438 psppire_syntax_window_init (PsppireSyntaxWindow *window)
439 {
440   GtkBuilder *xml = builder_new ("syntax-editor.ui");
441   GtkWidget *box = gtk_vbox_new (FALSE, 0);
442
443   GtkWidget *menubar = get_widget_assert (xml, "menubar");
444   GtkWidget *sw = get_widget_assert (xml, "scrolledwindow8");
445
446   GtkWidget *text_view = get_widget_assert (xml, "syntax_text_view");
447
448   PsppireSyntaxWindowClass *class
449     = PSPPIRE_SYNTAX_WINDOW_CLASS (G_OBJECT_GET_CLASS (window));
450
451   window->print_settings = NULL;
452   window->undo_menuitem = get_action_assert (xml, "edit_undo");
453   window->redo_menuitem = get_action_assert (xml, "edit_redo");
454
455   if (class->lan)
456     window->buffer = gtk_source_buffer_new_with_language (class->lan);
457   else
458     window->buffer = gtk_source_buffer_new (NULL);
459
460   gtk_text_view_set_buffer (GTK_TEXT_VIEW (text_view), GTK_TEXT_BUFFER (window->buffer));
461
462   g_object_set (window->buffer,
463                 "highlight-matching-brackets", TRUE,
464                 NULL);
465
466
467   g_object_set (text_view,
468                 "show-line-numbers", TRUE,
469                 "show-line-marks", TRUE,
470                 "auto-indent", TRUE,
471                 "indent-width", 4,
472                 "highlight-current-line", TRUE,
473                 NULL);
474   window->lexer = lex_create (the_source_stream);
475
476   window->sb = get_widget_assert (xml, "statusbar2");
477   window->text_context = gtk_statusbar_get_context_id (GTK_STATUSBAR (window->sb), "Text Context");
478
479   g_signal_connect (window->buffer, "changed", G_CALLBACK (on_text_changed), window);
480
481   g_signal_connect (window->buffer, "modified-changed",
482                     G_CALLBACK (on_modified_changed), window);
483
484   g_signal_connect_swapped (get_action_assert (xml, "file_print"), "activate",
485                             G_CALLBACK (psppire_syntax_window_print), window);
486
487
488   g_signal_connect_swapped (window->undo_menuitem,
489                             "activate",
490                             G_CALLBACK (undo_last_edit),
491                             window);
492
493   g_signal_connect_swapped (window->redo_menuitem,
494                             "activate",
495                             G_CALLBACK (redo_last_edit),
496                             window);
497
498   undo_redo_update (window);
499
500   connect_help (xml);
501
502   gtk_container_add (GTK_CONTAINER (window), box);
503
504   g_object_ref (menubar);
505
506   g_object_ref (sw);
507
508   g_object_ref (window->sb);
509
510
511   gtk_box_pack_start (GTK_BOX (box), menubar, FALSE, TRUE, 0);
512   gtk_box_pack_start (GTK_BOX (box), sw, TRUE, TRUE, 0);
513   gtk_box_pack_start (GTK_BOX (box), window->sb, FALSE, TRUE, 0);
514
515   gtk_widget_show_all (box);
516
517   g_signal_connect_swapped (get_action_assert (xml,"file_new_syntax"), "activate", G_CALLBACK (create_syntax_window), NULL);
518
519 #if 0
520   g_signal_connect (get_action_assert (xml,"file_new_data"),
521                     "activate",
522                     G_CALLBACK (create_data_window),
523                     window);
524 #endif
525
526   g_signal_connect_swapped (get_action_assert (xml, "file_save"),
527                     "activate",
528                     G_CALLBACK (syntax_save),
529                     window);
530
531   g_signal_connect_swapped (get_action_assert (xml, "file_save_as"),
532                     "activate",
533                     G_CALLBACK (syntax_save_as),
534                     window);
535
536   g_signal_connect (get_action_assert (xml,"file_quit"),
537                     "activate",
538                     G_CALLBACK (on_quit),
539                     window);
540
541   g_signal_connect (get_action_assert (xml,"run_all"),
542                     "activate",
543                     G_CALLBACK (on_run_all),
544                     window);
545
546
547   g_signal_connect (get_action_assert (xml,"run_selection"),
548                     "activate",
549                     G_CALLBACK (on_run_selection),
550                     window);
551
552   g_signal_connect (get_action_assert (xml,"run_current_line"),
553                     "activate",
554                     G_CALLBACK (on_run_current_line),
555                     window);
556
557   g_signal_connect (get_action_assert (xml,"run_to_end"),
558                     "activate",
559                     G_CALLBACK (on_run_to_end),
560                     window);
561
562   g_signal_connect (get_action_assert (xml,"windows_minimise_all"),
563                     "activate",
564                     G_CALLBACK (psppire_window_minimise_all), NULL);
565
566
567
568
569
570   {
571   GtkUIManager *uim = GTK_UI_MANAGER (get_object_assert (xml, "uimanager1", GTK_TYPE_UI_MANAGER));
572
573   merge_help_menu (uim);
574
575   PSPPIRE_WINDOW (window)->menu =
576     GTK_MENU_SHELL (gtk_ui_manager_get_widget (uim,"/ui/menubar/windows/windows_minimise_all")->parent);
577   }
578
579   g_object_unref (xml);
580 }
581
582
583 GtkWidget*
584 psppire_syntax_window_new (void)
585 {
586   return GTK_WIDGET (g_object_new (psppire_syntax_window_get_type (),
587                                    "filename", "Syntax",
588                                    "description", _("Syntax Editor"),
589                                    NULL));
590 }
591
592 static void
593 error_dialog (GtkWindow *w, const gchar *filename,  GError *err)
594 {
595   gchar *fn = g_filename_display_basename (filename);
596
597   GtkWidget *dialog =
598     gtk_message_dialog_new (w,
599                             GTK_DIALOG_DESTROY_WITH_PARENT,
600                             GTK_MESSAGE_ERROR,
601                             GTK_BUTTONS_CLOSE,
602                             _("Cannot load syntax file '%s'"),
603                             fn);
604
605   g_free (fn);
606
607   g_object_set (dialog, "icon-name", "psppicon", NULL);
608
609   gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
610                                             "%s", err->message);
611
612   gtk_dialog_run (GTK_DIALOG (dialog));
613
614   gtk_widget_destroy (dialog);
615 }
616
617 /*
618   Loads the buffer from the file called FILENAME
619 */
620 gboolean
621 syntax_load (PsppireWindow *window, const gchar *filename)
622 {
623   GError *err = NULL;
624   gchar *text_locale = NULL;
625   gchar *text_utf8 = NULL;
626   gsize len_locale = -1;
627   gsize len_utf8 = -1;
628   GtkTextIter iter;
629   PsppireSyntaxWindow *sw = PSPPIRE_SYNTAX_WINDOW (window);
630   GtkTextBuffer *buffer = GTK_TEXT_BUFFER (sw->buffer);
631   /* FIXME: What if it's a very big file ? */
632   if ( ! g_file_get_contents (filename, &text_locale, &len_locale, &err) )
633     {
634       error_dialog (GTK_WINDOW (window), filename, err);
635       g_clear_error (&err);
636       return FALSE;
637     }
638
639   text_utf8 = g_locale_to_utf8 (text_locale, len_locale, NULL, &len_utf8, &err);
640
641   free (text_locale);
642
643   if ( text_utf8 == NULL )
644     {
645       error_dialog (GTK_WINDOW (window), filename, err);
646       g_clear_error (&err);
647       return FALSE;
648     }
649
650   gtk_text_buffer_get_iter_at_line (buffer, &iter, 0);
651
652   gtk_text_buffer_insert (buffer, &iter, text_utf8, len_utf8);
653
654   gtk_text_buffer_set_modified (buffer, FALSE);
655
656   free (text_utf8);
657
658   return TRUE;
659 }
660
661 \f
662
663 static void
664 psppire_syntax_window_iface_init (PsppireWindowIface *iface)
665 {
666   iface->save = syntax_save;
667   iface->load = syntax_load;
668 }
669
670 \f
671
672 static void
673 undo_redo_update (PsppireSyntaxWindow *window)
674 {
675   gtk_action_set_sensitive (window->undo_menuitem,
676                             gtk_source_buffer_can_undo (window->buffer));
677
678   gtk_action_set_sensitive (window->redo_menuitem,
679                             gtk_source_buffer_can_redo (window->buffer));
680 }
681
682 static void
683 undo_last_edit (PsppireSyntaxWindow *window)
684 {
685   gtk_source_buffer_undo (window->buffer);
686   undo_redo_update (window);
687 }
688
689 static void
690 redo_last_edit (PsppireSyntaxWindow *window)
691 {
692   gtk_source_buffer_redo (window->buffer);
693   undo_redo_update (window);
694 }
695
696
697 \f
698 /* Printing related stuff */
699
700
701 static void
702 begin_print (GtkPrintOperation *operation,
703           GtkPrintContext   *context,
704           PsppireSyntaxWindow *window)
705 {
706   window->compositor =
707     gtk_source_print_compositor_new (window->buffer);
708 }
709
710
711 static void
712 end_print (GtkPrintOperation *operation,
713           GtkPrintContext   *context,
714           PsppireSyntaxWindow *window)
715 {
716   g_object_unref (window->compositor);
717   window->compositor = NULL;
718 }
719
720
721
722 static gboolean
723 paginate (GtkPrintOperation *operation,
724           GtkPrintContext   *context,
725           PsppireSyntaxWindow *window)
726 {
727   if (gtk_source_print_compositor_paginate (window->compositor, context))
728     {
729       gint n_pages = gtk_source_print_compositor_get_n_pages (window->compositor);
730       gtk_print_operation_set_n_pages (operation, n_pages);
731         
732       return TRUE;
733     }
734
735   return FALSE;
736 }
737
738 static void
739 draw_page (GtkPrintOperation *operation,
740            GtkPrintContext   *context,
741            gint               page_nr,
742           PsppireSyntaxWindow *window)
743 {
744   gtk_source_print_compositor_draw_page (window->compositor, 
745                                          context,
746                                          page_nr);
747 }
748
749
750
751 static void
752 psppire_syntax_window_print (PsppireSyntaxWindow *window)
753 {
754   GtkPrintOperationResult res;
755
756   GtkPrintOperation *print = gtk_print_operation_new ();
757
758   if (window->print_settings != NULL) 
759     gtk_print_operation_set_print_settings (print, window->print_settings);
760
761
762   g_signal_connect (print, "begin_print", G_CALLBACK (begin_print), window);
763   g_signal_connect (print, "end_print", G_CALLBACK (end_print),     window);
764   g_signal_connect (print, "draw_page", G_CALLBACK (draw_page),     window);
765   g_signal_connect (print, "paginate", G_CALLBACK (paginate),       window);
766
767   res = gtk_print_operation_run (print, GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG,
768                                  GTK_WINDOW (window), NULL);
769
770   if (res == GTK_PRINT_OPERATION_RESULT_APPLY)
771     {
772       if (window->print_settings != NULL)
773         g_object_unref (window->print_settings);
774       window->print_settings = g_object_ref (gtk_print_operation_get_print_settings (print));
775     }
776
777   g_object_unref (print);
778 }