1 /* exportlilypond.c
2  * Functions for generating LilyPond representation of the music
3  * for Denemo, a gtk+ frontend to GNU Lilypond
4  * (c) 2000, 2001, 2002 Matthew Hiller, Adam Tee
5  */
6 
7 
8 
9 #include "config.h"
10 #include <denemo/denemo.h>
11 #include <gtksourceview/gtksourceview.h>
12 #include <gtksourceview/gtksourcebuffer.h>
13 #include "core/utils.h"
14 #include <stdlib.h>
15 #include <string.h>
16 #include <unistd.h>
17 #include <stdio.h>
18 #include <fcntl.h>
19 #include "export/exportlilypond.h"
20 #include "export/print.h"
21 #include "printview/printview.h"
22 #include "command/score.h"
23 #include "command/object.h"
24 #include "export/xmldefs.h"
25 #include "command/lyric.h"
26 #include "command/processstaffname.h"
27 #include "command/commandfuncs.h"
28 #include "command/scorelayout.h"
29 #include "command/contexts.h"
30 #include "display/draw.h"
31 #include "core/view.h"
32 #include "audio/audiointerface.h"
33 #include "printview/printview.h"
34 
35 #define ENTER_NOTIFY_EVENT "focus-in-event"
36 #define LEAVE_NOTIFY_EVENT "focus-out-event"
37 
38 #define SIGNAL_WIDGET Denemo.textwindow /* Denemo.window */
39 
40 
41 #define GSTRINGP "gstring"
42 #define MUSIC "music"
43 #define START "start"
44 #define SCOREBLOCK "scoreblock"
45 #define CUSTOM "custom"
46 #define OBJECTNODE "object"
47 #define ORIGINAL "original"
48 
49 #define OBJECTNUM "objectnum"
50 #define TARGETTYPE "type"
51 #define MIDCOFFSET "midcoffset"
52 #define DIRECTIVENUM "directivenum"
53 #define MEASURENUM "measurenum"
54 #define STAFFNUM "staffnum"
55 #define MOVEMENTNUM "movementnum"
56 #define STANDARD_SCOREBLOCK "Standard scoreblock"
57 #define INEDITABLE "ineditable"
58 #define HIGHLIGHT "highlight"
59 #define ERRORTEXT "error text"
60 
61 gchar *get_postfix (GList * g);
62 
63 static void output_score_to_buffer (DenemoProject * gui, gboolean all_movements, gchar * partname, gchar *instrumentation);
64 static GtkTextTagTable *tagtable;
65 
66 /* inserts a navigation anchor into the lilypond textbuffer at curmark */
67 static void
place_navigation_anchor(GtkTextMark * curmark,gpointer curobjnode,gint movement_count,gint measurenum,gint voice_count,gint objnum,DenemoTargetType type,gint mid_c_offset)68 place_navigation_anchor (GtkTextMark * curmark, gpointer curobjnode, gint movement_count, gint measurenum, gint voice_count, gint objnum, DenemoTargetType type, gint mid_c_offset)
69 {
70   //GtkTextIter iter = *piter;
71   //put in an ineditable anchor to mark the start of the object
72   GtkTextIter iter;
73   gtk_text_buffer_get_iter_at_mark (Denemo.textbuffer, &iter, curmark);
74   GtkTextChildAnchor *objanc = gtk_text_buffer_create_child_anchor (Denemo.textbuffer, &iter);
75   g_object_set_data (G_OBJECT (objanc), OBJECTNODE, curobjnode);        //store objnode here
76   g_object_set_data (G_OBJECT (objanc), MOVEMENTNUM, GINT_TO_POINTER (movement_count));
77   g_object_set_data (G_OBJECT (objanc), MEASURENUM, GINT_TO_POINTER (measurenum));
78   g_object_set_data (G_OBJECT (objanc), STAFFNUM, GINT_TO_POINTER (voice_count));
79   g_object_set_data (G_OBJECT (objanc), OBJECTNUM, GINT_TO_POINTER (objnum));
80   g_object_set_data (G_OBJECT (objanc), TARGETTYPE, GINT_TO_POINTER (type));
81   g_object_set_data (G_OBJECT (objanc), MIDCOFFSET, GINT_TO_POINTER (mid_c_offset));
82 
83 
84   //g_debug("place nav anchor marked anchor %p as  type %d\n", objanc, type);
85   GtkTextIter back;
86   back = iter;
87   (void) gtk_text_iter_backward_char (&back);
88   gtk_text_buffer_apply_tag_by_name (Denemo.textbuffer, INEDITABLE, &back, &iter);
89 #if 1                           //0 makes anchors visible - but throws out locations
90   gtk_text_buffer_apply_tag_by_name (Denemo.textbuffer, "system_invisible", &back, &iter);
91 #endif
92 }
93 
94 void
highlight_lily_error()95 highlight_lily_error ()
96 {
97   if (Denemo.textbuffer == NULL)
98     return;
99   GtkTextIter enditer, iter;
100   gtk_text_buffer_get_end_iter (Denemo.textbuffer, &enditer);
101   gtk_text_buffer_get_start_iter (Denemo.textbuffer, &iter);
102   gtk_text_buffer_remove_tag_by_name (Denemo.textbuffer, ERRORTEXT, &enditer, &iter);
103   gint line, column;
104   line = (intptr_t) g_object_get_data (G_OBJECT (Denemo.textbuffer), "error line");
105   column = (intptr_t) g_object_get_data (G_OBJECT (Denemo.textbuffer), "error column");
106   line--;
107   if (line > 0)
108     {
109 #ifdef BUG_COLUMN_OFFSET_TOO_LARGE_FIXED
110       gtk_text_buffer_get_iter_at_line_offset (Denemo.textbuffer, &iter, line, column);
111 #else
112       gtk_text_buffer_get_iter_at_line_offset (Denemo.textbuffer, &iter, line, 0);
113       g_debug ("line %d column %d\n", line, column);
114       g_debug ("line has %d chars\n", gtk_text_iter_get_chars_in_line (&iter));
115       while (column--)
116         (void) gtk_text_iter_forward_char (&iter);      //EEEK TAB is 8 spaces for lilypond find these!!!!
117 
118 #endif
119       /*     gtk_text_iter_set_line(&iter, line); */
120       /*     gtk_text_iter_set_visible_line_offset(&iter, column); */
121 
122       gtk_text_buffer_apply_tag_by_name (Denemo.textbuffer, ERRORTEXT, &enditer, &iter);
123     }
124 }
125 
126 
127 /*  set_lily_error()
128  *  set line, column as the current line and column in Denemo.textbuffer where an error has been found
129  *  in the LilyPond interpreter. line starts from 1, column starts from 0
130  *  line=0 means no error
131  */
132 void
set_lily_error(gint line,gint column)133 set_lily_error (gint line, gint column)
134 {
135   if (Denemo.textbuffer)
136     {
137       g_object_set_data (G_OBJECT (Denemo.textbuffer), "error line", (gpointer) (intptr_t) line);
138       g_object_set_data (G_OBJECT (Denemo.textbuffer), "error column", (gpointer) (intptr_t) column);
139     }
140 }
141 
142 static void
explain_temporary_scoreblock(void)143 explain_temporary_scoreblock (void)
144 {
145   infodialog (_("This scorelayout is purely for continuous typesetting, and will change as you edit the score.\n"
146     "To get a real score layout turn off continuous typesetting in the Print View and "
147     "typeset using Part, Movement or Typeset (Default Layout) buttons."));
148 }
149 
150 static void
popup_score_layout_options(void)151 popup_score_layout_options (void)
152 {
153   GtkWidget *menu = gtk_menu_new ();
154   GtkWidget *item;
155   GList *g;
156   for (g = Denemo.project->standard_scoreblocks; g; g = g->next)
157     {
158       DenemoScoreblock *sb = g->data;
159       gchar *text = g_strdup_printf (_("Switch to Layout \"%s\""), sb->name);
160       item = gtk_menu_item_new_with_label (text);
161       g_free (text);
162       gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
163       g_signal_connect_swapped (G_OBJECT (item), "activate", G_CALLBACK (select_standard_layout), sb);
164     }
165   for (g = Denemo.project->custom_scoreblocks; g; g = g->next)
166     {
167       DenemoScoreblock *sb = g->data;
168       gchar *text = g_strdup_printf (_("Switch to Layout \"%s\""), sb->name);
169       item = gtk_menu_item_new_with_label (text);
170       g_free (text);
171       gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
172       g_signal_connect_swapped (G_OBJECT (item), "activate", G_CALLBACK (select_custom_layout), sb);
173     }
174 
175 
176   if (Denemo.project->standard_scoreblocks == NULL)
177     {
178       item = gtk_menu_item_new_with_label (_("Create Standard Score Layout"));
179       gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
180       g_signal_connect_swapped (G_OBJECT (item), "activate", G_CALLBACK (select_standard_layout), NULL);
181     }
182   item = gtk_menu_item_new_with_label ("Customize Score Layout");
183   gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
184   g_signal_connect_swapped (G_OBJECT (item), "activate", G_CALLBACK (make_scoreblock_editable), NULL);
185   gtk_widget_show_all (menu);
186 
187   gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL, 0, gtk_get_current_event_time ());
188 }
189 
190 void
make_scoreblock_editable(void)191 make_scoreblock_editable (void)
192 {
193   if (!gtk_widget_get_visible (Denemo.project->score_layout))
194     activate_action ("/MainMenu/ViewMenu/ToggleScoreLayout");
195   create_custom_lilypond_scoreblock ();
196   force_lily_refresh (Denemo.project);
197 }
198 
199 /* insert a pair of anchors and a mark to denote a section.
200    if str is non-null it is a target for saving edited versions of the section to, in this
201    case the start anchor of the section is prepended to the list gui->anchors
202    if name is non-null a button is attached to the start anchor.
203 */
204 static GtkTextChildAnchor *
insert_section(GString ** str,gchar * markname,gchar * name,GtkTextIter * iter,DenemoProject * gui)205 insert_section (GString ** str, gchar * markname, gchar * name, GtkTextIter * iter, DenemoProject * gui)
206 {
207   GtkTextIter back;
208   GtkTextChildAnchor *objanc = gtk_text_buffer_create_child_anchor (Denemo.textbuffer, iter);
209   back = *iter;
210   (void) gtk_text_iter_backward_char (&back);
211   gtk_text_buffer_apply_tag_by_name (Denemo.textbuffer, INEDITABLE, &back, iter);
212   if (name == NULL)
213     gtk_text_buffer_apply_tag_by_name (Denemo.textbuffer, "system_invisible", &back, iter);
214   gtk_text_buffer_insert (Denemo.textbuffer, iter, "\n", -1);//THE NEWLINE is needed to give something for the section to contain to which the attribute is then applied, but it causes problems as well...
215 
216   GtkTextChildAnchor *endanc = gtk_text_buffer_create_child_anchor (Denemo.textbuffer, iter);
217   back = *iter;
218   (void) gtk_text_iter_backward_char (&back);
219   gtk_text_buffer_apply_tag_by_name (Denemo.textbuffer, INEDITABLE, &back, iter);
220 
221   gtk_text_buffer_apply_tag_by_name (Denemo.textbuffer, "system_invisible", &back, iter);
222   g_object_set_data (G_OBJECT (objanc), "end", (gpointer) endanc);
223   g_object_set_data (G_OBJECT (objanc), GSTRINGP, (gpointer) str);
224   if (str)
225     gui->anchors = g_list_prepend (gui->anchors, objanc);
226 
227   if (!Denemo.non_interactive && name)
228     {
229       if (!strcmp (markname, "standard scoreblock"))
230         {
231           GtkWidget *button = gtk_button_new ();
232           gtk_button_set_label (GTK_BUTTON (button), _("Score Layout Options"));
233 
234           g_signal_connect (G_OBJECT (button), "button-press-event", G_CALLBACK (popup_score_layout_options), NULL);
235           gtk_widget_show_all (button);
236           gtk_text_view_add_child_at_anchor (GTK_TEXT_VIEW (Denemo.textview), button, objanc);
237         }
238       else if (!strcmp (markname, "temporary scoreblock"))
239         {
240           GtkWidget *button = gtk_button_new ();
241           gtk_button_set_label (GTK_BUTTON (button), _("Temporary Score Layout"));
242 
243           g_signal_connect (G_OBJECT (button), "button-press-event", G_CALLBACK (explain_temporary_scoreblock), NULL);
244           gtk_widget_show_all (button);
245           gtk_text_view_add_child_at_anchor (GTK_TEXT_VIEW (Denemo.textview), button, objanc);
246         }
247       else
248         {
249           char *markup = g_markup_printf_escaped ("<tt><big>%% %s</big></tt>\n", name); //monospace label to get serifs
250           GtkWidget *label = gtk_label_new ("");
251           gtk_label_set_markup (GTK_LABEL (label), markup);
252           gtk_text_view_add_child_at_anchor (GTK_TEXT_VIEW (Denemo.textview), label, objanc);
253           gtk_widget_show_all (label);
254         }
255     }
256   (void) gtk_text_iter_backward_char (iter);
257   (void) gtk_text_iter_backward_char (iter);
258   gtk_text_buffer_create_mark (Denemo.textbuffer, markname, iter, FALSE);
259   return objanc;
260 }
261 
262 #define FAKECHORD_SEP " |\t"      /*  | to separate chord symbols */
263 
264 #define FIGURES_SEP "|"
265 /* a separator for groups of figured bass figures on one note
266    this could be a user preference thingy */
267 
268 
269 /**
270  * Output the lilypond representation of the given keysignature
271  *
272  */
273 static void
determinekey(gint number,gchar ** keyname)274 determinekey (gint number, gchar ** keyname)
275 {
276   switch (number)
277     {
278     case -7:
279       *keyname = "ces";
280       break;
281     case -6:
282       *keyname = "ges";
283       break;
284     case -5:
285       *keyname = "des";
286       break;
287     case -4:
288       *keyname = "aes";
289       break;
290     case -3:
291       *keyname = "ees";
292       break;
293     case -2:
294       *keyname = "bes";
295       break;
296     case -1:
297       *keyname = "f";
298       break;
299     case 0:
300       *keyname = "c";
301       break;
302     case 1:
303       *keyname = "g";
304       break;
305     case 2:
306       *keyname = "d";
307       break;
308     case 3:
309       *keyname = "a";
310       break;
311     case 4:
312       *keyname = "e";
313       break;
314     case 5:
315       *keyname = "b";
316       break;
317     case 6:
318       *keyname = "fis";
319       break;
320     case 7:
321       *keyname = "cis";
322       break;
323     case 8:
324       *keyname = "gis";
325       break;
326     case 9:
327       *keyname = "dis";
328       break;
329     case 10:
330       *keyname = "ais";
331       break;
332     default:
333       *keyname = _("%{error. defaulting to%}c");
334       break;
335     }
336 }
337 
338 /**
339  * Output the lilypond representataion of the given clef
340  *
341  */
342 static void
determineclef(gint type,gchar ** clefname)343 determineclef (gint type, gchar ** clefname)
344 {
345   switch (type)
346     {
347     case DENEMO_TREBLE_CLEF:
348       *clefname = "treble";
349       break;
350     case DENEMO_BASS_CLEF:
351       *clefname = "bass";
352       break;
353     case DENEMO_ALTO_CLEF:
354       *clefname = "alto";
355       break;
356     case DENEMO_G_8_CLEF:
357       // *clefname = "\"G_8\"";
358       *clefname = "\"treble_8\"";
359       break;
360     case DENEMO_F_8_CLEF:
361       *clefname = "\"bass_8\"";
362       break;
363     case DENEMO_TENOR_CLEF:
364       *clefname = "tenor";
365       break;
366     case DENEMO_SOPRANO_CLEF:
367       *clefname = "soprano";
368       break;
369     case DENEMO_FRENCH_CLEF:
370       *clefname = "french";
371       break;
372     default:
373       *clefname = _("%{error. defaulting to%}treble");
374       break;
375     }
376   /* I've found the quotes are necessary for ^ and _ clefs
377    * to parse correctly */
378 }
379 
380 /**
381  * Convert denemo duration to lilypond duration
382  */
383 static gint
internaltomuduration(gint internalduration)384 internaltomuduration (gint internalduration)
385 {
386   if (internalduration < 0)
387     return internalduration;
388   return 1 << internalduration;
389 }
390 
391 
392 /**
393  * append mudela duration information to FIGURES.
394  * This could be optimized to remember the previous value and
395  * avoid repetition - an initialization call would be needed to
396  * set up initial values in that case
397  */
398 static GString *
append_duration(GString * figures,gint duration,gint numdots)399 append_duration (GString * figures, gint duration, gint numdots)
400 {
401   int i;
402   g_string_sprintfa (figures, "%d", duration);
403   for (i = 0; i < numdots; i++)
404     figures = g_string_append (figures, ".");
405   return figures;
406 }
407 
408 static void
output_figured_bass_prefix(GString * figures,DenemoDirective * directive)409 output_figured_bass_prefix (GString * figures, DenemoDirective * directive)
410 {
411   if ((directive->override & DENEMO_ALT_OVERRIDE) && directive->prefix)
412     g_string_append (figures, directive->prefix->str);
413 }
414 
415 /**
416  * add figures to *pfigures for *pchord
417  */
418 static void
output_figured_bass(GString * figures,chord * pchord)419 output_figured_bass (GString * figures, chord * pchord)
420 {
421   static gboolean continuation = FALSE;
422   static GString *last_figure;  // for continuations
423   gint duration = internaltomuduration (pchord->baseduration);
424   gint numdots = pchord->numdots;
425   GString *fig_str;             /*working copy of figures string stored in pchord */
426   char *str;                    /* pointer into the figure string fig_str */
427   gint num_groups = 1;          /* number of groups of figures */
428   gchar *duration_string = NULL;        //whole measure rests etc
429 
430   //First any override (e.g. to tweak position of figures)
431   //This is stored in note-directives with DENEMO_ALT_OVERRIDE set.
432   // This does mean that figures on rests can only be tweaked with a postfix on the previous note.
433   DenemoDirective *directive;
434   if (pchord->notes && (note *) (pchord->notes->data) && ((note *) (pchord->notes->data))->directives && (directive = ((note *) (pchord->notes->data))->directives->data))
435     {
436       output_figured_bass_prefix (figures, directive);
437     }
438 
439 
440   if (duration < 0)
441     {
442       gchar *lily = get_postfix (pchord->directives);
443       if (lily)
444         {
445           duration_string = g_strrstr (lily, "R1*");
446           if (!duration_string)
447             {
448               g_warning ("duration is special but cannot find R1* - output in figured bass");
449               duration_string = g_strdup ("R1*4/4");
450             }
451         }
452       else
453         {
454           g_warning ("duration is special but no directives to account for it - output in figured bass");
455           duration_string = g_strdup ("R1*4/4");
456         }
457       duration_string++;        //the duration, after the  R
458     }
459 #define APPEND_DUR(a, b, c) duration<0?g_string_append(a, duration_string):append_duration(a,b,c)
460 
461 
462   if (!last_figure)
463     last_figure = g_string_new ("");
464 
465   if (pchord->figure == NULL || (((GString *) ((chord *) pchord->figure))->str) == NULL)
466     fig_str = g_string_new ("_");       /* the no-figure figure */
467   else
468     fig_str = g_string_new (((GString *) ((chord *) pchord->figure))->str);
469   gchar *figstr = fig_str->str;
470 //handle direct insert into the figured bass staff
471 
472   if (*figstr == '$')
473     {
474       figstr++;
475       str = strchr (figstr, '$');
476       if (str)
477         {
478           *str = 0;
479           g_string_append (figures, figstr);
480           *str = '$';
481           figstr = str + 1;
482         }
483     }
484 
485   if (*figstr == '~')
486     {
487       if (!continuation)
488         {
489           figures = g_string_append (figures, "\\bassFigureExtendersOn ");
490           continuation = TRUE;
491         }
492       if (last_figure->len)
493         {
494           figures = g_string_append (figures, "<");
495           figures = g_string_append (figures, last_figure->str);
496         }
497     }
498   else
499     {
500         if (continuation)
501             figures = g_string_append (figures, "\\bassFigureExtendersOff <");
502         else
503             figures = g_string_append (figures, "<");
504     }
505 
506   /* multiple figures are separated by a FIGURES_SEP char,
507      output these at subdivisions of the duration */
508   str = strchr (figstr, *(char *) FIGURES_SEP);
509   if (str != NULL)
510     {
511       /* we have more than one group of figures to be output
512          for one bass note. Count the number of groups */
513       num_groups = 2;
514       /* one on either side of the FIGURES_SEP found */
515       while ((str = strchr (++str, *(char *) FIGURES_SEP)) != NULL)
516         num_groups++;
517     }
518 
519   switch (num_groups)
520     {
521     default:
522     case 1:
523       if (*figstr != '~')
524         {
525          if (continuation)
526                   continuation = FALSE;
527           figures = g_string_append (figures, figstr);
528           g_string_assign (last_figure, figstr);
529         }
530       figures = g_string_append (figures, ">");
531       APPEND_DUR (figures, duration, numdots);
532 
533       break;
534       /* Each group of figures is assigned a duration to
535          achieve a normal looking output */
536     case 2:
537       {
538         gint first_duration, second_duration;
539         if (numdots)
540           {                     /* divide unequally */
541             first_duration = duration;
542             second_duration = duration * 2;
543           }
544         else
545           {
546             first_duration = second_duration = duration * 2;
547           }
548         str = strtok (figstr, FIGURES_SEP);
549         figures = g_string_append (figures, str);
550         figures = g_string_append (figures, ">");
551         APPEND_DUR (figures, first_duration, 0);
552 
553 
554         if (pchord->notes && (note *) (pchord->notes->data) && ((note *) (pchord->notes->data))->directives && ((note *) (pchord->notes->data))->directives->next && (directive = ((note *) (pchord->notes->data))->directives->next->data))
555           {
556             output_figured_bass_prefix (figures, directive);
557           }
558 
559 
560         figures = g_string_append (figures, "<");
561         str = strtok (NULL, FIGURES_SEP);
562         figures = g_string_append (figures, str);
563         figures = g_string_append (figures, ">");
564         APPEND_DUR (figures, second_duration, 0);
565       }
566       break;
567     case 3:
568       {
569         gint first_duration, second_duration, third_duration;
570         if (numdots == 1)
571           {                     /* divide equally */
572 
573             first_duration = second_duration = third_duration = duration * 2;
574           }
575         else if (numdots == 2)
576           {
577             first_duration = second_duration = duration * 2;
578             third_duration = duration * 4;
579           }                     /* no more dots please! */
580         else
581           {                     /* divide unequally */
582             first_duration = duration * 2;
583             second_duration = third_duration = duration * 4;
584           }
585         str = strtok (figstr, FIGURES_SEP);
586         figures = g_string_append (figures, str);
587         figures = g_string_append (figures, ">");
588         APPEND_DUR (figures, first_duration, 0);
589         if (pchord->notes && (note *) (pchord->notes->data) && ((note *) (pchord->notes->data))->directives && ((note *) (pchord->notes->data))->directives->next && (directive = ((note *) (pchord->notes->data))->directives->next->data))
590           {
591             output_figured_bass_prefix (figures, directive);
592           }
593         figures = g_string_append (figures, "<");
594         str = strtok (NULL, FIGURES_SEP);
595         figures = g_string_append (figures, str);
596         figures = g_string_append (figures, ">");
597         APPEND_DUR (figures, second_duration, 0);
598         if (pchord->notes && (note *) (pchord->notes->data) && ((note *) (pchord->notes->data))->directives && ((note *) (pchord->notes->data))->directives->next && ((note *) (pchord->notes->data))->directives->next->next && (directive = ((note *) (pchord->notes->data))->directives->next->next->data))
599           {
600             output_figured_bass_prefix (figures, directive);
601           }
602         str = strtok (NULL, FIGURES_SEP);
603         figures = g_string_append (figures, "<");
604         figures = g_string_append (figures, str);
605         figures = g_string_append (figures, ">");
606         APPEND_DUR (figures, third_duration, 0);
607       }
608       break;
609     case 4:
610       {
611         gint first_duration, second_duration, third_duration, fourth_duration;
612         if (numdots == 1)
613           {                     /* divide unequally */
614 
615             first_duration = second_duration = duration * 2;
616             third_duration = fourth_duration = duration * 4;
617           }
618         else if (numdots == 2)
619           {
620             first_duration = second_duration = duration * 2;
621             third_duration = duration * 4;
622             fourth_duration = duration * 8;
623           }                     /* no more dots please! */
624         else
625           {                     /* divide equally */
626             first_duration = second_duration = third_duration = fourth_duration = duration * 4;
627           }
628         str = strtok (figstr, FIGURES_SEP);
629         figures = g_string_append (figures, str);
630         figures = g_string_append (figures, ">");
631         APPEND_DUR (figures, first_duration, 0);
632         if (pchord->notes && (note *) (pchord->notes->data) && ((note *) (pchord->notes->data))->directives && ((note *) (pchord->notes->data))->directives->next && (directive = ((note *) (pchord->notes->data))->directives->next->data))
633           {
634             output_figured_bass_prefix (figures, directive);
635           }
636         figures = g_string_append (figures, "<");
637         str = strtok (NULL, FIGURES_SEP);
638         figures = g_string_append (figures, str);
639         figures = g_string_append (figures, ">");
640         APPEND_DUR (figures, second_duration, 0);
641         if (pchord->notes && (note *) (pchord->notes->data) && ((note *) (pchord->notes->data))->directives && ((note *) (pchord->notes->data))->directives->next && ((note *) (pchord->notes->data))->directives->next->next && (directive = ((note *) (pchord->notes->data))->directives->next->next->data))
642           {
643             output_figured_bass_prefix (figures, directive);
644           }
645         str = strtok (NULL, FIGURES_SEP);
646         figures = g_string_append (figures, "<");
647         figures = g_string_append (figures, str);
648         figures = g_string_append (figures, ">");
649         APPEND_DUR (figures, third_duration, 0);
650         if (pchord->notes && (note *) (pchord->notes->data) && ((note *) (pchord->notes->data))->directives && ((note *) (pchord->notes->data))->directives->next && ((note *) (pchord->notes->data))->directives->next->next && (directive = ((note *) (pchord->notes->data))->directives->next->next->data))
651           {
652             output_figured_bass_prefix (figures, directive);
653           }
654         str = strtok (NULL, FIGURES_SEP);
655         figures = g_string_append (figures, "<");
656         figures = g_string_append (figures, str);
657         figures = g_string_append (figures, ">");
658         APPEND_DUR (figures, fourth_duration, 0);
659       }
660       break;
661     }
662   // if(duration_string) g_free(--duration_string);
663 }
664 
665 static gchar *
parse_extension(gchar * input)666 parse_extension (gchar * input)
667 {
668     while (*input && *input != ':')
669         input++;
670     if(*input==':')
671        return input++;
672     return NULL;
673 }
674 
num_fakechords(gchar * thestr)675 static gint num_fakechords (gchar *thestr)
676 {
677     gint num = 1;
678     gchar *str = g_strdup(thestr);
679     strtok(str, FAKECHORD_SEP);
680     while(strtok(NULL, FAKECHORD_SEP))
681         num++;
682     g_free (str);
683     return num;
684 }
685 /**
686  * add figures to *pfigures for *pchord
687  */
688 static void
output_fakechord(GString * fakechord,chord * pchord)689 output_fakechord (GString * fakechord, chord * pchord)
690 {
691   gint duration = internaltomuduration (pchord->baseduration);
692   gint numdots = pchord->numdots;
693   GString *fig_str;             /*working copy of figures string */
694   char *str;                    /* pointer into the figure string fig_str */
695   gint num_groups = 1;          /* number of groups of figures */
696   gchar *extension;
697   gchar *duration_string = NULL;        //whole measure rests etc
698 
699   fakechord = g_string_append (fakechord, " ");
700 
701     if (duration < 0)
702     {
703       gchar *lily = get_postfix (pchord->directives);
704       if (lily)
705         {
706           duration_string = g_strrstr (lily, "R1*");
707           if (!duration_string)
708             {
709               g_warning ("duration is special but cannot find R1* - output in fakechord");
710               duration_string = g_strdup ("R1*4/4");
711             }
712         }
713       else
714         {
715           g_warning ("duration is special but no directives to account for it - output in fakechord");
716           duration_string = g_strdup ("R1*4/4");
717         }
718       duration_string++;        //the duration, after the  R
719       //g_string_append_printf(fakechord, "%s%s", "s", duration_string);
720      // return;
721     }
722 
723 
724 
725 
726   if (pchord->fakechord == NULL || (((GString *) ((chord *) pchord->fakechord))->len) == 0)
727     fig_str = g_string_new ("s");       /* the no-fakechord figure */
728   else
729     {
730       fig_str = g_string_new (((GString *) ((chord *) pchord->fakechord))->str);
731       if(*fig_str->str>='A' && *fig_str->str<='G')
732         *fig_str->str = *fig_str->str - 'A' + 'a';//downcase only first Chord root name, allows inserted LilyPond syntax
733     }
734 
735  num_groups = num_fakechords (fig_str->str);
736 //g_print("for %s num groups %d\n",fig_str->str, num_groups);
737   switch (num_groups)
738     {
739     default:
740     case 1:
741       {gchar *c;
742         extension = parse_extension (fig_str->str);
743         for (c=fig_str->str;*c && *c!=':';c++)
744             g_string_append_c (fakechord, *c);
745         APPEND_DUR (fakechord, duration, numdots);
746         if (extension)
747           g_string_append (fakechord, extension);
748         break;
749       }
750       /* Each group of fakechord is assigned a duration to
751          achieve a normal looking output */
752     case 2:
753       {
754         gint first_duration, second_duration;
755         if (numdots)
756           {                     /* divide unequally */
757             first_duration = duration;
758             second_duration = duration * 2;
759           }
760         else
761           {
762             first_duration = second_duration = duration * 2;
763           }
764         gchar *c;
765         gchar *thestr = g_strdup(fig_str->str);
766         str = strtok (thestr, FAKECHORD_SEP);
767         g_print("str %s ", str);
768         extension = parse_extension (str);
769         for (c=str;*c && *c!=':';c++)
770             g_string_append_c (fakechord, *c);
771         APPEND_DUR (fakechord, first_duration, 0);
772         if (extension)
773           g_string_append (fakechord, extension);
774         fakechord = g_string_append (fakechord, " ");
775         str = strtok (NULL, FAKECHORD_SEP);g_print("str2 %s ", str);
776         extension = parse_extension (str);
777         for (c=str;*c && *c!=':';c++)
778             g_string_append_c (fakechord, *c);
779         APPEND_DUR (fakechord, second_duration, 0);
780         if (extension)
781           g_string_append (fakechord, extension);
782         fakechord = g_string_append (fakechord, " ");
783         g_free(thestr);
784       }
785       break;
786     case 3:
787       {
788         gint first_duration, second_duration, third_duration;
789         if (numdots == 1)
790           {                     /* divide equally */
791 
792             first_duration = second_duration = third_duration = duration * 2;
793           }
794         else if (numdots == 2)
795           {
796             first_duration = second_duration = duration * 2;
797             third_duration = duration * 4;
798           }                     /* no more dots please! */
799         else
800           {                     /* divide unequally */
801             first_duration = duration * 2;
802             second_duration = third_duration = duration * 4;
803           }
804         gchar *c;
805         gchar *thestr = g_strdup(fig_str->str);
806         str = strtok (thestr, FAKECHORD_SEP);
807         g_print("str %s ", str);
808         extension = parse_extension (str);
809         for (c=str;*c && *c!=':';c++)
810             g_string_append_c (fakechord, *c);
811         APPEND_DUR (fakechord, first_duration, 0);
812         if (extension)
813           g_string_append (fakechord, extension);
814         fakechord = g_string_append (fakechord, " ");
815         str = strtok (NULL, FAKECHORD_SEP);g_print("str2 %s ", str);
816         extension = parse_extension (str);
817         for (c=str;*c && *c!=':';c++)
818             g_string_append_c (fakechord, *c);
819         APPEND_DUR (fakechord, second_duration, 0);
820         if (extension)
821           g_string_append (fakechord, extension);
822         fakechord = g_string_append (fakechord, " ");
823 
824         str = strtok (NULL, FAKECHORD_SEP);g_print("str2 %s ", str);
825         extension = parse_extension (str);
826         for (c=str;*c && *c!=':';c++)
827             g_string_append_c (fakechord, *c);
828         APPEND_DUR (fakechord, third_duration, 0);
829         if (extension)
830           g_string_append (fakechord, extension);
831         fakechord = g_string_append (fakechord, " ");
832         g_free(thestr);
833       }
834       break;
835           case 4:
836       {
837         gint first_duration, second_duration;
838         if (numdots)
839           {                     /* divide unequally */
840             first_duration = duration * 2;
841             second_duration = duration * 4;
842           }
843         else
844           {
845             first_duration = second_duration = duration * 4;
846           }
847         gchar *c;
848         gchar *thestr = g_strdup(fig_str->str);
849         str = strtok (thestr, FAKECHORD_SEP);
850         g_print("str %s duration %d", str, first_duration);
851         extension = parse_extension (str);
852         for (c=str;*c && *c!=':';c++)
853             g_string_append_c (fakechord, *c);
854         APPEND_DUR (fakechord, first_duration, 0);
855         if (extension)
856           g_string_append (fakechord, extension);
857         fakechord = g_string_append (fakechord, " ");
858         str = strtok (NULL, FAKECHORD_SEP);g_print("str2 %s ", str);
859         extension = parse_extension (str);
860         for (c=str;*c && *c!=':';c++)
861             g_string_append_c (fakechord, *c);
862         APPEND_DUR (fakechord, second_duration, 0);
863         if (extension)
864           g_string_append (fakechord, extension);
865         fakechord = g_string_append (fakechord, " ");
866         str = strtok (NULL, FAKECHORD_SEP);g_print("str3 %s ", str);
867         extension = parse_extension (str);
868         for (c=str;*c && *c!=':';c++)
869             g_string_append_c (fakechord, *c);
870         APPEND_DUR (fakechord, second_duration, 0);
871         if (extension)
872           g_string_append (fakechord, extension);
873         fakechord = g_string_append (fakechord, " ");
874         str = strtok (NULL, FAKECHORD_SEP);g_print("str4 %s ", str);
875         extension = parse_extension (str);
876         for (c=str;*c && *c!=':';c++)
877             g_string_append_c (fakechord, *c);
878         APPEND_DUR (fakechord, second_duration, 0);
879         if (extension)
880           g_string_append (fakechord, extension);
881         g_free(thestr);
882       }
883       break;
884     }
885 }
886 #undef APPEND_DUR
887 /*
888  * insert_editable()
889  * Insert pair of invisble anchors and editable text between, adding the start anchor to the list in gui->anchors
890  * if directive is NULL or empty string provide a space for editing.
891  * ORIGINAL: string containing text to initialize with: the caller owns this string
892  * DIRECTIVE: pointer to a target GString where changes should be stored,
893  *            or NULL if editable text is to be allowed here (an editable space is inserted in this case)
894  * ITER: the current iter in Denemo.textbuffer
895 
896  * GUI: the gui with the textbuffer
897  *
898  */
899 static void
insert_editable(GString ** pdirective,gchar * original,GtkTextIter * iter,DenemoProject * gui,GString * lily_for_obj,DenemoTargetType type,gint movement_count,gint measurenum,gint voice_count,gint objnum,gint directive_index,gint midcoffset)900 insert_editable (GString ** pdirective, gchar * original, GtkTextIter * iter, DenemoProject * gui, GString * lily_for_obj, DenemoTargetType type, gint movement_count, gint measurenum, gint voice_count, gint objnum, gint directive_index, gint midcoffset)
901 {
902   gint directivenum = directive_index + 1;
903   GtkTextChildAnchor *lilyanc = gtk_text_buffer_create_child_anchor (Denemo.textbuffer, iter);
904   GtkTextIter back;
905   back = *iter;
906   (void) gtk_text_iter_backward_char (&back);
907   gtk_text_buffer_apply_tag_by_name (Denemo.textbuffer, INEDITABLE, &back, iter);
908   gtk_text_buffer_apply_tag_by_name (Denemo.textbuffer, "system_invisible", &back, iter);
909   g_object_set_data (G_OBJECT (lilyanc), GSTRINGP, (gpointer) pdirective);
910   g_object_set_data (G_OBJECT (lilyanc), ORIGINAL, original);
911 
912   g_object_set_data (G_OBJECT (lilyanc), MOVEMENTNUM, GINT_TO_POINTER (movement_count));
913   g_object_set_data (G_OBJECT (lilyanc), MEASURENUM, GINT_TO_POINTER (measurenum));
914   g_object_set_data (G_OBJECT (lilyanc), STAFFNUM, GINT_TO_POINTER (voice_count));
915   g_object_set_data (G_OBJECT (lilyanc), OBJECTNUM, GINT_TO_POINTER (objnum));
916   g_object_set_data (G_OBJECT (lilyanc), TARGETTYPE, GINT_TO_POINTER (type));
917   if (directivenum)
918     g_object_set_data (G_OBJECT (lilyanc), DIRECTIVENUM, GINT_TO_POINTER (directivenum));
919   //g_debug("insert editable marked target anchor %p directivenum %d type %d\n", lilyanc, directivenum, type);
920   if (midcoffset)
921     g_object_set_data (G_OBJECT (lilyanc), MIDCOFFSET, GINT_TO_POINTER (midcoffset));
922 
923   if (type)
924     g_object_set_data (G_OBJECT (lilyanc), TARGETTYPE, GINT_TO_POINTER (type));
925   //g_debug("marked anchor %p as %d %d %d %d type %d\n", lilyanc, movement_count, measurenum, voice_count, objnum, type);
926   gui->anchors = g_list_prepend (gui->anchors, lilyanc);
927   gtk_text_buffer_insert_with_tags_by_name (Denemo.textbuffer, iter, g_strdup (original), -1, "bold", NULL);
928   if (lily_for_obj)
929     g_string_append (lily_for_obj, original);
930   GtkTextChildAnchor *endanc = gtk_text_buffer_create_child_anchor (Denemo.textbuffer, iter);
931   back = *iter;
932   (void) gtk_text_iter_backward_char (&back);
933   gtk_text_buffer_apply_tag_by_name (Denemo.textbuffer, INEDITABLE, &back, iter);
934   gtk_text_buffer_apply_tag_by_name (Denemo.textbuffer, "system_invisible", &back, iter);
935   g_object_set_data (G_OBJECT (lilyanc), "end", (gpointer) endanc);
936   if ((*pdirective) == NULL || (*pdirective)->len == 0)
937     gtk_text_buffer_insert_with_tags_by_name (Denemo.textbuffer, iter, " ", -1, HIGHLIGHT, NULL);
938 }
939 
940 static gint
brace_count(gchar * str)941 brace_count (gchar * str)
942 {
943   gint ret;
944   for (ret = 0; *str; str++)
945     {
946       if (*str == '{')
947         ret++;
948       if (*str == '}')
949         ret--;
950     }
951   return ret;
952 }
953 
954 // get_overridden_prefix, postfix returns the relevant fields from the directive list assembled with those marked as overriding lilypond  in front and other at end; ones with AFFIX not matching override are omitted.
955 #define GET_OVERRIDDEN_AFFIX(field)\
956 static gchar *get_overridden_##field(GList *g, gboolean override) {\
957   if(g==NULL)\
958     return g_strdup("");\
959   GString *ret = g_string_new("");\
960   for(;g;g=g->next) {\
961     DenemoDirective *d = g->data;\
962     if(override == ((d->override&DENEMO_OVERRIDE_AFFIX)==0))\
963       continue;                 \
964     if(!((d->override & DENEMO_OVERRIDE_HIDDEN))){\
965       if(d->field && d->field->len) {\
966     if(d->override & DENEMO_OVERRIDE_LILYPOND)\
967       g_string_prepend(ret, d->field->str);\
968     else\
969       g_string_append(ret, d->field->str);\
970       }\
971     }\
972   }\
973 return g_string_free(ret, FALSE);\
974 }
975 
976 #define GET_AFFIX(field)\
977    gchar *get_##field(GList *g) {\
978   return get_overridden_##field(g, FALSE);\
979 }
980 
981 GET_OVERRIDDEN_AFFIX (prefix);
982 GET_OVERRIDDEN_AFFIX (postfix);
983 
984 GET_AFFIX (prefix);
985 GET_AFFIX (postfix);
986 
987 
988 
989 
990 /* insert editable prefix string from passed directives, updating duration and open brace count
991  omit or include those with AFFIX override set. Skip any directive with HIDDEN attribute set */
992 
993 
994 
995 //NAVANC
996 #define DIRECTIVES_INSERT_EDITABLE_AFFIX(field) static void \
997 directives_insert_##field##_editable (GList *directives, gint *popen_braces, gint *pprevduration, GtkTextIter *iter, gboolean override, GString *lily_for_obj,\
998                         DenemoTargetType type, gint movement_count, gint measurenum, gint voice_count, gint objnum, gint midcoffset, guint sbid) {\
999   DenemoProject *gui = Denemo.project;\
1000   GList *g = directives; gint num;\
1001   for(num=0;g;g=g->next, num++) {\
1002     DenemoDirective *directive = (DenemoDirective *)g->data;\
1003     if(override == ((directive->override&DENEMO_OVERRIDE_AFFIX)==0))\
1004       continue;\
1005     if(directive->override&DENEMO_OVERRIDE_HIDDEN)\
1006       continue;\
1007     if (!(((directive->x == 0 || (directive->x!=sbid))) && ((directive->y == 0 || (directive->y==sbid)))))\
1008         continue;\
1009     if(directive->field && directive->field->len) {\
1010       if(pprevduration) *pprevduration = -1;            \
1011       if(popen_braces) *popen_braces += brace_count(directive->field->str); \
1012       insert_editable(&directive->field, directive->field->str, iter, gui, lily_for_obj\
1013       , type, movement_count, measurenum, voice_count, objnum, num, midcoffset);\
1014     }\
1015   }\
1016 }
1017 
1018 DIRECTIVES_INSERT_EDITABLE_AFFIX (prefix);
1019 DIRECTIVES_INSERT_EDITABLE_AFFIX (postfix);
1020 
1021 static void
directives_insert_affix_postfix_editable(GList * directives,gint * popen_braces,gint * pprevduration,GtkTextIter * iter,GString * lily_for_obj,DenemoTargetType type,gint movement_count,gint measurenum,gint voice_count,gint objnum,gint midcoffset,guint sbid)1022 directives_insert_affix_postfix_editable (GList * directives, gint * popen_braces, gint * pprevduration, GtkTextIter * iter, GString * lily_for_obj,
1023         DenemoTargetType type, gint movement_count, gint measurenum, gint voice_count, gint objnum, gint midcoffset, guint sbid)
1024 {
1025   DenemoProject *gui = Denemo.project;
1026   GList *g = directives;;
1027   gint num;
1028   for (num = 0; g; g = g->next, num++)
1029     {
1030       DenemoDirective *directive = (DenemoDirective *) g->data;
1031       if (!(directive->override & DENEMO_OVERRIDE_AFFIX))
1032         continue;
1033       if (directive->override & DENEMO_OVERRIDE_HIDDEN)
1034         continue;
1035       if (!(((directive->x == 0 || (directive->x!=sbid))) && ((directive->y == 0 || (directive->y==sbid)))))
1036         continue;
1037       if (directive->postfix && directive->postfix->len)
1038         {
1039           if (pprevduration)
1040             *pprevduration = -1;
1041           if (popen_braces)
1042             *popen_braces += brace_count (directive->postfix->str);
1043           insert_editable (&directive->postfix, directive->postfix->str, iter, gui, lily_for_obj, type, movement_count, measurenum, voice_count, objnum, num, midcoffset);
1044         }
1045     }
1046 }
1047 
1048 
1049 /* returns if there is a directive overriding the normal LilyPond output */
1050 static gint
get_lily_override(GList * g)1051 get_lily_override (GList * g)
1052 {
1053   return get_override (g) & DENEMO_OVERRIDE_LILYPOND;
1054 }
1055 
1056 
1057 
1058 
1059 /**
1060  * generate the lilypond for the DenemoObject curobj
1061  * the state of the prevailing duration, clef keysignature are updated and returned.
1062  * returns the excess of open braces "{" created by this object.
1063  */
1064 static gint
generate_lily_for_obj(DenemoProject * gui,GtkTextIter * iter,DenemoObject * curobj,gint * pprevduration,gint * pprevnumdots,gchar ** pclefname,gchar ** pkeyname,gint * pcur_stime1,gint * pcur_stime2,gint * pgrace_status,GString * figures,GString * fakechords,GtkTextMark * curmark,gpointer curobjnode,gint movement_count,gint measurenum,gint voice_count,gint objnum,guint sbid)1065 generate_lily_for_obj (DenemoProject * gui, GtkTextIter * iter, DenemoObject * curobj, gint * pprevduration, gint * pprevnumdots, gchar ** pclefname, gchar ** pkeyname, gint * pcur_stime1,
1066     gint * pcur_stime2, gint * pgrace_status, GString * figures, GString * fakechords, GtkTextMark * curmark, gpointer curobjnode, gint movement_count, gint measurenum, gint voice_count, gint objnum, guint sbid)
1067 {
1068   GString *lily_for_obj = g_string_new ("");
1069   GString *ret = g_string_new ("");     //no longer returned, instead put into *music
1070 #define outputret gtk_text_buffer_insert_with_tags_by_name (Denemo.textbuffer, iter, ret->str, -1, INEDITABLE, NULL), \
1071     g_string_append(lily_for_obj, ret->str);\
1072     open_braces +=  brace_count(ret->str), \
1073     g_string_assign(ret, "")
1074 #define output(astring) (gtk_text_buffer_insert_with_tags_by_name (Denemo.textbuffer, iter, astring, -1, INEDITABLE, NULL));\
1075             g_string_append(lily_for_obj, astring);
1076   gint prevduration = *pprevduration;
1077   gint prevnumdots = *pprevnumdots;
1078   chord *pchord;
1079   gchar *clefname = *pclefname;
1080   gchar *keyname = *pkeyname;
1081   gint cur_stime1 = *pcur_stime1;
1082   gint cur_stime2 = *pcur_stime2;
1083   gint j, k;
1084   gint duration, numdots;
1085   gboolean is_normalnotehead = TRUE;
1086   gboolean is_chordmode = FALSE;
1087   gint octave, enshift;
1088   gint noteheadtype;
1089   gint mid_c_offset;
1090   gint open_braces = 0;         /* keep track of excess open braces "{" so as to ensure they are closed */
1091 
1092   GString *dynamic_string = NULL;
1093 
1094   gtk_text_buffer_insert_with_tags_by_name (Denemo.textbuffer, iter, " ", -1, INEDITABLE, HIGHLIGHT, NULL);     //A gray blank between objects
1095   g_string_append (lily_for_obj, " ");
1096 
1097 
1098 #define NAVANC(type, offset)  place_navigation_anchor(curmark, (gpointer)curobjnode, movement_count, measurenum, voice_count, objnum, type, offset);\
1099                                 gtk_text_buffer_get_iter_at_mark (Denemo.textbuffer, iter, curmark);
1100 
1101 
1102   switch (curobj->type)
1103     {
1104     case CHORD:
1105       {
1106         gint lily_override;
1107         pchord = (chord *) curobj->object;
1108         gchar *chord_prefix = get_prefix (pchord->directives);
1109         duration = internaltomuduration (pchord->baseduration);
1110         numdots = pchord->numdots;
1111         is_chordmode = FALSE;
1112         lily_override = get_lily_override (pchord->directives);
1113 
1114         if (!lily_override)
1115           if ((!*pgrace_status) && pchord->is_grace)
1116             {
1117               *pgrace_status = TRUE;
1118               if (pchord->is_grace & GRACED_NOTE)
1119                 g_string_append_printf (ret, "\\grace {");
1120               else
1121                 g_string_append_printf (ret, "\\acciaccatura {");
1122                             }
1123         /* prefix is before duration unless AFFIX override is set */
1124         directives_insert_prefix_editable (pchord->directives, &open_braces, &prevduration, iter, !lily_override, lily_for_obj, TARGET_CHORD, movement_count, measurenum, voice_count, objnum, 0, sbid);
1125 
1126         if (!lily_override)
1127           {                     //all LilyPond is output for this chord
1128             if (!pchord->notes)
1129               {                 /* A rest */
1130                 if (!curobj->isinvisible)
1131                   {
1132                     g_string_append_printf (ret, "r");
1133                     /* Duplicated code follows. I ought to fix that */
1134 
1135                     NAVANC (TARGET_CHORD, 0);
1136                     outputret;
1137                     directives_insert_prefix_editable (pchord->directives, &open_braces, &prevduration, iter, FALSE, lily_for_obj, TARGET_CHORD, movement_count, measurenum, voice_count, objnum, 0, sbid);
1138                     if (duration != prevduration || numdots != prevnumdots || duration < 0)
1139                       {
1140                         /* only in this case do we explicitly note the duration */
1141                         if (duration > 0)
1142                           g_string_append_printf (ret, "%d", duration);
1143                         prevduration = duration;
1144                         prevnumdots = numdots;
1145                         for (j = 0; j < numdots; j++)
1146                           g_string_append_printf (ret, ".");
1147                       }
1148 
1149                    if (pchord->crescendo_begin_p)
1150                       {
1151                         NAVANC (TARGET_CRESC, 0);
1152                         g_string_append_printf (ret, " \\cr");
1153                         outputret;
1154                       }
1155                     if (pchord->diminuendo_begin_p)
1156                       {
1157                         NAVANC (TARGET_DIM, 0);
1158                         g_string_append_printf (ret, " \\decr");
1159                         outputret;
1160                       }
1161                     if (pchord->crescendo_end_p)
1162                       g_string_append_printf (ret, " \\!");
1163                     if (pchord->diminuendo_end_p)
1164                       g_string_append_printf (ret, " \\!");
1165 
1166 
1167 
1168 
1169                   }
1170                 else
1171                   {             /* non printing rest */
1172                     g_string_append_printf (ret, "\\skip ");
1173                     NAVANC (TARGET_CHORD, 0);
1174                     outputret;
1175                     directives_insert_prefix_editable (pchord->directives, &open_braces, &prevduration, iter, FALSE, lily_for_obj, TARGET_CHORD, movement_count, measurenum, voice_count, objnum, 0, sbid);
1176                     if (duration > 0)
1177                       g_string_append_printf (ret, "%d", duration);
1178                     prevduration = -1;
1179                     prevnumdots = -1;
1180                     for (j = 0; j < numdots; j++)
1181                       g_string_append_printf (ret, ".");
1182                   }
1183 
1184                 outputret;
1185                 directives_insert_postfix_editable (pchord->directives, &open_braces, &prevduration, iter, FALSE, lily_for_obj, TARGET_CHORD, movement_count, measurenum, voice_count, objnum, 0, sbid);
1186               }
1187             else                /* there are notes */
1188               {
1189                 if (pchord->notes->next || pchord->chordize)
1190                   {             //multinote chord
1191                     is_chordmode = TRUE;
1192                     g_string_append_printf (ret, "<");
1193                   }
1194                 GList *notenode;
1195                 outputret;
1196                 for (notenode = pchord->notes; notenode; notenode = notenode->next)
1197                   {
1198                     note *curnote = (note *) notenode->data;
1199                     noteheadtype = curnote->noteheadtype;
1200                     //As with chord-prefix, this is perhaps not a useful position, but until some other use is found for this field it is here...
1201                     GList *g = curnote->directives;
1202                     gint num = 0;
1203                     for (; g; g = g->next, num++)
1204                       {
1205                         DenemoDirective *directive = (DenemoDirective *) g->data;
1206                         if (directive->prefix && (!(directive->override & DENEMO_ALT_OVERRIDE)) && ((directive->x == 0 || (directive->x!=sbid))) && ((directive->y == 0 || (directive->y==sbid))))
1207                           {
1208                             prevduration = -1;
1209                             insert_editable (&directive->prefix, directive->prefix->len ? directive->prefix->str : " ", iter, gui, lily_for_obj, TARGET_NOTE, movement_count, measurenum, voice_count, objnum, num, curnote->mid_c_offset);
1210                           }
1211                       }
1212 
1213                     if (!get_lily_override (curnote->directives))
1214                       {         //not skip all LilyPond output for this note
1215                         switch (noteheadtype)
1216                           {
1217                           case DENEMO_NORMAL_NOTEHEAD:
1218                             if (!is_normalnotehead)
1219                               {
1220                                // g_string_append_printf (ret, "\n" TAB "\\revert NoteHead #'style ");
1221                                 is_normalnotehead = !is_normalnotehead;
1222                               }
1223                             break;
1224                           case DENEMO_CROSS_NOTEHEAD:
1225                             g_string_append_printf (ret, "\n" TAB "\\once \\override NoteHead #'style = #'cross ");
1226                             is_normalnotehead = FALSE;
1227                             break;
1228                           case DENEMO_HARMONIC_NOTEHEAD:
1229                             g_string_append_printf (ret, "\n" TAB "\\once \\override NoteHead #'style = #'harmonic ");
1230                             is_normalnotehead = FALSE;
1231                             break;
1232                           case DENEMO_DIAMOND_NOTEHEAD:
1233                             g_string_append_printf (ret, "\n" TAB "\\once \\override Voice.NoteHead #'style = #'diamond ");
1234                             is_normalnotehead = FALSE;
1235                             break;
1236                           default:
1237                             g_string_append_printf (ret, "\n" TAB "\\revert Voice.NoteHead #'style ");
1238                             break;
1239                           }
1240                         mid_c_offset = curnote->mid_c_offset;
1241                         g_string_append_printf (ret, "%c", mid_c_offsettoname (mid_c_offset));
1242                         enshift = curnote->enshift;
1243                         if (enshift < 0)
1244                           for (k = enshift; k; k++)
1245                             g_string_append_printf (ret, "es");
1246                         else
1247                           for (k = enshift; k; k--)
1248                             g_string_append_printf (ret, "is");
1249                         octave = mid_c_offsettooctave (mid_c_offset);
1250                         if (octave < 0)
1251                           for (; octave; octave++)
1252                             g_string_append_printf (ret, ",");
1253                         else
1254                           for (; octave; octave--)
1255                             g_string_append_printf (ret, "\'");
1256                         NAVANC (TARGET_NOTE, mid_c_offset);     //we target the note
1257                         outputret;
1258                         g = curnote->directives;
1259                         if (!g && notenode->next)
1260                           output (" ");
1261                         for (num = 0; g; g = g->next, num++)
1262                           {
1263                             DenemoDirective *directive = (DenemoDirective *) g->data;
1264                             if (directive->postfix && !(directive->override & DENEMO_OVERRIDE_HIDDEN) && (!(directive->override & DENEMO_ALT_OVERRIDE))&& ((directive->x == 0 || (directive->x!=sbid))) && ((directive->y == 0 || (directive->y==sbid))))
1265                               {
1266                                 insert_editable (&directive->postfix, directive->postfix->len ? directive->postfix->str : " ", iter, gui, lily_for_obj, TARGET_NOTE, movement_count, measurenum, voice_count, objnum, num, curnote->mid_c_offset);
1267                                 prevduration = -1;
1268                               }
1269                             else if (notenode->next)
1270                               output (" ");
1271                           }     //for directives
1272                       }         /* End of LilyPond output for note, skipped if override set ie !get_lily_override (curnote->directives) */
1273                   }             /* End notes in chord loop */
1274 
1275                 if (pchord->notes->next || pchord->chordize)    //multi-note chord
1276                   g_string_append_printf (ret, ">");
1277 
1278                 if (duration != prevduration || numdots != prevnumdots || duration < 0)
1279                   {
1280                     /* only in this case do we explicitly note the duration */
1281                     outputret;
1282 
1283                     directives_insert_prefix_editable (pchord->directives, &open_braces, &prevduration, iter, FALSE, lily_for_obj, TARGET_CHORD, movement_count, measurenum, voice_count, objnum, 0, sbid);
1284                     if (duration > 0)
1285                       g_string_append_printf (ret, "%d", duration);
1286                     prevduration = duration;
1287                     prevnumdots = numdots;
1288                     for (j = 0; j < numdots; j++)
1289                       g_string_append_printf (ret, ".");
1290                     outputret;
1291                   }
1292                 else
1293                   {
1294                     outputret;
1295                     directives_insert_prefix_editable (pchord->directives, &open_braces, &prevduration, iter, FALSE, lily_for_obj, TARGET_CHORD, movement_count, measurenum, voice_count, objnum, 0, sbid);
1296                     outputret;
1297                   }
1298 
1299                 directives_insert_postfix_editable (pchord->directives, &open_braces, &prevduration, iter, FALSE, lily_for_obj, TARGET_CHORD, movement_count, measurenum, voice_count, objnum, 0, sbid);
1300 //!!! dynamics like \cr have their own positional info in LilyPond - how to tell Denemo????
1301                 if (pchord->dynamics && (pchord->notes->next == NULL))
1302                   {
1303                     dynamic_string = (GString *) pchord->dynamics->data;
1304                     if (is_chordmode)
1305                       g_string_append_printf (ret, "\\%s", dynamic_string->str);
1306                     else
1307                       g_string_append_printf (ret, "\\%s ", dynamic_string->str);
1308                   }
1309 
1310 //!! dynamics like \cr have their own positional info in LilyPond - how to tell Denemo????
1311 //We have to output the cresc/dim begin and the slur begin and tie with a NAVANC(type, 0) before each one.
1312                 if (pchord->crescendo_begin_p)
1313                   {
1314                     NAVANC (TARGET_CRESC, 0);
1315                     g_string_append_printf (ret, " \\cr");
1316                     outputret;
1317                   }
1318                 if (pchord->diminuendo_begin_p)
1319                   {
1320                     NAVANC (TARGET_DIM, 0);
1321                     g_string_append_printf (ret, " \\decr");
1322                     outputret;
1323                   }
1324 
1325 
1326                 if (pchord->is_tied)
1327                   {
1328                     NAVANC (TARGET_TIE, 0);
1329                     g_string_append_printf (ret, "~ ");
1330                     outputret;
1331                   }
1332                 if (pchord->slur_begin_p)
1333                   {
1334                     NAVANC (TARGET_SLUR, 0);
1335                     g_string_append_printf (ret, "(");
1336                     outputret;
1337                   }
1338 
1339                 if (pchord->crescendo_end_p)
1340                   g_string_append_printf (ret, " \\!");
1341                 if (pchord->diminuendo_end_p)
1342                   g_string_append_printf (ret, " \\!");
1343                 if (pchord->slur_end_p)
1344                   g_string_append_printf (ret, ")");
1345                 outputret;
1346               }                 /* End of else chord with note(s) */
1347             //now output the postfix field of directives that have AFFIX set, which are not emitted
1348             directives_insert_affix_postfix_editable (pchord->directives, &open_braces, &prevduration, iter, lily_for_obj, TARGET_CHORD, movement_count, measurenum, voice_count, objnum, 0, sbid);
1349           }                     /* End of outputting LilyPond for this chord because LILYPOND_OVERRIDE not set in a chord directive, ie !lily_override */
1350         else
1351           {
1352             GList *g = pchord->directives;
1353             gint num;
1354             for (num = 0; g; g = g->next, num++)
1355               {
1356                 DenemoDirective *directive = (DenemoDirective *) g->data;
1357                 if (directive->postfix && directive->postfix->len && (!(directive->override & DENEMO_OVERRIDE_HIDDEN)) && ((directive->x == 0 || (directive->x!=sbid))) && ((directive->y == 0 || (directive->y==sbid))))
1358 
1359                   {
1360                     prevduration = -1;
1361                     open_braces += brace_count (directive->postfix->str);
1362                     insert_editable (&directive->postfix, directive->postfix->str, iter, gui, lily_for_obj, TARGET_CHORD, movement_count, measurenum, voice_count, objnum, num, 0);
1363                   }
1364               }
1365           }
1366 
1367         if (!lily_override)
1368           if ((pchord->is_grace & ENDGRACE) && *pgrace_status)
1369             {
1370               *pgrace_status = FALSE, g_string_append_printf (ret, "} ");
1371             }
1372 
1373         g_free (chord_prefix);
1374       }                         //end of case CHORD
1375       break;
1376     case CLEF:
1377       {
1378 //                              no NAVANC ??? but one for keysig
1379         gboolean override = FALSE;
1380         gchar *clef_string = "";
1381         gchar *clef_prestring = "";
1382         GList *directives = ((clef *) curobj->object)->directives;
1383         if (directives)
1384           {
1385             override = get_lily_override (directives);
1386             clef_string = get_postfix (directives);
1387             clef_prestring = get_prefix (directives);
1388           }
1389         if (override)
1390           g_string_append_printf (ret, "%s", clef_string);
1391         else
1392           {
1393             if (!curobj->isinvisible)
1394               {
1395                 determineclef (((clef *) curobj->object)->type, &clefname);
1396                 g_string_append_printf (ret, "%s\\clef %s%s", clef_prestring, clefname, clef_string);
1397               }
1398           }
1399       }
1400       break;
1401     case KEYSIG:
1402       {
1403         gboolean override = FALSE;
1404         gchar *keysig_string = "";
1405         gchar *keysig_prestring = "";
1406         GList *directives = ((keysig *) curobj->object)->directives;
1407         if (directives)
1408           {
1409             override = get_lily_override (directives);
1410             keysig_string = get_postfix (directives);
1411             keysig_prestring = get_prefix (directives);
1412           }
1413         NAVANC (0, 0);          //this could indicate keysig type, although that is clear from the object at the cursor.
1414         if (override)
1415           g_string_append_printf (ret, "%s", keysig_string);
1416         else
1417           {
1418             determinekey (((keysig *) curobj->object)->isminor ? ((keysig *) curobj->object)->number + 3 : ((keysig *) curobj->object)->number, &keyname);
1419             g_string_append_printf (ret, "%s\\key %s", keysig_prestring, keyname);
1420             if (((keysig *) curobj->object)->isminor)
1421               g_string_append_printf (ret, " \\minor%s", keysig_string);
1422             else
1423               g_string_append_printf (ret, " \\major%s", keysig_string);
1424           }
1425       }
1426       break;
1427     case TIMESIG:
1428       {
1429         gboolean override = FALSE;
1430         gchar *timesig_string = "";
1431         gchar *timesig_prestring = "";
1432 
1433         GList *directives = ((timesig *) curobj->object)->directives;
1434         if (directives)
1435           {
1436             override = get_lily_override (directives);
1437             timesig_string = get_postfix (directives);
1438             timesig_prestring = get_prefix (directives);
1439           }
1440         if (override)
1441           g_string_append_printf (ret, "%s", timesig_string);
1442         else
1443           g_string_append_printf (ret, "%s\\time %d/%d%s ", timesig_prestring, ((timesig *) curobj->object)->time1, ((timesig *) curobj->object)->time2, timesig_string);
1444       }
1445       cur_stime1 = ((timesig *) curobj->object)->time1;
1446       cur_stime2 = ((timesig *) curobj->object)->time2;
1447       break;
1448     case TUPOPEN:
1449       {
1450         gboolean override = FALSE;
1451         gchar *prestem_string = "";
1452         gchar *poststem_string = "";
1453         GList *directives = ((tuplet *) curobj->object)->directives;
1454         if (directives)
1455           {
1456             override = get_lily_override (directives);
1457             poststem_string = get_postfix (directives);
1458             prestem_string = get_prefix (directives);
1459           }
1460 
1461         NAVANC (0, 0);          // 0 means we don't need to say what the target is, it is the object itself
1462         if (override)
1463           g_string_append_printf (ret, "%s%s", prestem_string, poststem_string);
1464         else
1465           {
1466             g_string_append_printf (ret, "%s\\tuplet %d/%d %s{", prestem_string, ((tupopen *) curobj->object)->denominator, ((tupopen *) curobj->object)->numerator, poststem_string);
1467             if (figures->len)
1468               g_string_append_printf (figures, " \\tuplet %d/%d {", ((tupopen *) curobj->object)->denominator, ((tupopen *) curobj->object)->numerator);
1469             if (fakechords->len)
1470               g_string_append_printf (fakechords, " \\tuplet %d/%d {", ((tupopen *) curobj->object)->denominator, ((tupopen *) curobj->object)->numerator);
1471           }
1472       }
1473       break;
1474     case TUPCLOSE:
1475       {
1476 //      no NAVANC
1477         gboolean override = FALSE;
1478         gchar *prestem_string = "";
1479         gchar *poststem_string = "";
1480         GList *directives = ((tuplet *) curobj->object)->directives;
1481         if (directives)
1482           {
1483             override = get_lily_override (directives);
1484             poststem_string = get_postfix (directives);
1485             prestem_string = get_prefix (directives);
1486           }
1487         if (override)
1488           g_string_append_printf (ret, "%s%s", prestem_string, poststem_string);
1489         else
1490           {
1491             g_string_append_printf (ret, "%s}%s", prestem_string, poststem_string);
1492             if (figures->len)
1493               g_string_append_printf (figures, "}");
1494             if (fakechords->len)
1495               g_string_append_printf (fakechords, "}");
1496           }
1497       }
1498       break;
1499     case STEMDIRECTIVE:
1500       {
1501 //no NAVANC
1502         gboolean override = FALSE;
1503         gchar *prestem_string = "";
1504         gchar *poststem_string = "";
1505         GList *directives = ((stemdirective *) curobj->object)->directives;
1506         if (directives)
1507           {
1508             override = get_lily_override (directives);
1509             poststem_string = get_postfix (directives);
1510             prestem_string = get_prefix (directives);
1511           }
1512         if (override)
1513           g_string_append_printf (ret, "%s%s", prestem_string, poststem_string);
1514         else
1515           switch (((stemdirective *) curobj->object)->type)
1516             {
1517             case DENEMO_STEMDOWN:
1518               g_string_append_printf (ret, "%s\\stemDown" "%s", prestem_string, poststem_string);
1519               break;
1520             case DENEMO_STEMBOTH:
1521               g_string_append_printf (ret, "%s\\stemNeutral" "%s", prestem_string, poststem_string);
1522               break;
1523             case DENEMO_STEMUP:
1524               g_string_append_printf (ret, "%s\\stemUp" "%s", prestem_string, poststem_string);
1525               break;
1526             }
1527         if (*poststem_string)
1528           g_free (poststem_string);
1529         if (*prestem_string)
1530           g_free (prestem_string);
1531       }
1532       break;
1533     case LILYDIRECTIVE:
1534       ;                         //handled in the if block
1535       break;
1536     default:
1537       break;
1538     }
1539 
1540   outputret;
1541 
1542   g_free (curobj->lilypond);
1543   curobj->lilypond = g_string_free (lily_for_obj, FALSE);       //There is a scheme command d-GetLilyPondthat retrieves the LilyPond text associated with the current object
1544   *pprevduration = prevduration;
1545   *pprevnumdots = prevnumdots;
1546 
1547   *pclefname = clefname;
1548   *pkeyname = keyname;
1549   *pcur_stime1 = cur_stime1;
1550   *pcur_stime2 = cur_stime2;
1551   return open_braces;
1552 }
1553 
1554 /* create and insertion point and button for the next piece of music */
1555 static void
insert_music_section(DenemoProject * gui,gchar * name)1556 insert_music_section (DenemoProject * gui, gchar * name)
1557 {
1558   GtkTextIter iter;
1559   gtk_text_buffer_get_iter_at_mark (Denemo.textbuffer, &iter, gtk_text_buffer_get_mark (Denemo.textbuffer, MUSIC));
1560   gtk_text_buffer_insert (Denemo.textbuffer, &iter, "\n", -1);
1561   (void) gtk_text_iter_backward_char (&iter);
1562   insert_section (NULL, name, name, &iter, gui);
1563 }
1564 
1565 /* create and insertion point and button for the next scoreblock */
1566 static GtkTextChildAnchor *
insert_scoreblock_section(DenemoProject * gui,gchar * name,DenemoScoreblock * sb)1567 insert_scoreblock_section (DenemoProject * gui, gchar * name, DenemoScoreblock * sb)
1568 {
1569   GString **target = sb ? &sb->lilypond : NULL;
1570   GtkTextChildAnchor *anchor;
1571   GtkTextIter iter;
1572   gtk_text_buffer_get_iter_at_mark (Denemo.textbuffer, &iter, gtk_text_buffer_get_mark (Denemo.textbuffer, SCOREBLOCK));
1573   gtk_text_buffer_insert (Denemo.textbuffer, &iter, "\n", -1);
1574   (void) gtk_text_iter_backward_char (&iter);
1575   if (sb && *target)
1576     {                           // custom scoreblock
1577       if ((*target)->len && *(*target)->str == '%')
1578         {
1579           gint maxlength = 50;
1580           gchar *v = g_malloc0 (maxlength * sizeof (gchar));
1581           strncpy (v, (*target)->str + 1, maxlength - 1);       //skip the opening % sign to make label, leave a NULL at the end
1582           while (--maxlength)
1583             if (*(v + maxlength) == '\n')
1584               *(v + maxlength) = 0;     //truncate at first end of line
1585           anchor = insert_section (target, name, v, &iter, gui);
1586           g_free (v);
1587         }
1588       else
1589         {
1590           anchor = insert_section (target, name, name, &iter, gui);
1591         }
1592       g_object_set_data (G_OBJECT (anchor), CUSTOM, (gpointer) sb);
1593     }
1594   else
1595     {                           //standard scoreblock
1596       anchor = insert_section (target, name, name, &iter, gui);
1597       g_object_set_data (G_OBJECT (anchor), STANDARD_SCOREBLOCK, (gpointer) 1);
1598     }
1599   return anchor;
1600 }
1601 
1602 
1603 /* gets the text for the section that starts at anchor */
1604 static gchar *
get_text(GtkTextChildAnchor * anchor)1605 get_text (GtkTextChildAnchor * anchor)
1606 {
1607   GtkTextIter start, end;
1608   gtk_text_buffer_get_iter_at_child_anchor (Denemo.textbuffer, &start, anchor);
1609   GtkTextChildAnchor *endanc = g_object_get_data (G_OBJECT (anchor), "end");
1610   gtk_text_buffer_get_iter_at_child_anchor (Denemo.textbuffer, &end, endanc);
1611   return gtk_text_buffer_get_text (Denemo.textbuffer, &start, &end, FALSE /* get only visible text */ );
1612 }
1613 
1614 /**
1615  * Output the header information using Lilypond syntax
1616  *
1617  *
1618  */
1619 static void
outputHeader(GString * str,DenemoProject * gui)1620 outputHeader (GString * str, DenemoProject * gui)
1621 {
1622   g_string_append_printf (str, "%s", _("%% LilyPond file generated by Denemo version "));
1623   g_string_append_printf (str, "%s", VERSION "\n\n");
1624   if (gui->lilycontrol.excerpt == TRUE)
1625     g_string_append_printf (str, "%s", "\\include \"lilypond-book-preamble.ly\" \n\n");
1626 
1627   g_string_append_printf (str, "%s", "%%http://www.gnu.org/software/denemo/\n\n");
1628   /*Print out lilypond syntax version */
1629   if (gui->lilycontrol.lilyversion->len)
1630     g_string_append_printf (str, "\\version \"%s\"\n", gui->lilycontrol.lilyversion->str /*LILYPOND_VERSION */ );
1631   else
1632     g_string_append_printf (str, "\\version \"%s\"\n", get_lily_version_string ());
1633 }
1634 
1635 gchar *
get_lilypond_paper(void)1636 get_lilypond_paper (void)
1637 {
1638   DenemoProject *gui = Denemo.project;
1639   GString *str = g_string_new ("");
1640   /* \paper block settings for excerpt */
1641   if (gui->lilycontrol.excerpt == TRUE)
1642     {
1643       g_string_append_printf (str, "%s", "print-all-headers = ##f\n");
1644       g_string_append_printf (str, "%s", TAB "#(define dump-extents #t)\n");
1645       g_string_append_printf (str, "%s", TAB "line-width = 160\\mm - 2.0 * 0.4\\in\n");
1646       g_string_append_printf (str, "%s", TAB "ragged-right = ##t\n");
1647       g_string_append_printf (str, "%s", TAB "indent = 0\\mm\n");
1648       g_string_append_printf (str, "%s", TAB "force-assignment = #\"\"\n");
1649       g_string_append_printf (str, "%s", TAB "line-width = #(- line-width (* mm  3.000000))\n");
1650 
1651     }
1652   /* \paper block settings for the score */
1653   else
1654     {
1655 
1656       gchar *paper_settings = get_postfix (gui->paper.directives);
1657       if (paper_settings)
1658         {
1659           g_string_append (str, paper_settings);
1660           g_free (paper_settings);
1661         }
1662       else
1663         g_string_append_printf (str, "%s", "print-all-headers = ##f\n");
1664     }
1665   return g_string_free (str, FALSE);
1666 }
1667 
1668 
1669 const gchar *
get_prevailing_clef_as_lilypond(void)1670 get_prevailing_clef_as_lilypond (void)
1671 {
1672   clef *theclef = get_prevailing_context (CLEF);
1673   const gchar *clefname = get_lilypond_for_clef (theclef);
1674   return clefname;
1675 }
1676 
1677 const gchar *
get_prevailing_keysig_as_lilypond(void)1678 get_prevailing_keysig_as_lilypond (void)
1679 {
1680   keysig *thekeysig = get_prevailing_context (KEYSIG);
1681   const gchar *keysigname = get_lilypond_for_keysig (thekeysig);
1682   return keysigname;
1683 }
1684 
1685 const gchar *
get_prevailing_timesig_as_lilypond(void)1686 get_prevailing_timesig_as_lilypond (void)
1687 {
1688   timesig *thetimesig = get_prevailing_context (TIMESIG);
1689   const gchar *timesigname = get_lilypond_for_timesig (thetimesig);
1690   return timesigname;
1691 }
1692 
1693 
1694 
1695 gchar *
get_lilypond_for_timesig(timesig * time)1696 get_lilypond_for_timesig (timesig * time)
1697 {
1698   gboolean override = get_lily_override (time->directives);
1699   gchar *timesig_string = get_postfix (time->directives);
1700   gchar *time_prefix = get_prefix (time->directives);
1701   if (override){
1702     g_free (time_prefix);
1703     return timesig_string;
1704   }
1705 
1706   gchar *ret = g_strdup_printf (" %s \\time %d/%d %s ", time_prefix, time->time1,
1707                                 time->time2, timesig_string);
1708   g_free (timesig_string);
1709   g_free (time_prefix);
1710   return ret;
1711 }
1712 
1713 
1714 gchar *
get_lilypond_for_keysig(struct keysig * key)1715 get_lilypond_for_keysig (struct keysig * key)
1716 {
1717   gchar *keyname;
1718   gboolean override = get_lily_override (key->directives);
1719   gchar *keysig_string = get_postfix (key->directives);
1720   gchar *key_prefix = get_prefix (key->directives);
1721   if (override){
1722     g_free (key_prefix);
1723     return keysig_string;
1724   }
1725   determinekey (key->isminor ? key->number + 3 : key->number, &keyname);
1726   gchar *ret = g_strdup_printf (" %s \\key %s%s %s", key_prefix, keyname, (key->isminor) ? " \\minor " : " \\major ", keysig_string);
1727   g_free (keysig_string);
1728   g_free (key_prefix);
1729   return ret;
1730 
1731 }
1732 
1733 void
do_clef(GString * definitions,DenemoStaff * curstaffstruct,gchar * movement,gchar * voice)1734 do_clef (GString * definitions, DenemoStaff * curstaffstruct, gchar * movement, gchar * voice)
1735 {
1736   gchar *clefname;
1737   determineclef (curstaffstruct->clef.type, &clefname);
1738   gboolean clef_override = get_lily_override (curstaffstruct->clef.directives);
1739   gchar *clef_postfix_insert = get_postfix (curstaffstruct->clef.directives);
1740   gchar *clef_prefix = get_prefix (curstaffstruct->clef.directives);
1741   if (clef_override)
1742     g_string_append_printf (definitions, "%s%sClef = %s\n", movement, voice, clef_postfix_insert);
1743   else
1744     g_string_append_printf (definitions, "%s%sClef = %s \\clef %s %s\n", movement, voice, clef_prefix, clefname, clef_postfix_insert);
1745   g_free (clef_postfix_insert);
1746   g_free (clef_prefix);
1747 }
1748 
1749 gchar *
get_lilypond_for_clef(clef * theclef)1750 get_lilypond_for_clef (clef * theclef)
1751 {
1752   gchar *clefname = NULL;
1753   determineclef (theclef->type, &clefname);
1754   gboolean clef_override = get_lily_override (theclef->directives);
1755   gchar *clef_postfix_insert = get_postfix (theclef->directives);
1756   gchar *clef_prefix = get_prefix (theclef->directives);
1757   if (clef_override){
1758     g_free (clef_prefix);
1759     return clef_postfix_insert;
1760 
1761   }
1762   gchar *ret = g_strdup_printf ("%s \\clef %s %s ", clef_prefix, clefname, clef_postfix_insert);
1763   g_free (clef_postfix_insert);
1764   g_free (clef_prefix);
1765   return ret;
1766 }
1767 
1768 
1769 
1770 
1771 
1772 
1773 /**
1774  * Output a Denemo Staff in Lilypond syntax
1775  * A section is created in the Denemo.textbuffer and the music inserted into it.
1776  * each DenemoObject is given an anchor and a pointer to the object is stored with the anchor,
1777  * so that it will be possible to create LilyPond directives from within the buffer (not yet
1778  * implemented FIXME).
1779  * Any lyrics, chord symbols and figured basses are put in separate sections.
1780  *
1781  */
1782 static void
outputStaff(DenemoProject * gui,DenemoStaff * curstaffstruct,gint start,gint end,gchar * movement,gchar * voice,gint movement_count,gint voice_count,DenemoScoreblock * sb)1783 outputStaff (DenemoProject * gui, DenemoStaff * curstaffstruct, gint start, gint end, gchar * movement, gchar * voice, gint movement_count, gint voice_count, DenemoScoreblock * sb)
1784 {
1785   gint cur_stime1 = curstaffstruct->timesig.time1;
1786   gint cur_stime2 = curstaffstruct->timesig.time2;
1787 
1788   gint prevduration, prevnumdots;
1789   gchar *clefname;
1790   /* clef name */
1791   gchar *keyname;
1792   /* key signature name */
1793   measurenode *curmeasure;
1794   objnode *curobjnode;
1795   DenemoObject *curobj;
1796   gint curmeasurenum;           // count of measures printed
1797   gint measurenum;              //count of measures from start of staff starting at 1
1798   gint objnum;                  //count of objects in measure starting at 1
1799   gint open_braces;             //Keep track of the number of open brace "{" chars in the music, in case of imbalance.
1800   GString *staff_str = g_string_new ("");       //Bits of the music of the staff are accumulated here and then stored in the lilypond view buffer
1801   GList *lyrics = NULL;
1802   GString *figures = g_string_new ("");
1803   GString *fakechords = g_string_new ("");
1804   prevduration = -1;
1805   prevnumdots = -1;
1806   gint grace_status = 0;
1807   GtkTextIter iter;
1808   GtkTextMark *curmark;         /* movable mark for insertion point of the music of the staff */
1809   /* a button and mark for the music of this staff */
1810 
1811 
1812   GString *voice_name = g_string_new (movement);
1813   g_string_prepend (voice_name, "Notes for ");
1814   g_string_append_printf (voice_name, " Voice %d", /* ABS */ (voice_count));
1815   //g_debug("making %s\n", voice_name->str);
1816   insert_music_section (gui, voice_name->str);
1817   gtk_text_buffer_get_iter_at_mark (Denemo.textbuffer, &iter, gtk_text_buffer_get_mark (Denemo.textbuffer, voice_name->str));
1818   curmark = gtk_text_buffer_create_mark (Denemo.textbuffer, NULL, &iter, FALSE);        //FIXME remove this mark at the end of the output of this staff...
1819 
1820   /* a button and mark for the lyrics of this staff */
1821   GString *lyrics_name = g_string_new (movement);
1822   if ((!curstaffstruct->hide_lyrics) && curstaffstruct->verse_views)
1823     {
1824       g_string_prepend (lyrics_name, "Lyrics for ");
1825       g_string_append_printf (lyrics_name, " Voice %d", voice_count);
1826       insert_music_section (gui, lyrics_name->str);
1827       GList *g;
1828       for (g = curstaffstruct->verse_views; g; g = g->next)
1829         {
1830           lyrics = g_list_append (lyrics, get_text_from_view (g->data));
1831         }
1832     }
1833 
1834   /* a button and mark for the figures of this staff */
1835   GString *figures_name = g_string_new (movement);
1836   if (curstaffstruct->hasfigures)
1837     {
1838       g_string_prepend (figures_name, "Figured Bass for ");
1839       g_string_append_printf (figures_name, " Voice %d", voice_count);
1840       insert_music_section (gui, figures_name->str);
1841       g_string_append (figures, "%figures follow\n\\set Staff.implicitBassFigures = #'(0)\n");
1842     }
1843   /* a button and mark for the chord symbols of this staff */
1844   GString *fakechords_name = g_string_new (movement);
1845   if (curstaffstruct->hasfakechords)
1846     {
1847       g_string_prepend (fakechords_name, "Chord symbols for ");
1848       g_string_append_printf (fakechords_name, " Voice %d", voice_count);
1849       insert_music_section (gui, fakechords_name->str);
1850       g_string_append (fakechords, "%chord symbols follow\n");
1851     }
1852 
1853   gtk_text_buffer_get_iter_at_mark (Denemo.textbuffer, &iter, curmark);
1854 
1855   {                             /* standard staff-prolog */
1856     /* Determine the key signature */
1857 
1858     gchar *keyname;
1859     /* key signature name */
1860 
1861     determinekey (curstaffstruct->keysig.isminor ? curstaffstruct->keysig.number + 3 : curstaffstruct->keysig.number, &keyname);
1862     gchar *clefname;
1863 
1864     /* Determine the clef */
1865 
1866     determineclef (curstaffstruct->clef.type, &clefname);
1867 
1868 
1869     g_string_append_printf (staff_str, "%s%s = {\n", movement, voice);
1870 
1871     gtk_text_buffer_get_iter_at_mark (Denemo.textbuffer, &iter, curmark);
1872     gtk_text_buffer_insert_with_tags_by_name (Denemo.textbuffer, &iter, staff_str->str, -1, INEDITABLE, NULL);
1873   }                             /*end standard staff-prolog */
1874 
1875   g_string_assign (staff_str, "");
1876 
1877   curmeasurenum = 0;
1878   curmeasure = curstaffstruct->themeasures;
1879   if (!end)
1880     end = g_list_length (curmeasure);
1881   /* Now each measure */
1882   if (start)
1883     curmeasure = g_list_nth (curmeasure, start - 1);
1884   open_braces = 0;              //keep track of excess open braces "{"
1885   gboolean nonprintingnotes = FALSE;    //no nonprinting notes found yet in this voice, once there are issue a cross-head directive
1886   for (measurenum = MAX (start, 1); curmeasure && measurenum <= end; curmeasure = curmeasure->next, measurenum++)
1887     {
1888 
1889       gboolean empty_measure = TRUE;
1890 
1891 
1892       if ((++curmeasurenum % 5) == 0)
1893         {
1894           g_string_append_printf (staff_str, "%%%d\n", curmeasurenum);
1895           if (figures->len)
1896             g_string_append_printf (figures, "\n%%%d\n", curmeasurenum);
1897           if (fakechords->len)
1898             g_string_append_printf (fakechords, "\n%%%d\n", curmeasurenum);
1899         }
1900       g_string_append_printf (staff_str, "%s", TAB);
1901       gtk_text_buffer_get_iter_at_mark (Denemo.textbuffer, &iter, curmark);
1902       gtk_text_buffer_insert_with_tags_by_name (Denemo.textbuffer, &iter, staff_str->str, -1, INEDITABLE, NULL);
1903       g_string_assign (staff_str, "");
1904       gint firstobj = 1, lastobj = G_MAXINT - 1;
1905       if (start && gui->movement->markstaffnum)
1906         {                       //markstaffnum==0 means not set
1907           firstobj = 1 + gui->movement->selection.firstobjmarked;
1908           lastobj = 1 + gui->movement->selection.lastobjmarked;
1909         }
1910       //g_debug("First last, %d %d %d\n", firstobj, lastobj, start);
1911       for (objnum = 1, curobjnode = (objnode *) ((DenemoMeasure*)curmeasure->data)->objects; /* curobjnode NULL checked at end */ ;
1912            curobjnode = curobjnode->next, objnum++)
1913         {
1914           curobj = NULL;        //avoid random values for debugabililty
1915           if ((measurenum > MAX (start, 1) && (measurenum < end)) || (start == end && measurenum == start && objnum >= firstobj && objnum <= lastobj) || (start != end && ((((measurenum == MAX (start, 1)) && (objnum >= firstobj))) || ((measurenum == end) && (objnum <= lastobj)))))
1916             {
1917 
1918               if (curobjnode)
1919                 {
1920                   curobj = (DenemoObject *) curobjnode->data;
1921                   // if (curobj->type==CHORD||curobj->type==PARTIAL||curobj->type==LILYDIRECTIVE)
1922                   if (curobj->durinticks || (curobj->type == LILYDIRECTIVE && (((lilydirective *) curobj->object)->override & DENEMO_OVERRIDE_LILYPOND)))
1923                     empty_measure = FALSE;
1924                   //Print rhythm notes with cross head. We ignore the case where someone reverts to real notes after rhythm only notes
1925                   if (curobj->type == CHORD && ((chord *) curobj->object)->notes && curobj->isinvisible && !nonprintingnotes)
1926                     {
1927                       gtk_text_buffer_get_iter_at_mark (Denemo.textbuffer, &iter, curmark);
1928                       gtk_text_buffer_insert_with_tags_by_name (Denemo.textbuffer, &iter, "\n" TAB "\\override NoteHead #'style = #'cross" "\n\\override NoteHead #'color = #darkyellow" "\n\\override Stem #'color = #darkyellow" "\n\\override Flag #'color = #darkyellow" "\n\\override Beam #'color = #darkyellow ", -1, INEDITABLE, NULL);
1929                       nonprintingnotes = TRUE;
1930                     }
1931 
1932                   if (curobj->type == LILYDIRECTIVE)
1933                     {
1934                       DenemoDirective *directive = ((lilydirective *) curobj->object);
1935 #define OUTPUT_LILY(what) \
1936   if(directive->what && directive->what->len && ((directive->x == 0 || (directive->x!=sb->id))) && ((directive->y == 0 || (directive->y==sb->id))) \
1937      && (!(directive->override & DENEMO_OVERRIDE_HIDDEN)) \
1938      ) {                                \
1939       gtk_text_buffer_get_iter_at_mark (Denemo.textbuffer, &iter, curmark);\
1940       GtkTextChildAnchor *objanc = gtk_text_buffer_create_child_anchor (Denemo.textbuffer, &iter);\
1941       g_object_set_data(G_OBJECT(objanc), OBJECTNODE, (gpointer)curobjnode);\
1942       g_object_set_data(G_OBJECT(objanc), MOVEMENTNUM, (gpointer)(intptr_t)ABS(movement_count));\
1943       g_object_set_data(G_OBJECT(objanc), MEASURENUM, (gpointer)(intptr_t)measurenum);\
1944       g_object_set_data(G_OBJECT(objanc), STAFFNUM, (gpointer)(intptr_t)ABS(voice_count));\
1945       g_object_set_data(G_OBJECT(objanc), OBJECTNUM, (gpointer)(intptr_t)ABS(objnum));\
1946       g_object_set_data(G_OBJECT(objanc), TARGETTYPE, (gpointer)(intptr_t)ABS(TARGET_OBJECT));\
1947       GtkTextIter back;\
1948       back = iter;\
1949       (void)gtk_text_iter_backward_char(&back);\
1950       gtk_text_buffer_apply_tag_by_name(Denemo.textbuffer, INEDITABLE, &back, &iter);\
1951       gtk_text_buffer_apply_tag_by_name(Denemo.textbuffer, "system_invisible", &back, &iter);\
1952     open_braces += brace_count( directive->what->str);\
1953     gtk_text_buffer_insert_with_tags_by_name (Denemo.textbuffer, &iter,  directive->what->str, -1, "bold", NULL); \
1954         GtkTextChildAnchor *endanc  = gtk_text_buffer_create_child_anchor (Denemo.textbuffer, &iter);\
1955     back = iter;\
1956     (void)gtk_text_iter_backward_char(&back);\
1957     gtk_text_buffer_apply_tag_by_name(Denemo.textbuffer, INEDITABLE, &back, &iter);\
1958     gtk_text_buffer_apply_tag_by_name(Denemo.textbuffer, "system_invisible", &back, &iter);\
1959     g_object_set_data(G_OBJECT(objanc), "end", (gpointer)endanc);\
1960     g_object_set_data(G_OBJECT(objanc), GSTRINGP, (gpointer)&directive->what);\
1961     gui->anchors = g_list_prepend(gui->anchors, objanc);\
1962   }
1963 
1964 g_free(curobj->lilypond);
1965 
1966                       OUTPUT_LILY (prefix);
1967                       gtk_text_buffer_insert_with_tags_by_name (Denemo.textbuffer, &iter, " ", -1, INEDITABLE, HIGHLIGHT, NULL);
1968                       OUTPUT_LILY (postfix);
1969     curobj->lilypond = g_strconcat(directive->prefix?directive->prefix->str : "", directive->postfix? directive->postfix->str:"", NULL);
1970 #undef OUTPUT_LILY
1971 
1972 
1973 
1974                       prevduration = -1;
1975                       prevnumdots = -1; // the LILYDIRECTIVE may have changed the duration
1976                     }
1977                   else
1978                     {
1979 
1980 #if 0
1981                       place_navigation_anchor (curmark, (gpointer) curobjnode, ABS (movement_count), measurenum, ABS (voice_count), ABS (objnum), 0, 0);
1982 #endif
1983 
1984 
1985 
1986                       open_braces += generate_lily_for_obj (gui, &iter, curobj, &prevduration, &prevnumdots, &clefname, &keyname, &cur_stime1, &cur_stime2, &grace_status, figures, fakechords, curmark, (gpointer) curobjnode, ABS (movement_count), measurenum, ABS (voice_count), ABS (objnum), sb->id);
1987                     }           // end not lilydirective
1988 
1989 
1990 
1991                 }               // if curobjnode
1992 
1993               if ((curobjnode == NULL) || (curobjnode->next == NULL))
1994                 {               //at end of measure
1995                   GString *endstr = g_string_new ("");
1996                   if (empty_measure)    // measure has nothing to use up the duration, assume  SKIP
1997                     {
1998                       g_string_append_printf (endstr, " s1*%d/%d ", cur_stime1, cur_stime2);
1999                       gtk_text_buffer_get_iter_at_mark (Denemo.textbuffer, &iter, curmark);
2000                       gtk_text_buffer_insert_with_tags_by_name (Denemo.textbuffer, &iter, endstr->str, -1, NULL, NULL);
2001                       g_string_assign (endstr, "");
2002                       prevduration = -1;
2003                     }
2004                   if (figures->len)
2005                     g_string_append (figures, "\n");
2006                   if (fakechords->len)
2007                     g_string_append (fakechords, "\n");
2008 
2009                   if ((curobjnode != NULL) && ((curobj == NULL) || curobj->type != LILYDIRECTIVE))      /* if it ends in a lilydirective, the user may want to choose their own barline style, let them */
2010                     {
2011                       if (curmeasure->next)
2012                         g_string_append_printf (endstr, "%s", "\\AutoBarline\n");
2013                       else
2014                         g_string_append_printf (endstr, "%s", " \\AutoEndMovementBarline\n");
2015                     }
2016 
2017                   gtk_text_buffer_get_iter_at_mark (Denemo.textbuffer, &iter, curmark);
2018                   gtk_text_buffer_insert_with_tags_by_name (Denemo.textbuffer, &iter, endstr->str, -1, INEDITABLE, NULL);
2019                 }               //if end of measure
2020 
2021               if (curobjnode)
2022                 {
2023                   curobj = (DenemoObject *) curobjnode->data;
2024                   /*  figures and chord symbols */
2025                   if (curobj->type == CHORD)
2026                     {
2027                       chord *pchord = (chord *) curobj->object;
2028 
2029 
2030                       if (curstaffstruct->hasfigures && !pchord->is_grace)
2031                         output_figured_bass (figures, pchord);
2032 
2033                       if (curstaffstruct->hasfakechords && !pchord->is_grace)
2034                         output_fakechord (fakechords, pchord);
2035                       /* end of figures and chord symbols */
2036                     }           // if CHORD
2037                     else if(curobj->type == LILYDIRECTIVE)
2038                     {
2039                         DenemoDirective *directive = ((lilydirective *) curobj->object);
2040                         if (directive->tag && !strcmp(directive->tag->str, "MultiMeasureRests"))
2041                             {
2042                                 if(curstaffstruct->hasfigures)
2043                                     g_string_append (figures, directive->postfix->str);
2044                                 if(curstaffstruct->hasfakechords)
2045                                     g_string_append (fakechords, directive->postfix->str);
2046                             }
2047 
2048                     }
2049 
2050                 }               // if object
2051             }                   //in obj range
2052           if (curobjnode == NULL || curobjnode->next == NULL)
2053             break;              //we want to go through once for empty measures
2054         }                       /* For each object in the measure */
2055     }                           /* for each measure */
2056 
2057 
2058   for (; open_braces > 0; open_braces--)
2059     {
2060       g_string_append_printf (staff_str, "%s", "\n} %% missing close brace\n");
2061     }
2062   g_string_append_printf (staff_str, "%s", "}\n");
2063   gchar *voice_prolog_insert = get_postfix (curstaffstruct->voice_directives);
2064 
2065 
2066 
2067   g_free (voice_prolog_insert);
2068   gtk_text_buffer_get_iter_at_mark (Denemo.textbuffer, &iter, curmark);
2069 
2070   gtk_text_buffer_insert_with_tags_by_name (Denemo.textbuffer, &iter, staff_str->str, -1, INEDITABLE, NULL);
2071 
2072 
2073   if (lyrics)
2074     {
2075       GList *g;
2076       gint versenum;
2077       for (versenum = 1, g = lyrics; g; g = g->next, versenum++)
2078         {
2079           GString *versename = g_string_new ("");
2080           GString *temp = g_string_new ("");
2081           g_string_printf (temp, "Verse%d", versenum);
2082           set_lily_name (temp, versename);
2083           gtk_text_buffer_get_iter_at_mark (Denemo.textbuffer, &iter, gtk_text_buffer_get_mark (Denemo.textbuffer, lyrics_name->str));
2084           g_string_printf (temp, "%s%sLyrics%s = \\lyricmode { \n", movement, voice, versename->str);
2085           g_string_append_printf (temp, "%s \n}\n", (char *) g->data);
2086           gtk_text_buffer_insert_with_tags_by_name (Denemo.textbuffer, &iter, temp->str, -1, INEDITABLE, NULL);
2087           g_string_free (temp, TRUE);
2088           g_string_free (versename, TRUE);
2089           g_free (g->data);
2090         }
2091     }
2092   g_string_free (lyrics_name, TRUE);
2093 
2094   if (figures->len)
2095     {
2096       GString *temp = g_string_new ("");
2097       gtk_text_buffer_get_iter_at_mark (Denemo.textbuffer, &iter, gtk_text_buffer_get_mark (Denemo.textbuffer, figures_name->str));
2098       /* output figures prolog */
2099 
2100       g_string_printf (temp, "%s%sBassFiguresLine = \\figuremode {\n" "\\set figuredBassAlterationDirection = #1\n" "\\set figuredBassPlusDirection = #1\n" "\\override FiguredBass.BassFigure " "#'font-size = #-1\n", movement, voice);
2101 
2102       gtk_text_buffer_insert_with_tags_by_name (Denemo.textbuffer, &iter, temp->str, -1, INEDITABLE, NULL);
2103 
2104       g_string_printf (temp, "%s \n}\n", figures->str);
2105       gtk_text_buffer_insert_with_tags_by_name (Denemo.textbuffer, &iter, temp->str, -1, INEDITABLE, NULL);
2106       g_string_free (temp, TRUE);
2107     }
2108   g_string_free (figures_name, TRUE);
2109 
2110   if (fakechords->len)
2111     {
2112       GString *temp = g_string_new ("");
2113       gtk_text_buffer_get_iter_at_mark (Denemo.textbuffer, &iter, gtk_text_buffer_get_mark (Denemo.textbuffer, fakechords_name->str));
2114       /* output fakechords prolog */
2115 
2116       g_string_append_printf (temp, "%s%sChords = \\new ChordNames \\chordmode {\n", movement, voice);
2117 
2118       gtk_text_buffer_insert_with_tags_by_name (Denemo.textbuffer, &iter, temp->str, -1, INEDITABLE, NULL);
2119 
2120       g_string_printf (temp, "%s \n}\n" /* another definition here */ , fakechords->str);
2121       gtk_text_buffer_insert_with_tags_by_name (Denemo.textbuffer, &iter, temp->str, -1, INEDITABLE, NULL);
2122       g_string_free (temp, TRUE);
2123     }
2124   g_string_free (fakechords_name, TRUE);
2125 
2126   g_string_free (staff_str, TRUE);
2127   //g_string_free(lyrics, TRUE);
2128   g_string_free (figures, TRUE);
2129   g_string_free (fakechords, TRUE);
2130 }                               /* outputStaff */
2131 
2132 /* Merge back any modified LilyPond text into the Denemo Score */
2133 void
merge_lily_strings(DenemoProject * gui)2134 merge_lily_strings (DenemoProject * gui)
2135 {
2136   //g_debug("Merge...\n");
2137   GList *g;
2138   if (gui == Denemo.project)
2139     write_status (gui);
2140   if (!gtk_text_buffer_get_modified (Denemo.textbuffer))
2141     {
2142       //g_debug("not modified\n");
2143       return;
2144     }
2145   if (gui->lilysync != gui->changecount)
2146     {
2147       warningdialog (_("The score has been altered so that this LilyPond text is out of date - ignoring request"));
2148       return;
2149     }
2150   for (g = gui->anchors; g; g = g->next)
2151     {
2152       GtkTextChildAnchor *anchor = g->data;
2153       GString **gstringp = g_object_get_data (G_OBJECT (anchor), GSTRINGP);
2154       if (gstringp)
2155         {
2156           gchar *lily = get_text (anchor);
2157           if (strcmp (lily, g_object_get_data (G_OBJECT (anchor), ORIGINAL)))
2158             {
2159               //g_debug("Compare %s\nwith %s for gstringp %p\n", lily, g_object_get_data(anchor,ORIGINAL), *gstringp);
2160               if (!*gstringp)
2161                 *gstringp = g_string_new (lily);
2162               else
2163                 g_string_assign (*gstringp, lily);
2164 
2165 
2166               //this does not prevent corruption!!!!! on deleting all the string...
2167               /* white space becomes empty string */
2168               g_strstrip (lily);
2169               if (*lily == '\0')
2170                 {
2171                   g_string_free (*gstringp, TRUE);
2172                   *gstringp = g_string_new ("");
2173                 }
2174 #if 0
2175               g_debug ("gstringp %p at %p holds %s\n", *gstringp, gstringp, (*gstringp)->str);
2176 #endif
2177               /* this is    ((DenemoDirective*)((DenemoObject*)(Denemo.project->movement->currentobject->data))->object)->postfix */
2178               g_free (g_object_get_data (G_OBJECT (anchor), ORIGINAL));
2179               g_object_set_data (G_OBJECT (anchor), ORIGINAL, get_text (anchor));
2180 
2181 
2182               score_status (gui, TRUE);
2183               g_free (lily);
2184             }
2185 
2186         }
2187 
2188     }
2189   gtk_text_buffer_set_modified (Denemo.textbuffer, FALSE);
2190 }
2191 /* UNUSED
2192 void
2193 merge_lily_cb (GtkAction * action, DenemoProject * gui)
2194 {
2195   merge_lily_strings (gui);
2196 }
2197 */
2198 /* if there is not yet a textbuffer for the passed gui, it creates and populates one,
2199    if there is it finds the offset of the current point in the buffer, refreshes it from
2200    the Denemo data and then repositions the cursor at that offset. The refresh is subject to
2201    conditions (see output_score_to_buffer()).
2202 */
2203 void
refresh_lily_cb(GtkAction * action,DenemoProject * gui)2204 refresh_lily_cb (GtkAction * action, DenemoProject * gui)
2205 {
2206   if (Denemo.textbuffer)
2207     {
2208       GtkTextIter iter;
2209       GtkTextMark *cursor = gtk_text_buffer_get_insert (Denemo.textbuffer);
2210       gtk_text_buffer_get_iter_at_mark (Denemo.textbuffer, &iter, cursor);
2211       gint offset = gtk_text_iter_get_offset (&iter);
2212       output_score_to_buffer (gui, TRUE, NULL, NULL);
2213       //restore the cursor position
2214       gtk_text_buffer_get_iter_at_offset (Denemo.textbuffer, &iter, offset);
2215       gtk_text_buffer_place_cursor (Denemo.textbuffer, &iter);
2216     }
2217   else
2218     output_score_to_buffer (gui, TRUE, NULL, NULL);
2219 }
2220 
2221 void
force_lily_refresh(DenemoProject * gui)2222 force_lily_refresh (DenemoProject * gui)
2223 {
2224   gui->lilysync = G_MAXUINT;
2225   refresh_lily_cb (NULL, gui);
2226 }
2227 
2228 void
delete_lily_cb(GtkAction * action,gpointer param)2229 delete_lily_cb (GtkAction * action, gpointer param)
2230 {
2231   DenemoProject *gui = Denemo.project;
2232   GtkTextChildAnchor *anchor = gui->lilystart;
2233   GtkTextIter start, end;
2234   gtk_text_buffer_get_iter_at_child_anchor (Denemo.textbuffer, &start, anchor);
2235   GtkTextChildAnchor *endanc = g_object_get_data (G_OBJECT (anchor), "end");
2236   gtk_text_buffer_get_iter_at_child_anchor (Denemo.textbuffer, &end, endanc);
2237   gpointer sb = g_object_get_data (G_OBJECT (anchor), CUSTOM);
2238   gui->anchors = g_list_remove (gui->anchors, anchor);
2239   gui->custom_scoreblocks = g_list_remove (gui->custom_scoreblocks, sb);
2240 
2241 
2242   gtk_text_buffer_delete (Denemo.textbuffer, &start, &end);
2243 }
2244 
2245 
2246 void
toggle_lily_visible_cb(GtkAction * action,gpointer param)2247 toggle_lily_visible_cb (GtkAction * action, gpointer param)
2248 {
2249   DenemoProject *gui = Denemo.project;
2250   GtkTextIter start, end;
2251   GtkTextChildAnchor *anchor = gui->lilystart;
2252   DenemoScoreblock *sb = g_object_get_data (G_OBJECT (anchor), CUSTOM);
2253   gtk_text_buffer_get_iter_at_child_anchor (Denemo.textbuffer, &start, anchor);
2254   (void) gtk_text_iter_forward_char (&start);
2255   GtkTextChildAnchor *endanc = g_object_get_data (G_OBJECT (anchor), "end");
2256 
2257   gtk_text_buffer_get_iter_at_child_anchor (Denemo.textbuffer, &end, endanc);
2258 
2259   GtkTextTag *tag = gtk_text_tag_table_lookup (tagtable, "invisible");
2260   /*   GtkTextTag *systemtag = gtk_text_tag_table_lookup(tagtable, "system_invisible"); */
2261   if (gtk_text_iter_has_tag (&start, tag))
2262     {
2263       if (sb)
2264         sb->visible = TRUE;
2265       gtk_text_buffer_remove_tag_by_name (Denemo.textbuffer, "invisible", &start, &end);
2266     }
2267   else
2268     {
2269       if (sb)
2270         sb->visible = FALSE;
2271       gtk_text_buffer_apply_tag_by_name (Denemo.textbuffer, "invisible", &start, &end);
2272     }
2273   //g_debug("visible %d\n", sb?sb->visible:-1);
2274 }
2275 
2276 static void
place_cursor_cb(void)2277 place_cursor_cb (void)
2278 {
2279     DenemoProject *gui = Denemo.project;
2280   /* place cursor on current object */
2281   if (gui->movement->currentobject)
2282     {
2283       DenemoObject *targetobj = gui->movement->currentobject->data;
2284       GList *curobjnode;
2285       GtkTextIter iter;
2286       gtk_text_buffer_get_start_iter (Denemo.textbuffer, &iter);
2287       while (gtk_text_iter_forward_char (&iter))
2288         {
2289           GtkTextChildAnchor *anchor;
2290           anchor = gtk_text_iter_get_child_anchor (&iter);
2291           if (anchor && (curobjnode = g_object_get_data (G_OBJECT (anchor), OBJECTNODE)) && curobjnode->data == targetobj)
2292             {
2293               gtk_text_buffer_place_cursor (Denemo.textbuffer, &iter);
2294               gtk_text_view_scroll_mark_onscreen (GTK_TEXT_VIEW (Denemo.textview), gtk_text_buffer_get_insert (Denemo.textbuffer));
2295               gtk_text_view_scroll_to_mark (GTK_TEXT_VIEW (Denemo.textview), gtk_text_buffer_get_insert (Denemo.textbuffer), 0.0, TRUE, 0.5, 0.5);
2296               //g_debug("placed cursor\n"); FIXME as well color in relevant objects
2297             }
2298         }
2299     }
2300 }
2301 
2302 static void
insert_lilypond_directive(void)2303 insert_lilypond_directive (void)
2304 {
2305 call_out_to_guile ("(d-InsertStandaloneDirective)");
2306 }
2307 #if 0
2308 static void
2309 print_cursor_cb (void)
2310 {
2311   GtkTextIter iter;
2312   DenemoProject *gui = Denemo.project;
2313   gtk_text_buffer_get_iter_at_mark (Denemo.textbuffer, &iter, gtk_text_buffer_get_insert (Denemo.textbuffer));
2314   g_debug ("Char is %c at bytes=%d chars=%d\n", gtk_text_iter_get_char (&iter), gtk_text_iter_get_visible_line_index (&iter), gtk_text_iter_get_visible_line_offset (&iter));
2315 
2316 }
2317 #endif
2318 
2319 void
set_initiate_scoreblock(DenemoMovement * si,GString * scoreblock)2320 set_initiate_scoreblock (DenemoMovement * si, GString * scoreblock)
2321 {
2322   gchar *movement_prolog = get_postfix (si->movementcontrol.directives);
2323   g_string_append_printf (scoreblock, "%s", get_lily_override (si->movementcontrol.directives) ? movement_prolog : "          <<\n");
2324   g_free (movement_prolog);
2325 }
2326 
get_alt_overridden_prefix(GList * g)2327 static gchar *get_alt_overridden_prefix (GList *g)
2328 {
2329     GString *s = g_string_new ("");
2330     for(;g;g=g->next) {
2331         DenemoDirective *d = g->data;
2332         if ((d->override & DENEMO_ALT_OVERRIDE) && d->prefix)
2333             g_string_append (s, d->prefix->str);
2334         }
2335     return g_string_free (s, FALSE);
2336 }
2337 void
set_staff_definition(GString * str,DenemoStaff * curstaffstruct)2338 set_staff_definition (GString * str, DenemoStaff * curstaffstruct)
2339 {
2340   gint staff_override = get_lily_override (curstaffstruct->staff_directives);
2341 
2342   gchar *staff_prolog_insert = get_prefix (curstaffstruct->staff_directives);
2343   gchar *staff_epilog_insert = get_postfix (curstaffstruct->staff_directives);
2344   gchar *denemo_name = curstaffstruct->subpart?g_strdup_printf("%s_%s", curstaffstruct->denemo_name->str, curstaffstruct->subpart->str): curstaffstruct->denemo_name->str;
2345   if (staff_override)
2346     {
2347       g_string_append_printf (str, "%s%s", staff_prolog_insert, staff_epilog_insert);
2348     }
2349   else
2350     {
2351      gchar *alt_override = get_alt_overridden_prefix (curstaffstruct->staff_directives);//AFFIX_OVERRIDE is for staff groupings
2352      if(*alt_override)
2353       g_string_append_printf (str, "\n%%Start of Staff\n %s  \\new Staff = \"%s\" << %s\n", alt_override, denemo_name, staff_epilog_insert);
2354      else
2355       g_string_append_printf (str, "\n%%Start of Staff\n\\new Staff = \"%s\" %s << %s\n", denemo_name, staff_prolog_insert, staff_epilog_insert);
2356      g_free(alt_override);
2357     }
2358     if (curstaffstruct->subpart)
2359         g_free (denemo_name);
2360    g_free(staff_prolog_insert);
2361    g_free(staff_epilog_insert);
2362 }
2363 
2364 void
set_voice_definition(GString * str,DenemoStaff * curstaffstruct,gchar * voicetag)2365 set_voice_definition (GString * str, DenemoStaff * curstaffstruct, gchar * voicetag)
2366 {
2367   gint voice_override = get_lily_override (curstaffstruct->voice_directives);
2368 
2369   gchar *voice_prolog_insert = get_prefix (curstaffstruct->voice_directives);
2370   gchar *voice_epilog_insert = get_postfix (curstaffstruct->voice_directives);
2371   if (voice_override)
2372     {
2373       g_string_append_printf (str, "%s", voice_prolog_insert);
2374     }
2375   else
2376     {
2377       g_string_append_printf (str, "\\new Voice = \"%s\" %s { %s\n", voicetag, voice_prolog_insert, voice_epilog_insert);
2378     }
2379 }
2380 
2381 void
set_voice_termination(GString * str,DenemoStaff * curstaffstruct)2382 set_voice_termination (GString * str, DenemoStaff * curstaffstruct)
2383 {
2384   gint voice_override = get_lily_override (curstaffstruct->voice_directives);
2385   gchar *voice_epilog_insert = get_postfix (curstaffstruct->voice_directives);
2386   if (voice_override)
2387     {
2388       g_string_append_printf (str, "%s", voice_epilog_insert);
2389     }
2390   else
2391     {
2392       g_string_assign (str,  "\n" TAB  TAB TAB "} %End of voice\n");
2393     }
2394 }
2395 
2396 void
set_staff_termination(GString * str,DenemoStaff * curstaffstruct)2397 set_staff_termination (GString * str, DenemoStaff * curstaffstruct)
2398 {
2399   gint staff_override = (DENEMO_OVERRIDE_LILYPOND | DENEMO_OVERRIDE_AFFIX) == (get_override (curstaffstruct->staff_directives) & (DENEMO_OVERRIDE_LILYPOND | DENEMO_OVERRIDE_AFFIX));
2400   gchar *staff_epilog_insert = get_postfix (curstaffstruct->staff_directives);
2401   if (staff_override)
2402     {
2403       g_string_append_printf (str, "%s", staff_epilog_insert);
2404     }
2405   else
2406     {
2407       g_string_assign (str,  "\n" TAB  TAB TAB ">> %End of Staff\n");
2408     }
2409 }
2410 
2411 void
generate_lilypond_part(void)2412 generate_lilypond_part (void)
2413 {DenemoStaff *staff = (DenemoStaff *) (Denemo.project->movement->currentstaff->data);
2414   output_score_to_buffer (Denemo.project, TRUE, staff->lily_name->str, staff->denemo_name->str);
2415 }
2416 
2417 /*
2418  *writes the current score in LilyPond format to the textbuffer.
2419  *sets gui->lilysync equal to gui->changecount
2420  *if gui->lilysync is up to date with changecount on entry does nothing unless
2421  *the set of score blocks will be different from the last call
2422  * this namespec is not otherwise used FIXME
2423  */
2424 
2425 
2426 static void
output_score_to_buffer(DenemoProject * gui,gboolean all_movements,gchar * partname,gchar * instrumentation)2427 output_score_to_buffer (DenemoProject * gui, gboolean all_movements, gchar * partname, gchar *instrumentation)
2428 {
2429   GString *definitions = g_string_new ("");
2430   GString *staffdefinitions = g_string_new ("");
2431 
2432   if (gui->namespec == NULL)
2433     gui->namespec = g_strdup ("");      /* to check if the scoreblocks to make visible are different */
2434 
2435   gchar *namespec;
2436   gchar *movementname;
2437   if (all_movements)
2438     movementname = g_strdup ("All movements");
2439   else
2440     movementname = g_strdup_printf ("Movement %d", 1 + g_list_index (gui->movements, gui->movement));
2441   if (partname)
2442     namespec = g_strdup_printf ("%s Part %s", movementname, partname);
2443   else
2444     namespec = g_strdup_printf ("%s all parts", movementname);
2445   g_free (movementname);
2446   //if(Denemo.textview==NULL)
2447   //  create_lilywindow();
2448 
2449 
2450   DenemoScoreblock *sb = select_layout (all_movements, partname, instrumentation);       //FIXME gui->namespec mechanism is probably redundant, and could well cause trouble...
2451 
2452   if (gui->movement->markstaffnum)
2453     all_movements = FALSE;
2454 
2455   staffnode *curstaff;
2456   DenemoStaff *curstaffstruct;
2457 //  if(Denemo.project->custom_scoreblocks==NULL)
2458   //   create_default_scoreblock();
2459   if ((gui->movement->markstaffnum == 0) && Denemo.textbuffer && (gui->changecount == gui->lilysync) && !strcmp (gui->namespec, namespec))
2460     {
2461       g_free (gui->namespec);
2462       gui->namespec = namespec;
2463       //g_debug("changecount=%d and lilysync= %d\n", gui->changecount, gui->lilysync);
2464       return;
2465     }
2466   g_free (gui->namespec);
2467   gui->namespec = namespec;
2468   //g_debug("actually refreshing %d %d", gui->lilysync, gui->changecount);
2469   gui->lilysync = gui->changecount;
2470   if (Denemo.textbuffer)
2471     gtk_text_buffer_set_text (Denemo.textbuffer, "", -1);
2472   else
2473     warningdialog (_("No textbuffer"));
2474   if (gui->anchors)
2475     {
2476       //FIXME  the working curmark at the end of the creation of the text
2477       g_list_free (gui->anchors);
2478       gui->anchors = NULL;
2479     }
2480 
2481 
2482 
2483   /* divide up the buffer for the various parts of the lily file */
2484   GtkTextIter iter;
2485 
2486   gtk_text_buffer_get_start_iter (Denemo.textbuffer, &iter);
2487 
2488   insert_section (NULL, START, "Prolog", &iter, gui);
2489 
2490   gtk_text_buffer_get_end_iter (Denemo.textbuffer, &iter);
2491 
2492   insert_section (NULL, MUSIC, NULL, &iter, gui);
2493   gtk_text_buffer_get_end_iter (Denemo.textbuffer, &iter);
2494 
2495   insert_section (NULL, SCOREBLOCK, NULL, &iter, gui);
2496 
2497   gtk_text_buffer_get_iter_at_mark (Denemo.textbuffer, &iter, gtk_text_buffer_get_mark (Denemo.textbuffer, START));
2498   gtk_text_buffer_insert_with_tags_by_name (Denemo.textbuffer, &iter, "\n", -1, "bold", NULL);
2499 
2500 
2501   {                             //no custom prolog
2502 
2503     GString *header = g_string_new ("");
2504     outputHeader (header, gui);
2505     gtk_text_buffer_insert_with_tags_by_name (Denemo.textbuffer, &iter, header->str, -1, INEDITABLE, NULL);
2506     g_string_free (header, TRUE);
2507 
2508   }                             //end of standard prolog
2509 
2510   {                             //Score prefix
2511 //    !!used in DenemoBar command (set barlines literally) along with postfix.
2512 //    change this script to have DENEMO_OVERRIDE_AFFIX set and then move all others to the score layout section
2513 
2514     //Default value for barline = barline check
2515     gtk_text_buffer_insert_with_tags_by_name (Denemo.textbuffer, &iter,
2516     LILYPOND_SYMBOL_DEFINITIONS,
2517  -1, INEDITABLE, NULL, NULL);
2518     GList *g = gui->lilycontrol.directives;
2519     /* num is not needed, as at the moment we can never get this location from LilyPond */
2520     for (; g; g = g->next)
2521       {
2522         DenemoDirective *directive = g->data;
2523         if (directive->prefix && (directive->override & (DENEMO_OVERRIDE_AFFIX)))       //This used to be (mistakenly) DENEMO_ALT_OVERRIDE
2524           insert_editable (&directive->prefix, directive->prefix->str, &iter, gui, NULL, TARGET_OBJECT, 0, 0, 0, 0, 0, 0);
2525         //insert_section(&directive->prefix, directive->tag->str, NULL, &iter, gui);
2526       }
2527   }
2528 
2529   gtk_text_buffer_insert_with_tags_by_name (Denemo.textbuffer, &iter, "\n% The music follows\n", -1, INEDITABLE, NULL);
2530 
2531   gtk_text_buffer_get_iter_at_mark (Denemo.textbuffer, &iter, gtk_text_buffer_get_mark (Denemo.textbuffer, SCOREBLOCK));
2532   gtk_text_buffer_insert_with_tags_by_name (Denemo.textbuffer, &iter, "% The scoreblocks follow\n", -1, "bold", "system_invisible", NULL);
2533 
2534   /* output scoreblock */
2535   {
2536     gchar *scoreblock_tag;
2537 #ifdef USE_EVINCE
2538     if (continuous_typesetting ())
2539       scoreblock_tag = "temporary scoreblock";
2540     else
2541       scoreblock_tag = "standard scoreblock";
2542 #else
2543       scoreblock_tag = "standard scoreblock";
2544 #endif
2545     insert_scoreblock_section (gui, scoreblock_tag, sb);
2546     gtk_text_buffer_get_iter_at_mark (Denemo.textbuffer, &iter, gtk_text_buffer_get_mark (Denemo.textbuffer, scoreblock_tag));
2547     if (sb->text_only)
2548       insert_editable (&sb->lilypond, g_strchomp((sb->lilypond)->str), &iter, gui, 0, 0, 0, 0, 0, 0, 0, 0); //without strchomp a newline is appended each refresh.
2549     else
2550       gtk_text_buffer_insert_with_tags_by_name (Denemo.textbuffer, &iter, (sb->lilypond)->str, -1, INEDITABLE, NULL);
2551   }
2552   /* insert standard scoreblock section */
2553   //insert_scoreblock_section(gui, STANDARD_SCOREBLOCK, NULL);
2554 
2555   GList *g;
2556   gint movement_count;
2557   gint visible_movement;        /* 1 for visible -1 for invisible */
2558   for (g = gui->movements, movement_count = 1; g; g = g->next, movement_count++)
2559     {
2560       DenemoMovement *si = g->data;
2561       gint voice_count;         //which voice counting from 1st voice of 1st staff thru to last voice of last staff.
2562       gint staff_count;         //which staff (not counting voices)
2563       visible_movement = (((all_movements) || (g->data == gui->movement)) ? 1 : -1);
2564       GString *movement_name = g_string_new ("");
2565       GString *name = g_string_new ("");
2566       g_string_printf (name, "Mvmnt%d", movement_count);
2567       set_lily_name (name, movement_name);
2568       g_string_free (name, TRUE);
2569       //context = FALSE;
2570 
2571 
2572 
2573       for (curstaff = si->thescore, voice_count = 1, staff_count = 0; curstaff; curstaff = curstaff->next, voice_count++)
2574         {
2575           gint visible_part = 1;        /* 1 for visible -1 for invisible */
2576           curstaffstruct = (DenemoStaff *) curstaff->data;
2577           GString *voice_name = g_string_new ("");
2578           GString *staff_name = g_string_new ("");
2579           GString *name = g_string_new ("");
2580           if (curstaffstruct->voicecontrol == DENEMO_PRIMARY)
2581             staff_count++;
2582 
2583           g_string_printf (name, "Voice%d", voice_count);
2584           set_lily_name (name, voice_name);
2585 
2586           g_string_printf (name, "Staff%d", staff_count);
2587           set_lily_name (name, staff_name);
2588 
2589           g_string_free (name, TRUE);
2590           gint start = 0, end = 0;
2591           if (gui->movement->markstaffnum)
2592             {
2593               if (!(voice_count >= gui->movement->selection.firststaffmarked && voice_count <= gui->movement->selection.laststaffmarked))
2594                 visible_part = -1;
2595               start = gui->movement->selection.firstmeasuremarked;
2596               end = gui->movement->selection.lastmeasuremarked;
2597             }
2598           if (visible_part > 0 && visible_movement > 0)
2599             outputStaff (gui, curstaffstruct, start, end, movement_name->str, voice_name->str, movement_count * visible_movement, voice_count * visible_part, sb);
2600           //g_debug("Music for staff is \n%s\n", visible_part>0?"visible":"NOT visible");
2601 
2602           //FIXME amalgamate movement and voice names below here...
2603           /* output score block */
2604           if (visible_movement == 1 && (visible_part == 1))
2605             {
2606               if (!(curstaffstruct->voicecontrol & DENEMO_SECONDARY))
2607                 {
2608                   if ((!curstaffstruct->hide_lyrics) && curstaffstruct->verse_views)
2609                     {
2610                       GList *g;
2611                       gint versenum;
2612                       for (g = curstaffstruct->verse_views, versenum = 1; g; g = g->next, versenum++)
2613                         {
2614                           GString *versename = g_string_new ("");
2615                           GString *temp = g_string_new ("");
2616                           g_string_printf (temp, "Verse%d", versenum);
2617                           set_lily_name (temp, versename);
2618 
2619                           gchar *sofar = g_strdup (staffdefinitions->str);
2620                           //this definition is used by score_layout.c to get LilyPond to provide the durations for lyrics, which denemo does not compute (contrast figured bass and chord symbols where durations are computed, see above).
2621                           g_string_printf (staffdefinitions, "\n%s%s%sContext = \\context Lyrics = %s%s%s \\lyricsto %s%s \\%s%sLyrics%s\n%s", movement_name->str, voice_name->str, versename->str, movement_name->str, voice_name->str, versename->str, voice_name->str, movement_name->str, movement_name->str, voice_name->str, versename->str, sofar);
2622                           g_free (sofar);
2623                           g_string_free (versename, TRUE);
2624                           g_string_free (temp, TRUE);
2625 
2626                         }
2627                     }
2628 
2629                  //g_string_append_printf (staffdefinitions, "\n\\addQuote \"%s\" \\%s%s\n", curstaffstruct->denemo_name->str, movement_name->str, voice_name->str);
2630 
2631 
2632                   //g_string_append_printf(staffdefinitions, TAB TAB"%s\n", endofblock);
2633                 }
2634               else if (curstaffstruct->voicecontrol & DENEMO_SECONDARY)
2635                 {
2636                   //g_string_append_printf(staffdefinitions, "%s"TAB TAB"\\%s%s\n"TAB TAB"\n"TAB TAB"\n", thestr->str, movement_name->str, voice_name->str);
2637 
2638                   if ((!curstaffstruct->hide_lyrics) && curstaffstruct->verse_views)
2639                     {
2640                       GList *g;
2641                       gint versenum;
2642                       for (g = curstaffstruct->verse_views, versenum = 1; g; g = g->next, versenum++)
2643                         {
2644                           GString *versename = g_string_new ("");
2645                           GString *temp = g_string_new ("");
2646                           g_string_printf (temp, "Verse%d", versenum);
2647                           set_lily_name (temp, versename);
2648 
2649                           gchar *sofar = g_strdup (staffdefinitions->str);
2650                           //this definition is used by score_layout.c to get LilyPond to provide the durations for lyrics, which denemo does not compute (contrast figured bass and chord symbols where durations are computed, see above).
2651                           g_string_printf (staffdefinitions, "\n%s%s%sContext = \\context Lyrics = %s%s%s \\lyricsto %s%s \\%s%sLyrics%s\n%s", movement_name->str, voice_name->str, versename->str, movement_name->str, voice_name->str, versename->str, voice_name->str, movement_name->str, movement_name->str, voice_name->str, versename->str, sofar);
2652                           g_free (sofar);
2653 
2654 
2655                           g_string_free (versename, TRUE);
2656                           g_string_free (temp, TRUE);
2657 
2658                         }
2659                     }
2660                 }
2661 
2662 
2663            // g_string_append_printf (staffdefinitions, "\n\\addQuote \"%s Mvmnt %d\" \\%s%s\n", curstaffstruct->denemo_name->str, movement_count, movement_name->str, voice_name->str);
2664             }
2665         }                       /*end for staff loop */
2666 
2667 
2668 
2669       if (visible_movement == 1)
2670         {
2671 
2672 
2673 
2674 
2675           /* output the definitions to a definitions block in the music section */
2676           {
2677             GtkTextIter iter;
2678             GtkTextMark *curmark;
2679             gchar *name = g_strdup_printf ("%s Definitions", movement_name->str);
2680             insert_music_section (gui, name);
2681             gtk_text_buffer_get_iter_at_mark (Denemo.textbuffer, &iter, gtk_text_buffer_get_mark (Denemo.textbuffer, name));
2682             curmark = gtk_text_buffer_create_mark (Denemo.textbuffer, NULL, &iter, FALSE);
2683             gtk_text_buffer_get_iter_at_mark (Denemo.textbuffer, &iter, curmark);
2684             gtk_text_buffer_insert_with_tags_by_name (Denemo.textbuffer, &iter, definitions->str, -1, INEDITABLE, NULL);
2685 
2686             gtk_text_buffer_insert_with_tags_by_name (Denemo.textbuffer, &iter, staffdefinitions->str, -1, INEDITABLE, NULL);
2687 
2688             g_free (name);
2689             g_string_assign (definitions, "");
2690             g_string_assign (staffdefinitions, "");
2691           }
2692 
2693 
2694 
2695         }                       /* if visible movement */
2696 
2697 
2698 
2699     }                           /* for each movement */
2700 
2701 
2702   g_string_free (definitions, TRUE);
2703 
2704   // now go through gui->anchors, and to each anchor attach a copy of the original text, for checking when saving.
2705   {
2706     GList *g;
2707     for (g = gui->anchors; g; g = g->next)
2708       {
2709         GtkTextChildAnchor *anchor = g->data;
2710         GString **target = g_object_get_data (G_OBJECT (anchor), GSTRINGP);
2711         if (target)
2712           g_object_set_data (G_OBJECT (anchor), ORIGINAL, get_text (anchor));
2713       }
2714 
2715 
2716   }
2717 #if 0
2718   g_get_current_time (&time);
2719   g_debug ("time %ld secs", time.tv_sec);
2720   seconds -= time.tv_sec;
2721   g_debug ("time diff = %ld\n", seconds);
2722 #endif
2723 
2724   {
2725     GtkTextIter startiter, enditer;
2726     gtk_text_buffer_get_start_iter (Denemo.textbuffer, &startiter);
2727     gtk_text_buffer_get_end_iter (Denemo.textbuffer, &enditer);
2728     gtk_text_buffer_apply_tag_by_name (Denemo.textbuffer, "monospace", &startiter, &enditer);
2729   }
2730 
2731   gtk_text_buffer_set_modified (Denemo.textbuffer, FALSE);
2732 
2733 }                               /* output_score_to_buffer */
2734 
2735 
2736 
2737 /**
2738  * Write out LilyPond to correspond with the music in the DenemoProject from measure start to measure end
2739  * in the current movement or all the movements if all_movements is TRUE.
2740  * param PARTNAME if not NULL, print only this parts of this name
2741  *
2742  * The function works in two passes: the first pass writes out all the
2743  * LilyPond music blocks defined by identifiers;  the second pass writes out the score blocks (one for
2744  * each movement) with the
2745  * identifiers placed suitably.
2746  */
2747 static void
export_lilypond(gchar * thefilename,DenemoProject * gui,gboolean all_movements,gchar * partname,gchar * instrumentation)2748 export_lilypond (gchar * thefilename, DenemoProject * gui, gboolean all_movements, gchar * partname, gchar *instrumentation)
2749 {
2750   GtkTextIter startiter, enditer, iter;
2751   gint offset;
2752   offset = get_cursor_offset ();
2753   output_score_to_buffer (gui, all_movements, partname, instrumentation);
2754   GString *filename = g_string_new (thefilename);
2755   if (filename)
2756     {
2757       gtk_text_buffer_get_start_iter (Denemo.textbuffer, &startiter);
2758       gtk_text_buffer_get_end_iter (Denemo.textbuffer, &enditer);
2759       gchar *lily = gtk_text_buffer_get_text (Denemo.textbuffer, &startiter, &enditer, FALSE);
2760       /* Append .ly onto the filename if necessary */
2761       if (strcmp (filename->str + filename->len - 3, ".ly"))
2762         g_string_append (filename, ".ly");
2763       /* Now open the file */
2764       FILE *fp;
2765       fp = fopen (filename->str, "w");
2766       if (!fp)
2767         {
2768           warningdialog (_("Could not open output file for writing"));
2769           g_warning ("Cannot open %s", filename->str);
2770           return;
2771         }
2772       fprintf (fp, "%s", lily);
2773       g_free (lily);
2774       fclose (fp);
2775       g_string_free (filename, TRUE);
2776     }
2777     //restore the insertion point
2778     gtk_text_buffer_get_iter_at_offset (Denemo.textbuffer, &iter, offset);
2779     gtk_text_buffer_place_cursor (Denemo.textbuffer, &iter);
2780 }
2781 
2782 void
exportlilypond(gchar * thefilename,DenemoProject * gui,gboolean all_movements)2783 exportlilypond (gchar * thefilename, DenemoProject * gui, gboolean all_movements)
2784 {
2785   export_lilypond (thefilename, gui, all_movements, NULL, NULL);
2786 }
2787 
2788 
2789 
2790 
2791 
2792 /* output lilypond for the current staff
2793  */
2794 void
export_lilypond_part(char * filename,DenemoProject * gui,gboolean all_movements)2795 export_lilypond_part (char *filename, DenemoProject * gui, gboolean all_movements)
2796 { DenemoStaff *staff = (DenemoStaff *) gui->movement->currentstaff->data;
2797   export_lilypond (filename, gui, all_movements, staff->lily_name->str, staff->denemo_name->str);
2798 }
2799 
2800 /* output lilypond for each part into a separate file
2801  */
2802 void
export_lilypond_parts(char * filename,DenemoProject * gui)2803 export_lilypond_parts (char *filename, DenemoProject * gui)
2804 {
2805   gchar *staff_filename;
2806   staffnode *curstaff;
2807   DenemoStaff *curstaffstruct;
2808   DenemoMovement *si = gui->movement;
2809   for (curstaff = si->thescore; curstaff; curstaff = curstaff->next)
2810     {
2811 
2812       curstaffstruct = (DenemoStaff *) curstaff->data;
2813       gchar *c = filename + strlen (filename);  // find .extension FIXME dots in filename
2814       while (*c != '.' && c != filename)
2815         c--;
2816       if (c != filename)
2817         *c = '\0';
2818       else
2819         {
2820           warningdialog (_("Filename does not have extension"));
2821           return;
2822         }
2823       staff_filename = g_strconcat (filename, "_", curstaffstruct->lily_name->str, ".ly", NULL);
2824       *c = '.';
2825       export_lilypond (staff_filename, gui, FALSE, ((DenemoStaff *) curstaff->data)->lily_name->str, ((DenemoStaff *) curstaff->data)->denemo_name->str);
2826 
2827     }
2828 
2829   if (staff_filename)
2830     g_free (staff_filename);
2831 }
2832 
2833 /* callback on closing lilypond window */
2834 static gboolean
lilywindow_closed()2835 lilywindow_closed ()
2836 {
2837   activate_action ("/MainMenu/ViewMenu/ToggleLilyText");
2838   return TRUE;
2839 }
2840 
2841 
2842 static gboolean lily_refresh (GtkWidget * item, GdkEventCrossing * e);
2843 
2844 static gboolean
lily_save(G_GNUC_UNUSED GtkWidget * item,G_GNUC_UNUSED GdkEventCrossing * e)2845 lily_save (G_GNUC_UNUSED GtkWidget * item, G_GNUC_UNUSED GdkEventCrossing * e)
2846 {
2847   DenemoProject *gui = Denemo.project;
2848   //g_debug("Consider Save ... %d %d", gui->lilysync, gui->changecount);
2849   // g_signal_handlers_block_by_func (G_OBJECT (SIGNAL_WIDGET), G_CALLBACK (lily_save), NULL);
2850   // g_signal_handlers_unblock_by_func (G_OBJECT (SIGNAL_WIDGET), G_CALLBACK (lily_refresh), gui);
2851   merge_lily_strings (gui);
2852   if (gui->movement)
2853     update_drawing_cache ();
2854   return FALSE;
2855 }
2856 
2857 static gboolean
lily_refresh(G_GNUC_UNUSED GtkWidget * item,G_GNUC_UNUSED GdkEventCrossing * e)2858 lily_refresh (G_GNUC_UNUSED GtkWidget * item, G_GNUC_UNUSED GdkEventCrossing * e)
2859 {
2860   DenemoProject *gui = Denemo.project;
2861   //g_debug("Consider Refresh ... %d %d", gui->lilysync, gui->changecount);
2862 
2863   //g_signal_handlers_block_by_func(G_OBJECT (SIGNAL_WIDGET), G_CALLBACK (lily_refresh), NULL);
2864   //g_signal_handlers_unblock_by_func (G_OBJECT (SIGNAL_WIDGET), G_CALLBACK (lily_save), NULL);
2865 
2866   if (gui->movement->markstaffnum || (gui->lilysync != gui->changecount))
2867     {
2868       gui->movement->markstaffnum = 0;        //remove selection, else we will only see that bit in LilyText
2869       refresh_lily_cb (NULL, gui);
2870     }
2871   return FALSE;
2872 }
2873 
2874 
2875 static void
prepend_menu_item(GtkMenuShell * menu,DenemoProject * gui,gchar * text,gpointer callback,gchar * tooltip)2876 prepend_menu_item (GtkMenuShell * menu, DenemoProject * gui, gchar * text, gpointer callback, gchar *tooltip)
2877 {
2878   GtkWidget *item;
2879   item = gtk_menu_item_new_with_label (text);
2880   gtk_widget_set_tooltip_text (item, tooltip);
2881   g_signal_connect (item, "activate", G_CALLBACK (callback), gui);
2882   gtk_menu_shell_prepend (menu, GTK_WIDGET (item));
2883   gtk_widget_show (GTK_WIDGET (item));
2884 }
2885 
position_display_cursor(G_GNUC_UNUSED GtkWidget * view,GdkEventButton * event)2886 static gboolean position_display_cursor (G_GNUC_UNUSED GtkWidget *view, GdkEventButton *event)
2887 {
2888     if (event->button == 1 && (GDK_SHIFT_MASK & event->state))
2889     {
2890     GtkTextIter iter;
2891     gtk_text_buffer_get_iter_at_mark (Denemo.textbuffer, &iter, gtk_text_buffer_get_insert (Denemo.textbuffer));
2892     gtk_text_buffer_place_cursor (Denemo.textbuffer, &iter);
2893     gint column = gtk_text_iter_get_visible_line_offset (&iter);
2894     gint line = gtk_text_iter_get_line (&iter);
2895     goto_lilypond_position (line + 1, column);
2896     place_cursor_cb ();//this is purely for the side effect of taking off the marking which happens without it.
2897     }
2898     return FALSE;
2899 }
2900 
2901 static gboolean
populate_called(G_GNUC_UNUSED GtkWidget * view,GtkMenuShell * menu)2902 populate_called (G_GNUC_UNUSED GtkWidget * view, GtkMenuShell * menu)
2903 {
2904   DenemoProject *gui = Denemo.project;
2905   //g_debug("populate called with %p\n", menu);
2906   gtk_container_foreach (GTK_CONTAINER (menu), (GtkCallback) (gtk_widget_destroy), NULL);
2907   prepend_menu_item (menu, gui, _("Find Current Object"), (gpointer) place_cursor_cb, _("Move the text cursor in this window to the object that the Denemo cursor is on"));
2908   prepend_menu_item (menu, gui, _("Insert LilyPond Text"), (gpointer) insert_lilypond_directive, _("Insert LilyPond text at the cursor position.\nWarning! Shift click to position Denemo cursor first"));
2909 #ifdef USE_EVINCE
2910   prepend_menu_item (menu, gui, _("Typeset this LilyPond text"), (gpointer) typeset_current_layout, _("Typesets the current LilyPond text, which will display in the Print View window. Any errors are shown below in the errors pane."));
2911 #endif
2912   //position_display_cursor();
2913   return FALSE;
2914 }
2915 
2916 
get_object_at_lilypond(gint line,gint column)2917 DenemoObject *get_object_at_lilypond (gint line, gint column)
2918 {
2919   DenemoProject *gui = Denemo.project;
2920   GtkTextIter enditer, iter;
2921   gtk_text_buffer_get_end_iter (Denemo.textbuffer, &enditer);
2922   gtk_text_buffer_get_start_iter (Denemo.textbuffer, &iter);
2923   line--;
2924   column++; //needed to avoid stepping back after anchor on directives
2925   if (column > 0 && line > 0)
2926     {
2927       gtk_text_buffer_get_iter_at_line_offset (Denemo.textbuffer, &iter, line, 0);
2928       gint maxcol = gtk_text_iter_get_chars_in_line (&iter);
2929       gtk_text_iter_set_visible_line_offset (&iter, MIN (maxcol, column));
2930       gtk_text_buffer_place_cursor (Denemo.textbuffer, &iter);
2931       GtkTextChildAnchor *anchor = gtk_text_iter_get_child_anchor (&iter);
2932       if (anchor && (g_object_get_data (G_OBJECT (anchor), MOVEMENTNUM) == NULL))
2933         anchor = NULL;
2934       while ((anchor == NULL) && gtk_text_iter_backward_char (&iter))
2935         {
2936           anchor = gtk_text_iter_get_child_anchor (&iter);
2937           if (anchor && (g_object_get_data (G_OBJECT (anchor), MOVEMENTNUM) == NULL))
2938             anchor = NULL;
2939         }
2940       if (anchor)
2941         {
2942           gint objnum = (intptr_t) g_object_get_data (G_OBJECT (anchor), OBJECTNUM);
2943           gint measurenum = (intptr_t) g_object_get_data (G_OBJECT (anchor), MEASURENUM);
2944           gint staffnum = (intptr_t) g_object_get_data (G_OBJECT (anchor), STAFFNUM);
2945           gint movementnum = (intptr_t) g_object_get_data (G_OBJECT (anchor), MOVEMENTNUM);//g_print ("Getting object from %d, %d as measure %d obj %d\n", line, column, measurenum, objnum);
2946           return get_object_by_position (movementnum, staffnum, measurenum, objnum);
2947         }
2948     }
2949     return NULL;
2950 }
2951 
2952 // moves cursor to position indicated by anchor found before line and column, and sets si->target to indicate type of construct there.
2953 gboolean
goto_lilypond_position(gint line,gint column)2954 goto_lilypond_position (gint line, gint column)
2955 {
2956   DenemoProject *gui = Denemo.project;
2957   GtkTextIter enditer, iter;
2958 
2959  if (gui->lilysync != gui->changecount)
2960       refresh_lily_cb (NULL, gui);
2961 
2962 #ifdef USE_EVINCE
2963  if (printview_is_stale ())
2964       play_note (DEFAULT_BACKEND, 0, 9, 69, 300, 100);
2965   //g_print ("goto_lilypond_position called for line %d column %d\n", line, column);
2966 #endif
2967 
2968   gtk_text_buffer_get_end_iter (Denemo.textbuffer, &enditer);
2969   gtk_text_buffer_get_start_iter (Denemo.textbuffer, &iter);
2970 
2971   line--;
2972 
2973   column++; //needed to avoid stepping back after anchor on directives
2974   if (column > 0 && line > 0)
2975     {
2976       gtk_text_buffer_get_iter_at_line_offset (Denemo.textbuffer, &iter, line, 0);
2977       gint maxcol = gtk_text_iter_get_chars_in_line (&iter);
2978       //g_debug("line %d column %d\n", line, column);
2979       //g_debug("line has %d chars\n", maxcol);
2980       gtk_text_iter_set_visible_line_offset (&iter, MIN (maxcol, column));
2981       gtk_text_buffer_place_cursor (Denemo.textbuffer, &iter);
2982       GtkTextChildAnchor *anchor = gtk_text_iter_get_child_anchor (&iter);
2983      // if(anchor) g_print("Initially at anchor %x <%c> type %d\n", anchor, gtk_text_iter_get_char (&iter),g_object_get_data (G_OBJECT (anchor), TARGETTYPE)) ;
2984      // else g_print("Not at anchor <%c> ", gtk_text_iter_get_char (&iter));
2985       if (anchor && (g_object_get_data (G_OBJECT (anchor), MOVEMENTNUM) == NULL))
2986         anchor = NULL;
2987       while ((anchor == NULL) && gtk_text_iter_backward_char (&iter))
2988         {
2989           anchor = gtk_text_iter_get_child_anchor (&iter);
2990           if (anchor && (g_object_get_data (G_OBJECT (anchor), MOVEMENTNUM) == NULL))
2991                     //g_print("Now At movementless anchor %x <%c> type %d\n", anchor, gtk_text_iter_get_char (&iter),g_object_get_data (G_OBJECT (anchor), TARGETTYPE)),
2992             anchor = NULL;      //ignore anchors without positional info
2993          // else if(anchor)
2994          //   g_print("Now proper anchor %x <%c> type %d\n", anchor, gtk_text_iter_get_char (&iter),g_object_get_data (G_OBJECT (anchor), TARGETTYPE));
2995 
2996 
2997           //g_debug("#%c#", gtk_text_iter_get_char (&iter));
2998         }
2999       if (anchor)
3000         {
3001           gint objnum = (intptr_t) g_object_get_data (G_OBJECT (anchor), OBJECTNUM);
3002           gint measurenum = (intptr_t) g_object_get_data (G_OBJECT (anchor), MEASURENUM);
3003           gint staffnum = (intptr_t) g_object_get_data (G_OBJECT (anchor), STAFFNUM);
3004           gint movementnum = (intptr_t) g_object_get_data (G_OBJECT (anchor), MOVEMENTNUM);
3005           gint directivenum = (intptr_t) g_object_get_data (G_OBJECT (anchor), DIRECTIVENUM);
3006           gint mid_c_offset = (intptr_t) g_object_get_data (G_OBJECT (anchor), MIDCOFFSET);
3007 
3008           DenemoTargetType type = (intptr_t) g_object_get_data (G_OBJECT (anchor), TARGETTYPE);
3009           //g_print("location %d %d %d movement %d, type %d at %d %d \n", objnum, measurenum, staffnum, movementnum, type, line, column);
3010           gui->movement->target.objnum = objnum;
3011           gui->movement->target.measurenum = measurenum;
3012           gui->movement->target.staffnum = staffnum;
3013           gui->movement->target.type = type;
3014           gui->movement->target.directivenum = directivenum;
3015 #ifdef G_OS_WIN32
3016           g_debug ("goto_lilypond_position: anchor located and target set %d %d\n", measurenum, objnum);
3017 #endif
3018           if (movementnum < 1)
3019             {
3020               g_warning ("Object %p has no location data", g_object_get_data (G_OBJECT (anchor), OBJECTNODE));
3021               return FALSE;
3022             }
3023           hide_lyrics();
3024           if (!goto_movement_staff_obj (gui, movementnum, staffnum, measurenum, objnum, 0))
3025             {
3026                 show_lyrics ();
3027                 return FALSE;
3028             }
3029           show_lyrics ();
3030           //g_debug("TARGET is %d\n", type);
3031           if (type == TARGET_NOTE)
3032             {
3033               int midcoffset = (intptr_t) g_object_get_data (G_OBJECT (anchor), MIDCOFFSET);
3034               //!!!!move cursor to midcoffset  This has been lifted from view.c, but there surely should exist a function to do this
3035               {
3036                 //dclef =  find_prevailing_clef(gui->movement); This should be dropped from scheme_cursor_to_note() as well I guess.
3037                 gui->movement->cursor_y = mid_c_offset;
3038                 gui->movement->staffletter_y = offsettonumber (gui->movement->cursor_y);
3039                 displayhelper (gui);
3040               }
3041               gui->movement->target.mid_c_offset = midcoffset;
3042             }
3043 #ifdef G_OS_WIN32
3044           g_debug ("goto_lilypond_position: Success\n");
3045 #endif
3046           return TRUE;
3047         }
3048       else
3049         {
3050             play_note (DEFAULT_BACKEND, 0, 9, 43, 300, 127);
3051             g_warning ("Anchor not found");
3052         }
3053     }                           //if reasonable column and line number
3054 
3055   return FALSE;
3056 }
3057 
get_cursor_offset(void)3058 gint get_cursor_offset (void) {
3059     GtkTextIter cursor;
3060     gint offset;
3061     gtk_text_buffer_get_iter_at_mark (Denemo.textbuffer, &cursor, gtk_text_buffer_get_insert (Denemo.textbuffer));
3062     offset = gtk_text_iter_get_offset (&cursor);
3063     //g_print("Offset %d\n", offset);
3064     return offset;
3065 }
3066 static gboolean
lily_keypress(G_GNUC_UNUSED GtkWidget * w,GdkEventKey * event,gboolean after)3067 lily_keypress (G_GNUC_UNUSED GtkWidget * w, GdkEventKey * event, gboolean after)
3068 {
3069   DenemoProject *gui = Denemo.project;
3070   GtkTextIter cursor;
3071   static gint offset;
3072   if(after) {
3073       //g_print("Called after for %d\n", offset);
3074       if(offset) {
3075         gtk_text_buffer_get_iter_at_offset (Denemo.textbuffer, &cursor, offset);
3076         gtk_text_buffer_place_cursor (Denemo.textbuffer, &cursor);
3077         offset = 0;
3078     }
3079       return TRUE;
3080   }
3081   offset = 0;
3082   gtk_text_buffer_get_iter_at_mark (Denemo.textbuffer, &cursor, gtk_text_buffer_get_insert (Denemo.textbuffer));
3083 
3084 
3085 #ifndef TEXTBUFFER_BUG_FIXED
3086   //FIXME workaround for a nasty bug, presumably in GTK, where the back arrow gets a wrong char count, off end of line
3087   if ((event->keyval == 65361) && (gtk_text_iter_get_line_offset (&cursor) < 2))
3088     {
3089       g_debug ("avoiding gtk bug...");
3090       GtkTextTag *tag = gtk_text_tag_table_lookup (tagtable, "invisible");
3091       if (tag && gtk_text_iter_has_tag (&cursor, tag))
3092         {
3093           while (gtk_text_iter_backward_cursor_position (&cursor) && gtk_text_iter_has_tag (&cursor, tag))
3094             gtk_text_buffer_place_cursor (Denemo.textbuffer, &cursor);
3095           g_debug ("backed up");
3096           return TRUE;
3097         }
3098       if (gtk_text_iter_backward_cursor_position (&cursor))
3099         gtk_text_buffer_place_cursor (Denemo.textbuffer, &cursor);
3100       return TRUE;
3101     }
3102 #endif
3103 
3104   if (event->state & (GDK_CONTROL_MASK)) {
3105       switch (event->keyval) {
3106           case 'z': g_warning( "Undo is disabled because gtk source view crashes with its use\n");
3107                 return TRUE; //Do not allow Ctrl-Z undo as it breaks a lot of stuff
3108            case 'c':
3109                 return FALSE;
3110            case 'v':
3111                 return FALSE;
3112            case 'x':
3113                 return FALSE;
3114         default:
3115             return TRUE;
3116         }
3117     }
3118   // if you have a visible marker you do this gtk_text_iter_backward_cursor_position(&cursor);
3119   GtkTextChildAnchor *anchor = gtk_text_iter_get_child_anchor (&cursor);
3120   //g_print("Got a keypress event at anchor %p\n", anchor);g_print("Initially the offset %d at anchor %p\n", gtk_text_iter_get_offset (&cursor), anchor);
3121   //g_print("The character is %x keyval %x at %d\n", (guint)gdk_keyval_to_unicode(event->keyval), event->keyval,  gtk_text_iter_get_line_offset(&cursor));
3122   if (anchor)
3123     {
3124       gint objnum = (intptr_t) g_object_get_data (G_OBJECT (anchor), OBJECTNUM);
3125       gint measurenum = (intptr_t) g_object_get_data (G_OBJECT (anchor), MEASURENUM);
3126       gint staffnum = (intptr_t) g_object_get_data (G_OBJECT (anchor), STAFFNUM);
3127       gint movementnum = (intptr_t) g_object_get_data (G_OBJECT (anchor), MOVEMENTNUM);
3128      // g_print("location %d %d %d %d\n", objnum, measurenum, staffnum, movementnum);
3129       if (movementnum < 1)
3130         return FALSE;
3131       if (!goto_movement_staff_obj (gui, movementnum, staffnum, measurenum, objnum, 0))
3132         return FALSE;
3133       gchar *key = g_strdup_printf ("%c", gdk_keyval_to_unicode (event->keyval));
3134       GList *curobjnode = gui->movement->currentobject;
3135       DenemoObject *obj = curobjnode ? curobjnode->data : NULL;
3136       if (obj && *key > 0x1f)
3137         {
3138           switch (obj->type)
3139             {
3140             case LILYDIRECTIVE:
3141               gtk_text_iter_forward_char (&cursor);     // past anchor
3142               GString **target = g_object_get_data (G_OBJECT (anchor), GSTRINGP);
3143               if (!*target)
3144                 {
3145                   *target = g_string_new (key);
3146                   //g_debug("new string %s (%x)\n", key, *key);
3147                 }
3148               else
3149                 {
3150                   gchar *lily = get_text (anchor);
3151                   g_string_assign (*target, lily);      //FIXME free original
3152 
3153                   g_free (lily);
3154                   g_string_prepend (*target, key);
3155                   g_object_set_data (G_OBJECT (anchor), ORIGINAL, get_text (anchor));
3156                   //g_debug("prepended %s (%x)\n", key, *key);
3157                 }
3158               score_status (gui, TRUE);
3159               refresh_lily_cb (NULL, gui);
3160               gtk_text_buffer_get_iter_at_mark (Denemo.textbuffer, &cursor, gtk_text_buffer_get_insert (Denemo.textbuffer));
3161               if (gtk_text_iter_forward_char (&cursor))
3162                 gtk_text_buffer_place_cursor (Denemo.textbuffer, &cursor);
3163               offset = get_cursor_offset ();
3164               g_free (key);
3165               return TRUE;
3166             case CHORD:
3167             default:
3168               {
3169                   GString **target = g_object_get_data (G_OBJECT (anchor), GSTRINGP);
3170                   if(target && *target)
3171                   {
3172                     //g_print("Target is %s\n", (*target)->str);
3173                     g_string_prepend (*target, key);
3174                     g_object_set_data (G_OBJECT (anchor), ORIGINAL, get_text (anchor));
3175                     offset = get_cursor_offset ();
3176                     score_status (gui, TRUE);
3177                     refresh_lily_cb (NULL, gui);
3178                     //g_print("After lily refresh %d", offset);
3179                     gtk_text_buffer_get_iter_at_offset (Denemo.textbuffer, &cursor, offset);
3180                     gtk_text_buffer_place_cursor (Denemo.textbuffer, &cursor);
3181                     if (gtk_text_iter_forward_char (&cursor) && gtk_text_iter_forward_char (&cursor))
3182                       gtk_text_buffer_place_cursor (Denemo.textbuffer, &cursor);
3183                     offset = get_cursor_offset ();
3184                    // g_print("resetting lily refresh %d", offset);
3185 
3186                   } else
3187                   {
3188                     DenemoObject *lilyobj = lily_directive_new (key);
3189                     ((DenemoDirective*)lilyobj->object)->tag = g_string_new("LilyInsert");
3190                     //g_debug("inserted a lilydirective  %s (%x)\n", key, *key);
3191                     //  offset = gtk_text_iter_get_offset (&cursor);
3192                     // g_print("The offset %d at anchor %p\n", offset, anchor);
3193                     offset = get_cursor_offset ();
3194                     object_insert (gui, lilyobj);
3195 
3196                     gtk_text_buffer_get_iter_at_offset (Denemo.textbuffer, &cursor, offset);
3197                     gtk_text_buffer_place_cursor (Denemo.textbuffer, &cursor);
3198 
3199                     displayhelper (gui);
3200                         //    gtk_text_buffer_get_iter_at_mark (Denemo.textbuffer, &cursor, gtk_text_buffer_get_insert (Denemo.textbuffer));
3201 
3202                         //   g_print("Before advancing %d\n", gtk_text_iter_get_offset (&cursor));
3203 
3204                     if (gtk_text_iter_forward_char (&cursor) && gtk_text_iter_forward_char (&cursor))
3205                       gtk_text_buffer_place_cursor (Denemo.textbuffer, &cursor);
3206                             //  g_print("after advancing %d\n", gtk_text_iter_get_offset (&cursor));
3207                     refresh_lily_cb (NULL, gui);
3208                             //  g_print ("After refresh %d\n\n", get_cursor_offset());
3209                     offset = get_cursor_offset ();
3210                         //if (gtk_text_iter_forward_char (&cursor) && gtk_text_iter_forward_char (&cursor))
3211                         // gtk_text_buffer_place_cursor (Denemo.textbuffer, &cursor);
3212                  }
3213                     g_free (key);
3214                 return TRUE;
3215               }
3216             }                   // switch obj->type
3217 
3218         }                       //if useful keypress??
3219       g_free (key);
3220     }                           //if cursor is at anchor
3221 
3222 
3223   return FALSE;                 //let the normal handler have the keypress
3224 }
3225 
3226 static void
create_console(GtkWidget * box)3227 create_console (GtkWidget * box)
3228 {
3229   //GtkWidget *vpaned = gtk_vpaned_new ();
3230   //gtk_container_set_border_width (GTK_CONTAINER(vpaned), 5);
3231   //gtk_box_pack_start (GTK_BOX (box), vpaned, FALSE, TRUE, 0);
3232   if (Denemo.console)
3233     return;
3234   Denemo.console = gtk_text_view_new ();
3235   GtkWidget *sw = gtk_scrolled_window_new (gtk_adjustment_new (1.0, 1.0, 2.0, 1.0, 4.0, 1.0), gtk_adjustment_new (1.0, 1.0, 2.0, 1.0, 4.0, 1.0));
3236   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
3237   gtk_box_pack_start (GTK_BOX (box), sw, TRUE, TRUE, 0);
3238   gtk_container_add (GTK_CONTAINER (sw), Denemo.console);
3239   gtk_widget_show_all (sw);
3240 }
3241 
drag_begin(void)3242 void drag_begin (void)
3243 {
3244     g_message("Drag begin");
3245 }
3246 
3247 void
init_lilypond_buffer(void)3248 init_lilypond_buffer(void){
3249   tagtable = (GtkTextTagTable *) gtk_text_tag_table_new ();
3250   GtkTextTag *t;
3251 
3252   t = gtk_text_tag_new ("system_invisible");
3253   g_object_set (G_OBJECT (t), "invisible", TRUE, NULL);
3254   gtk_text_tag_table_add (tagtable, t);
3255 
3256   t = gtk_text_tag_new (INEDITABLE);
3257   g_object_set (G_OBJECT (t), "editable", FALSE, NULL);
3258   gtk_text_tag_table_add (tagtable, t);
3259 
3260   t = gtk_text_tag_new (HIGHLIGHT);
3261   g_object_set (G_OBJECT (t), "background", "light gray", NULL);
3262   gtk_text_tag_table_add (tagtable, t);
3263 
3264   t = gtk_text_tag_new (ERRORTEXT);
3265   g_object_set (G_OBJECT (t), "background", "pink", NULL);
3266   gtk_text_tag_table_add (tagtable, t);
3267 
3268 
3269   t = gtk_text_tag_new ("bold");
3270   g_object_set (G_OBJECT (t), "weight", PANGO_WEIGHT_BOLD, "family", "monospace", NULL);
3271   gtk_text_tag_table_add (tagtable, t);
3272 
3273   t = gtk_text_tag_new ("monospace");
3274   g_object_set (G_OBJECT (t), "family", "monospace", NULL);
3275   gtk_text_tag_table_add (tagtable, t);
3276 
3277 
3278   Denemo.textbuffer = (GtkTextBuffer *)gtk_source_buffer_new (tagtable);
3279   gtk_source_buffer_set_highlight_syntax (GTK_SOURCE_BUFFER (Denemo.textbuffer), TRUE);
3280 }
3281 
3282 void
create_lilywindow(void)3283 create_lilywindow (void)
3284 {
3285   gchar *helptext = _("Shift left click in music in this window to move the Denemo cursor the corresponding position\n"
3286   "Using arrows to move the cursor in the music here also moves the Denemo cursor.\n"
3287   "Right click for menu.\n"
3288   "Turn off continuous typesetting before using the score layout options.");
3289   Denemo.textwindow = gtk_window_new (GTK_WINDOW_TOPLEVEL);
3290   //gtk_window_set_position (GTK_WINDOW (Denemo.textwindow), GTK_WIN_POS_NONE);
3291   gtk_window_set_default_size (GTK_WINDOW (Denemo.textwindow), 800, 600);
3292   gtk_window_set_title (GTK_WINDOW (Denemo.textwindow), "LilyPond Text - Denemo");
3293   g_signal_connect (G_OBJECT (Denemo.textwindow), "delete-event", G_CALLBACK (lilywindow_closed), NULL);
3294 #if GTK_MAJOR_VERSION == 2
3295   GtkWidget *top_pane = (GtkWidget*)gtk_vpaned_new ();
3296 #else
3297   GtkWidget *top_pane = (GtkWidget*)gtk_paned_new (GTK_ORIENTATION_VERTICAL);
3298 #endif
3299   GtkWidget *vbox = (GtkWidget*)gtk_vbox_new (FALSE, 8);
3300 
3301   gtk_paned_add2 (GTK_PANED (top_pane), vbox);//gtk_container_add (GTK_CONTAINER (Denemo.textwindow), top_pane);
3302   gtk_container_add (GTK_CONTAINER (Denemo.textwindow), top_pane);
3303   create_console (vbox);
3304 
3305   GtkWidget *view = (GtkWidget *)gtk_source_view_new ();
3306   GtkWidget *sw = gtk_scrolled_window_new (gtk_adjustment_new (1.0, 1.0, 2.0, 1.0, 4.0, 1.0), gtk_adjustment_new (1.0, 1.0, 2.0, 1.0, 4.0, 1.0));
3307   gtk_widget_set_tooltip_text (sw, helptext);
3308   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
3309   gtk_paned_add1 (GTK_PANED (top_pane), sw);
3310   gtk_container_add (GTK_CONTAINER (sw), view);
3311 
3312   gtk_paned_set_position (GTK_PANED (top_pane), 500);
3313   gtk_widget_show_all (top_pane);
3314   gtk_source_view_set_show_line_numbers (GTK_SOURCE_VIEW (view), TRUE);
3315   gtk_source_view_set_highlight_current_line (GTK_SOURCE_VIEW (view), TRUE);
3316   gtk_source_view_set_show_line_marks (GTK_SOURCE_VIEW (view), TRUE);
3317   Denemo.textview = (GtkTextView *) view;
3318 
3319 
3320   g_signal_connect (G_OBJECT (Denemo.textview), "key-press-event", G_CALLBACK (lily_keypress), NULL);
3321   g_signal_connect_after (G_OBJECT (Denemo.textview), "key-release-event", G_CALLBACK (lily_keypress), GINT_TO_POINTER(TRUE));
3322 
3323 
3324   g_signal_connect_after (G_OBJECT (Denemo.textview), "populate-popup", G_CALLBACK (populate_called), NULL);
3325 
3326   g_signal_connect (G_OBJECT (Denemo.textview), "button-release-event", G_CALLBACK (position_display_cursor), NULL);
3327 
3328 
3329 
3330   /*   g_object_set_data(G_OBJECT (SIGNAL_WIDGET),"enter-signal", (gpointer)id); */
3331 
3332   gtk_text_view_set_buffer (GTK_TEXT_VIEW (Denemo.textview), Denemo.textbuffer);
3333   //gui->lilysync = G_MAXUINT;//buffer not yet up to date
3334 
3335 
3336   g_signal_connect (G_OBJECT (SIGNAL_WIDGET), LEAVE_NOTIFY_EVENT, G_CALLBACK (lily_save), NULL);
3337   g_signal_connect (G_OBJECT (SIGNAL_WIDGET), ENTER_NOTIFY_EVENT, G_CALLBACK (lily_refresh), NULL);
3338   //g_signal_handlers_block_by_func(G_OBJECT (SIGNAL_WIDGET), G_CALLBACK (lily_refresh), NULL);
3339 }
3340