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