1 /*  file.c
2  * License: this file may be used under the FSF GPL version 3 or later
3  *  Denemo File IO
4  *
5  *  for Denemo, a gtk+ frontend to GNU Lilypond
6  *  (c) Adam Tee, Matthew Hiller 2000-2005
7  *  (c) University of Leeds 2000-2005
8  *      (c) Richard Shann 2010
9  */
10 
11 #include "display/calculatepositions.h"
12 #include "command/commandfuncs.h"
13 #include "command/contexts.h"
14 #include <denemo/denemo.h>
15 #include "ui/dialogs.h"
16 #include "export/exportabc.h"
17 #include "export/exportlilypond.h"
18 #include "export/file.h"
19 #include "export/guidedimportmidi.h"
20 #include "ui/moveviewport.h"
21 #include "command/staff.h"
22 #include "command/score.h"
23 #include "core/cache.h"
24 #include "core/utils.h"
25 #include "core/exportxml.h"
26 #include "export/exportmidi.h"
27 #include "core/importxml.h"
28 #include "export/importmusicxml.h"
29 #include "importmidi.h"
30 
31 #include "core/prefops.h"
32 #include "core/binreloc.h"
33 #include "core/view.h"
34 #include "command/lilydirectives.h"
35 #include "ui/texteditors.h"
36 #include "export/print.h"
37 #include <stdio.h>
38 #include <string.h>
39 #include <sys/stat.h>           /* check existance and type of files */
40 #include <dirent.h>             /* filter and sort filenames */
41 #include "source/source.h"
42 #include "source/sourceaudio.h"
43 #include "source/proof.h"
44 #include "audio/pitchentry.h"
45 #include "audio/audiointerface.h"
46 
47 static gint file_open (DenemoProject * gui, DenemoSaveType template, ImportType type, gchar * filename);
48 static gint file_import_lilypond (DenemoProject * gui, DenemoSaveType template, ImportType type, gchar * filename);
49 static gint file_import_midi (DenemoProject * gui, DenemoSaveType template, ImportType type, gchar * filename);
50 static gint file_import_musicxml (DenemoProject * gui, DenemoSaveType template, ImportType type, gchar * filename);
51 static gboolean replace_existing_file_dialog (const gchar * filename, gint format_id);
52 
53 typedef enum
54 {
55   DENEMO_FORMAT = 0,
56   DNM_FORMAT,
57   MUDELA_FORMAT,
58   PDF_FORMAT,
59   PNG_FORMAT,
60   ABC_FORMAT,
61   MIDI_FORMAT,
62   CSOUND_FORMAT,
63   MUSICXML_FORMAT
64 }
65 FileFormatNames;
66 
67 struct FileFormatData
68 {
69   gchar *filename_mask;
70   gchar *description;
71   gchar *filename_extension;
72   gboolean async;               /* TRUE if uses async */
73 };
74 
75 /* WARNING this array has to match the FileFormatNames enum above which is used to index it!!!!!!!!!" */
76 static struct FileFormatData supported_file_formats[] = {
77   {"*.denemo", N_("Denemo XML format (*.denemo)"),  ".denemo", 0},
78   {"*.dnm",    N_("Denemo XML format (*.dnm)"),     ".dnm", 0},
79   {"*.ly",     N_("Lilypond (*.ly)"),               ".ly", 0},
80   {"*.pdf",    N_("PDF (*.pdf)"),                   ".pdf", 1},
81   {"*.png",    N_("PNG Image format (*.png)"),      ".png", 1},
82   {"*.abc",    N_("ABC (*.abc)"),                   ".abc", 0},
83   {"*.mid",    N_("Midi (*.mid, *.midi)"),          ".mid", 0},
84   {"*.sco",    N_("CSound Score File (*.sco)"),     ".sco", 0},
85   {"*.mxml",   N_("MusicXML file (*.mxml, *.xml)"), ".mxml", 0}
86 };
87 
88 static GList*
supported_file_extensions(gchar * format)89 supported_file_extensions(gchar* format){
90   GList* exts = NULL;
91 
92   if(g_strcmp0 ("denemo", format) == 0){
93     exts = g_list_append(exts, "*.denemo");
94     exts = g_list_append(exts, "*.DENEMO");
95   }
96 
97   if(g_strcmp0 ("lilypond", format) == 0){
98     exts = g_list_append(exts, "*.ly");
99     exts = g_list_append(exts, "*.LY");
100   }
101 
102   if(g_strcmp0 ("midi", format) == 0){
103     exts = g_list_append(exts, "*.midi");
104     exts = g_list_append(exts, "*.mid");
105     exts = g_list_append(exts, "*.MIDI");
106     exts = g_list_append(exts, "*.MID");
107   }
108 
109   if(g_strcmp0 ("musicxml", format) == 0){
110     exts = g_list_append(exts, "*.mxml");
111     exts = g_list_append(exts, "*.MXML");
112     exts = g_list_append(exts, "*.xml");
113   }
114 
115   if(g_strcmp0 ("pdf", format) == 0){
116     exts = g_list_append(exts, "*.pdf");
117     exts = g_list_append(exts, "*.PDF");
118   }
119   if(g_strcmp0 ("evince", format) == 0){
120     exts = g_list_append(exts, "*.pdf");
121     exts = g_list_append(exts, "*.PDF");
122   }
123   if(g_strcmp0 ("proof", format) == 0){
124     exts = g_list_append(exts, "*.pdf");
125     exts = g_list_append(exts, "*.PDF");
126   }
127   return exts;
128 }
129 
130 /* Some macros just to shorten lines */
131 #define FORMAT_MASK(i) supported_file_formats[i].filename_mask
132 #define FORMAT_DESCRIPTION(i) supported_file_formats[i].description
133 #define FORMAT_EXTENSION(i) supported_file_formats[i].filename_extension
134 #define FORMAT_ASYNC(i) supported_file_formats[i].async
135 
136 struct FileDialogData
137 {
138   DenemoSaveType template;
139   gint format_id;
140 };
141 
142 /* directory last used for saving */
143 static gchar *file_selection_path = NULL;
144 static gchar *system_template_path = NULL;
145 static gchar *system_example_path = NULL;
146 static gchar *local_template_path = NULL;
147 static gchar *default_template_path = NULL;
148 
149 
150 /**
151  * Display a message box asking the user whether to save unsaved changes
152  * or close without saving
153  */
154 static gboolean
confirm_save(DenemoProject * gui,gchar * primary,gchar * secondary)155 confirm_save (DenemoProject * gui, gchar * primary, gchar * secondary)
156 {
157   if (Denemo.non_interactive)
158     return TRUE;
159   GtkWidget *dialog;
160   gboolean r = FALSE;
161 
162   dialog = gtk_message_dialog_new (GTK_WINDOW (Denemo.window), (GtkDialogFlags) (GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT), GTK_MESSAGE_QUESTION, GTK_BUTTONS_NONE, "%s", primary);
163   (void) gtk_dialog_add_button ((GtkDialog *) dialog, _("Close without Saving"), GTK_RESPONSE_NO);
164 
165   (void) gtk_dialog_add_button ((GtkDialog *) dialog, _("_Cancel"), GTK_RESPONSE_CANCEL);
166 
167   (void) gtk_dialog_add_button ((GtkDialog *) dialog, _("Save _As"), GTK_RESPONSE_YES);
168 
169   gtk_dialog_set_default_response ((GtkDialog *) dialog, GTK_RESPONSE_YES);
170 
171   gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog), "%s", secondary);
172   gtk_widget_show_all (dialog);
173   gint response = gtk_dialog_run (GTK_DIALOG (dialog));
174 
175   if (response == GTK_RESPONSE_YES)
176     {
177       gtk_widget_destroy (dialog);
178       file_saveas (SAVE_NORMAL);
179       if (gui->notsaved)
180         r = FALSE;
181       else
182         r = TRUE;
183     }
184   else if (response == GTK_RESPONSE_NO)
185     {
186       gtk_widget_destroy (dialog);
187       r = TRUE;
188     }
189   else
190     {
191       gtk_widget_destroy (dialog);
192       r = FALSE;
193     }
194   return r;
195 }
196 
197 /**
198  * Display a message box asking the user to confirm that unsaved
199  * changes will be lost
200  * @return TRUE if the OK button clicked or Enter pressed
201  */
202 gboolean
confirmbox(DenemoProject * gui)203 confirmbox (DenemoProject * gui)
204 {
205   gboolean ret;
206   gchar *primary = g_strdup_printf (_("The score %s has unsaved changes"), gui->filename->len ? gui->filename->str : _("(Untitled)"));
207   ret = confirm_save (gui, primary, _("Save changes?"));
208   g_free (primary);
209   return ret;
210 }
211 
212 /**
213  * Custom function to compare the elements of the History queue
214  * it simply wraps up stcmp
215  *
216  * @param a pointer to a queue elements
217  * @param b pointer to the comparison value
218  * @return gint 0 if match -1 or 1 otherwise
219  */
220 static gint
history_compare(gconstpointer a,gconstpointer b)221 history_compare (gconstpointer a, gconstpointer b)
222 {
223   return (strcmp ((gchar *) a, (gchar *) b));
224 }
225 
226 
227 /**
228  * Callback for the history menu
229  * opens the selected file
230  */
231 void
openrecent(G_GNUC_UNUSED GtkWidget * widget,gchar * filename)232 openrecent (G_GNUC_UNUSED GtkWidget * widget, gchar * filename)
233 {
234   DenemoProject *gui = Denemo.project;
235   if (!gui->notsaved || (gui->notsaved && confirmbox (gui)))
236     {
237       // deletescore(NULL, gui);
238       if (open_for_real (filename, gui, FALSE, FALSE))
239         {
240           gchar *warning = g_strdup_printf (_("Load of recently used file %s failed"), filename);
241           warningdialog (warning);
242           g_free (warning);
243         }
244     }
245 }
246 
247 /**
248  * Decorate the window with the tile
249  */
250 static void
set_gui_tabname(DenemoProject * gui,gchar * filename)251 set_gui_tabname (DenemoProject * gui, gchar * filename)
252 {
253     if(gui->tabname==NULL)
254        gui->tabname = g_string_new (filename);
255     else
256         g_string_assign (gui->tabname, filename);
257   if(!Denemo.non_interactive)
258     set_title_bar (gui);
259 }
260 
261 /**
262  * Sets the filename for storing the passed in gui.
263  * and adds it to the history
264  */
265 static void
set_project_filename(DenemoProject * gui,gchar * filename)266 set_project_filename (DenemoProject * gui, gchar * filename)
267 {
268   GList *link = NULL;
269   g_string_assign (gui->filename, filename);
270   set_gui_tabname (gui, filename);
271 
272   if ((link = g_queue_find_custom (Denemo.prefs.history, gui->filename->str, &history_compare)))
273     g_queue_remove (Denemo.prefs.history, link->data);
274 
275   g_debug ("max history now %d\n", Denemo.prefs.maxhistory);
276   if (g_queue_get_length (Denemo.prefs.history) > Denemo.prefs.maxhistory)
277     {
278       gpointer data = g_queue_pop_head (Denemo.prefs.history);
279       g_debug ("Losing one history");
280       if (data)
281         g_free (data);
282     }
283   if(!Denemo.non_interactive){
284     if (link)                     /* not a new one */
285       addhistorymenuitem (filename);
286   }
287   g_queue_push_tail (Denemo.prefs.history, g_strdup (gui->filename->str));
288 }
289 
290 static gchar *
strip_path_and_extension(gchar * filename)291 strip_path_and_extension (gchar * filename)
292 {
293   gchar *basename;
294   basename = g_path_get_basename (filename);
295   (void) strtok (basename, ".");
296   return basename;
297 }
298 
299 static void
update_file_selection_path(gchar * file)300 update_file_selection_path (gchar * file)
301 {
302   if (file_selection_path)
303     g_free (file_selection_path);
304   file_selection_path = g_path_get_dirname (file);
305 }
306 
307 gint
lyinput(gchar * filename)308 lyinput (gchar * filename)
309 {
310   gchar *path = g_path_get_dirname (filename);
311   gchar *base = g_path_get_basename (filename);
312 #ifdef G_OS_WIN32
313   gchar *call = g_strescape (path, "");
314   call = g_strdup_printf ("%s%s%s%s%s", "(debug-set! stack 200000) (lyimport::load-file \"", call, "\\\\\" \"", base, "\")");
315   g_debug ("Calling %s\n", call);
316 #else
317   gchar *call = g_strdup_printf ("%s%s%c%s%s%s", "(lyimport::load-file \"", path, G_DIR_SEPARATOR, "\" \"", base, "\")");
318 #endif
319 
320 
321   call_out_to_guile (call);
322   g_free (path);
323   g_free (base);
324   g_free (call);
325   return 0;
326 }
327 
328 static gboolean
exists(gchar * filename,const gchar * extension)329 exists(gchar* filename, const gchar* extension)
330 {
331   return (strcmp (filename + strlen (filename) - strlen(extension), extension) == 0);
332 }
333 
delete_all_rhythms(void)334 static void delete_all_rhythms (void)
335 {
336   DenemoProject *project = Denemo.project;
337   GList *g;
338   for (g = project->rhythms;g;g=project->rhythms)
339     {
340         delete_rhythm_pattern (g->data);
341     }
342 }
enquire_rhythms(void)343 static void enquire_rhythms (void) {
344 if (Denemo.project->rhythms && choose_option (_("Music Snippets Can be Kept"), _("Drop Music Snippets"), _("Keep Music Snippets")))
345     delete_all_rhythms ();
346 }
347 /**
348  * The function that actually determines the file type and calls the
349  *  function that opens the file.  (So many layers of indirection...)
350  *filename must be full path
351  * @return 0 for success non zero for failure
352  */
353 gint
open_for_real(gchar * filename,DenemoProject * gui,DenemoSaveType template,ImportType type)354 open_for_real (gchar * filename, DenemoProject * gui, DenemoSaveType template, ImportType type)
355 {
356   if(!Denemo.non_interactive)
357     g_signal_handlers_block_by_func (G_OBJECT (Denemo.scorearea), G_CALLBACK (scorearea_draw_event), NULL);
358   gint result;
359   gboolean xml = FALSE;
360   result = 1;                   //FAILURE
361   if (type == REPLACE_SCORE)
362   {
363     if(Denemo.non_interactive)
364         delete_all_rhythms ();
365     else
366         enquire_rhythms ();
367   }
368   if (g_file_test (filename, G_FILE_TEST_EXISTS))
369     {
370       if (exists (filename, ".denemo") || exists (filename, ".dnm"))
371         xml = TRUE, result = importXML (filename, gui, type);
372       else if (exists (filename, ".ly"))
373         result = lyinput (filename);
374       else if (exists (filename, ".mxml") || exists (filename, ".xml"))
375         result = mxmlinput (filename);
376       else if (exists (filename, ".mid") || exists (filename, ".midi"))
377         result = (type==GUIDED_IMPORT)?guidedImportMidi (filename):importMidi (filename);
378       else if (exists (filename, ".pdf") || exists (filename, ".PDF"))
379         {
380 #ifndef USE_EVINCE
381           g_debug("This feature requires denemo to be built with evince");
382 #else
383           // a .pdf file for transcribing from, does not affect the current score.
384           g_signal_handlers_unblock_by_func (G_OBJECT (Denemo.scorearea), G_CALLBACK (scorearea_draw_event), NULL);
385           return type==PROOFREAD? (!open_proofread_file(filename)) : !open_source (filename, 0, 0, 0);
386 #endif
387         }
388     g_message("Opening file %s", filename);
389     }
390   //printf("\nResult == %d type == %d template == %d xml == %d\n",result,type,template,(int)xml);
391   if (result == 0)
392     {
393       if (!template)
394         {                       // not a template
395           update_file_selection_path (filename);
396           if (type == REPLACE_SCORE)
397             {
398               if (xml){
399                  set_project_filename (gui, filename);
400               }
401               else
402                 {
403                   gchar *sname = strip_path_and_extension (filename);
404                   set_gui_tabname (gui, sname);
405                   g_free (sname);
406                 }
407             }
408           if (type == ADD_STAFFS || type == ADD_MOVEMENTS)
409             score_status (gui, TRUE);
410         }
411       else
412         {
413           g_string_assign (gui->filename, "");
414           set_gui_tabname (gui, "");
415         }
416       //if (Denemo.printarea)
417       //  g_object_set_data (G_OBJECT (Denemo.printarea), "printviewupdate", (gpointer) G_MAXUINT);
418       if (!xml)
419         updatescoreinfo (gui);
420       else
421         {
422           if ((gui->script) && !(type == ADD_STAFFS || type == ADD_MOVEMENTS))
423             {
424               gui->has_script = TRUE;
425               cache_all ();
426               executeScript ();
427             }
428         }
429       set_rightmeasurenum (gui->movement);
430       select_lyrics ();
431 
432       if(!Denemo.non_interactive){
433         set_bottom_staff (gui);
434         update_hscrollbar (gui);
435         update_vscrollbar (gui);
436         draw_score_area();
437         g_signal_emit_by_name (G_OBJECT (Denemo.hadjustment), "changed");
438         g_signal_emit_by_name (G_OBJECT (Denemo.vadjustment), "changed");
439         force_lily_refresh (gui);
440       }
441     }
442   else                          /*file load failed - gui may not be valid */
443     {
444       if(!Denemo.non_interactive)
445         deletescore (NULL, gui);
446     }
447   if(!Denemo.non_interactive){
448     g_signal_handlers_unblock_by_func (G_OBJECT (Denemo.scorearea), G_CALLBACK (scorearea_draw_event), NULL);
449     gui->movement->undo_guard = 1;
450   }
451   denemo_scheme_init ();        //to re-instate any user defined directives for whole score
452   if(!Denemo.non_interactive){
453     if (!(type == ADD_STAFFS || type == ADD_MOVEMENTS))
454       score_status (gui, FALSE);
455     rewind_audio ();
456     panic_all ();// g_print ("Reset synth in file open\n");
457     gui->movement->undo_guard = Denemo.prefs.disable_undo;      //user pref to (dis)allow undo information to be collected
458   }
459 
460   return result;
461 }
462 
463 /*
464     If the filename format already has the correct extension use
465     it. otherwise add the file name extension
466 */
467 static gchar *
create_filename(const gchar * file_name,gint format_id)468 create_filename (const gchar * file_name, gint format_id)
469 {
470   if (g_pattern_match_simple (FORMAT_MASK (format_id), file_name))
471     return (g_strdup (file_name));
472   else
473     return (g_strconcat (file_name, FORMAT_EXTENSION (format_id), NULL));
474 }
475 
476 /*
477   This is used to strip the extension (if it exists) off of ASYNC file types.
478 */
479 static gchar *
strip_filename_ext(const gchar * file_name,gint format_id)480 strip_filename_ext (const gchar * file_name, gint format_id)
481 {
482   gchar *ext = strrchr (file_name, '.');
483   if (ext == NULL)
484     return g_strdup (file_name);
485   gint i;
486   GString *file_name_stripped = g_string_new ("");
487   gint filename_size = strlen (file_name);
488   gint ext_size = strlen (FORMAT_EXTENSION (format_id));
489   if (strlen (ext) != ext_size)
490     return g_strdup (file_name);
491   gint stripped_filename_size = filename_size - ext_size;
492   for (i = 0; i < stripped_filename_size; i++)
493     {
494       g_string_append_c (file_name_stripped, file_name[i]);
495     }
496   printf ("\nTruncated filename == %s\n", file_name_stripped->str);
497   return g_string_free (file_name_stripped, FALSE);
498 }
499 
500 /* Save gui in the file in format format_id to the file filename (or gui->filename
501    if filename is NULL)
502    If there is a scheme script, offers to save that with the file.
503  */
504 static gint
save_in_format(gint format_id,DenemoProject * gui,gchar * filename)505 save_in_format (gint format_id, DenemoProject * gui, gchar * filename)
506 {
507   gint ret = 0;
508   gchar *file = filename ? filename : gui->filename->str;
509   switch (format_id)
510     {
511     case DENEMO_FORMAT:
512     case DNM_FORMAT:
513       {
514         /* HERE examine Denemo.Script and
515          * if present ask it it should be
516          * saved with the file, if not
517          * delete the script.
518          */
519 
520         if (!Denemo.non_interactive && (!gui->has_script) && getNumCharsSchemeText ())
521           if (!confirm (_("You have a Script defined"), _("Use this script every time this file is opened?")))
522             {
523               deleteSchemeText ();
524             }
525         ret = exportXML (file, gui);
526         break;
527       };
528     case MUDELA_FORMAT:
529       {
530         gui->movement->markstaffnum = 0;
531         exportlilypond (file, gui, TRUE);
532         break;
533       };
534     case PDF_FORMAT:
535       {
536         gui->movement->markstaffnum = 0;
537         export_pdf (file, gui);
538         break;
539       };
540     case PNG_FORMAT:
541       {
542         gui->movement->markstaffnum = 0;
543         export_png (file, (GChildWatchFunc) printpng_finished, gui);
544         break;
545       };
546     case ABC_FORMAT:
547       {
548         exportabc (file, gui, 0, 0);
549         break;
550       };
551     case MIDI_FORMAT:
552       {
553         exportmidi (file, gui->movement);
554         break;
555       };
556     default:
557       break;
558     };
559   return ret;
560 }
561 
562 /**
563  * File save called by fileselsave callback
564  * param file_name is full path to file possibly with extension
565  */
566 static gint
filesel_save(DenemoProject * gui,const gchar * file_name,gint format_id,DenemoSaveType template)567 filesel_save (DenemoProject * gui, const gchar * file_name, gint format_id, DenemoSaveType template)
568 {
569   gint ret = 0;
570   //g_assert (gui != NULL);
571   //g_assert (file_name != NULL);
572   //g_assert (format_id >= 0 && format_id < (int) G_N_ELEMENTS (supported_file_formats));
573 
574   // Append file extension if needed
575   gchar *file = NULL;
576   gchar *basename = NULL;
577   file = create_filename (file_name, format_id);
578   if (!template && format_id == DENEMO_FORMAT)
579     {
580       update_file_selection_path (file);
581       if(!Denemo.non_interactive)
582         set_project_filename (gui, file);
583     }
584   basename = g_path_get_basename (file);
585   if (basename[0] != '.')       // avoids empty filename
586     {
587       if (FORMAT_ASYNC (format_id))
588         ret = save_in_format (format_id, gui, strip_filename_ext (file_name, format_id));       //FIXME strip_filename is not freed
589       else
590         ret = save_in_format (format_id, gui, file);
591 
592       /*export parts as lilypond files */
593       if (Denemo.prefs.saveparts)
594         export_lilypond_parts (file, gui);
595       if(!Denemo.non_interactive)
596         gui->movement->readonly = FALSE;
597     }
598   g_free (basename);
599   g_free (file);
600   return ret;
601 }
602 
603 /* set local_template_path up */
604 static void
init_local_path(void)605 init_local_path (void)
606 {
607   local_template_path = g_build_filename (get_user_data_dir (TRUE), "templates", NULL);
608   gboolean err = g_mkdir_with_parents (local_template_path, 0770);
609   if (err)
610     {
611       warningdialog (_("Could not create .denemo/templates for you personal templates"));
612       g_free (local_template_path);
613       local_template_path = NULL;
614     }
615 }
616 
617 typedef enum
618 {
619   LOCAL,
620   SYSTEM,
621   EXAMPLE
622 } TemplateType;
623 
624 /*
625  * Sets the file_selection_path to the templates directory and
626  * calls file_open to create the file selection dialog
627  * LOCAL whether to use the local templates or systemwide templates or examples
628  * does nothing if unable to access templates
629  * filename is NULL for interactive use, otherwise file base name
630  */
631 static gint
template_open(DenemoProject * gui,TemplateType local,gchar * filename)632 template_open (DenemoProject * gui, TemplateType local, gchar * filename)
633 {
634   gboolean ret = FALSE;
635   if (local == LOCAL)
636     {
637       if (local_template_path == NULL)
638         {
639           init_local_path ();
640         }
641       default_template_path = local_template_path;
642     }
643   else if (local == EXAMPLE)
644     {
645       if (system_example_path == NULL)
646         {
647           system_example_path = g_build_filename (get_system_data_dir (), "..", "examples", "denemo", NULL);
648           GDir *denemo_path = g_dir_open (system_example_path, 0, NULL);
649           if (denemo_path == NULL)
650             {
651               warningdialog (_("No examples directory in installation"));
652               system_example_path = NULL;
653             }
654         }
655       default_template_path = system_example_path;
656     }
657   else
658     {
659       if (system_template_path == NULL)
660         {
661           system_template_path = g_build_filename (get_system_data_dir (), "templates", NULL);
662           GDir *denemo_path = g_dir_open (system_template_path, 0, NULL);
663           if (denemo_path == NULL)
664             {
665               warningdialog (_("No templates directory in installation"));
666               system_template_path = NULL;
667             }
668         }
669       default_template_path = system_template_path;
670     }
671   if (default_template_path)
672     {
673       gchar *filepath = g_build_filename (default_template_path, filename, NULL);
674       ret = file_open (gui, TRUE, REPLACE_SCORE, filepath);
675       g_free (filepath);
676       gui->filename = g_string_new ("");
677       gui->tabname = g_string_new ("");
678     }
679   return ret;
680 }
681 
682 static void
open_with_check(TemplateType dir,GtkAction * action,DenemoScriptParam * param)683 open_with_check(TemplateType dir, GtkAction * action, DenemoScriptParam * param){
684   GET_1PARAM(action, param, filename);
685   if (Denemo.project->notsaved){
686     if (filename==NULL && confirmbox (Denemo.project)){
687       param->status = !template_open (Denemo.project, dir, filename);
688     }
689   }
690   else{
691     param->status = !template_open (Denemo.project, dir, filename);
692   }
693 }
694 
695 /*
696  * Open system template file callback function
697  */
698 void
system_template_open_with_check(GtkAction * action,DenemoScriptParam * param)699 system_template_open_with_check (GtkAction * action, DenemoScriptParam * param)
700 {
701   open_with_check (SYSTEM, action, param);
702 }
703 
704 /*
705  * Open system template file callback function
706  */
707 void
system_example_open_with_check(GtkAction * action,DenemoScriptParam * param)708 system_example_open_with_check (GtkAction * action, DenemoScriptParam * param)
709 {
710   open_with_check (EXAMPLE, action, param);
711 }
712 
713 /*
714  * Open local template file callback function
715  */
716 void
local_template_open_with_check(GtkAction * action,DenemoScriptParam * param)717 local_template_open_with_check (GtkAction * action, DenemoScriptParam * param)
718 {
719   open_with_check (LOCAL, action, param);
720 }
721 
722 /**
723  * Wrapper function for opening a file, d-Open
724  * if no param checks to see if current score has changed and prompts user to save
725  * otherwise opens the file
726  */
727 void
file_open_with_check(GtkAction * action,DenemoScriptParam * param)728 file_open_with_check (GtkAction * action, DenemoScriptParam * param)
729 {
730   GET_1PARAM (action, param, filename);
731   if (query)
732     {
733       param->status = (Denemo.project->filename != NULL) && Denemo.project->filename->len;
734       if (param->status)
735         g_string_assign (param->string, Denemo.project->filename->str);
736       return;
737     }
738   DenemoProject *gui = Denemo.project;
739   if (!gui->notsaved || (gui->notsaved && (confirmbox (gui))))
740     {
741       param->status = !file_open (gui, FALSE, REPLACE_SCORE, filename);
742     }
743 }
744 
745 void
file_import_lilypond_with_check(GtkAction * action,DenemoScriptParam * param)746 file_import_lilypond_with_check (GtkAction * action, DenemoScriptParam * param)
747 {
748   GET_1PARAM(action, param, filename);
749   param->status = !file_import_lilypond (Denemo.project, FALSE, REPLACE_SCORE, filename);
750 }
751 
752 void
file_import_midi_with_check(GtkAction * action,DenemoScriptParam * param)753 file_import_midi_with_check (GtkAction * action, DenemoScriptParam * param)
754 {
755     GET_2PARAMS(action, param, filename, guided);
756     if(guided)
757         file_import_midi (Denemo.project, FALSE, GUIDED_IMPORT, filename);
758     else
759         file_import_midi (Denemo.project, FALSE, REPLACE_SCORE, filename);
760 }
761 
762 void
file_import_musicxml_with_check(GtkAction * action,DenemoScriptParam * param)763 file_import_musicxml_with_check (GtkAction * action, DenemoScriptParam * param)
764 {
765   GET_1PARAM(action, param, filename);
766   param->status = !file_import_musicxml (Denemo.project, FALSE, REPLACE_SCORE, filename);
767 }
768 
769 #define ADD(insertion_strategy)\
770   GET_1PARAM(action, param, filename);\
771   (void)signal_structural_change(Denemo.project);\
772   param->status = !file_open(Denemo.project, FALSE, insertion_strategy, filename);\
773   score_status(Denemo.project, TRUE);\
774 
775 /**
776  * Wrapper function for opening a file to add movements to the current score
777  *
778  */
779 void
file_add_movements(GtkAction * action,DenemoScriptParam * param)780 file_add_movements (GtkAction * action, DenemoScriptParam * param)
781 {
782 ADD (ADD_MOVEMENTS)}
783 
784 /**
785  * Wrapper function for opening a file to add staffs to the current movement
786  *
787  */
788 void
file_add_staffs(GtkAction * action,DenemoScriptParam * param)789 file_add_staffs (GtkAction * action, DenemoScriptParam * param)
790 {
791 ADD (ADD_STAFFS)}
792 
793 static void
set_current_folder(GtkWidget * file_selection,DenemoSaveType template)794 set_current_folder (GtkWidget * file_selection, DenemoSaveType template)
795 {
796   gchar *path, *fallback;
797   if (template == SAVE_TEMPLATE)
798     {
799       fallback = path = default_template_path;
800     }
801   else
802     {
803       fallback = path = file_selection_path;
804       GDir *denemo_path = g_dir_open (Denemo.prefs.denemopath->str, 0, NULL);
805       if (denemo_path != NULL)
806         {
807           g_dir_close (denemo_path);
808           fallback = Denemo.prefs.denemopath->str;
809         }
810     }
811   if (path != NULL)
812     {
813       gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (file_selection), path);
814     }
815   else
816     {
817       if (fallback != NULL)
818         gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (file_selection), fallback);
819     }
820 }
821 
822 gchar *
file_dialog(gchar * message,gboolean type,gchar * location)823 file_dialog (gchar * message, gboolean type, gchar * location)
824 {
825   GtkWidget *file_selection;
826   gchar *filename;
827   file_selection = gtk_file_chooser_dialog_new (message, GTK_WINDOW (Denemo.window), type ? GTK_FILE_CHOOSER_ACTION_OPEN : GTK_FILE_CHOOSER_ACTION_SAVE, _("_Cancel"), GTK_RESPONSE_REJECT, type ? _("_Open") : _("_Save"), GTK_RESPONSE_ACCEPT, NULL);
828 
829   if (location)
830     gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (file_selection), location);
831   gtk_dialog_set_default_response (GTK_DIALOG (file_selection), GTK_RESPONSE_ACCEPT);
832   gtk_widget_show_all (file_selection);
833   if (gtk_dialog_run (GTK_DIALOG (file_selection)) == GTK_RESPONSE_ACCEPT)
834     filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (file_selection));
835   else
836     filename = NULL;
837   gtk_widget_destroy (file_selection);
838   return filename;
839 }
840 
841 static void
update_preview_cb(GtkFileChooser * file_chooser,gpointer data)842 update_preview_cb (GtkFileChooser * file_chooser, gpointer data)
843 {
844 #ifndef USE_EVINCE
845   g_debug("This feature requires denemo to be built with evince");
846 #else
847   GtkWidget *preview = NULL;
848   gchar *thumb_filename = NULL;
849   gchar *selection_filename = NULL;
850   GdkPixbuf *pixbuf = NULL;
851   gboolean have_preview = FALSE;
852 
853   preview = GTK_WIDGET (data);
854   selection_filename = gtk_file_chooser_get_preview_filename (file_chooser);
855   thumb_filename = large_thumbnail_name (selection_filename);
856   pixbuf = gdk_pixbuf_new_from_file_at_size (thumb_filename, 512, 512, NULL);
857   have_preview = (pixbuf != NULL);
858   g_debug ("\n# %s for %s thumbnail = %s\n", have_preview ? "We have a thumbnail generated" : "We have not yet generated a thumbnail", selection_filename, thumb_filename);
859   g_free (selection_filename);
860   g_free (thumb_filename);
861 
862   gtk_image_set_from_pixbuf (GTK_IMAGE (preview), pixbuf);
863   if (pixbuf)
864     g_object_unref (pixbuf);
865 
866   gtk_file_chooser_set_preview_widget_active (file_chooser, have_preview);
867 #endif
868 }
869 
870 static gboolean
file_open_dialog(gchar * message,gchar * format,FileFormatNames save_type,DenemoSaveType template,ImportType type,gchar * filename)871 file_open_dialog(gchar* message, gchar* format, FileFormatNames save_type, DenemoSaveType template, ImportType type, gchar* filename){
872   gboolean ret = -1;
873    if(filename && (!g_file_test(filename, G_FILE_TEST_EXISTS)) && (!g_path_is_absolute (filename)) && file_selection_path)
874             filename = g_build_filename (file_selection_path, filename, NULL);//memory leak
875 
876   if(filename && !g_file_test(filename, G_FILE_TEST_IS_DIR))
877     return (open_for_real(filename, Denemo.project, template, type));
878 
879   GtkWidget *file_selection;
880   GtkFileFilter *filter;
881   gint i;
882 
883 
884   file_selection = gtk_file_chooser_dialog_new (_(message),
885                         GTK_WINDOW (Denemo.window),
886                         GTK_FILE_CHOOSER_ACTION_OPEN,
887                         _("_Cancel"),
888                         GTK_RESPONSE_REJECT,
889                         _("_Open"),
890                         GTK_RESPONSE_ACCEPT, NULL);
891   /* Open in passed in directory or the last visited directory, if any, or a default depending on template. */
892   if (filename && g_file_test(filename, G_FILE_TEST_IS_DIR))
893     gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (file_selection), filename);
894   else
895     set_current_folder(file_selection, template);
896 
897   filter = gtk_file_filter_new ();
898   gtk_file_filter_set_name (filter, FORMAT_DESCRIPTION(save_type));
899 
900   GList* exts = supported_file_extensions (format);
901   GList* cur = NULL;
902   for (cur = exts; cur; cur = cur->next)
903     gtk_file_filter_add_pattern (filter, cur->data);
904   gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (file_selection), filter);
905   gtk_dialog_set_default_response (GTK_DIALOG (file_selection),
906                    GTK_RESPONSE_ACCEPT);
907   gtk_widget_show_all (file_selection);
908   GtkWidget *preview;
909   preview = gtk_image_new();
910   gtk_file_chooser_set_preview_widget(GTK_FILE_CHOOSER (file_selection), preview);
911   g_signal_connect (GTK_FILE_CHOOSER(file_selection), "update-preview",
912             G_CALLBACK (update_preview_cb), preview);
913   gtk_widget_show_all (preview);
914   if (gtk_dialog_run (GTK_DIALOG (file_selection)) == GTK_RESPONSE_ACCEPT)
915     {
916       gchar *name = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (file_selection));
917       if((ret=open_for_real (name, Denemo.project, template, type))) {
918         gchar *warning = g_strdup_printf(_("Load of file %s failed"), name);
919         warningdialog(warning);
920         g_free(warning);
921       }
922       g_free (name);
923     }
924   gtk_widget_destroy (file_selection);
925 
926 
927   return ret;
928 }
929 
930 /**
931  * File open dialog - opened where appropriate
932  * return 0 on success non-zero on failure.
933  * filename must be full path or NULL for dialog
934  */
935 static gint
file_open(DenemoProject * gui,DenemoSaveType template,ImportType type,gchar * filename)936 file_open (DenemoProject * gui, DenemoSaveType template, ImportType type, gchar * filename)
937 {
938   return file_open_dialog ("Open", "denemo", DENEMO_FORMAT, template, type, filename);
939 }
940 
941 gint
open_source_file(void)942 open_source_file (void)
943 {
944   return file_open_dialog ("Open", "evince", PDF_FORMAT, 0, SOURCE_PDF, NULL);
945 }
946 gint
open_proof_file(void)947 open_proof_file (void)
948 {
949   return file_open_dialog ("Open", "proof", PDF_FORMAT, 0, PROOFREAD, NULL);
950 }
951 
952 /**
953  * Lilypond Import dialog - opened where appropriate
954  * return 0 on success non-zero on failure.
955  * filename must be full path or NULL for dialog
956  */
957 static gint
file_import_lilypond(DenemoProject * gui,DenemoSaveType template,ImportType type,gchar * filename)958 file_import_lilypond (DenemoProject * gui, DenemoSaveType template, ImportType type, gchar * filename)
959 {
960   return file_open_dialog ("Import Lilypond", "lilypond", MUDELA_FORMAT, template, type, filename);
961 }
962 
963 /**
964  * Midi Import dialog - opened where appropriate
965  * return 0 on success non-zero on failure.
966  * filename must be full path or NULL for dialog
967  */
968 static gint
file_import_midi(DenemoProject * gui,DenemoSaveType template,ImportType type,gchar * filename)969 file_import_midi (DenemoProject * gui, DenemoSaveType template, ImportType type, gchar * filename)
970 {
971   return file_open_dialog ("Import Midi", "midi", MIDI_FORMAT, template, type, filename);
972 }
973 
974 /**
975  * MusicXML Import dialog - opened where appropriate
976  * return 0 on success non-zero on failure.
977  * filename must be full path or NULL for dialog
978  */
979 static gint
file_import_musicxml(DenemoProject * gui,DenemoSaveType template,ImportType type,gchar * filename)980 file_import_musicxml (DenemoProject * gui, DenemoSaveType template, ImportType type, gchar * filename)
981 {
982   return file_open_dialog ("Import MusicXML", "musicxml", MUSICXML_FORMAT, template, type, filename);
983 }
984 
985 /**
986  * Wrapper function to save the current file if not already
987  * saved.
988  */
989 void
file_saveaswrapper(GtkAction * action,DenemoScriptParam * param)990 file_saveaswrapper (GtkAction * action, DenemoScriptParam * param)
991 {
992   GET_1PARAM (action, param, filename);
993   DenemoProject *gui = Denemo.project;
994   if (filename == NULL)
995     {
996       file_saveas (FALSE);
997     }
998   else
999     {
1000       gint status = filesel_save (gui, filename, DENEMO_FORMAT, FALSE);
1001 
1002       if(!Denemo.non_interactive){
1003         if (status == 0)
1004           score_status (gui, FALSE);
1005         force_lily_refresh (gui);
1006       }
1007     }
1008 }
1009 
1010 /**
1011  * Wrapper function to save the current file as template
1012  */
1013 void
template_save(G_GNUC_UNUSED GtkAction * action,G_GNUC_UNUSED DenemoScriptParam * param)1014 template_save (G_GNUC_UNUSED GtkAction * action, G_GNUC_UNUSED DenemoScriptParam * param)
1015 {
1016   init_local_path ();
1017   default_template_path = local_template_path;
1018   file_saveas (SAVE_TEMPLATE);
1019 }
1020 
1021 
1022 /**
1023  * Wrapper function to save the current file as a copy
1024  */
1025 void
file_copy_save(G_GNUC_UNUSED GtkAction * action,G_GNUC_UNUSED DenemoScriptParam * param)1026 file_copy_save (G_GNUC_UNUSED GtkAction * action, G_GNUC_UNUSED DenemoScriptParam * param)
1027 {
1028   init_local_path ();
1029   file_saveas (SAVE_COPY);
1030 }
1031 
1032 /**
1033  * Wrapper function for saving an existing file
1034  *
1035  */
1036 void
file_savewrapper(GtkAction * action,DenemoScriptParam * param)1037 file_savewrapper (GtkAction * action, DenemoScriptParam * param)
1038 {
1039   DenemoProject *gui = Denemo.project;
1040   GET_1PARAM (action, param, filename);
1041   if (filename) {
1042     exportXML (filename, gui);
1043     return;
1044   }
1045   if (file_save (NULL, gui))
1046     {
1047       if (action && Denemo.project->filename && Denemo.project->filename->len)
1048         {
1049           warningdialog (_("File save failed"));
1050           score_status (gui, TRUE);
1051         }
1052       else
1053         {
1054           if (param)
1055             param->status = FALSE;
1056         }
1057     }
1058 }
1059 
1060 /**
1061  * if gui->filename exists saves gui to the filename  based on its extension
1062  * otherwise call saveas routine
1063  */
1064 gint
file_save(GtkWidget * widget,DenemoProject * gui)1065 file_save (GtkWidget * widget, DenemoProject * gui)
1066 {
1067   gint ret;
1068   DenemoMovement *si = gui->movement;
1069   g_debug ("READONLY %d\n", si->readonly);
1070   if ((gui->filename->len == 0) /* || (si->readonly == TRUE) */ )
1071     /* No filename's been given or is opened from template */
1072     file_saveas (FALSE);
1073   else
1074     ret = save_in_format (DENEMO_FORMAT, gui, NULL);
1075 
1076   /*Save parts as lilypond files */
1077   if (Denemo.prefs.saveparts)
1078     export_lilypond_parts (gui->filename->str, gui);
1079 
1080   score_status (gui, FALSE);
1081   return ret;
1082 }
1083 
1084 static void
file_dialog_response(GtkWidget * dialog,gint response_id,struct FileDialogData * data)1085 file_dialog_response (GtkWidget * dialog, gint response_id, struct FileDialogData *data)
1086 {
1087   DenemoProject *gui = Denemo.project;
1088   if (response_id == GTK_RESPONSE_ACCEPT)
1089     {
1090       gchar *file_name = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
1091       if (replace_existing_file_dialog (file_name, data->format_id))
1092         {
1093           gint status = filesel_save (gui, file_name, data->format_id, data->template);
1094           if (status == 0)
1095             score_status (gui, FALSE);
1096           force_lily_refresh (gui);     //FIXME why is this here???
1097         }
1098       g_free (file_name);
1099     }
1100   gtk_widget_destroy (dialog);
1101   g_free (data);
1102 }
1103 
1104 
1105 #define FILE_SAVE_DIALOG(description, template)\
1106   GtkWidget *file_selection;\
1107   GtkFileFilter *filter;\
1108   file_selection = gtk_file_chooser_dialog_new (description,\
1109                         GTK_WINDOW (Denemo.window),\
1110                         GTK_FILE_CHOOSER_ACTION_SAVE,\
1111                         _("_Cancel"),\
1112                         GTK_RESPONSE_REJECT,\
1113                         _("_Save"),\
1114                         GTK_RESPONSE_ACCEPT, NULL);\
1115   /*set default folder for saving */\
1116   set_current_folder(file_selection, template?SAVE_TEMPLATE:SAVE_NORMAL);\
1117   \
1118   /* assign title */ \
1119   gchar *title = get_scoretitle();\
1120   if (title)\
1121     { \
1122       gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (file_selection), title);\
1123     } \
1124   \
1125   filter = gtk_file_filter_new ();\
1126   gtk_file_filter_set_name (filter, FORMAT_DESCRIPTION(format_id));\
1127   gtk_file_filter_add_pattern (filter, FORMAT_MASK(format_id));\
1128   gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (file_selection), filter);\
1129   gtk_dialog_set_default_response (GTK_DIALOG (file_selection),\
1130                    GTK_RESPONSE_ACCEPT);\
1131   gtk_widget_show_all (file_selection);\
1132   struct FileDialogData *data = (struct FileDialogData *) g_malloc (sizeof (struct FileDialogData));\
1133   data->template=template;\
1134   data->format_id=format_id;\
1135   g_signal_connect(file_selection, "response", G_CALLBACK(file_dialog_response), data);
1136 
1137 /**
1138  * Create file saveas dialog to enable user to export the current file to
1139  *
1140  *
1141  */
1142 static void
file_export(FileFormatNames format_id)1143 file_export (FileFormatNames format_id)
1144 {
1145   gchar *description = g_strconcat (_("Export As "), FORMAT_DESCRIPTION (format_id), NULL);
1146   DenemoSaveType template = FALSE;
1147   FILE_SAVE_DIALOG (description, template) g_free (description);
1148 }
1149 
1150 /**
1151  * Create file saveas dialog to enable user to save the current file to
1152  *
1153  *
1154  */
1155 void
file_saveas(DenemoSaveType template)1156 file_saveas (DenemoSaveType template)
1157 {
1158   gint format_id = DENEMO_FORMAT;
1159 FILE_SAVE_DIALOG (_("Save As"), template)}
1160 
1161 /**
1162  * Wrapper function for command New which asks to delete the current gui and on success creates an empty score
1163  *
1164  */
1165 void
file_newwrapper(GtkAction * action,DenemoScriptParam * param)1166 file_newwrapper (GtkAction * action, DenemoScriptParam * param)
1167 {
1168   DenemoScriptParam dummy;
1169   dummy.string = NULL;
1170   if (param == NULL)
1171     param = &dummy;
1172   DenemoProject *gui = Denemo.project;
1173   if(!Denemo.non_interactive)
1174     g_signal_handlers_block_by_func (G_OBJECT (Denemo.scorearea), G_CALLBACK (scorearea_draw_event), NULL);
1175   if (!Denemo.non_interactive && gui->notsaved)
1176     {
1177       if (confirmbox (gui))
1178         {
1179           enquire_rhythms ();
1180           deletescore (NULL, gui);
1181         }
1182       else
1183         {
1184           param->status = FALSE;
1185           g_signal_handlers_unblock_by_func (G_OBJECT (Denemo.scorearea), G_CALLBACK (scorearea_draw_event), NULL);
1186           return;
1187         }
1188     }
1189   else
1190     {  if(Denemo.non_interactive)
1191             delete_all_rhythms ();
1192         else
1193             enquire_rhythms ();
1194       deletescore (NULL, gui);
1195     }
1196   deleteSchemeText ();
1197   gui->has_script = FALSE;
1198   set_enharmonic_position (0);
1199  // if (Denemo.printarea)
1200   //  g_object_set_data (G_OBJECT (Denemo.printarea), "printviewupdate", (gpointer) G_MAXUINT);
1201   score_status (gui, FALSE);
1202   param->status = TRUE;
1203   if(!Denemo.non_interactive)
1204     g_signal_handlers_unblock_by_func (G_OBJECT (Denemo.scorearea), G_CALLBACK (scorearea_draw_event), NULL);
1205 }
1206 
1207 #if 0
1208 /* open_user_default_template
1209  * open the user's standard template if there is one
1210  * @return 0 for success non zero for failure
1211  **/
1212 gint
1213 open_user_default_template (ImportType type)
1214 {
1215   gint ret = -1;
1216   gchar *filename = g_build_filename (get_user_data_dir (TRUE), "templates", "default.denemo", NULL);
1217   if (g_file_test (filename, G_FILE_TEST_EXISTS))
1218     {
1219       ret = open_for_real (filename, Denemo.project, TRUE, type);
1220     }
1221   g_free (filename);
1222   return ret;
1223 }
1224 #endif
1225 
1226 /**
1227  * Creates dialog to say that the chosen filename already exists
1228  * and do you want to overwrite it.
1229  *
1230  */
1231 static gboolean
replace_existing_file_dialog(const gchar * filename,gint format_id)1232 replace_existing_file_dialog (const gchar * filename, gint format_id)
1233 {
1234   gboolean ret;
1235   gchar *file = create_filename (filename, format_id);
1236   if (!g_file_test (file, G_FILE_TEST_EXISTS))
1237     {
1238       g_free (file);
1239       return TRUE;
1240     }
1241 
1242   gchar *primary = g_strdup_printf (_("A file with the name %s already exists"), file);
1243   ret = confirm (primary, _("Do you want to replace it?"));
1244 
1245   g_free (file);
1246   g_free (primary);
1247   return ret;
1248 }
1249 
1250 
1251 /**
1252  * Save parts to individual files
1253  */
1254 void
file_savepartswrapper(GtkAction * action,DenemoScriptParam * param)1255 file_savepartswrapper (GtkAction * action, DenemoScriptParam * param)
1256 {
1257   DenemoProject *gui = Denemo.project;
1258   if (gui->filename->len == 0)
1259     {
1260       file_saveas (FALSE);
1261     }
1262 
1263   export_lilypond_parts (gui->filename->str, gui);
1264 }
1265 
1266 
1267 static void
lilypond_selection_received(G_GNUC_UNUSED GtkClipboard * clipboard,const gchar * text,G_GNUC_UNUSED gpointer data)1268 lilypond_selection_received (G_GNUC_UNUSED GtkClipboard * clipboard, const gchar * text, G_GNUC_UNUSED gpointer data)
1269 {
1270   if (!text)
1271     {
1272       warningdialog (_("No selection text available"));
1273       return;
1274     }
1275   gchar *filename = g_build_filename (get_user_data_dir (TRUE), "denemopaste.ly", NULL);
1276   FILE *fp = fopen (filename, "w");
1277   if (fp)
1278     {
1279       fprintf (fp, "music = { %s }\n\\score {\n\\music\n\\layout {}\n}\n", text);
1280       fclose (fp);
1281       gint theclef = find_prevailing_clef (Denemo.project->movement);
1282       newview (NULL, NULL);
1283       gint fail = open_for_real (filename, Denemo.project, TRUE, REPLACE_SCORE);
1284       //thescore can be NULL after failed load....
1285       if (fail)
1286         {
1287           DenemoProject *gui = Denemo.project;
1288           //FIXME repeated code
1289           free_movements (gui);
1290           gtk_widget_destroy (Denemo.page);
1291           Denemo.projects = g_list_remove (Denemo.projects, gui);
1292           g_free (gui);
1293           warningdialog (_("Could not interpret selection as LilyPond notes"));
1294           return;
1295         }
1296       dnm_setinitialclef (Denemo.project->movement, (DenemoStaff *) Denemo.project->movement->currentstaff->data, theclef);
1297       call_out_to_guile ("(while (and (None?) (d-MoveToStaffDown)) (begin (d-MoveToStaffUp)(d-DeleteStaff)))");
1298       if (confirm (_("Paste from Selection"), _("Paste this music into your score?")))
1299         {
1300           DenemoProject *gui = Denemo.project;
1301           tohome (NULL, NULL);
1302           set_mark (NULL, NULL);
1303           toend (NULL, NULL);
1304           copywrapper (NULL, NULL);
1305           free_movements (gui);
1306           gtk_widget_destroy (Denemo.page);
1307           Denemo.projects = g_list_remove (Denemo.projects, gui);
1308           g_free (gui);
1309           pastewrapper (NULL, NULL);
1310         }
1311     }
1312 }
1313 
1314 void
paste_clipboard(GtkAction * action,DenemoScriptParam * param)1315 paste_clipboard (GtkAction * action, DenemoScriptParam * param)
1316 {
1317   if (Denemo.project != g_list_last (Denemo.projects)->data)
1318     {
1319       warningdialog (_("Can only paste LilyPond text into the last tab, sorry"));
1320       return;
1321     }
1322   GtkClipboard *clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
1323   gtk_clipboard_request_text (clipboard, (GtkClipboardTextReceivedFunc) lilypond_selection_received, NULL);
1324 
1325 }
1326 
1327 static void
comment_selection_received(G_GNUC_UNUSED GtkClipboard * clipboard,const gchar * text)1328 comment_selection_received (G_GNUC_UNUSED GtkClipboard * clipboard, const gchar * text)
1329 {
1330  gchar *comment;
1331  GString *exceptions = g_string_new ("");
1332  gint i;
1333  for (i=0x1;i<0x10;i++)
1334     g_string_append_printf (exceptions, "%c", i);
1335   for (i=0x7F;i<0x100;i++)
1336     g_string_append_printf (exceptions, "%c", i);
1337 
1338   if ((!text) || (*text == 0))
1339     {
1340       warningdialog (_("No selection text available"));
1341       return;
1342     }
1343     gchar *escaped = g_strescape(text, exceptions->str);
1344     gchar *info = g_strconcat(_("Inserted:\n"), escaped, NULL);
1345     comment = g_strdup_printf ("(d-Comment \"%s\")(d-InfoDialog \"%s\")", escaped, info);
1346     call_out_to_guile (comment);
1347     g_string_free (exceptions, TRUE);
1348     g_free (escaped);
1349     g_free (info);
1350     g_free (comment);
1351 }
1352 void
paste_comment(GtkAction * action,DenemoScriptParam * param)1353 paste_comment (GtkAction * action, DenemoScriptParam * param)
1354 {
1355     if(param && param->string && param->string->len)
1356         comment_selection_received (NULL, param->string->str);
1357     else
1358         {
1359         GtkClipboard *clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
1360         gtk_clipboard_request_text (clipboard, (GtkClipboardTextReceivedFunc) comment_selection_received, NULL);
1361         }
1362 }
1363 static void
export_interface(GtkAction * action,DenemoScriptParam * param,gint format_id)1364 export_interface(GtkAction* action, DenemoScriptParam* param, gint format_id){
1365   GET_1PARAM(action, param, filename);
1366   if (filename==NULL)
1367     file_export(format_id);
1368   else
1369     if (action==NULL || replace_existing_file_dialog(filename, format_id)){
1370       filesel_save (Denemo.project, filename, format_id, SAVE_COPY);
1371       force_lily_refresh(Denemo.project);
1372     }
1373 }
1374 
1375 /**
1376  * Export mudela callback prompts for filename
1377  *
1378  */
1379 void
export_mudela_action(GtkAction * action,DenemoScriptParam * param)1380 export_mudela_action (GtkAction * action, DenemoScriptParam * param)
1381 {
1382   export_interface (action, param, MUDELA_FORMAT);
1383 }
1384 
1385 /**
1386  * Export pdf callback prompts for filename
1387  *
1388  */
1389 void
export_pdf_action(GtkAction * action,DenemoScriptParam * param)1390 export_pdf_action (GtkAction * action, DenemoScriptParam * param)
1391 {
1392   export_interface (action, param, PDF_FORMAT);
1393 }
1394 
1395 /**
1396  * Export pdf callback prompts for filename
1397  *
1398  */
1399 void
export_png_action(GtkAction * action,DenemoScriptParam * param)1400 export_png_action (GtkAction * action, DenemoScriptParam * param)
1401 {
1402   export_interface (action, param, PNG_FORMAT);
1403 }
1404 
1405 /**
1406  * Export ABC callback prompts for filename
1407  *
1408  */
1409 void
export_ABC_action(GtkAction * action,DenemoScriptParam * param)1410 export_ABC_action (GtkAction * action, DenemoScriptParam * param)
1411 {
1412   export_interface (action, param, ABC_FORMAT);
1413 }
1414 
1415 /**
1416  * Export MIDI callback prompts for filename
1417  *
1418  */
1419 void
export_midi_action(GtkAction * action,DenemoScriptParam * param)1420 export_midi_action (GtkAction * action, DenemoScriptParam * param)
1421 {
1422   export_interface (action, param, MIDI_FORMAT);
1423 }
1424