1 /* object.c
2  * functions that do operations to DenemoObjects
3  *
4  * for Denemo, a gtk+ frontend to GNU Lilypond
5  * (c) 1999-2005 Matthew Hiller
6  */
7 
8 #include <denemo/denemo.h>
9 #include "command/chord.h"
10 #include "core/utils.h"
11 #include "command/commandfuncs.h"
12 #include "command/object.h"
13 #include "command/staff.h"
14 #include "command/tuplet.h"
15 #include "command/select.h"
16 #include "audio/pitchentry.h"
17 #include "core/utils.h"
18 #include "core/view.h"
19 #include "command/lilydirectives.h"
20 #include <string.h>
21 static void edit_staff_and_voice_properties (gboolean show_staff);
22 void initkeyaccs (gint * accs, gint number);
23 
24 DenemoObject *
get_object(void)25 get_object (void)
26 {
27   DenemoProject *gui = Denemo.project;
28   DenemoMovement *si = gui->movement;
29   return (DenemoObject *) si->currentobject ? (DenemoObject *) si->currentobject->data : NULL;
30 }
31 
32 /**
33  * Free the given object
34  * @param mudobj the DenemoObject to free
35 FIXME is this failing to free the object field???
36  */
37 void
freeobject(DenemoObject * mudobj)38 freeobject (DenemoObject * mudobj)
39 {
40   if (mudobj == NULL)
41     return;
42   if (mudobj->lilypond)
43     g_free (mudobj->lilypond);
44   switch (mudobj->type)
45     {
46     case CHORD:
47       freechord (mudobj);       /* Which also frees mudobj itself */
48       break;
49     case CLEF:
50       free_directives (((clef *) mudobj->object)->directives);
51       g_free (mudobj->object);
52       g_free (mudobj);
53       break;
54     case KEYSIG:
55       free_directives (((keysig *) mudobj->object)->directives);
56       g_free (mudobj->object);
57       g_free (mudobj);
58       break;
59     case TIMESIG:
60       free_directives (((timesig *) mudobj->object)->directives);
61       g_free (mudobj->object);
62       g_free (mudobj);
63       break;
64 
65     case TUPOPEN:
66     case TUPCLOSE:
67       free_directives (((tuplet *) mudobj->object)->directives);
68       g_free (mudobj->object);
69       g_free (mudobj);
70       break;
71     default:
72       g_free (mudobj);
73       break;
74     }
75 }
76 /* drop display full information about the object at the cursor */
77 static GtkWidget *ObjectInfo = NULL;
78 static gboolean
drop_object_info(void)79 drop_object_info (void)
80 {
81   if (ObjectInfo)
82     gtk_widget_hide (ObjectInfo);
83   return TRUE;
84 }
85 /* display full information about the object at the cursor if Inspector is open*/
86 void
update_object_info(void)87 update_object_info (void)
88 {
89   if (ObjectInfo && gtk_widget_get_visible (ObjectInfo))
90     display_current_object ();
91 }
92 static void
append_directives_information(GString * selection,GList * directives)93 append_directives_information (GString * selection, GList * directives)
94 {
95     gboolean first = TRUE;
96   do
97     {
98       DenemoDirective *directive = directives->data;
99       if(directive->tag==NULL)
100             directive->tag = g_string_new("<Unknown Tag>");//shouldn't happen
101       const gchar *label = get_label_for_command (directive->tag->str);
102       const gchar *menupath = get_menu_path_for_command (directive->tag->str);
103       const gchar *tooltip = get_tooltip_for_command (directive->tag->str);
104       if (tooltip == NULL) tooltip = _("No tooltip");
105 
106       if(directive->tag==NULL)
107             directive->tag = g_string_new("<Unknown Tag>");//shouldn't happen
108       gchar *label_e = label? g_markup_escape_text(label, -1): g_markup_escape_text(directive->tag->str, -1);
109       if(!first)
110         g_string_append (selection, "\n<span foreground=\"blue\"weight=\"bold\">---------------------------------------------------------</span>\n");
111       else
112          g_string_append (selection, "\n<span foreground=\"green\"weight=\"bold\">---------------------------------------------------------</span>\n");
113       first = FALSE;
114       if(label)
115                 g_string_append_printf (selection, _("Directive for command: <span weight=\"bold\">\"%s\"</span>\n"), label_e);
116       else
117                 g_string_append_printf (selection, _("Directive tagged: <span foreground=\"red\"weight=\"bold\">\"%s\"</span>\n"), label_e);
118       g_free (label_e);
119       if(menupath)
120         {
121             gchar *menupath_e = g_markup_escape_text(menupath, -1);
122             g_string_append_printf (selection, _("Menu location for this command: <span style=\"italic\" weight=\"bold\">\"%s\"</span>\n"), menupath_e);
123             g_free (menupath_e);
124         }
125       if(tooltip)
126         {
127             gchar * tooltip_e = g_markup_escape_text(tooltip, -1);
128             g_string_append_printf (selection, _("The help for the command that created this directive is:\n<big>\"%s\"</big>\n"), tooltip_e);
129             g_free (tooltip_e);
130         }
131       if(directive->prefix)
132         {
133             gchar *lily = g_markup_escape_text(directive->prefix->str, -1);
134             g_string_append_printf (selection, _("LilyPond inserted in prefix to this object is <tt>\"%s\"</tt>\n"), lily);
135             g_free (lily);
136         }
137       if(directive->postfix)
138         {
139             gchar *lily = g_markup_escape_text(directive->postfix->str, -1);
140             g_string_append_printf (selection, _("LilyPond inserted in postfix to this object is <tt>\"%s\"</tt>\n"), lily);
141             g_free (lily);
142         }
143      if(directive->x || directive->y)
144         g_string_append (selection, _( "<span foreground=\"red\"weight=\"bold\">THIS DIRECTIVE IS CONDITIONAL ON THE LAYOUT\n</span>"));
145      if(!directives->next)
146         g_string_append (selection, "<span foreground=\"blue\"weight=\"bold\">---------------------------------------------------------</span>");
147 
148     }
149   while (directives->next && (directives = directives->next));
150   g_string_append (selection, "\n");
151 }
152 
append_lilypond(DenemoObject * curObj,GString * selection)153 static void append_lilypond (DenemoObject *curObj, GString *selection)
154     {
155         DenemoProject *gui = Denemo.project;
156         if( gui->lilysync != gui->changecount)
157             refresh_lily_cb (NULL, gui); //if(curObj->lilypond)g_print ("lili |%s|\n", curObj->lilypond);
158         if(curObj->lilypond && *curObj->lilypond)
159             g_string_append_printf (selection, _("The LilyPond syntax generated is: <tt>\"%s\"</tt>\n"), g_markup_escape_text(curObj->lilypond, -1));
160         else
161             g_string_append_printf (selection, _("This object does not affect the music typesetting, (no LilyPond syntax is generated)\n"));
162     }
163 
gcd384(gint n)164 static gint gcd384 (gint n)
165 {
166     gint remainder, m = 384;
167     while (n != 0)
168     {
169         remainder = m % n;
170         m = n;
171         n = remainder;
172     }
173     return m;
174 }
reset_cursors(void)175 static void reset_cursors (void)
176 {
177     gdk_window_set_cursor (gtk_widget_get_window (Denemo.window), gdk_cursor_new (GDK_LEFT_PTR));
178     if(ObjectInfo)
179         gdk_window_set_cursor (gtk_widget_get_window (ObjectInfo), gdk_cursor_new (GDK_LEFT_PTR));
180     if(Denemo.printarea && gtk_widget_get_window (Denemo.printarea))
181         gdk_window_set_cursor (gtk_widget_get_window (Denemo.printarea), gdk_cursor_new (GDK_LEFT_PTR));
182 }
183 
move_to_next_note(GtkWidget * editwin)184 static void move_to_next_note (GtkWidget *editwin)
185 {
186 if(!cursor_to_next_note_height())
187     cursor_to_nth_note_height (0);
188 if (editwin)
189    {
190     gtk_widget_destroy (editwin);
191     reset_cursors ();
192     edit_object();
193     }
194 }
195 
go_left(GtkWidget * editwin)196 static void go_left(GtkWidget *editwin)
197 {
198 cursor_to_prev_object (FALSE, FALSE);
199 if(Denemo.project->movement->currentobject == NULL)
200     {
201         cursor_to_next_object (FALSE, FALSE);
202         warningdialog (_("Preceding measures are empty"));
203     }
204 if (editwin)
205    {
206     gtk_widget_destroy (editwin);
207     reset_cursors ();
208     edit_object();
209     }
210 }
go_right(GtkWidget * editwin)211 static void go_right(GtkWidget *editwin)
212 {
213 cursor_to_next_object (FALSE, FALSE);
214 if(Denemo.project->movement->currentobject == NULL)
215     {
216       cursor_to_prev_object (FALSE, FALSE);
217       warningdialog (_("Subsequent measures are empty"));
218     }
219 if (editwin)
220    {
221     gtk_widget_destroy (editwin);
222     reset_cursors ();
223     edit_object();
224     }
225 }
226 
227 static gint display_timeout_id = 0; //timeout to avoid calling display_current_object() repeatedly during rapid changes/entry of music
228 static gboolean
display_current_object_callback(void)229 display_current_object_callback (void)
230 {
231   DenemoProject *gui = Denemo.project;
232   if(Denemo.project->movement == NULL)
233     return FALSE;
234   gchar *type = "object";
235   if (ObjectInfo == NULL)
236     {
237       ObjectInfo = gtk_window_new (GTK_WINDOW_TOPLEVEL);
238       gtk_window_set_title (GTK_WINDOW (ObjectInfo), _("Denemo Object Inspector"));
239       g_signal_connect (G_OBJECT (ObjectInfo), "delete-event", G_CALLBACK (drop_object_info), NULL);
240      // gtk_window_set_keep_above (GTK_WINDOW (ObjectInfo), TRUE);
241      gtk_window_set_default_size (GTK_WINDOW (ObjectInfo), 400, 400);
242      gtk_window_set_accept_focus (GTK_WINDOW (ObjectInfo), FALSE);
243     }
244   else
245     {
246       gtk_widget_destroy (gtk_bin_get_child (GTK_BIN (ObjectInfo)));
247     }
248 
249   GtkWidget *vbox = gtk_vbox_new (FALSE, 8);
250   gtk_container_add (GTK_CONTAINER (ObjectInfo), vbox);
251 
252   if (gui->movement->currentobject == NULL)
253     {
254       GtkWidget *label = gtk_label_new ("The cursor is in an empty measure.\n" "As a special case this will be typeset as a non-printing whole measure rest.\n" "Note that if you put anything at all in this measure\n" "you must insert a real whole measure rest if that is what you want.");
255       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, TRUE, 0);
256     }
257   else
258     {
259     DenemoObject *curObj = gui->movement->currentobject->data;
260 
261     if (curObj->type==CHORD)
262        {
263             chord *thechord = ((chord *) curObj->object);
264             if (thechord->notes)
265               {
266                 note *thenote = findnote (curObj, Denemo.project->movement->cursor_y);
267                 GtkWidget *button = gtk_button_new_with_label (
268                     thechord->notes->next?_("Inspect next note in chord"):_("Inspect the note"));
269                 gtk_widget_set_sensitive (button,
270                     ( (!thenote) || thechord->notes->next || (Denemo.project->movement->cursor_y!=thenote->mid_c_offset)));
271 
272                 g_signal_connect_swapped (button, "clicked", G_CALLBACK (move_to_next_note), NULL);
273                 gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, TRUE, 0);
274             }
275         }
276     GtkWidget *edit_button = gtk_button_new_with_label (_("Run the Object Editor"));
277     g_signal_connect (edit_button, "clicked", G_CALLBACK (edit_object), NULL);
278     gtk_box_pack_start (GTK_BOX (vbox), edit_button, FALSE, TRUE, 0);
279 
280 
281       GString *selection = g_string_new (gui->movement->cursor_appending ? _("The cursor is in the appending position after ") : _("The cursor is on "));
282       GString *warning = g_string_new ("");
283       switch (curObj->type)
284         {
285         case CHORD:
286           {
287             chord *thechord = ((chord *) curObj->object);
288             if (thechord->notes)
289               {
290                 if (thechord->notes->next)
291                   {
292                     type = _("chord");
293                     selection = g_string_append (selection, _("a chord.\n"));
294                   }
295                 else
296                   {
297                     type = _("note");
298                     selection = g_string_append (selection, _("a one-note chord.\n"));
299                   }
300                 if (thechord->slur_begin_p)
301                   selection = g_string_append (selection, _("A slur starts from here.\n" "There should be a matching end slur later.\n"));
302                 if (thechord->slur_end_p)
303                   selection = g_string_append (selection, _("A slur ends here\n" "There should be a matching start slur earlier.\n"));
304                 if (thechord->is_tied)
305                   selection = g_string_append (selection, _("This is tied to the following note or chord.\n" "The following note or chord should have the same pitch\n"));
306                  if (thechord->crescendo_begin_p)
307                   selection = g_string_append (selection, _("This note begins a crescendo. Use the Right Click → Dynamics menu to control this.\n"));
308                  if (thechord->crescendo_end_p)
309                   selection = g_string_append (selection, _("This note ends a crescendo. Use the Right Click → Dynamics menu to control this.\n"));
310                 if (thechord->diminuendo_begin_p)
311                   selection = g_string_append (selection, _("This note begins a diminuendo. Use the Right Click → Dynamics menu to control this.\n"));
312                  if (thechord->diminuendo_end_p)
313                   selection = g_string_append (selection, _("This note ends a diminuendo. Use the Right Click → Dynamics menu to control this.\n"));
314 
315                 if (thechord->is_grace && !(thechord->is_grace & GRACED_NOTE))
316                   selection = g_string_append (selection, _("This is an acciaccatura note\n"));
317 
318                 if (thechord->is_grace & GRACED_NOTE)
319                   selection = g_string_append (selection, _("This is an appoggiatura note\n"));
320                 if (curObj->isinvisible)
321                   selection = g_string_append (selection, _("This note denotes a rhythm - use a MIDI keyboard to add pitches by playing.\n"));
322                 if (thechord->fakechord)
323                     g_string_append_printf (selection, _("A Chord Symbol \"%s\" is attached to this note.\n"), ((GString *)thechord->fakechord)->str);
324 
325                 if (thechord->figure)
326                     g_string_append_printf (selection, _("A Bass Figure \"%s\" is attached to this note.\n"), ((GString *)thechord->figure)->str);
327 
328 
329 
330                 note *thenote = findnote (curObj, gui->movement->cursor_y);
331                 if (thenote && gui->movement->cursor_y==thenote->mid_c_offset)
332                   {
333 
334                     g_string_append_printf (selection, _("<b>Within the chord the cursor is on the note %s </b>\n"),
335                                             pretty_name(mid_c_offsettolily (thenote->mid_c_offset, thenote->enshift)));
336                     if (thenote->directives)
337                       {
338                         selection = g_string_append (selection, _("Attached to this note:"));
339                         append_directives_information (selection, thenote->directives);
340                       }
341                   }
342                 if ((thechord->notes->next) && curObj->isinvisible)
343                         warning = g_string_append (warning, _("This rhythm has extra notes added to it, delete them and use the foot-pedal or Alt key to enter chords with the MIDI controller.\n"));
344 
345               }
346             else
347               {
348                 type = _("rest");
349                 selection = g_string_append (selection, _("a rest.\n"));
350                 if (thechord->slur_begin_p)
351                   warning = g_string_append (warning, _("This rest has a slur start on it, use the Right Click  → Slurs menu to remove it\n"));
352                 if (thechord->slur_end_p)
353                   warning = g_string_append (warning, _("This rest has a slur end on it, use the Right Click → Slurs menu to remove it\n"));
354                 if (thechord->is_tied)
355                   warning = g_string_append (warning, _("This rest has a tie starting on it, use the Right Click  → Tied Note to remove it\n"));
356 
357 
358                 if (curObj->isinvisible)
359                   selection = g_string_append (selection, _("This rest will not print, just act as a spacer.\n"));
360                 if (thechord->is_grace && curObj->isinvisible)
361                   warning = g_string_append (warning, _("This rest has the grace attribute set: these objects are usually inserted automatically to match real grace notes in other parts, this helps the music typesetter place the grace note correctly in the Print View.\n"));
362 
363               }
364             if (thechord->directives)
365                             {
366                             selection = g_string_append (selection, _("Attached to the chord:"));
367                             append_directives_information (selection, thechord->directives);
368                             }
369            gint gcd_s = gcd384 (curObj->starttick);
370            gint gcd_d = gcd384 (curObj->durinticks);
371            if (gcd_s == 384)
372             {
373                 if (gcd_d == 384)
374                  g_string_append_printf (selection, _("This %s starts %d ��  's into the measure and lasts %d �� 's.\n"), type, curObj->starttick/384, curObj->durinticks/384);
375                 else
376                 g_string_append_printf (selection, _("This %s starts %d ��  's into the measure and lasts %d/%d �� 's.\n"), type, curObj->starttick/384, curObj->durinticks/gcd_d, 384/gcd_d);
377             } else
378             {
379                 if (gcd_d == 384)
380                     g_string_append_printf (selection, _("This %s starts %d/%d ��  's into the measure and lasts %d �� 's.\n"), type, curObj->starttick/gcd_s, 384/gcd_s, curObj->durinticks/384);
381                 else
382                     g_string_append_printf (selection, _("This %s starts %d/%d ��  's into the measure and lasts %d/%d �� 's.\n"), type, curObj->starttick/gcd_s, 384/gcd_s, curObj->durinticks/gcd_d, 384/gcd_d);
383             }
384            append_lilypond (curObj, selection);
385           }
386           break;
387         case TUPOPEN:
388           { tuplet *thetup = ((tuplet *) curObj->object);
389             //type = _("start tuplet marker");
390             g_string_append_printf (selection, _(" a Start Tuplet object\n""Meaning %d notes will take the time of %d notes\n" "until an End Tuplet object.\nSee the Notes/Rests → Tuplets for control over how tuplets print\n"), thetup->denominator, thetup->numerator);
391                         if (thetup->directives)
392                             {
393                                 selection = g_string_append (selection, _("Attached to the Start Tuplet:"));
394                                 append_directives_information (selection, thetup->directives);
395                             }
396              append_lilypond (curObj, selection);
397           }
398           break;
399         case TUPCLOSE:
400           { tuplet *thetup = ((tuplet *) curObj->object);
401             //type = _("end tuplet marker");
402             g_string_append_printf (selection, _("an End Tuplet object\n" "Note: the Start Tuplet must be in the same measure.\n"));
403             if (thetup->directives)
404                             {
405                                 selection = g_string_append (selection, _("Attached to the End Tuplet:"));
406                                 append_directives_information (selection, thetup->directives);
407                             }
408             append_lilypond (curObj, selection);
409           }
410           break;
411         case CLEF:
412           {
413             clef *theclef = ((clef *) curObj->object);
414             //type = _("clef change object");
415             g_string_append_printf (selection, _("a Clef Change object.\n"));
416             if (theclef->directives)
417                             {
418                                 selection = g_string_append (selection, _("Attached to the Clef Change:"));
419                                 append_directives_information (selection, theclef->directives);
420                             }
421             if (curObj->isinvisible)
422                            selection = g_string_append (selection, _("This clef change is non-printing, it just affects the display.\n"));
423             append_lilypond (curObj, selection);
424 
425           }
426           break;
427         case TIMESIG:
428           {
429             timesig *thetime = ((timesig *) curObj->object);
430             //type = _("time signature change object");
431             g_string_append_printf (selection, _("a Time Signature Change object.\n"));
432                         if (thetime->directives)
433                             {
434                                 selection = g_string_append (selection, _("Attached to the Time Signature Change:"));
435                                 append_directives_information (selection, thetime->directives);
436                             }
437             append_lilypond (curObj, selection);
438             if (gui->movement->currentobject->prev)
439               g_string_append_printf (warning, _("A Time Signature Change should be the first object in a measure\n" "unless you are trying to do something unusual"));
440           }
441           break;
442         case KEYSIG:
443           {
444             keysig *thekey = ((keysig *) curObj->object);
445             //type = _("key signature change object");
446 
447             g_string_append_printf (selection, _("a Key Signature Change object.\n"));
448             if (thekey->directives)
449                 {
450                     selection = g_string_append (selection, _("Attached to the Key Signature Change:"));
451                     append_directives_information (selection, thekey->directives);
452                 }
453             append_lilypond (curObj, selection);
454             }
455           break;
456         case STEMDIRECTIVE:
457           {
458             stemdirective *thestem = ((stemdirective *) curObj->object);
459             //type = _("stem direction change object");
460             g_string_append_printf (selection, _("a Stem Direction Control Object. The notes after the cursor %s"), ((stemdirective *) curObj->object)->type == DENEMO_STEMDOWN ? _("will have stems downwards.") : ((stemdirective *) curObj->object)->type == DENEMO_STEMUP ? _("will have stems upwards.") : _("will have stems up or down as needed."));
461                         if (thestem->directives)
462                             {
463                                 selection = g_string_append (selection, _("\nAttached to the Stemming Change:"));
464                                 append_directives_information (selection, thestem->directives);
465                             }
466             append_lilypond (curObj, selection);
467           }
468           break;
469         case LILYDIRECTIVE:
470           {
471             DenemoDirective *directive = (DenemoDirective *) curObj->object;
472             //type = _("Denemo directive object");
473 
474             if(directive->tag==NULL)
475                             directive->tag = g_string_new("<Unknown Tag>");//shouldn't happen
476             const gchar *label = get_label_for_command (directive->tag->str);
477             const gchar *menupath = get_menu_path_for_command (directive->tag->str);
478             const gchar *tooltip = get_tooltip_for_command (directive->tag->str);
479             if (tooltip == NULL) tooltip = _("No tooltip");
480             gchar *label_e = label? g_markup_escape_text(label, -1): g_markup_escape_text(directive->tag->str, -1);
481             if(label)
482                g_string_append_printf (selection, _("a Denemo Directive: <span weight=\"bold\">%s</span>\n"), label_e);
483             else
484                 g_string_append_printf (selection, _("a Denemo Directive tagged: <span foreground=\"red\"weight=\"bold\">%s</span>\n"), label_e);
485             g_free (label_e);
486             if(tooltip)
487                 {
488                     gchar *tooltip_e = g_markup_escape_text(tooltip, -1);
489                     g_string_append_printf (selection, _("\nThe help for the command that created this directive is\n<big>\"%s\"</big>"), tooltip_e);
490                     g_free (tooltip_e);
491                 }
492 
493            g_string_append_printf (selection, _("%s"), directive->x ? _("\nNot all layouts\n") : directive->y ? _("\nOnly for one Layout\n"): "\n");
494            if(menupath)
495                 {
496                     gchar *menupath_e = g_markup_escape_text(menupath, -1);
497                     g_string_append_printf (selection, _("Menu location for this command: <span style=\"italic\" weight=\"bold\">\"%s\"</span>\n"), menupath_e);
498                     g_free (menupath_e);
499                 }
500 
501             {
502                gchar *text =  g_strconcat(directive->prefix?directive->prefix->str:"",
503                             directive->postfix?directive->postfix->str:"", NULL);
504                g_strchug (text); //does not allocate memory
505                if (*text)
506                 {
507                 gchar *lily1 = directive->prefix?g_markup_escape_text(directive->prefix->str, -1):g_strdup("");
508                 gchar *lily2 = directive->postfix?g_markup_escape_text(directive->postfix->str, -1):g_strdup("");
509 
510                 g_string_append_printf (selection, _("The LilyPond text inserted is <tt>%s%s</tt>\n"),
511                           lily1,lily2);//puts the whitespace back
512                 g_free (lily1);
513                 g_free (lily2);
514                 }
515             else
516                 g_string_append_printf (selection, _("This object does not affect the printed output (no LilyPond syntax is generated for the typesetter)\n"));//well this ignores possible effect of whitespace...
517             g_free (text);
518             if(directive->x || directive->y)
519                 g_string_append (selection, _( "<span foreground=\"red\"weight=\"bold\">THIS DIRECTIVE IS CONDITIONAL ON THE LAYOUT\n</span>"));
520             }
521            if (gui->movement->currentobject->next == NULL && (gui->movement->currentmeasure->next == NULL))
522               g_string_assign (warning, _("This Directive is at the end of the music"
523                 "\nYou may need a closing double bar line -\n"
524                 "see Directives → Markings → Inserting Barlines"));
525           }
526           break;
527         default:
528           {
529             g_string_append (selection, _("The cursor is on an unknown object type. Please report how this happened!"));
530           }
531           break;
532         } //end switch curObj type
533 
534         if (gui->movement->smfsync == gui->movement->changecount)
535         {
536 
537           gdouble time = curObj->earliest_time;
538           gint minutes = time / 60.0;
539           gdouble seconds = time - 60 * minutes;
540           g_string_append_printf (selection, _("Playback timing: %d minutes %1.2f seconds"), minutes, seconds);
541         }
542 
543         if (warning->len)
544         {
545           GtkWidget *label = gtk_label_new ("");
546           warning = g_string_prepend (warning, _("<span font-desc=\"30\">Warning</span> "));
547           gtk_label_set_markup (GTK_LABEL (label), warning->str);
548           gtk_label_set_line_wrap (GTK_LABEL(label), TRUE);
549           gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, TRUE, 0);
550         }
551         if (selection->len)
552         {
553           GtkWidget *scrolled_window = 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));
554           gtk_box_pack_start (GTK_BOX (vbox), scrolled_window, TRUE, TRUE, 0);
555           GtkWidget *inner_box = gtk_vbox_new (FALSE, 0);
556           gtk_scrolled_window_add_with_viewport  (GTK_SCROLLED_WINDOW(scrolled_window),  inner_box);
557           GtkWidget *label = gtk_label_new ("");
558           gtk_label_set_selectable (GTK_LABEL(label), TRUE);
559 
560          /*
561               making the text selectable unfortunately results in the label text being selected at the start
562               the following code would undo that, but selection-bound cannot be written to, so it does not work.
563               int start, end;
564               gtk_label_get_selection_bounds (GTK_LABEL(label), &start, &end);
565               GValue value = { 0 };
566               g_value_init (&value, G_TYPE_INT);
567               g_value_set_int (&value, end);
568               g_object_set_property (G_OBJECT (label), "selection-bound", &value);
569             *this also does not work:
570               g_signal_emit_by_name (GTK_LABEL(label), "move-cursor", GTK_MOVEMENT_BUFFER_ENDS, -1, FALSE);
571           */
572           gtk_label_set_markup (GTK_LABEL (label), selection->str);
573           gtk_label_set_line_wrap (GTK_LABEL(label), TRUE);
574           gtk_box_pack_start (GTK_BOX (inner_box), label, TRUE, TRUE, 0);
575         }
576       g_string_free (warning, TRUE);
577       g_string_free (selection, TRUE);
578     }
579   gtk_widget_show_all (ObjectInfo);
580 #ifdef G_OS_WIN32
581 //on windows, the ObjectInfo window takes the focus regardless of having told it not to, so it is up to the user to bring the inspector to the front.
582   gtk_window_set_transient_for (GTK_WINDOW(ObjectInfo), GTK_WINDOW(Denemo.window));
583   gtk_window_set_keep_above (GTK_WINDOW (ObjectInfo), TRUE);
584 
585 #else
586   gtk_window_present (GTK_WINDOW (ObjectInfo));
587 #endif
588   display_timeout_id = 0;
589   return FALSE;
590 }
591 void
display_current_object(void)592 display_current_object (void) {
593   static gint delay = 10;
594     if (display_timeout_id == 0) {
595         display_timeout_id = g_timeout_add (delay, (GSourceFunc)display_current_object_callback, NULL);
596         delay = 10;
597     }
598     else {
599 
600         if (delay<1500)
601             delay += 100;
602     }
603 }
show_window(GtkWidget * w)604 static void show_window (GtkWidget *w) {
605     w = gtk_widget_get_toplevel (w);
606     gtk_widget_show (w);
607     gtk_window_present (GTK_WINDOW(w));
608     //g_print ("Window presented");
609 }
610 
611 static void
set_false(GtkWidget * button,gboolean * bool)612 set_false (GtkWidget *button, gboolean *bool)
613 {
614     GtkWidget *w = gtk_widget_get_toplevel (button);
615     gtk_widget_destroy (button);
616     show_window (w);
617     if (*bool)
618         score_status(Denemo.project, TRUE);
619     *bool = FALSE;
620 }
621 
622 typedef gboolean fn_type (gchar*);
advanced_edit_type_directive(GtkWidget * button,gpointer fn)623 static void advanced_edit_type_directive (GtkWidget *button, gpointer fn)
624 {
625     DenemoDirective *directive = (DenemoDirective*) g_object_get_data (G_OBJECT(button), "directive");
626     GList **directives = (GList **)g_object_get_data (G_OBJECT(button), "directives");
627     gtk_widget_hide (gtk_widget_get_toplevel (button));
628     if (!( ((fn_type *)fn) (directive->tag->str)))
629         {
630             if(directives)
631                 *directives = g_list_remove (*directives, directive);
632             else
633                 dnm_deleteobject (Denemo.project->movement);
634             gtk_widget_destroy (gtk_widget_get_parent (gtk_widget_get_parent (button)));
635             score_status(Denemo.project, TRUE);
636         }
637     else
638         show_window (button);//gtk_widget_show (gtk_widget_get_toplevel (button));
639 
640 }
641 
create_palette_button_for_directive(GtkWidget * button,gchar * what)642 static void  create_palette_button_for_directive (GtkWidget *button, gchar *what)
643 {
644     DenemoDirective *directive = (DenemoDirective*) g_object_get_data (G_OBJECT(button), "directive");
645     DenemoPalette *pal = NULL;
646     if(!strcmp (what, "lilycontrol"))
647         what = "score";
648     GString *script = g_string_new (get_script_for_directive (directive, what));
649     gchar *name = choose_palette_by_name (TRUE, FALSE);
650     DenemoObject *curObj = get_object ();
651     if (curObj && curObj->type == CHORD)
652         {
653             chord *thechord = (chord *) curObj->object;
654             if (thechord->chordize)
655                 g_string_append (script, "(d-Chordize #t)\n");
656         }
657 
658     if (name)
659         pal = create_palette (name, FALSE, TRUE);
660     if(pal) {
661         gchar *button_name = g_strdup_printf (_( "Clone %s"), directive->tag->str);
662         gchar *label = string_dialog_entry (Denemo.project, _("Palette Button Creation"), _("Give a (unique) name for the button"), button_name);
663         if (label)
664             {
665                 if (!palette_add_button (pal, label, _("Creates a cloned Denemo Directive"), script->str))
666                     warningdialog (_("Could not create a button of that name in that palette"));
667             } else
668             warningdialog (_("Cancelled"));
669         g_free (label);
670         g_free (button_name);
671         gtk_widget_show_all (gtk_widget_get_parent(pal->box));
672         gtk_widget_destroy (gtk_widget_get_toplevel (button));
673         reset_cursors ();
674     }
675     g_string_free (script, TRUE);
676 }
create_palette_button_for_command(GtkWidget * button,gchar * tooltip)677 static void  create_palette_button_for_command (GtkWidget *button, gchar *tooltip)
678 {
679     DenemoDirective *directive = (DenemoDirective*) g_object_get_data (G_OBJECT(button), "directive");
680     DenemoPalette *pal = NULL;
681     gchar *script = g_strdup_printf ("(d-%s)", directive->tag->str);
682     gchar *name = choose_palette_by_name (TRUE, FALSE);
683     if (name)
684         pal = create_palette (name, FALSE, TRUE);
685     if(pal) {
686         gboolean success = palette_add_button (pal, directive->tag->str, tooltip, script);
687         gtk_widget_show_all (gtk_widget_get_parent(pal->box));
688         gtk_widget_destroy (gtk_widget_get_toplevel (button));
689         reset_cursors ();
690     }
691     g_free (script);
692 }
693 
delete_directive(GtkWidget * button,gpointer fn)694 static void delete_directive (GtkWidget *button, gpointer fn)
695 {
696     DenemoDirective *directive = (DenemoDirective*) g_object_get_data (G_OBJECT(button), "directive");
697     GList **directives = (GList **)g_object_get_data (G_OBJECT(button), "directives");
698     if(directives)
699         *directives = g_list_remove (*directives, directive);
700     else
701         dnm_deleteobject (Denemo.project->movement);
702     gtk_widget_destroy (gtk_widget_get_parent (gtk_widget_get_parent (button)));
703     score_status(Denemo.project, TRUE);
704 }
705 typedef enum DIRECTIVE_TYPE {DIRECTIVE_OBJECT = 0,  DIRECTIVE_SCORE = 1, DIRECTIVE_MOVEMENT = 2, DIRECTIVE_STAFF = 3, DIRECTIVE_VOICE = 4, DIRECTIVE_KEYSIG = 5, DIRECTIVE_TIMESIG = 6} DIRECTIVE_TYPE;
706 
707 static void
call_edit_on_action(GtkWidget * button,DIRECTIVE_TYPE score_edit)708 call_edit_on_action (GtkWidget *button, DIRECTIVE_TYPE score_edit)
709 {
710    gtk_widget_destroy (gtk_widget_get_toplevel (button));
711    DenemoScriptParam param;
712    GtkAction *action = (GtkAction*)g_object_get_data (G_OBJECT (button), "action");
713    GList *currentobject = Denemo.project->movement->currentobject;
714    param.string = g_string_new ("edit");
715    g_debug ("Script can look for params \"edit\" - a string to catch this");
716    activate_script (action, &param);
717    g_string_free (param.string, TRUE);
718 //   gtk_widget_destroy (gtk_widget_get_toplevel (button));
719    if (score_edit)
720     {
721         if (score_edit==DIRECTIVE_SCORE)
722             edit_score_properties ();
723         else
724         if (score_edit==DIRECTIVE_MOVEMENT)
725             edit_movement_properties ();
726         else
727         if (score_edit==DIRECTIVE_VOICE)
728             edit_voice_properties ();
729         else
730             edit_staff_properties ();//also for KEYSIG AND TIMESIG
731 
732     } else
733     {
734        if (!score_edit && (currentobject == Denemo.project->movement->currentobject))
735         edit_object();
736        else
737         reset_cursors ();
738     }
739 }
740 static void
call_score_properties_dialog(GtkWidget * button)741 call_score_properties_dialog (GtkWidget *button)
742 {
743        gtk_widget_hide (gtk_widget_get_toplevel (button));
744        score_properties_dialog (NULL, NULL);
745        show_window (button);//gtk_widget_show (gtk_widget_get_toplevel (button));
746 }
execute_editscript(GtkWidget * button,gchar * filename)747 static void execute_editscript (GtkWidget *button, gchar *filename)
748 {
749  gchar *keep = g_strdup (filename);
750  gtk_widget_destroy (gtk_widget_get_toplevel (button));
751  GError *error = (GError *) execute_script_file (keep);
752  g_free (keep);
753  GList *currentobject = Denemo.project->movement->currentobject;
754 
755  if (error)
756     g_warning ("%s", error->message);
757 
758  if (currentobject == Denemo.project->movement->currentobject)
759     edit_object();
760  else
761     reset_cursors ();
762 }
763 
764 /* linked to type_str[] array!!! */
765 typedef enum {
766   EDIT_CHORD = 0,
767   EDIT_NOTE,
768   EDIT_TUPLET_START,
769   EDIT_TUPLET_END,
770   EDIT_CLEF,
771   EDIT_KEY,
772   EDIT_TIMESIG,
773   EDIT_STEMDIR,
774   EDIT_STANDALONE,
775 
776 } EditObjectType;
777 
778 static gchar *type_str [] =
779 {
780  "chord",
781   "note",
782   "tuplet",
783   "tuplet",
784   "clef",
785   "keysig",
786   "timesig",
787   "stemdirective",
788   "standalone",
789 };
general_edit_popup(GtkWidget * button,EditObjectType type)790 static void general_edit_popup (GtkWidget *button, EditObjectType type)
791 {
792 
793 #ifdef G_OS_WIN32
794 //the popup does not work on windows...
795 #else
796  if (type == EDIT_CHORD)
797             popup_menu ("/NoteEditPopup");
798  else
799 #endif
800  infodialog (_("To add or remove built-in attributes right click on the object in the display window"));
801 
802     gtk_widget_destroy (gtk_widget_get_parent (gtk_widget_get_parent (button)));
803     reset_cursors ();
804 
805 }
display_help(gchar * help)806 static void display_help(gchar *help)
807     {
808        infowarningdialog (help, TRUE);
809     }
810 
811 
seek_directive(GtkWidget * button,gchar * type,gchar * tag)812 static void seek_directive(GtkWidget *button, gchar *type, gchar *tag)
813     {
814         gtk_widget_destroy (gtk_widget_get_toplevel (button));
815         GList *currentobject = Denemo.project->movement->currentobject;
816         gchar *script = type? g_strconcat ("(define-once EditSimilar::last #f)\n(set! EditSimilar::last (cons ",
817                                     type, " \"",
818                                     tag, "\"))\n(d-ResumeEdit)",
819                                     NULL):
820                              g_strdup ("(d-EditSimilar)");
821         call_out_to_guile (script);
822         g_free(script);
823 
824         if (currentobject == Denemo.project->movement->currentobject)
825         edit_object();
826         else
827         reset_cursors ();
828     }
seek_note_directive(GtkWidget * button,gchar * tag)829 static void seek_note_directive(GtkWidget *button, gchar *tag)
830     {
831         seek_directive (button, "'note", tag);
832     }
seek_chord_directive(GtkWidget * button,gchar * tag)833 static void seek_chord_directive(GtkWidget *button, gchar *tag)
834     {
835         seek_directive (button, "'chord", tag);
836     }
seek_keysig_directive(GtkWidget * button,gchar * tag)837 static void seek_keysig_directive(GtkWidget *button, gchar *tag)
838     {
839         seek_directive (button, "'keysigdir", tag);
840     }
seek_timesig_directive(GtkWidget * button,gchar * tag)841 static void seek_timesig_directive(GtkWidget *button, gchar *tag)
842     {
843         seek_directive (button, "'timesigdir", tag);
844     }
seek_stemdirective_directive(GtkWidget * button,gchar * tag)845 static void seek_stemdirective_directive(GtkWidget *button, gchar *tag)
846     {
847         seek_directive (button, "'stemdir", tag);
848     }
seek_clef_directive(GtkWidget * button,gchar * tag)849 static void seek_clef_directive(GtkWidget *button, gchar *tag)
850     {
851         seek_directive (button, "'clefdir", tag);
852     }
seek_standalone_directive(GtkWidget * button,gchar * tag)853 static void seek_standalone_directive (GtkWidget *button, gchar *tag)
854     {
855         seek_directive (button, NULL, tag);
856     }
make_chord_directive_conditional(gchar * tag)857 static void make_chord_directive_conditional (gchar *tag)
858     {gchar *script = g_strdup_printf ("(d-ChooseCondition (cons \"%s\" #f))", tag);
859         call_out_to_guile (script);
860         g_free (script);
861     }
make_note_directive_conditional(gchar * tag)862 static void make_note_directive_conditional (gchar *tag)
863     {gchar *script = g_strdup_printf ("(d-ChooseCondition (cons \"%s\" #t))", tag);
864         call_out_to_guile (script);
865         g_free (script);
866     }
867 
868 
869 
870 
871 
872 #if GTK_MAJOR_VERSION == 2
873 #define GdkRGBA GdkColor
874 #define gtk_widget_override_color gtk_widget_modify_fg
875 #define gtk_widget_override_background_color gtk_widget_modify_bg
876 #define GTK_STATE_FLAG_NORMAL (0)
get_color(GdkColor * color,gdouble r,gdouble g,gdouble b,gdouble a)877 static void get_color (GdkColor *color, gdouble r, gdouble g, gdouble b, gdouble a) {
878     gchar *col = g_strdup_printf ( "#%02x%02x%02x", (gint)(r*254),(gint)(g*254),(gint)(b*254));
879     gdk_color_parse (col, color);
880     g_free(col);
881 }
882 #else
get_color(GdkRGBA * color,gdouble r,gdouble g,gdouble b,gdouble a)883 static void get_color (GdkRGBA *color, gdouble r, gdouble g, gdouble b, gdouble a) {
884             color->red = r; color->green = g;
885             color->blue = b;
886             color->alpha = a;
887             }
888 #endif
889 
890 static void
place_directives(GtkWidget * vbox,GList ** pdirectives,EditObjectType type)891 place_directives (GtkWidget *vbox, GList **pdirectives, EditObjectType type)
892 {
893     GList *directives = *pdirectives;
894     for (; directives;directives = directives->next)
895         {
896             DenemoDirective *directive = directives->data;
897             const gchar *label = get_label_for_command (directive->tag->str);
898             GtkAction *action = lookup_action_from_name (directive->tag->str);
899             gchar *name = label?(gchar*)label:directive->tag->str;
900             const gchar *tooltip = get_tooltip_for_command (directive->tag->str);
901 
902             gchar *filename = get_editscript_filename (directive->tag->str);
903 
904             if (!label)
905                 label = directive->tag->str;
906             GtkWidget *expander = gtk_expander_new (label);
907             gtk_expander_set_expanded (GTK_EXPANDER(expander), TRUE);
908             gtk_widget_set_sensitive (expander, TRUE);
909             gtk_container_set_border_width (GTK_CONTAINER (expander), 0);
910             gtk_box_pack_start (GTK_BOX (vbox), expander, FALSE, TRUE, 0);
911             GtkWidget *inner_box = gtk_vbox_new (FALSE, 0);
912             gtk_container_add (GTK_CONTAINER (expander), inner_box);
913 
914             if (filename)
915                 {
916                 gchar *thelabel = g_strconcat (_("Run the Edit Script for "), name, NULL);
917                 GtkWidget *button = gtk_button_new_with_label (thelabel);
918                 g_signal_connect (button, "clicked", G_CALLBACK (execute_editscript), filename);
919                 g_signal_connect_swapped (button, "destroy", G_CALLBACK (g_free), filename);
920                 gtk_box_pack_start (GTK_BOX (inner_box), button, FALSE, TRUE, 0);
921                 g_free(thelabel);
922                 }
923             else if (action)
924                 {
925                 gchar *thelabel = g_strconcat (_("Execute command: "), name, NULL);
926                 GtkWidget *button = gtk_button_new_with_label (thelabel);
927                 gtk_widget_set_tooltip_text (button, _("Re-run the command to edit the Denemo Directive"));
928                 g_object_set_data (G_OBJECT(button), "action", (gpointer)action);
929                 g_signal_connect (button, "clicked", G_CALLBACK (call_edit_on_action), NULL);
930                 gtk_box_pack_start (GTK_BOX (inner_box), button, FALSE, TRUE, 0);
931                 g_free(thelabel);
932                 }
933 
934 
935             fn_type *func;
936             switch (type) {
937                 case EDIT_NOTE:
938                         func = text_edit_note_directive;
939                         break;
940                 case EDIT_CHORD:
941                         func = text_edit_chord_directive;
942                         break;
943                 case EDIT_CLEF:
944                         func = text_edit_clef_directive;
945                         break;
946                 case EDIT_KEY:
947                         func = text_edit_keysig_directive;
948                         break;
949                 case EDIT_TIMESIG:
950                         func = text_edit_timesig_directive;
951                         break;
952                 case EDIT_STEMDIR:
953                         func = text_edit_stemdirective_directive;
954                         break;
955                 default:
956                         g_critical ("Unknown type");
957                         func = text_edit_standalone_directive;
958                         break;
959 
960             }
961             GtkWidget *hbox = gtk_hbox_new (FALSE, 0);
962             gtk_box_pack_start (GTK_BOX (inner_box), hbox, FALSE, TRUE, 0);
963 
964             //gtk_widget_override_color (inner_box, GTK_STATE_FLAG_NORMAL, &color);
965             GtkWidget *button = gtk_button_new_with_label (_("Delete"));
966             GtkWidget *labelwidget = (GtkWidget *) gtk_bin_get_child (GTK_BIN (button));
967 
968             GdkRGBA color;
969             get_color (&color, 1.0, 0.0, 0.0, 1.0);
970             gtk_widget_override_color (labelwidget, GTK_STATE_FLAG_NORMAL, &color);
971             g_object_set_data (G_OBJECT(button), "directives", (gpointer)pdirectives);
972             g_object_set_data (G_OBJECT(button), "directive", (gpointer)directive);
973             g_signal_connect (button, "clicked", G_CALLBACK (delete_directive), func);
974             gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, TRUE, 30);
975 
976 
977            {
978                fn_type *func;
979                switch (type) {
980                     case EDIT_NOTE:
981                             func = (fn_type *)seek_note_directive;//seek_directive (note, tag);
982                             break;
983                     case EDIT_CHORD:
984                             func = (fn_type *)seek_chord_directive;
985                             break;
986 
987                     case EDIT_CLEF:
988                             func = (fn_type *)seek_clef_directive;
989                             break;
990                     case EDIT_KEY:
991                             func = (fn_type *)seek_keysig_directive;
992                             break;
993                     case EDIT_TIMESIG:
994                             func = (fn_type *)seek_timesig_directive;
995                             break;
996                     case EDIT_STEMDIR:
997                             func = (fn_type *)seek_stemdirective_directive;
998                             break;
999                     default:
1000                             g_critical ("Unknown type");
1001                             func = NULL;
1002                             break;
1003 
1004                 }
1005                 if(func) {
1006                         button = gtk_button_new_with_label (_("Next ➡"));
1007                         get_color (&color, 0.0, 0.7, 0.7, 1.0);
1008                         gtk_widget_override_color (button, GTK_STATE_FLAG_NORMAL, &color);
1009                         g_signal_connect (G_OBJECT(button), "clicked", G_CALLBACK (func), (gpointer)label);
1010                         gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, TRUE, 0);
1011                 }
1012             }
1013             if ((type==EDIT_NOTE) || (type==EDIT_CHORD))
1014                {
1015                         button = gtk_button_new_with_label (_("Conditional"));
1016                         get_color (&color, 0.0, 0., 0.5, 1.0);
1017                         gtk_widget_override_color (button, GTK_STATE_FLAG_NORMAL, &color);
1018                         if (type==EDIT_CHORD)
1019                             g_signal_connect_swapped (G_OBJECT(button), "clicked", G_CALLBACK (make_chord_directive_conditional), (gpointer)directive->tag->str);
1020                         else
1021                             g_signal_connect_swapped (G_OBJECT(button), "clicked", G_CALLBACK (make_note_directive_conditional), (gpointer)directive->tag->str);
1022 
1023 
1024 
1025                         gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, TRUE, 0);
1026                 }
1027 
1028             if (tooltip)
1029                 {
1030                     button = gtk_button_new_with_label (_("Help"));
1031                     get_color (&color, 0.0, 0.7, 0.7, 1.0);//color.red = 0.0; color.green = 0.7,  color.blue = 0.3; color.alpha = 1.0;
1032                     gtk_widget_override_color (button, GTK_STATE_FLAG_NORMAL, &color);
1033                     g_signal_connect_swapped (G_OBJECT(button), "clicked", G_CALLBACK (display_help), (gpointer)tooltip);
1034                     gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, TRUE, 0);
1035                 }
1036             if (tooltip == NULL) tooltip = _("No tooltip");
1037 
1038             if (action) {
1039                 button = gtk_button_new_with_label (_("Create Button for Command"));
1040                 gtk_widget_set_tooltip_text (button, _( "Make a palette button for running the command that created this attribute."));
1041                 g_object_set_data (G_OBJECT(button), "directive", (gpointer)directive);
1042                 g_signal_connect (button, "clicked", G_CALLBACK (create_palette_button_for_command), (gpointer)tooltip);
1043                 gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, TRUE, 0);
1044             }
1045 
1046             button = gtk_button_new_with_label (_("Create Button for Clone"));
1047             gtk_widget_set_tooltip_text (button, _( "Make a palette button for installing this attribute elsewhere."));
1048             g_object_set_data (G_OBJECT(button), "directive", (gpointer)directive);
1049             g_signal_connect (button, "clicked", G_CALLBACK (create_palette_button_for_directive), (gpointer)(type_str[type]));
1050             gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, TRUE, 0);
1051 
1052             button = gtk_button_new_with_label (_("Advanced"));
1053             gtk_widget_set_tooltip_text (button, _( "Examine/Edit this directive at a low-level"));
1054             g_object_set_data (G_OBJECT(button), "directives", (gpointer)pdirectives);
1055             g_object_set_data (G_OBJECT(button), "directive", (gpointer)directive);
1056             g_signal_connect (button, "clicked", G_CALLBACK (advanced_edit_type_directive), func);
1057             gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, TRUE, 0);
1058         }
1059 }
1060 static void
place_chord_attributes(GtkWidget * vbox,chord * thechord)1061 place_chord_attributes (GtkWidget *vbox, chord *thechord)
1062 {
1063     GtkWidget *expander = gtk_expander_new (_("Built-in Chord Attributes"));//gtk_expander_new
1064     gtk_expander_set_expanded (GTK_EXPANDER(expander), TRUE);
1065     gtk_widget_set_sensitive (expander, TRUE);
1066     gtk_container_set_border_width (GTK_CONTAINER (expander),10);
1067     GdkRGBA color;
1068     get_color (&color, 0.1, 0.1, 0.8, 1.0);
1069     gtk_widget_override_color (expander, GTK_STATE_FLAG_NORMAL, &color);
1070     gtk_box_pack_start (GTK_BOX (vbox), expander, FALSE, TRUE, 0);
1071     GtkWidget *inner_box = gtk_vbox_new (FALSE, 0);
1072     gtk_container_add (GTK_CONTAINER (expander), inner_box);
1073     GtkWidget *hbox = gtk_hbox_new (FALSE, 0);
1074     gtk_box_pack_start (GTK_BOX (inner_box), hbox, FALSE, TRUE, 0);
1075     inner_box = gtk_vbox_new (FALSE, 0);
1076     gtk_box_pack_start (GTK_BOX (hbox), inner_box, FALSE, TRUE, 30);
1077     if (thechord->slur_begin_p)
1078           {
1079             GtkWidget *button = gtk_button_new_with_label (_("Remove slur start"));
1080             g_signal_connect (button, "clicked", G_CALLBACK (set_false), &thechord->slur_begin_p);
1081             gtk_box_pack_start (GTK_BOX (inner_box), button, FALSE, TRUE, 0);
1082         }
1083     if (thechord->slur_end_p)
1084             {
1085             GtkWidget *button = gtk_button_new_with_label (_("Remove slur end"));
1086             g_signal_connect (button, "clicked", G_CALLBACK (set_false), &thechord->slur_end_p);
1087             gtk_box_pack_start (GTK_BOX (inner_box), button, FALSE, TRUE, 0);
1088             }
1089     if (thechord->is_tied)
1090             {
1091             GtkWidget *button = gtk_button_new_with_label (_("Remove tie"));
1092             g_signal_connect (button, "clicked", G_CALLBACK (set_false), &thechord->is_tied);
1093             gtk_box_pack_start (GTK_BOX (inner_box), button, FALSE, TRUE, 0);
1094             }
1095     if (thechord->crescendo_begin_p)
1096             {
1097             GtkWidget *button = gtk_button_new_with_label (_("Remove Start cresc. marking"));
1098             g_signal_connect (button, "clicked", G_CALLBACK (set_false), &thechord->crescendo_begin_p);
1099             gtk_box_pack_start (GTK_BOX (inner_box), button, FALSE, TRUE, 0);
1100             }
1101     if (thechord->crescendo_end_p)
1102             {
1103             GtkWidget *button = gtk_button_new_with_label (_("Remove End cresc. marking"));
1104             g_signal_connect (button, "clicked", G_CALLBACK (set_false), &thechord->crescendo_end_p);
1105             gtk_box_pack_start (GTK_BOX (inner_box), button, FALSE, TRUE, 0);
1106             }
1107     if (thechord->diminuendo_begin_p)
1108             {
1109             GtkWidget *button = gtk_button_new_with_label (_("Remove Start dim. marking"));
1110             g_signal_connect (button, "clicked", G_CALLBACK (set_false), &thechord->diminuendo_begin_p);
1111             gtk_box_pack_start (GTK_BOX (inner_box), button, FALSE, TRUE, 0);
1112             }
1113     if (thechord->diminuendo_end_p)
1114             {
1115             GtkWidget *button = gtk_button_new_with_label (_("Remove End dim. marking"));
1116             g_signal_connect (button, "clicked", G_CALLBACK (set_false), &thechord->diminuendo_end_p);
1117             gtk_box_pack_start (GTK_BOX (inner_box), button, FALSE, TRUE, 0);
1118             }
1119 
1120     if (thechord->is_grace)
1121             {
1122             GtkWidget *button = gtk_button_new_with_label (_("Un-grace the note"));
1123             g_signal_connect (button, "clicked", G_CALLBACK (set_false), &thechord->is_grace);
1124             gtk_box_pack_start (GTK_BOX (inner_box), button, FALSE, TRUE, 0);
1125             }
1126     if(!gtk_container_get_children (GTK_CONTAINER (inner_box)))
1127         gtk_widget_destroy (expander);
1128 }
1129 
update_and_close(GtkWidget * editwin)1130 static void update_and_close (GtkWidget *editwin)
1131 {
1132     update_object_info ();
1133     gtk_widget_destroy (editwin);
1134     reset_cursors ();
1135 }
1136 
run_script(GtkWidget * button,gchar * script)1137 static void run_script (GtkWidget *button, gchar *script)
1138 {
1139     call_out_to_guile (script);
1140     gtk_widget_destroy (gtk_widget_get_parent (gtk_widget_get_parent (button)));
1141     reset_cursors ();
1142 }
1143 
delete_standalone(GtkWidget * button)1144 static void delete_standalone (GtkWidget *button)
1145 {
1146     dnm_deleteobject (Denemo.project->movement);
1147     gtk_widget_destroy (gtk_widget_get_toplevel (button));
1148     score_status(Denemo.project, TRUE);
1149     reset_cursors ();
1150 }
1151 // edit the specific object at the cursor
1152 void
edit_object(void)1153 edit_object (void)
1154 {
1155     DenemoMovement *si = Denemo.project->movement;
1156     DenemoObject *curObj = get_object ();
1157     if (curObj == NULL)
1158     {
1159       warningmessage (_("No object here to edit"));
1160       return;
1161     }
1162     GtkWidget *editwin = gtk_window_new (GTK_WINDOW_TOPLEVEL);
1163     GdkRGBA color;
1164     get_color (&color, 1.0, 1.0, 1.0, 1.0);//.red = color.green = color.blue = color.alpha = 1.0;
1165     gtk_widget_override_background_color (editwin, GTK_STATE_FLAG_NORMAL, &color);
1166     gtk_window_set_modal (GTK_WINDOW (editwin), TRUE);
1167     gtk_window_set_title (GTK_WINDOW (editwin), _("Denemo Object Editor"));
1168     gtk_window_set_transient_for (GTK_WINDOW(editwin), GTK_WINDOW(Denemo.window));
1169     gtk_window_set_keep_above (GTK_WINDOW (editwin), TRUE);
1170     GtkWidget *vbox = gtk_vbox_new (FALSE, 0);
1171     gtk_container_add (GTK_CONTAINER (editwin), vbox);
1172     GtkWidget *close_button = gtk_button_new_with_label (_("Close"));
1173     g_signal_connect_swapped (close_button, "clicked", G_CALLBACK (update_and_close), editwin);
1174 
1175     g_signal_connect (G_OBJECT (editwin), "destroy", G_CALLBACK (reset_cursors), NULL);
1176     gtk_box_pack_start (GTK_BOX (vbox), close_button, FALSE, TRUE, 0);
1177     GtkWidget *hbox = gtk_hbox_new (FALSE, 0);
1178     gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);
1179 
1180     GtkWidget *button = gtk_button_new_with_label (_("⬅ Previous Object"));
1181     g_signal_connect_swapped (button, "clicked", G_CALLBACK (go_left), editwin);
1182     gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, TRUE, 0);
1183 
1184     if ((!si->currentobject->prev)&&(!si->currentmeasure->prev))
1185         gtk_widget_set_sensitive (button, FALSE);
1186 
1187     GtkWidget *note_up_button = gtk_button_new_with_label (_("Next note in chord"));
1188     g_signal_connect_swapped (note_up_button, "clicked", G_CALLBACK (move_to_next_note), editwin);
1189     gtk_box_pack_start (GTK_BOX (hbox), note_up_button, FALSE, TRUE, 0);
1190 
1191     button = gtk_button_new_with_label (_("Next Object ➡"));
1192     g_signal_connect_swapped (button, "clicked", G_CALLBACK (go_right), editwin);
1193     gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, TRUE, 0);
1194 
1195     if ((!si->currentobject->next) && (!si->currentmeasure->next))
1196         gtk_widget_set_sensitive (button, FALSE);
1197 
1198     switch (curObj->type)
1199     {
1200         case CHORD:
1201           {
1202             chord *thechord = ((chord *) curObj->object);
1203             if (thechord->directives)
1204                 {
1205                 GtkWidget *frame = gtk_frame_new (thechord->notes? _("Attached to the chord:"):
1206                                                                    _("Attached to the rest:"));
1207                 gtk_frame_set_shadow_type ((GtkFrame *) frame, GTK_SHADOW_IN);
1208                 GdkRGBA color;
1209                 get_color (&color, 0.8, 0.1, 0.1, 1.0);//color.red = 0.8;color.green = color.blue = 0.1; color.alpha = 1;
1210                 gtk_widget_override_color (frame, GTK_STATE_FLAG_NORMAL, &color);
1211                 gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, TRUE, 0);
1212                 GtkWidget *inner_box = gtk_vbox_new (FALSE, 0);
1213                 get_color (&color, 0.1, 0.8, 0.1, 1.0);
1214                 gtk_widget_override_color (inner_box, GTK_STATE_FLAG_NORMAL, &color);
1215                 gtk_container_add (GTK_CONTAINER (frame), inner_box);
1216                 place_directives (inner_box, &thechord->directives, EDIT_CHORD);
1217                 }
1218 
1219             if (thechord->notes)
1220               {
1221                 place_chord_attributes (vbox, thechord);
1222                 note *thenote = findnote (curObj, Denemo.project->movement->cursor_y);
1223                 if (!thechord->notes->next)
1224                     gtk_button_set_label (GTK_BUTTON (note_up_button), _("Edit the note"));
1225                 if ( (!thenote) || thechord->notes->next || (Denemo.project->movement->cursor_y!=thenote->mid_c_offset))
1226                     {
1227                         note_up_button = NULL; // a tricksy bit of code this: the button is already packed in the vbox, by setting this NULL we stop it being set insensitive as it must be for all other cases.
1228                     }
1229                 if (thenote && Denemo.project->movement->cursor_y==thenote->mid_c_offset)
1230                   {
1231                     GString *text = g_string_new ("");
1232 
1233                     if (thenote->directives)
1234                       {
1235                         g_string_append_printf (text, _("Attached to Note %s"),
1236                                             pretty_name (mid_c_offsettolily (thenote->mid_c_offset, thenote->enshift)));
1237                         GtkWidget *frame = gtk_frame_new (text->str);
1238                         gtk_container_set_border_width (GTK_CONTAINER (frame), 20);
1239                         gtk_frame_set_shadow_type ((GtkFrame *) frame, GTK_SHADOW_IN);
1240                         GdkRGBA color;
1241                         get_color (&color, 0.2, 0.7, 0.2, 1.0);/// color.green = 0.7; color.red = color.blue = 0.2; color.alpha = 1;
1242                         gtk_widget_override_color (frame, GTK_STATE_FLAG_NORMAL, &color);
1243                         gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, TRUE, 0);
1244                         GtkWidget *inner_box = gtk_vbox_new (FALSE, 0);
1245                         get_color (&color, 0.1, 0.8, 0.1, 1.0);
1246                         gtk_widget_override_color (inner_box, GTK_STATE_FLAG_NORMAL, &color);
1247 
1248                         gtk_container_add (GTK_CONTAINER (frame), inner_box);
1249                         place_directives (inner_box, &thenote->directives, EDIT_NOTE);
1250                       }
1251                     else
1252                       {
1253                         g_string_append_printf (text, _("Nothing attached to Note %s"),
1254                                             pretty_name (mid_c_offsettolily (thenote->mid_c_offset, thenote->enshift)));
1255                         GtkWidget *frame = gtk_frame_new (text->str);
1256                         gtk_container_set_border_width (GTK_CONTAINER (frame), 20);
1257                         gtk_frame_set_shadow_type ((GtkFrame *) frame, GTK_SHADOW_IN);
1258                         GdkRGBA color;
1259                         get_color (&color, 0.8, 0.1, 0.1, 1.0);//color.red = 0.8;color.green = color.blue = 0.1; color.alpha = 1;
1260                         gtk_widget_override_color (frame, GTK_STATE_FLAG_NORMAL, &color);
1261                         gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, TRUE, 0);
1262                       }
1263 
1264                       g_string_free (text, TRUE);
1265 
1266                   }
1267                 if ((thechord->notes) && curObj->isinvisible)
1268                     {
1269                         GtkWidget *button = gtk_button_new_with_label (_("Assign Pitch to Rhythm"));
1270                         g_signal_connect (button, "clicked", G_CALLBACK (set_false), &curObj->isinvisible);
1271                         gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, TRUE, 0);
1272                     }
1273             }
1274             else
1275               {
1276                 //type = _("rest");
1277                 place_chord_attributes (vbox, thechord);
1278 
1279               }
1280               if (thechord->fakechord)
1281                 {
1282                     GtkWidget *button = gtk_button_new_with_label (_("Edit Chord Symbol"));
1283                     g_signal_connect (button, "clicked", G_CALLBACK (run_script), "(d-EditChords)");
1284                     gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, TRUE, 0);
1285                 }
1286 
1287             if (thechord->figure)
1288                 {
1289                     GtkWidget *button = gtk_button_new_with_label (_("Edit Bass Figure"));
1290                     g_signal_connect (button, "clicked", G_CALLBACK (run_script), "(d-EditFiguredBass)");
1291                     gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, TRUE, 0);
1292                 }
1293 
1294             {
1295             GtkWidget *separator =
1296 #if GTK_MAJOR_VERSION == 2
1297             gtk_hseparator_new ();
1298 #else
1299             gtk_separator_new (GTK_ORIENTATION_HORIZONTAL);
1300 #endif
1301             gtk_box_pack_start (GTK_BOX (vbox), separator, FALSE, TRUE, 0);
1302 
1303             GtkWidget *button = gtk_button_new_with_label (_("Add/Remove attributes"));
1304             g_signal_connect (button, "clicked", G_CALLBACK (general_edit_popup), EDIT_CHORD);
1305             gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, TRUE, 0);
1306             }
1307 
1308         }
1309         break;
1310         case TUPOPEN:
1311           { tuplet *thetup = ((tuplet *) curObj->object);
1312             //type = _("start tuplet marker");
1313             GtkWidget *button = gtk_button_new_with_label (_("Alter Tuplet Type"));
1314             g_signal_connect_swapped (button, "clicked", G_CALLBACK (call_out_to_guile), "(d-StartTuplet)");
1315             gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, TRUE, 0);
1316             if (thetup->directives)
1317                 {
1318                 GtkWidget *frame = gtk_frame_new (_("Attached to the tuplet start:"));
1319                 GdkRGBA color;
1320                 get_color (&color, 0.8, 0.1, 0.1, 1.0);
1321                 gtk_widget_override_color (frame, GTK_STATE_FLAG_NORMAL, &color);
1322                 gtk_frame_set_shadow_type ((GtkFrame *) frame, GTK_SHADOW_IN);
1323                 gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, TRUE, 0);
1324                 GtkWidget *inner_box = gtk_vbox_new (FALSE, 8);
1325                 gtk_container_add (GTK_CONTAINER (frame), inner_box);
1326                 place_directives (inner_box, &thetup->directives, EDIT_TUPLET_START);
1327                 }
1328           }
1329           break;
1330         case TUPCLOSE:
1331             { tuplet *thetup = ((tuplet *) curObj->object);
1332             //type = _("start tuplet marker");
1333             if (thetup->directives)
1334                 {
1335                 GtkWidget *frame = gtk_frame_new (_("Attached to the tuplet end:"));
1336                 GdkRGBA color;
1337                 get_color (&color, 0.8, 0.1, 0.1, 1.0);
1338                 gtk_widget_override_color (frame, GTK_STATE_FLAG_NORMAL, &color);
1339                 gtk_frame_set_shadow_type ((GtkFrame *) frame, GTK_SHADOW_IN);
1340                 gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, TRUE, 0);
1341                 GtkWidget *inner_box = gtk_vbox_new (FALSE, 8);
1342                 gtk_container_add (GTK_CONTAINER (frame), inner_box);
1343                 place_directives (inner_box, &thetup->directives, EDIT_TUPLET_END);
1344                 }
1345           }
1346           break;
1347 
1348         case CLEF:
1349           {
1350             clef *theclef = ((clef *) curObj->object);
1351             //type = _("clef change object");
1352 
1353             if (theclef->directives)
1354                 {
1355                 GtkWidget *frame = gtk_frame_new (_("Attached to the clef change object:"));
1356                 GdkRGBA color;
1357                 get_color (&color, 0.8, 0.1, 0.1, 1.0);
1358                 gtk_widget_override_color (frame, GTK_STATE_FLAG_NORMAL, &color);
1359                 gtk_frame_set_shadow_type ((GtkFrame *) frame, GTK_SHADOW_IN);
1360                 gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, TRUE, 0);
1361                 GtkWidget *inner_box = gtk_vbox_new (FALSE, 8);
1362                 gtk_container_add (GTK_CONTAINER (frame), inner_box);
1363                 place_directives (inner_box, &theclef->directives, EDIT_CLEF);
1364                 }
1365             if (curObj->isinvisible)
1366                 {
1367                 GtkWidget *button = gtk_button_new_with_label (_("Transform to printing clef"));
1368                 g_signal_connect (button, "clicked", G_CALLBACK (set_false), &curObj->isinvisible);
1369                 gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, TRUE, 0);
1370                 }
1371           }
1372           break;
1373 
1374         case TIMESIG:
1375           {
1376             timesig *thetime = ((timesig *) curObj->object);
1377             //type = _("time signature change object");
1378             if (thetime->directives)
1379                 {
1380                 GtkWidget *frame = gtk_frame_new (_("Attached to the time signature change object:"));
1381                 GdkRGBA color;
1382                 get_color (&color, 0.8, 0.1, 0.1, 1.0);
1383                 gtk_widget_override_color (frame, GTK_STATE_FLAG_NORMAL, &color);
1384                 gtk_frame_set_shadow_type ((GtkFrame *) frame, GTK_SHADOW_IN);
1385                 gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, TRUE, 0);
1386                 GtkWidget *inner_box = gtk_vbox_new (FALSE, 8);
1387                 gtk_container_add (GTK_CONTAINER (frame), inner_box);
1388                 place_directives (inner_box, &thetime->directives, EDIT_TIMESIG);
1389                 }
1390            }
1391           break;
1392 
1393         case KEYSIG:
1394           {
1395             keysig *thekey = ((keysig *) curObj->object);
1396             //type = _("key signature change object");
1397             if (thekey->directives)
1398                 {
1399                 GtkWidget *frame = gtk_frame_new (_("Attached to the key signature change object:"));
1400                                 GdkRGBA color;
1401                 get_color (&color, 0.8, 0.1, 0.1, 1.0);
1402                 gtk_widget_override_color (frame, GTK_STATE_FLAG_NORMAL, &color);
1403                 gtk_frame_set_shadow_type ((GtkFrame *) frame, GTK_SHADOW_IN);
1404                 gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, TRUE, 0);
1405                 GtkWidget *inner_box = gtk_vbox_new (FALSE, 8);
1406                 gtk_container_add (GTK_CONTAINER (frame), inner_box);
1407                 place_directives (inner_box, &thekey->directives, EDIT_KEY);
1408                 }
1409             }
1410           break;
1411 
1412 
1413         case STEMDIRECTIVE:
1414           {
1415             stemdirective *thestem = ((stemdirective *) curObj->object);
1416             //type = _("stem direction change object");
1417             if (thestem->directives)
1418                              {
1419                 GtkWidget *frame = gtk_frame_new (_("Attached to the stemming change object:"));
1420                                 GdkRGBA color;
1421                 get_color (&color, 0.8, 0.1, 0.1, 1.0);
1422                 gtk_widget_override_color (frame, GTK_STATE_FLAG_NORMAL, &color);
1423                 gtk_frame_set_shadow_type ((GtkFrame *) frame, GTK_SHADOW_IN);
1424                 gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, TRUE, 0);
1425                 GtkWidget *inner_box = gtk_vbox_new (FALSE, 8);
1426                 gtk_container_add (GTK_CONTAINER (frame), inner_box);
1427                 place_directives (inner_box, &thestem->directives, EDIT_STEMDIR);
1428                 }
1429 
1430           }
1431           break;
1432 
1433         case LILYDIRECTIVE:
1434             {
1435             DenemoDirective *directive = (DenemoDirective *) curObj->object;
1436             const gchar *label = get_label_for_command (directive->tag->str);
1437             GtkAction *action = lookup_action_from_name (directive->tag->str);
1438             gchar *name = label?(gchar*)label:directive->tag->str;
1439             const gchar *tooltip = get_tooltip_for_command (directive->tag->str);
1440             gchar *filename = get_editscript_filename (directive->tag->str);
1441             GtkWidget *frame = gtk_frame_new ( _("Standalone Denemo Directive:"));
1442             gtk_frame_set_shadow_type ((GtkFrame *) frame, GTK_SHADOW_IN);
1443             GdkRGBA color;
1444             get_color (&color, 0.5, 0.5, 0.1, 1.0);// .red = 0.5;
1445             //color.green = 0.5; color.blue = 0.1; color.alpha = 1;
1446             gtk_widget_override_color (frame, GTK_STATE_FLAG_NORMAL, &color);
1447             gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, TRUE, 0);
1448             GtkWidget *inner_box = gtk_vbox_new (FALSE, 0);
1449             get_color (&color, 0.8, 0.1, 0.1, 1.0);
1450             gtk_widget_override_color (inner_box, GTK_STATE_FLAG_NORMAL, &color);
1451             gtk_container_add (GTK_CONTAINER (frame), inner_box);
1452 
1453              if (filename)
1454                 {
1455                 gchar *thelabel = g_strconcat ( _("Run the Edit Script for "), name, NULL);
1456                 GtkWidget *button = gtk_button_new_with_label (thelabel);
1457                 g_signal_connect (button, "clicked", G_CALLBACK (execute_editscript), filename);
1458                 g_signal_connect_swapped (button, "destroy", G_CALLBACK (g_free), filename);
1459                 gtk_box_pack_start (GTK_BOX (inner_box), button, FALSE, TRUE, 0);
1460                 g_free(thelabel);
1461                 }
1462             else if (action)
1463                 {
1464                 gchar *thelabel = g_strconcat ( _("Execute command: "), name, NULL);
1465                 GtkWidget *button = gtk_button_new_with_label (thelabel);
1466                 gtk_widget_set_tooltip_text (button, _("Re-run the command to edit the Denemo Directive"));
1467 
1468                 g_object_set_data (G_OBJECT(button), "action", (gpointer)action);
1469                 g_signal_connect (button, "clicked", G_CALLBACK (call_edit_on_action), NULL);
1470                 gtk_box_pack_start (GTK_BOX (inner_box), button, FALSE, TRUE, 0);
1471                 g_free(thelabel);
1472                 }
1473             {
1474                 GtkWidget *hbox = gtk_hbox_new (FALSE, 0);
1475                 gtk_box_pack_start (GTK_BOX (inner_box), hbox, FALSE, TRUE, 0);
1476 
1477 
1478                 button = gtk_button_new_with_label (_("Delete"));
1479                 GtkWidget *labelwidget = (GtkWidget *) gtk_bin_get_child (GTK_BIN (button));
1480                 get_color (&color, 1.0, 0.0, 0.0, 1.0);
1481                 //color.red = 1.0; color.green = color.blue = 0.0; color.alpha = 1.0;
1482                 gtk_widget_override_color (labelwidget, GTK_STATE_FLAG_NORMAL, &color);
1483                 g_object_set_data (G_OBJECT(button), "directive", (gpointer)directive);
1484                 g_signal_connect (button, "clicked", G_CALLBACK (delete_standalone), NULL);
1485                 gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, TRUE, 30);
1486 
1487                 button = gtk_button_new_with_label (_("Next ➡"));
1488                 get_color (&color, 0.0, 0.7, 0.7, 1.0);
1489                 gtk_widget_override_color (button, GTK_STATE_FLAG_NORMAL, &color);
1490                 g_signal_connect (G_OBJECT(button), "clicked", G_CALLBACK (seek_standalone_directive), (gpointer)label);
1491                 gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, TRUE, 0);
1492 
1493                 {
1494                         button = gtk_button_new_with_label (_("Conditional"));
1495                         get_color (&color, 0.0, 0., 0.5, 1.0);
1496                         gtk_widget_override_color (button, GTK_STATE_FLAG_NORMAL, &color);
1497 
1498                         g_signal_connect_swapped (G_OBJECT(button), "clicked", G_CALLBACK (call_out_to_guile), (gpointer)"(d-ChooseCondition #f)");
1499 
1500                         gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, TRUE, 0);
1501                 }
1502 
1503                 if (tooltip)
1504                     {
1505                         button = gtk_button_new_with_label (_("Help"));
1506                         get_color (&color, 0.0, 0.7, 0.3, 1.0);//color.red = 0.0; color.green = 0.7,  color.blue = 0.3; color.alpha = 1.0;
1507                         gtk_widget_override_color (button, GTK_STATE_FLAG_NORMAL, &color);
1508                         g_signal_connect_swapped (G_OBJECT(button), "clicked", G_CALLBACK (display_help), (gpointer)tooltip);
1509                         gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, TRUE, 0);
1510                     }
1511                 if (tooltip == NULL) tooltip = _("No tooltip");
1512 
1513                 if (action) {
1514                             button = gtk_button_new_with_label (_("Create Button for Command"));
1515                             gtk_widget_set_tooltip_text (button, _( "Make a palette button for running the command that created/inserted this object."));
1516                             g_object_set_data (G_OBJECT(button), "directive", (gpointer)directive);
1517                             g_signal_connect (G_OBJECT(button), "clicked", G_CALLBACK (create_palette_button_for_command), (gpointer)tooltip);
1518                             gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, TRUE, 0);
1519                             }
1520                 button = gtk_button_new_with_label (_("Create Button for Clone"));
1521                 gtk_widget_set_tooltip_text (button, _( "Make a palette button for inserting a clone of this object elsewhere."));
1522                 g_object_set_data (G_OBJECT(button), "directive", (gpointer)directive);
1523                 g_signal_connect (button, "clicked", G_CALLBACK (create_palette_button_for_directive), "standalone");
1524                 gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, TRUE, 0);
1525 
1526                 button = gtk_button_new_with_label (_("Advanced"));
1527                 g_object_set_data (G_OBJECT(button), "directives", NULL);
1528                 g_object_set_data (G_OBJECT(button), "directive", (gpointer)directive);
1529                 g_signal_connect (button, "clicked", G_CALLBACK (advanced_edit_type_directive), text_edit_standalone_directive);
1530                 gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, TRUE, 0);
1531             }
1532             }
1533             break;
1534 
1535         default:
1536             g_critical ("Type not done");
1537             break;
1538     }
1539   if(g_list_length ( gtk_container_get_children (GTK_CONTAINER(vbox))) == 1)
1540     {//just the close button
1541         warningdialog ("Nothing editable on this object\nYou can add attributes to the object at the cursor by right-clicking on it.");
1542         gtk_widget_destroy (editwin);
1543     }
1544     else
1545     {
1546       if (note_up_button)
1547             gtk_widget_set_sensitive (note_up_button, FALSE);
1548       gtk_widget_show_all (editwin);
1549       gtk_window_present (GTK_WINDOW (editwin));
1550       gdk_window_set_cursor (gtk_widget_get_window (editwin), gdk_cursor_new (GDK_RIGHT_PTR));
1551       gdk_window_set_cursor (gtk_widget_get_window (Denemo.window), gdk_cursor_new (GDK_X_CURSOR));
1552       if(ObjectInfo)
1553         gdk_window_set_cursor (gtk_widget_get_window (ObjectInfo), gdk_cursor_new (GDK_X_CURSOR));
1554      if(Denemo.printarea && gtk_widget_get_window (Denemo.printarea))
1555         gdk_window_set_cursor (gtk_widget_get_window (Denemo.printarea), gdk_cursor_new (GDK_X_CURSOR));
1556 #ifdef G_OS_WIN32
1557         if(ObjectInfo)
1558             gtk_widget_hide (ObjectInfo);//windows doesn't handle order properly, so this can hide the object editor
1559 #endif
1560     }
1561 }
1562 
1563 
1564 
1565 
1566 
1567 
score_update_and_close(GtkWidget * editwin)1568 static void score_update_and_close (GtkWidget *editwin)
1569 {
1570     gtk_widget_destroy (editwin);
1571     reset_cursors ();
1572 }
go_previous(GtkWidget * editwin)1573 static void go_previous(GtkWidget *editwin)
1574 {
1575 prev_movement (NULL, NULL);//FIXME pass in a DenemoParam * to get status
1576 if (editwin)
1577    {
1578     gtk_widget_destroy (editwin);
1579     reset_cursors ();
1580     edit_movement_properties();
1581     }
1582 }
go_next(GtkWidget * editwin)1583 static void go_next(GtkWidget *editwin)
1584 {
1585 next_movement (NULL, NULL);//FIXME pass in a DenemoParam * to get status
1586 if (editwin)
1587    {
1588     gtk_widget_destroy (editwin);
1589     reset_cursors ();
1590     edit_movement_properties();
1591     }
1592 }
1593 typedef gboolean fn2_type (DenemoDirective*);
low_level_edit_type_directive(GtkWidget * button,gpointer fn)1594 static void low_level_edit_type_directive (GtkWidget *button, gpointer fn)
1595 {
1596     gtk_widget_hide (gtk_widget_get_toplevel (button));
1597     DenemoDirective *directive = (DenemoDirective*) g_object_get_data (G_OBJECT(button), "directive");
1598     GList **directives = (GList **)g_object_get_data (G_OBJECT(button), "directives");
1599     if (!( ((fn2_type *)fn) (directive)))
1600         {
1601             if(directives)
1602                 *directives = g_list_remove (*directives, directive);
1603             gtk_widget_destroy (gtk_widget_get_parent (gtk_widget_get_parent (button)));
1604             score_status(Denemo.project, TRUE);
1605         }
1606     else
1607         show_window (button);//gtk_widget_show (gtk_widget_get_toplevel (button));
1608 
1609 }
delete_score_directive(GtkWidget * button)1610 static void delete_score_directive (GtkWidget *button)
1611 {
1612     DenemoDirective *directive = (DenemoDirective*) g_object_get_data (G_OBJECT(button), "directive");
1613     GList **directives = (GList **)g_object_get_data (G_OBJECT(button), "directives");
1614     *directives = g_list_remove (*directives, directive);
1615     gtk_widget_destroy (gtk_widget_get_parent (gtk_widget_get_parent (button)));
1616     score_status(Denemo.project, TRUE);
1617 }
1618 
place_buttons_for_directives(GList ** pdirectives,GtkWidget * vbox,DIRECTIVE_TYPE score_or_movement,gchar * field)1619 static void place_buttons_for_directives (GList **pdirectives, GtkWidget *vbox, DIRECTIVE_TYPE score_or_movement, gchar *field)
1620 {
1621     GList *g;
1622     gchar *type = "";
1623     if(!strcmp (field, "lilycontrol"))
1624         type = _( "Score ");
1625     else  if(!strcmp (field, "movementcontrol"))
1626         type = _( "Movement ");
1627     else  if(!strcmp (field, "scoreheader"))
1628         type = _( "Score Header ");
1629     else  if(!strcmp (field, "paper"))
1630         type = _( "Paper ");
1631     else  if(!strcmp (field, "header"))
1632         type = _( "Movement Header ");
1633     else  if(!strcmp (field, "layout"))
1634         type = _( "Movement Layout ");
1635     for (g = *pdirectives; g; g = g->next)
1636       {
1637             DenemoDirective *directive = g->data;
1638             const gchar *label = get_label_for_command (directive->tag->str);
1639             GtkAction *action = lookup_action_from_name (directive->tag->str);
1640             gchar *name = label?(gchar*)label:directive->tag->str;
1641             const gchar *tooltip = get_tooltip_for_command (directive->tag->str);
1642             gchar *filename = get_editscript_filename (directive->tag->str);
1643              GtkWidget *frame;
1644              gchar *text;
1645             if (label == NULL)
1646                 text = g_strdup_printf( _("Denemo %s Directive tagged: %s"), type, name);
1647             else
1648                 text = g_strdup_printf (_("Denemo %s Directive: %s"), type, label);
1649             frame = gtk_frame_new (text);
1650             g_free(text);
1651             //gtk_frame_set_shadow_type ((GtkFrame *) frame, GTK_SHADOW_IN);
1652             GdkRGBA color;
1653             get_color (&color, 0.5, 0.5, 0.1, 1.0); //color.red = 0.5;
1654             //color.green = 0.5; color.blue = 0.1; color.alpha = 1;
1655             gtk_widget_override_color (frame, GTK_STATE_FLAG_NORMAL, &color);
1656             gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, TRUE, 0);
1657             GtkWidget *inner_box = gtk_vbox_new (FALSE, 0);
1658             get_color (&color, 0.8, 0.8, 0.1, 1.0);
1659             gtk_widget_override_color (inner_box, GTK_STATE_FLAG_NORMAL, &color);
1660             gtk_container_add (GTK_CONTAINER (frame), inner_box);
1661             GtkWidget *button;
1662              if (filename)
1663                 {
1664                 gchar *thelabel = g_strconcat ( _("Run the Edit Script for "), name, NULL);
1665                 button = gtk_button_new_with_label (thelabel);
1666                 g_signal_connect (button, "clicked", G_CALLBACK (execute_editscript), filename);
1667                 g_signal_connect_swapped (button, "destroy", G_CALLBACK (g_free), filename);
1668                 gtk_box_pack_start (GTK_BOX (inner_box), button, FALSE, TRUE, 0);
1669                 g_free(thelabel);
1670                 }
1671             else if (action)
1672                 {
1673                 gchar *thelabel = g_strconcat ( _("Execute command: "), name, NULL);
1674                 button = gtk_button_new_with_label (thelabel);
1675                 gtk_widget_set_tooltip_text (button, _("Re-run the command to edit the Denemo Directive"));
1676 
1677                 g_object_set_data (G_OBJECT(button), "action", (gpointer)action);
1678                 g_signal_connect (button, "clicked", G_CALLBACK (call_edit_on_action), GINT_TO_POINTER(score_or_movement));
1679                 gtk_box_pack_start (GTK_BOX (inner_box), button, FALSE, TRUE, 0);
1680                 g_free(thelabel);
1681                 }
1682             if (tooltip)
1683                     gtk_widget_set_tooltip_text (button, tooltip);
1684 
1685             GtkWidget *hbox = gtk_hbox_new (FALSE, 0);
1686             gtk_box_pack_start (GTK_BOX (inner_box), hbox, FALSE, TRUE, 0);
1687 
1688             button = gtk_button_new_with_label (_("Delete"));
1689             GtkWidget *labelwidget = (GtkWidget *) gtk_bin_get_child (GTK_BIN (button));
1690             get_color (&color, 1.0, 0.0, 0.0, 1.0);
1691             //color.red = 1.0; color.green = color.blue = 0.0; color.alpha = 1.0;
1692             gtk_widget_override_color (labelwidget, GTK_STATE_FLAG_NORMAL, &color);
1693             g_object_set_data (G_OBJECT(button), "directives", (gpointer)pdirectives);
1694             g_object_set_data (G_OBJECT(button), "directive", (gpointer)directive);
1695             g_signal_connect (button, "clicked", G_CALLBACK (delete_score_directive), NULL);
1696             gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, TRUE, 30);
1697 
1698              if (tooltip)
1699             {
1700                 button = gtk_button_new_with_label (_("Help"));
1701                 get_color (&color, 0.0, 0.7, 0.3, 1.0);
1702                 gtk_widget_override_color (button, GTK_STATE_FLAG_NORMAL, &color);
1703                 g_signal_connect_swapped (G_OBJECT(button), "clicked", G_CALLBACK (display_help), (gpointer)tooltip);
1704                 gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, TRUE, 0);
1705             }
1706             if (tooltip == NULL) tooltip = _("No tooltip");
1707 
1708             if (action) {
1709                 button = gtk_button_new_with_label (_("Create Button for Command"));
1710             gtk_widget_set_tooltip_text (button, _( "Make a palette button for running the command that created this attribute."));
1711             g_object_set_data (G_OBJECT(button), "directive", (gpointer)directive);
1712             g_signal_connect (G_OBJECT(button), "clicked", G_CALLBACK (create_palette_button_for_command), (gpointer)tooltip);
1713             gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, TRUE, 0);
1714             }
1715             button = gtk_button_new_with_label (_("Create Button for Clone"));
1716             gtk_widget_set_tooltip_text (button, _( "Make a palette button for installing a clone of this attribute elsewhere."));
1717             g_object_set_data (G_OBJECT(button), "directive", (gpointer)directive);
1718             g_signal_connect (button, "clicked", G_CALLBACK (create_palette_button_for_directive), (gpointer)(field));
1719             gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, TRUE, 0);
1720 
1721 
1722             button = gtk_button_new_with_label (_("Advanced"));
1723             g_object_set_data (G_OBJECT(button), "directives", pdirectives);
1724             g_object_set_data (G_OBJECT(button), "directive", (gpointer)directive);
1725             g_signal_connect (G_OBJECT(button), "clicked", G_CALLBACK (low_level_edit_type_directive), low_level_directive_edit);
1726             gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, TRUE, 0);
1727 
1728 
1729 
1730 
1731 
1732     }
1733 }
1734 
1735 
1736 static void
edit_score_and_movement_properties(gboolean show_score)1737 edit_score_and_movement_properties (gboolean show_score)
1738 {
1739     GtkWidget *editscorewin = gtk_window_new (GTK_WINDOW_TOPLEVEL);
1740     GdkRGBA color;
1741     gint window_height = 800;
1742     //color.red = color.green = color.blue = color.alpha = 1.0;
1743     get_color (&color, 1.0, 1.0, 1.0, 1.0);
1744     gtk_widget_override_background_color (editscorewin, GTK_STATE_FLAG_NORMAL, &color);
1745     gtk_window_set_modal (GTK_WINDOW (editscorewin), TRUE);
1746     gtk_window_set_title (GTK_WINDOW (editscorewin), _("Score and Movement Properties Editor"));
1747     gtk_window_set_transient_for (GTK_WINDOW(editscorewin), GTK_WINDOW(Denemo.window));
1748     gtk_window_set_keep_above (GTK_WINDOW (editscorewin), TRUE);
1749     gtk_window_set_default_size (GTK_WINDOW (editscorewin), 600, window_height);
1750 
1751 
1752     GtkWidget *vbox = gtk_vbox_new (FALSE, 0);
1753     gtk_container_add (GTK_CONTAINER (editscorewin), vbox);
1754     GtkWidget *close_button = gtk_button_new_with_label (_("Close"));
1755     g_signal_connect_swapped (close_button, "clicked", G_CALLBACK (score_update_and_close), editscorewin);
1756 
1757     g_signal_connect (G_OBJECT (editscorewin), "destroy", G_CALLBACK (reset_cursors), NULL);
1758     gtk_box_pack_start (GTK_BOX (vbox), close_button, FALSE, TRUE, 0);
1759 
1760     GtkWidget *button;
1761     GtkWidget *pane;
1762 #if GTK_MAJOR_VERSION == 2
1763     pane = gtk_vpaned_new ();
1764 #else
1765     pane = gtk_paned_new (GTK_ORIENTATION_VERTICAL);
1766 #endif
1767     gtk_box_pack_start (GTK_BOX (vbox), pane, TRUE, TRUE, 0);
1768     GtkWidget *expander = gtk_expander_new (_("Score Properties"));
1769     gtk_expander_set_expanded (GTK_EXPANDER(expander), show_score);
1770     gtk_widget_set_sensitive (expander, TRUE);
1771     gtk_container_set_border_width (GTK_CONTAINER (expander),10);
1772     get_color (&color, 0.1, 0.8, 0.1, 1.0);
1773 
1774     gtk_widget_override_color (expander, GTK_STATE_FLAG_NORMAL, &color);
1775    // gtk_box_pack_start (GTK_BOX (vbox), expander, TRUE, TRUE, 0);
1776 
1777    GtkWidget *frame = gtk_frame_new (NULL);
1778    //gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
1779 
1780 
1781 
1782     gtk_paned_add1 (GTK_PANED(pane), frame);
1783 
1784     gtk_container_add (GTK_CONTAINER (frame), expander);
1785 
1786     GtkWidget  *scrolled_window = 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));
1787 
1788     gtk_container_add (GTK_CONTAINER (expander), scrolled_window);
1789 
1790     GtkWidget *inner_box = gtk_vbox_new (FALSE, 0);
1791     gtk_scrolled_window_add_with_viewport  (GTK_SCROLLED_WINDOW(scrolled_window),  inner_box);
1792 
1793     button = gtk_button_new_with_label (_("Edit Built-in Score Properties"));
1794     g_signal_connect (button, "clicked", G_CALLBACK (call_score_properties_dialog), NULL);
1795     gtk_box_pack_start (GTK_BOX (inner_box), button, FALSE, TRUE, 0);
1796 
1797     place_buttons_for_directives ((GList**)&Denemo.project->lilycontrol.directives, inner_box, DIRECTIVE_SCORE, "lilycontrol");
1798     place_buttons_for_directives ((GList**)&Denemo.project->scoreheader, inner_box, DIRECTIVE_SCORE, "scoreheader");
1799     place_buttons_for_directives ((GList**)&Denemo.project->paper, inner_box, DIRECTIVE_SCORE, "paper");
1800 
1801 
1802 
1803     gchar *mnum = g_strdup_printf ("%s %d %s", _("Movement"), Denemo.project->movement->currentmovementnum, _("Properties"));
1804     expander = gtk_expander_new (mnum);
1805     g_free(mnum);
1806     gtk_expander_set_expanded (GTK_EXPANDER(expander), !show_score);
1807     gtk_widget_set_sensitive (expander, TRUE);
1808     gtk_container_set_border_width (GTK_CONTAINER (expander),10);
1809     get_color (&color, 0.1, 0.1, 0.8, 1.0);
1810 
1811     gtk_widget_override_color (expander, GTK_STATE_FLAG_NORMAL, &color);
1812 
1813     frame = gtk_frame_new (NULL);
1814     //gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
1815 
1816     gtk_paned_add2 (GTK_PANED(pane), frame);
1817     gtk_container_add (GTK_CONTAINER (frame), expander);
1818 
1819     scrolled_window = 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));
1820     gtk_container_add (GTK_CONTAINER (expander), scrolled_window);
1821     inner_box = gtk_vbox_new (FALSE, 0);
1822     gtk_scrolled_window_add_with_viewport  (GTK_SCROLLED_WINDOW(scrolled_window),  inner_box);
1823 
1824     GtkWidget *hbox = gtk_hbox_new (FALSE, 0);
1825     gtk_box_pack_start (GTK_BOX (inner_box), hbox, FALSE, TRUE, 0);
1826 
1827     button = gtk_button_new_with_label (_("⬅ Previous Movement"));
1828     g_signal_connect_swapped (button, "clicked", G_CALLBACK (go_previous), editscorewin);
1829     gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, TRUE, 0);
1830 
1831     if ( Denemo.project->movement->currentmovementnum == 1)
1832         gtk_widget_set_sensitive (button, FALSE);
1833 
1834     button = gtk_button_new_with_label (_("Next Movement ➡"));
1835     g_signal_connect_swapped (button, "clicked", G_CALLBACK (go_next), editscorewin);
1836     gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, TRUE, 0);
1837     if (g_list_length(Denemo.project->movements) == Denemo.project->movement->currentmovementnum)
1838         gtk_widget_set_sensitive (button, FALSE);
1839 
1840 
1841     place_buttons_for_directives ((GList**)&Denemo.project->movement->movementcontrol, inner_box, DIRECTIVE_MOVEMENT, "movementcontrol");
1842     place_buttons_for_directives ((GList**)&Denemo.project->movement->header, inner_box, DIRECTIVE_MOVEMENT, "header");
1843     place_buttons_for_directives ((GList**)&Denemo.project->movement->layout, inner_box, DIRECTIVE_MOVEMENT, "layout");
1844 
1845    gtk_paned_set_position (GTK_PANED(pane), show_score? window_height-50 : 50);
1846 
1847 
1848 
1849   if(g_list_length ( gtk_container_get_children (GTK_CONTAINER(vbox))) == 1)
1850     {//just the close button
1851         warningdialog ("No properties have been set on the current score.");
1852         gtk_widget_destroy (editscorewin);
1853     }
1854     else
1855     {
1856       gtk_widget_show_all (editscorewin);
1857       gtk_window_present (GTK_WINDOW (editscorewin));
1858       gdk_window_set_cursor (gtk_widget_get_window (editscorewin), gdk_cursor_new (GDK_RIGHT_PTR));
1859       gdk_window_set_cursor (gtk_widget_get_window (Denemo.window), gdk_cursor_new (GDK_X_CURSOR));
1860       if(ObjectInfo)
1861         gdk_window_set_cursor (gtk_widget_get_window (ObjectInfo), gdk_cursor_new (GDK_X_CURSOR));
1862      if(Denemo.printarea && gtk_widget_get_window (Denemo.printarea))
1863         gdk_window_set_cursor (gtk_widget_get_window (Denemo.printarea), gdk_cursor_new (GDK_X_CURSOR));
1864 
1865     }
1866 
1867 }
1868 
1869 
edit_score_properties(void)1870 void edit_score_properties (void)
1871 {
1872     edit_score_and_movement_properties (TRUE);
1873 }
1874 
edit_movement_properties(void)1875 void edit_movement_properties (void)
1876 {
1877     edit_score_and_movement_properties (FALSE);
1878 }
1879 
clef_change_initial_cb(GtkWidget * editstaffwin)1880 static void clef_change_initial_cb (GtkWidget *editstaffwin)
1881 {
1882     DenemoStaff *thestaff = (DenemoStaff *) Denemo.project->movement->currentstaff->data;
1883     if(thestaff->voicecontrol != DENEMO_PRIMARY)
1884         warningdialog (_("The clef here only affects the display as this voice is typeset on the staff above.\nNormally you will want it set the same as the staff the notes will appear on.\nDismiss this warning and make any needed changes via the popup dialog coming next."));
1885     clef_change_initial (NULL, NULL);
1886 }
keysig_change_info(void)1887 static void keysig_change_info (void)
1888 {
1889     DenemoStaff *thestaff = (DenemoStaff *) Denemo.project->movement->currentstaff->data;
1890     if(thestaff->voicecontrol != DENEMO_PRIMARY)
1891         {
1892            warningdialog (_("This voice should have the same key signature as the staff it appears on. Use the key signature menu commands to correct it if needed."));// warningdialog (param.string);
1893         }
1894     else
1895         {
1896         warningdialog (_("Change the keysignature by clicking on it, or via the Key Signatures menu (after closing this editor).")); //for some reason the change_key() call does not get the keyboard focus so we can't change the key here.
1897         }
1898 }
1899 
timesig_change_initial_cb(GtkWidget * editstaffwin)1900 static void timesig_change_initial_cb (GtkWidget *editstaffwin)
1901 {
1902       DenemoStaff *thestaff = (DenemoStaff *) Denemo.project->movement->currentstaff->data;
1903     if(thestaff->voicecontrol != DENEMO_PRIMARY)
1904         {
1905         warningdialog (_("This voice should have the same time signature as the staff it appears on. Use the time signature menu commands to correct it if needed."));// warningdialog (param.string);
1906         }
1907     else
1908         {
1909         timesig_change (Denemo.project, CHANGEINITIAL);
1910         gtk_widget_destroy (editstaffwin);
1911         edit_staff_and_voice_properties (TRUE);
1912         }
1913 }
staff_above(GtkWidget * editstaffwin)1914 static void staff_above (GtkWidget *editstaffwin)
1915 {
1916     movetostaffup (NULL, NULL);
1917     gtk_widget_destroy (editstaffwin);
1918     edit_staff_and_voice_properties (TRUE);
1919 }
staff_below(GtkWidget * editstaffwin)1920 static void staff_below (GtkWidget *editstaffwin)
1921 {
1922     movetostaffdown (NULL, NULL);
1923     gtk_widget_destroy (editstaffwin);
1924     edit_staff_and_voice_properties (TRUE);
1925 }
1926 
change_staff_properties(GtkWidget * editstaffwin)1927 static void change_staff_properties (GtkWidget *editstaffwin)
1928 {
1929     gtk_widget_destroy (editstaffwin);
1930     staff_properties_change_cb (NULL, NULL);
1931     edit_staff_and_voice_properties (TRUE);
1932 }
1933 static void
edit_staff_and_voice_properties(gboolean show_staff)1934 edit_staff_and_voice_properties (gboolean show_staff)
1935 {
1936     GtkWidget *editstaffwin = gtk_window_new (GTK_WINDOW_TOPLEVEL);
1937     GdkRGBA color;
1938     gint window_height = 800;
1939     get_color (&color, 1.0, 1.0, 1.0, 1.0);
1940     gtk_widget_override_background_color (editstaffwin, GTK_STATE_FLAG_NORMAL, &color);
1941     gtk_window_set_modal (GTK_WINDOW (editstaffwin), TRUE);
1942     gtk_window_set_title (GTK_WINDOW (editstaffwin), _("Staff and Voice Properties Editor"));
1943     gtk_window_set_transient_for (GTK_WINDOW(editstaffwin), GTK_WINDOW(Denemo.window));
1944     gtk_window_set_keep_above (GTK_WINDOW (editstaffwin), TRUE);
1945     gtk_window_set_default_size (GTK_WINDOW (editstaffwin), 600, window_height);
1946 
1947 
1948     GtkWidget *vbox = gtk_vbox_new (FALSE, 0);
1949     gtk_container_add (GTK_CONTAINER (editstaffwin), vbox);
1950     GtkWidget *close_button = gtk_button_new_with_label (_("Close"));
1951     g_signal_connect_swapped (close_button, "clicked", G_CALLBACK (score_update_and_close), editstaffwin);
1952 
1953     g_signal_connect (G_OBJECT (editstaffwin), "destroy", G_CALLBACK (reset_cursors), NULL);
1954     gtk_box_pack_start (GTK_BOX (vbox), close_button, FALSE, TRUE, 0);
1955 
1956     GtkWidget *button;
1957     GtkWidget *pane;
1958 #if GTK_MAJOR_VERSION == 2
1959     pane = gtk_vpaned_new ();
1960 #else
1961     pane = gtk_paned_new (GTK_ORIENTATION_VERTICAL);
1962 #endif
1963     gtk_box_pack_start (GTK_BOX (vbox), pane, TRUE, TRUE, 0);
1964     GtkWidget *expander = gtk_expander_new (_("Staff Properties"));
1965     gtk_expander_set_expanded (GTK_EXPANDER(expander), TRUE);
1966     gtk_widget_set_sensitive (expander, TRUE);
1967     gtk_container_set_border_width (GTK_CONTAINER (expander),10);
1968     get_color (&color, 0.1, 0.1, 0.8, 1.0);
1969     gtk_widget_override_color (expander, GTK_STATE_FLAG_NORMAL, &color);
1970    // gtk_box_pack_start (GTK_BOX (vbox), expander, TRUE, TRUE, 0);
1971 
1972    GtkWidget *frame = gtk_frame_new (NULL);
1973    //gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
1974 
1975 
1976 
1977     gtk_paned_add1 (GTK_PANED(pane), frame);
1978 
1979     gtk_container_add (GTK_CONTAINER (frame), expander);
1980 
1981     GtkWidget *scrolled_window = 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));
1982     gtk_container_add (GTK_CONTAINER (expander), scrolled_window);
1983 
1984     GtkWidget *inner_box = gtk_vbox_new (FALSE, 0);
1985     gtk_scrolled_window_add_with_viewport  (GTK_SCROLLED_WINDOW(scrolled_window),  inner_box);
1986     GtkWidget *inner_hbox;
1987     inner_hbox = gtk_hbox_new (FALSE, 0);
1988     gtk_box_pack_start (GTK_BOX (inner_box), inner_hbox, FALSE, TRUE, 0);
1989     button = gtk_button_new_with_label (_("Staff Above"));
1990     g_signal_connect_swapped (button, "clicked", G_CALLBACK (staff_above), editstaffwin);
1991     gtk_box_pack_start (GTK_BOX (inner_hbox), button, FALSE, TRUE, 0);
1992 
1993     if ( Denemo.project->movement->currentstaffnum == 1)
1994         gtk_widget_set_sensitive (button, FALSE);
1995 
1996     button = gtk_button_new_with_label (_("Staff Below"));
1997     g_signal_connect_swapped (button, "clicked", G_CALLBACK (staff_below), editstaffwin);
1998     gtk_box_pack_start (GTK_BOX (inner_hbox), button, FALSE, TRUE, 0);
1999     if (g_list_length(Denemo.project->movement->thescore) == Denemo.project->movement->currentstaffnum)
2000         gtk_widget_set_sensitive (button, FALSE);
2001     DenemoStaff *thestaff = (DenemoStaff *) Denemo.project->movement->currentstaff->data;
2002      if(thestaff->voicecontrol != DENEMO_PRIMARY)
2003     {
2004         GtkWidget *label = gtk_label_new ("");
2005         gtk_label_set_markup (GTK_LABEL (label), _("<b>This voice will be typeset on the staff above</b>"));
2006         gtk_label_set_line_wrap (GTK_LABEL(label), TRUE);
2007         gtk_box_pack_start (GTK_BOX (inner_box), label, FALSE, TRUE, 0);
2008     }
2009     inner_hbox = gtk_hbox_new (FALSE, 0);
2010     gtk_box_pack_start (GTK_BOX (inner_box), inner_hbox, FALSE, TRUE, 0);
2011 
2012     button = gtk_button_new_with_label (_("Edit Built-in Staff Properties"));
2013     g_signal_connect_swapped (button, "clicked", G_CALLBACK (change_staff_properties), editstaffwin);
2014     gtk_box_pack_start (GTK_BOX (inner_hbox), button, FALSE, TRUE, 0);
2015 
2016 
2017     const gchar *theclef = get_clef_name (thestaff->clef.type);
2018     gchar *text = g_strconcat (_("Clef: "), theclef, NULL);
2019     button = gtk_button_new_with_label (text);
2020     g_signal_connect_swapped (button, "clicked", G_CALLBACK (clef_change_initial_cb), editstaffwin);
2021     gtk_box_pack_start (GTK_BOX (inner_hbox), button, FALSE, TRUE, 0);
2022     g_free (text);
2023 
2024     text = g_strdup_printf (_("Time: %d/%d"), thestaff->timesig.time1, thestaff->timesig.time2);
2025     button = gtk_button_new_with_label (text);
2026     g_signal_connect_swapped (button, "clicked", G_CALLBACK (timesig_change_initial_cb), editstaffwin);
2027     gtk_box_pack_start (GTK_BOX (inner_hbox), button, FALSE, TRUE, 0);
2028     g_free (text);
2029 
2030     text = g_strdup_printf (_("Key: %s"), get_lilypond_for_keysig (&(thestaff->keysig)));
2031     button = gtk_button_new_with_label (text);
2032     g_signal_connect (button, "clicked", G_CALLBACK (keysig_change_info), NULL);
2033     gtk_box_pack_start (GTK_BOX (inner_hbox), button, FALSE, TRUE, 0);
2034     g_free (text);
2035 
2036 
2037     place_buttons_for_directives ((GList**)&thestaff->staff_directives, inner_box, DIRECTIVE_STAFF, "staff");
2038      if(thestaff->keysig.directives)
2039         {
2040         GtkWidget *label = gtk_label_new (_("Key Signature Directives"));
2041         gtk_box_pack_start (GTK_BOX (inner_box), label, FALSE, TRUE, 0);
2042         place_buttons_for_directives ((GList**)&(thestaff->keysig.directives), inner_box, DIRECTIVE_KEYSIG, "keysig");
2043         }
2044     if(thestaff->timesig.directives)
2045         {
2046         GtkWidget *label = gtk_label_new (_("Time Signature Directives"));
2047         gtk_box_pack_start (GTK_BOX (inner_box), label, FALSE, TRUE, 0);
2048         place_buttons_for_directives ((GList**)&(thestaff->timesig.directives), inner_box, DIRECTIVE_TIMESIG, "timesig");
2049         }
2050 
2051 
2052     expander = gtk_expander_new (_("Voice Properties"));
2053 
2054     gtk_expander_set_expanded (GTK_EXPANDER(expander),TRUE);
2055     gtk_widget_set_sensitive (expander, TRUE);
2056     gtk_container_set_border_width (GTK_CONTAINER (expander),10);
2057     get_color (&color, 0.1, 0.1, 0.8, 1.0);
2058     gtk_widget_override_color (expander, GTK_STATE_FLAG_NORMAL, &color);
2059 
2060     frame = gtk_frame_new (NULL);
2061     //gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
2062 
2063     gtk_paned_add2 (GTK_PANED(pane), frame);
2064     gtk_container_add (GTK_CONTAINER (frame), expander);
2065 
2066     scrolled_window = 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));
2067     gtk_container_add (GTK_CONTAINER (expander), scrolled_window);
2068     inner_box = gtk_vbox_new (FALSE, 0);
2069     gtk_scrolled_window_add_with_viewport  (GTK_SCROLLED_WINDOW(scrolled_window),  inner_box);
2070 
2071     GtkWidget *hbox = gtk_hbox_new (FALSE, 0);
2072     gtk_box_pack_start (GTK_BOX (inner_box), hbox, FALSE, TRUE, 0);
2073 
2074 
2075 
2076 
2077     place_buttons_for_directives ((GList**)&thestaff->voice_directives, inner_box, DIRECTIVE_VOICE, "voice");
2078 
2079 
2080     gtk_paned_set_position (GTK_PANED(pane), window_height/2);
2081 
2082 
2083 
2084   if(g_list_length ( gtk_container_get_children (GTK_CONTAINER(vbox))) == 1)
2085     {//just the close button
2086         warningdialog ("No properties have been set on the current score.");
2087         gtk_widget_destroy (editstaffwin);
2088     }
2089     else
2090     {
2091       gtk_widget_show_all (editstaffwin);
2092       gtk_window_present (GTK_WINDOW (editstaffwin));
2093       gdk_window_set_cursor (gtk_widget_get_window (editstaffwin), gdk_cursor_new (GDK_RIGHT_PTR));
2094       gdk_window_set_cursor (gtk_widget_get_window (Denemo.window), gdk_cursor_new (GDK_X_CURSOR));
2095       if(ObjectInfo)
2096         gdk_window_set_cursor (gtk_widget_get_window (ObjectInfo), gdk_cursor_new (GDK_X_CURSOR));
2097      if(Denemo.printarea && gtk_widget_get_window (Denemo.printarea))
2098         gdk_window_set_cursor (gtk_widget_get_window (Denemo.printarea), gdk_cursor_new (GDK_X_CURSOR));
2099 
2100     }
2101 
2102 }
2103 void
edit_staff_properties(void)2104 edit_staff_properties (void)
2105 {
2106     edit_staff_and_voice_properties (TRUE);
2107 }
2108 void
edit_voice_properties(void)2109 edit_voice_properties (void)
2110 {
2111     edit_staff_and_voice_properties (FALSE);
2112 }
2113 
2114 
2115 
2116 
2117 void
set_modeaccs(gint * accs,gint number,gint mode)2118 set_modeaccs (gint * accs, gint number, gint mode)
2119 {
2120 
2121   g_debug ("Mode %d : %d \n", number, mode);
2122   if (mode == 0)
2123     {
2124       switch (number)
2125         {
2126         case 11:
2127           number -= 7;
2128           break;
2129         }
2130       initkeyaccs (accs, number);
2131 
2132     }
2133   else if (mode == 2)
2134     initkeyaccs (accs, 0);
2135   else if (number == 1 && mode == 1)
2136     initkeyaccs (accs, 0);
2137 }
2138 
2139 /**
2140  * This function initializes the accidental-context array associated with
2141  * a key signature or a staff to that appropriate for _number_
2142  */
2143 void
initkeyaccs(gint * accs,gint number)2144 initkeyaccs (gint * accs, gint number)
2145 {
2146   int index;
2147   memset (accs, 0, SEVENGINTS);
2148   if (number > 0)
2149     for (index = 3; number; number--, index = (index + 4) % 7)
2150       accs[index] = 1;
2151   else if (number < 0)
2152     for (index = 6; number; number++, index = (index + 3) % 7)
2153       accs[index] = -1;
2154 
2155 }
2156 
2157 /**
2158  * Create a new measure break object
2159  * @return the measurebreak
2160  */
2161 DenemoObject *
newmeasurebreakobject()2162 newmeasurebreakobject ()
2163 {
2164   DenemoObject *ret;
2165 
2166   ret = (DenemoObject *) g_malloc0 (sizeof (DenemoObject));
2167   ret->type = MEASUREBREAK;
2168   return ret;
2169 }
2170 
2171 /**
2172  * Create a new staff break object
2173  * @return the staffbreak
2174  */
2175 DenemoObject *
newstaffbreakobject()2176 newstaffbreakobject ()
2177 {
2178   DenemoObject *ret;
2179   ret = (DenemoObject *) g_malloc0 (sizeof (DenemoObject));
2180   ret->type = STAFFBREAK;
2181   return ret;
2182 }
2183 
2184 /* clone the directive, excluding the widget */
2185 DenemoDirective *
clone_directive(DenemoDirective * directive)2186 clone_directive (DenemoDirective * directive)
2187 {
2188   DenemoDirective *ret = (DenemoDirective *) g_malloc0 (sizeof (DenemoDirective));
2189   memcpy (ret, directive, sizeof (DenemoDirective));    //BEWARE all pointers in DenemoDirective require code, as follows:
2190 #define CLONE(field) \
2191       if(directive->field && directive->field->len)\
2192         ret->field = g_string_new(directive->field->str);\
2193       else\
2194         ret->field = NULL;
2195   CLONE (tag);
2196   CLONE (prefix);
2197   CLONE (postfix);
2198   CLONE (display);
2199   CLONE (graphic_name);
2200   CLONE (grob);
2201   CLONE (midibytes);
2202   CLONE (data);
2203 #undef CLONE
2204   if (directive->graphic)
2205     {
2206       ret->graphic = directive->graphic;        //alternatively could load it via loadGraphicItem, is the same
2207     }
2208   if (directive->widget)
2209     {
2210       //  gpointer fn = g_object_get_data(G_OBJECT(directive->widget), "fn");
2211       ret->widget = NULL;       //FIXME call widget_for_directive here???
2212       //   widget_for_directive(ret, fn);
2213     }
2214   return ret;
2215 }
2216 
2217 
2218 GList *
clone_directives(GList * directives)2219 clone_directives (GList * directives)
2220 {
2221   GList *ret = NULL;
2222   for (; directives; directives = directives->next)
2223     ret = g_list_append (ret, clone_directive (directives->data));
2224   return ret;
2225 }
2226 
2227 void
free_directive_data(DenemoDirective * directive)2228 free_directive_data (DenemoDirective * directive)
2229 {
2230 #define DFREE(field) if(directive->field) g_string_free(directive->field, TRUE);
2231   DFREE (tag);
2232   DFREE (display);
2233   DFREE (prefix);
2234   DFREE (postfix);
2235   DFREE (graphic_name);
2236   DFREE (grob);
2237 #undef DFREE
2238 
2239   if (directive->widget && !G_IS_OBJECT (directive->widget))
2240     {
2241       g_debug ("Found non-gobject widget %p\n", directive->widget);
2242     }
2243   if (directive->widget && G_IS_OBJECT (directive->widget))
2244     {
2245       //g_debug("We should destroy the widget now ");
2246       GtkWidget *texteditor = (GtkWidget *) g_object_get_data (G_OBJECT (directive->widget), DENEMO_TEXTEDITOR_TAG);
2247       if (texteditor)
2248         gtk_widget_destroy (texteditor);        //FIXME we may need to destroy its parents
2249       gtk_widget_destroy ((GtkWidget *) directive->widget);
2250     }
2251 
2252 
2253 
2254 }
2255 
2256 void
free_directive(DenemoDirective * directive)2257 free_directive (DenemoDirective * directive)
2258 {
2259   free_directive_data (directive);
2260   g_free (directive);
2261 }
2262 
2263 void
free_directives(GList * directives)2264 free_directives (GList * directives)
2265 {
2266   for (; directives; directives = directives->next)
2267     {
2268       DenemoDirective *directive = directives->data;
2269       free_directive (directive);
2270     }
2271   g_list_free (directives);
2272 }
2273 
2274 /**
2275  * Create a clone of the given object
2276  * @param orig the object to clone
2277  * @return the cloned object
2278  */
2279 DenemoObject *
dnm_clone_object(DenemoObject * orig)2280 dnm_clone_object (DenemoObject * orig)
2281 {
2282   DenemoObject *ret = NULL;
2283   if (orig != NULL)
2284     {
2285       switch (orig->type)
2286         {
2287         case CHORD:
2288           ret = clone_chord (orig);
2289           break;
2290 
2291         case TUPOPEN:
2292           ret = (DenemoObject *) tuplet_open_new (((tupopen *) orig->object)->numerator, ((tupopen *) orig->object)->denominator);
2293           ((tupopen *) ret->object)->directives = clone_directives (((tupopen *) orig->object)->directives);
2294 
2295           break;
2296         case TUPCLOSE:
2297           ret = (DenemoObject *) tuplet_close_new ();
2298           ((tupopen *) ret->object)->directives = clone_directives (((tupopen *) orig->object)->directives);
2299 
2300           break;
2301         case CLEF:
2302           ret = clef_new (((clef *) orig->object)->type);
2303           ((clef *) ret->object)->directives = clone_directives (((clef *) orig->object)->directives);
2304           break;
2305         case TIMESIG:
2306           ret = dnm_newtimesigobj (((timesig *) orig->object)->time1, ((timesig *) orig->object)->time2);
2307           ((timesig *) ret->object)->directives = clone_directives (((timesig *) orig->object)->directives);
2308 
2309           break;
2310         case KEYSIG:
2311           ret = dnm_newkeyobj (((keysig *) orig->object)->number, ((keysig *) orig->object)->isminor, ((keysig *) orig->object)->mode);
2312           ((keysig *) ret->object)->directives = clone_directives (((keysig *) orig->object)->directives);
2313 
2314           break;
2315           break;
2316         case STEMDIRECTIVE:
2317           ret = dnm_stem_directive_new (((stemdirective *) orig->object)->type);
2318 
2319           ((stemdirective *) ret->object)->directives = clone_directives (((stemdirective *) orig->object)->directives);
2320 
2321           break;
2322         case MEASUREBREAK:
2323           ret = newmeasurebreakobject ();
2324           break;
2325         case STAFFBREAK:
2326           ret = newstaffbreakobject ();
2327           break;
2328         case LILYDIRECTIVE:
2329           {
2330             lilydirective *curlily = (lilydirective *) orig->object;
2331             ret = directive_object_new (clone_directive (curlily));
2332             ret->durinticks = orig->durinticks;
2333             ret->basic_durinticks = orig->basic_durinticks;
2334 
2335           }
2336           break;
2337         default:
2338           g_warning ("Unknown object type %x", orig->type);
2339           ret = lily_directive_new ("%unknown object\n");
2340           break;
2341         }
2342     }
2343     if(ret){
2344         if (orig->lilypond)
2345             ret->lilypond = g_strdup (orig->lilypond);
2346         else
2347             ret->lilypond = NULL;
2348 
2349         ret->isinvisible = orig->isinvisible;
2350   }
2351   return ret;
2352 }
2353 
2354 /**
2355  *  Create a new stem directive
2356  *  @param type the stem directive type
2357  *  @return the stem directive
2358  */
2359 DenemoObject *
dnm_stem_directive_new(enum stemdirections type)2360 dnm_stem_directive_new (enum stemdirections type)
2361 {
2362   DenemoObject *ret;
2363   stemdirective *newstemdir = (stemdirective *) g_malloc (sizeof (stemdirective));
2364   ret = (DenemoObject *) g_malloc0 (sizeof (DenemoObject));
2365   ret->type = STEMDIRECTIVE;
2366   ret->isinvisible = FALSE;
2367   newstemdir->type = type;
2368   ret->object = newstemdir;
2369   set_basic_numticks (ret);
2370   setpixelmin (ret);
2371   return ret;
2372 }
2373 
2374 /**
2375  * Create a new lilypond directive
2376  *
2377  * @param type the lilypond directive body
2378  * @return the lilypond directive
2379  *
2380 */
2381 DenemoObject *
lily_directive_new(gchar * type)2382 lily_directive_new (gchar * type)
2383 {
2384   DenemoObject *ret;
2385   lilydirective *newlily = (lilydirective *) g_malloc0 (sizeof (lilydirective));
2386   ret = (DenemoObject *) g_malloc0 (sizeof (DenemoObject));
2387   ret->type = LILYDIRECTIVE;
2388   newlily->postfix = g_string_new (type);
2389   ret->object = newlily;
2390   set_basic_numticks (ret);
2391   setpixelmin (ret);
2392   return ret;
2393 }
2394 
2395 DenemoObject *
directive_object_new(DenemoDirective * directive)2396 directive_object_new (DenemoDirective * directive)
2397 {
2398   DenemoObject *ret;
2399   ret = (DenemoObject *) g_malloc0 (sizeof (DenemoObject));
2400   ret->type = LILYDIRECTIVE;
2401   ret->object = directive;
2402   set_basic_numticks (ret);
2403   setpixelmin (ret);
2404   return ret;
2405 }
2406 
2407 /**
2408  * Create a new dynamic object
2409  * @param type the dynamic to create
2410  * @return the dynamic
2411   */
2412 DenemoObject *
dynamic_new(gchar * type)2413 dynamic_new (gchar * type)
2414 {
2415   DenemoObject *ret;
2416   dynamic *newdyn = (dynamic *) g_malloc0 (sizeof (dynamic));
2417   ret = (DenemoObject *) g_malloc0 (sizeof (DenemoObject));
2418   ret->type = DYNAMIC;
2419   ret->isinvisible = FALSE;
2420   newdyn->type = g_string_new (type);
2421   ret->object = newdyn;
2422   set_basic_numticks (ret);
2423   setpixelmin (ret);
2424   return ret;
2425 }
2426 
2427 /**
2428  * Create a new lyric object
2429  * @param type the lyric to create
2430  * @param position whether it shoul be centered or not
2431  * @param syllable whether it is a syllable
2432  * @return the dynamic
2433   */
2434 DenemoObject *
dnm_lyric_new(gchar * type,gint position,gboolean syllable)2435 dnm_lyric_new (gchar * type, gint position, gboolean syllable)
2436 {
2437   DenemoObject *ret;
2438   lyric *newlyric = (lyric *) g_malloc0 (sizeof (lyric));
2439   ret = (DenemoObject *) g_malloc0 (sizeof (DenemoObject));
2440   ret->type = LYRIC;
2441   ret->isinvisible = FALSE;
2442 
2443 
2444   newlyric->lyrics = g_string_new (type);
2445   newlyric->position = position;
2446   newlyric->is_syllable = syllable;
2447   ret->object = newlyric;
2448   set_basic_numticks (ret);
2449   setpixelmin (ret);
2450   return ret;
2451 }
2452 
2453 /**
2454  *  Create a DenemoObject
2455  * @param type DenemoObject type
2456  * @return the DenemoObject
2457  */
2458 
2459 DenemoObject *
dnm_newobj(DenemoObjType type)2460 dnm_newobj (DenemoObjType type)
2461 {
2462   DenemoObject *ret = (DenemoObject *) g_malloc0 (sizeof (DenemoObject));;
2463   ret->type = type;
2464   set_basic_numticks (ret);
2465   setpixelmin (ret);            /* these do nothing at present - but if we introduce
2466                                    a show markers option then we will want to allot
2467                                    some space
2468                                  */
2469   return ret;
2470 }
2471 
2472 /**
2473  * Set the key signature into the score
2474  * @param curstaff the current staff
2475  * @param tokey the key sig to insert
2476  * @param type  major/minor/mode
2477  */
2478 void
dnm_setinitialkeysig(DenemoStaff * curstaff,gint tokey,gint type)2479 dnm_setinitialkeysig (DenemoStaff * curstaff, gint tokey, gint type)
2480 {
2481   take_snapshot ();
2482   curstaff->keysig.number = tokey;
2483   curstaff->keysig.isminor = type;
2484 
2485   initkeyaccs (curstaff->keysig.accs, tokey);
2486   curstaff->leftmost_keysig = &curstaff->keysig;
2487   staff_show_which_accidentals (curstaff);
2488   adjust_tonal_center (curstaff->keysig.accs);
2489   displayhelper (Denemo.project);
2490   score_status(Denemo.project, TRUE);
2491 }
2492