1 /* lilydirectives.c
2  * Implements lilydirectives which are not notes
3  *
4  * for Denemo, a gtk+ frontend to GNU Lilypond
5  * Richard Shann 2009, 2010, 2011
6  * A Tee  (c) 2000-2005
7  */
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <denemo/denemo.h>
12 #include "command/lilydirectives.h"
13 #include "command/chord.h"
14 #include "display/calculatepositions.h"
15 #include "command/commandfuncs.h"
16 #include "command/contexts.h"
17 #include "ui/dialogs.h"
18 #include "display/draw.h"
19 #include "command/object.h"
20 #include "command/staff.h"
21 #include "core/utils.h"
22 #include "core/prefops.h"
23 #include "core/view.h"
24 #include "ui/texteditors.h"
25 //#if GTK_MAJOR_VERSION==2
26 //#define GDK_KEY_Escape GDK_Escape
27 //#define GDK_KEY_Return GDK_Return
28 //#define GDK_KEY_Tab GDK_Tab
29 //#define GDK_KEY_BackSpace GDK_BackSpace
30 //#endif
31 
32 
33 static gboolean text_edit_directive (DenemoDirective * directive, gchar * what);
34 
35 static GHashTable *action_scripts;
36 
37 
38 
39 
40 
41 static void
action_script_table_insert(gchar * name,gchar * script)42 action_script_table_insert (gchar * name, gchar * script)
43 {
44   if (!action_scripts)
45     action_scripts = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
46   g_hash_table_insert (action_scripts, g_strdup (name), script);
47 }
48 
49 void
set_action_script_for_tag(gchar * tag,gchar * script)50 set_action_script_for_tag (gchar * tag, gchar * script)
51 {
52   action_script_table_insert (tag, script);
53 }
54 
55 
56 gchar *
get_action_script(gchar * name)57 get_action_script (gchar * name)
58 {
59   if (action_scripts)
60     return (gchar *) g_hash_table_lookup (action_scripts, name);
61   return NULL;
62 }
63 
64 
65 static void
gtk_menu_item_set_label_text(GtkMenuItem * item,gchar * text)66 gtk_menu_item_set_label_text (GtkMenuItem * item, gchar * text)
67 {
68   GtkWidget *label = (GtkWidget *) gtk_bin_get_child (GTK_BIN (item));
69   if (label)
70     gtk_label_set_text (GTK_LABEL (label), text);
71 }
72 
73 
74 
75 
76 static void
toggle_locked(GtkWidget * widget,gboolean * locked)77 toggle_locked (GtkWidget * widget, gboolean * locked)
78 {
79   //g_debug("Called with %d\n", *locked);
80   *locked = !*locked;
81 }
82 
83 /* lookup a directive tagged with TAG in a list DIRECTIVES and return it.
84    if TAG is NULL or "" return the first directive
85    else return NULL
86    DEPRECATED * If TAG has two lines the first only is matched, while the second is
87    DEPRECATED* interpreted as a number selecting which matching directive to return
88    * USE d-DirectiveGetNthTag-##what## instead.
89    * */
90 DenemoDirective *
find_directive(GList * directives,gchar * tag)91 find_directive (GList * directives, gchar * tag)
92 {
93   DenemoDirective *directive = NULL;
94   if (tag && *tag)
95     {
96       GList *g;
97       gchar *newline;
98       gint number = 0;          //number of matching directive required 1 is first matching
99       gint count = 0;           //count of directives with matching name
100       if (*tag == '\n')
101         return NULL;
102 
103       for (newline = tag; *newline; newline++)
104         {
105           if (*newline == '\n')
106             {
107               number = atoi (newline + 1);
108               if (number)
109                 *newline = 0;
110               break;
111             }
112         }
113 
114       for (g = directives; g; g = g->next)
115         {
116           directive = (DenemoDirective *) g->data;
117           if (directive->tag && (number ? g_str_has_prefix (directive->tag->str, tag) : !strcmp (tag, directive->tag->str)))
118             {
119               if (number == 0)
120                 return directive;
121               count++;
122               if (number == count)
123                 {
124                   if (newline != tag)
125                     *newline = '\n';
126                   return directive;
127                 }
128             }
129           directive = NULL;
130         }
131     }
132   else
133     directive = (DenemoDirective *) directives->data;
134   return directive;
135 }
136 
137 static DenemoDirective *
find_directive_number(GList * directives,gint num)138 find_directive_number (GList * directives, gint num)
139 {
140   return g_list_nth_data (directives, num - 1);
141 }
142 
143 static gboolean
delete_directive(GList ** directives,gchar * tag)144 delete_directive (GList ** directives, gchar * tag)
145 {
146   DenemoDirective *directive = NULL;
147   if (tag)
148     {
149       GList *g;
150       for (g = *directives; g; g = g->next)
151         {
152           directive = (DenemoDirective *) g->data;
153           if (directive->tag && !strcmp (tag, directive->tag->str))
154             {
155               *directives = g_list_remove (*directives, directive);
156               free_directive (directive);
157               score_status (Denemo.project, TRUE);
158               displayhelper (Denemo.project);
159               return TRUE;
160             }
161         }
162     }
163   return FALSE;
164 }
165 
166 /* free a list of directives and set to NULL */
167 void
delete_directives(GList ** directives)168 delete_directives (GList ** directives)
169 {
170   DenemoDirective *directive = NULL;    //FIXME use free_directives
171   if (directives)
172     while (*directives)
173       {
174         directive = (DenemoDirective *) (*directives)->data;
175         *directives = g_list_remove (*directives, directive);
176         free_directive (directive);
177       }
178 }
179 
180 
181 
182 static DenemoDirective *
new_directive(gchar * tag)183 new_directive (gchar * tag)
184 {
185   DenemoDirective *directive = (DenemoDirective *) g_malloc0 (sizeof (DenemoDirective));
186   if (tag)
187     directive->tag = g_string_new (tag);
188   return directive;
189 }
190 
191 
192 
193 
194 typedef enum attach_type
195 { ATTACH_NOTE, ATTACH_CHORD } attach_type;
196 /**
197  * Denemo directive attach or edit.
198 if interactive: Allows user to attach a lilypond directive
199 else attache the passed strings as lilypond directive
200 attachment is to chord ( attach is ATTACH_CHORD) or to the note at the cursor
201  */
202 static void
attach_directive(attach_type attach,gchar * postfix,gchar * prefix,gchar * display,gchar * tag,gboolean interactive)203 attach_directive (attach_type attach, gchar * postfix, gchar * prefix, gchar * display, gchar * tag, gboolean interactive)
204 {
205   gchar *prefixstring = NULL, *postfixstring = NULL, *displaystring = NULL;
206   DenemoProject *gui = Denemo.project;
207   note *curnote = NULL;
208   DenemoObject *curObj = get_object ();
209   if (curObj == NULL)
210     {
211       if (interactive)
212         warningdialog (_("You must put the cursor on a chord to attach LilyPond"));     //FIXME find a note and ask
213       return;
214     }
215   chord *thechord = NULL;
216   thechord = (chord *) curObj->object;
217   if (curObj->type != CHORD)
218     {
219       if (interactive)
220         warningdialog (_("You must put the cursor on a chord to attach LilyPond"));
221       return;
222     }
223 
224   curnote = findnote (curObj, gui->movement->cursor_y);
225   if (attach == ATTACH_NOTE && (curnote == NULL))
226     {
227       if (interactive)
228         warningdialog (_("You must put the cursor on a note to attach LilyPond to the note"));  //FIXME find a note and ask
229       return;
230     }
231   if (tag==NULL)
232     {
233         if (attach==ATTACH_CHORD)
234             tag = "AttachLilyToChord";
235         else
236          tag = "AttachLilyToNote";
237     }
238   // setup directive to be data from thechord->directives or curnote->directives which has matching tag, or first if tag is NULL.
239   DenemoDirective *directive = NULL;
240   switch (attach)
241     {
242     case ATTACH_CHORD:
243       if (thechord->directives == NULL)
244         {
245           directive = new_directive (tag);
246           thechord->directives = g_list_append (NULL, directive);
247         }
248       else
249         {
250           directive = find_directive (thechord->directives, tag);
251           if (directive == NULL)
252             {
253               if (tag)
254                 {
255                   directive = new_directive (tag);
256                   thechord->directives = g_list_append (thechord->directives, directive);
257                 }
258             }
259         }
260       break;
261     case ATTACH_NOTE:
262       if (curnote->directives == NULL)
263         {
264           directive = new_directive (tag);
265           curnote->directives = g_list_append (NULL, directive);
266         }
267       else
268         {
269           directive = find_directive (curnote->directives, tag);
270           if (directive == NULL)
271             {
272               if (tag)
273                 {
274                   directive = new_directive (tag);
275                   curnote->directives = g_list_append (curnote->directives, directive);
276                 }
277             }
278         }
279       break;
280     default:
281       g_warning (_("Error in attach type"));
282       return;
283     }
284 
285   if (interactive)
286     {
287       if (directive->postfix)
288         postfixstring = directive->postfix->str;
289       if (directive->prefix)
290         prefixstring = directive->prefix->str;
291       if (directive->display)
292         displaystring = directive->display->str;
293 
294       prefixstring = string_dialog_entry (gui, _("Attach LilyPond"), _("Give text to place before the note"), prefixstring);
295       postfixstring = string_dialog_entry (gui, curnote ? _("Attach LilyPond to Note") : _("Attach LilyPond to Chord"), curnote ? _("Give LilyPond text to postfix to note of chord") : _("Give LilyPond text to postfix to chord"), postfixstring);
296       displaystring = string_dialog_entry (gui, _("Attach LilyPond"), _("Give Display text if required"), displaystring);
297     }
298   else
299     {                           //not interactive
300       if (prefix)
301         prefixstring = g_strdup (prefix);
302       if (postfix)
303         postfixstring = g_strdup (postfix);
304       if (display)
305         displaystring = g_strdup (display);
306     }
307 
308 #define STRINGASSIGN(field, val) \
309      if(val && *val) {\
310      if(directive->field) g_string_assign(directive->field, val);\
311      else directive->field=g_string_new(val);}
312   STRINGASSIGN (postfix, postfixstring);
313   STRINGASSIGN (prefix, prefixstring);
314   STRINGASSIGN (display, displaystring);
315 
316 #undef STRINGASSIGN
317 
318   score_status (gui, TRUE);
319   displayhelper (gui);
320   g_free (postfixstring);
321   g_free (displaystring);
322   g_free (prefixstring);
323 }
324 
325 static void
create_directives(GList ** directives,gchar * tag)326 create_directives (GList ** directives, gchar * tag)
327 {
328   *directives = g_list_append (NULL, new_directive (tag));
329 }
330 
331 static void
get_lily_parameter(gchar * query,DenemoScriptParam * param)332 get_lily_parameter (gchar * query, DenemoScriptParam * param)
333 {
334   DenemoObject *curObj = (DenemoObject *) Denemo.project->movement->currentobject ? (DenemoObject *) Denemo.project->movement->currentobject->data : NULL;
335   param->status = curObj && curObj->type == LILYDIRECTIVE;
336 #define ASSIGN_PARAM(field)  if(!strcmp(#field, query))\
337   g_string_assign(param->string, lilyobj->field->str);
338   if (param->status)
339     {
340       lilydirective *lilyobj = (lilydirective *) curObj->object;
341       ASSIGN_PARAM (postfix);
342       ASSIGN_PARAM (display);
343       if (!strcmp ("minpixels", query))
344         g_string_printf (param->string, "%d", curObj->minpixelsalloted);
345     }
346 #undef ASSIGN_PARAM
347 }
348 
349 
350 static void
insert_lily_directive(gchar * postfix,gchar * display,gboolean locked,gint minpixels)351 insert_lily_directive (gchar * postfix, gchar * display, gboolean locked, gint minpixels)
352 {
353   DenemoProject *gui = Denemo.project;
354   DenemoMovement *si = gui->movement;
355   DenemoObject *lily;
356   lilydirective *lilyobj = NULL;        /* a lily directive object */
357   DenemoObject *curObj = (DenemoObject *) si->currentobject ? (DenemoObject *) si->currentobject->data : NULL;
358   if (postfix == NULL)
359     postfix = "";
360   gboolean is_new = FALSE;
361   if (curObj && curObj->type == LILYDIRECTIVE)
362     {
363       g_string_assign ((lilyobj = (lilydirective *) curObj->object)->postfix, postfix);
364       setpixelmin (curObj);     //curObj->minpixelsalloted = minpixels;
365     }
366   else
367     {
368       lily = lily_directive_new (postfix);
369       is_new = TRUE;
370       lilyobj = (lilydirective *) lily->object;
371       setpixelmin (lily);       //lily->minpixelsalloted = minpixels;//g_debug("min pixels %d\n", lily->minpixelsalloted);
372     }
373   if (lilyobj)
374     {
375       lilyobj->locked = locked;
376       if (*postfix == '%')
377         {                       //append newline if directive starts with a LilyPond comment indicator
378           g_string_append (lilyobj->postfix, "\n");
379         }
380       if (display)
381         {
382           if (lilyobj->display)
383             g_string_assign (lilyobj->display, display);
384           else
385             lilyobj->display = g_string_new (display);
386         }
387     }
388   if (is_new)
389     object_insert (gui, lily);
390   score_status (gui, TRUE);
391   displayhelper (gui);
392 }
393 
394 
395 /* Run a dialog to get a lily directive from the user
396  the values returned must be freed by the caller */
397 static gboolean
get_lily_directive(gchar ** directive,gchar ** display,gboolean * locked)398 get_lily_directive (gchar ** directive, gchar ** display, gboolean * locked)
399 {
400   DenemoProject *gui = Denemo.project;
401   GtkToggleButton *button = NULL;
402   button = (GtkToggleButton *) gtk_check_button_new_with_label ("locked");
403   g_signal_connect (button, "toggled", G_CALLBACK (toggle_locked), locked);
404   if (*locked)
405     gtk_toggle_button_set_active (button, *locked), *locked = TRUE;     //FIXME how is this supposed to be done?
406   *directive = string_dialog_entry_with_widget (gui, _("Insert LilyPond"), _("Give LilyPond text to insert"), *directive, GTK_WIDGET (button));
407   if (!*directive)
408     return FALSE;
409   *display = string_dialog_entry (gui, _("Insert LilyPond"), _("Give Display text if required"), *display);
410   return TRUE;
411 }
412 
413 /* return the directive whose tag is prefixed with tag if present at cursor postion
414  if tag is NULL, return any directive at current position*/
415 static DenemoDirective *
get_standalone_directive(gchar * tag)416 get_standalone_directive (gchar * tag)
417 {
418   DenemoObject *curObj = (DenemoObject *) Denemo.project->movement->currentobject ? (DenemoObject *) Denemo.project->movement->currentobject->data : NULL;
419   if (curObj && curObj->type == LILYDIRECTIVE)
420     {
421       DenemoDirective *ret = (DenemoDirective *) curObj->object;
422       if (tag == NULL)
423         return ret;
424       if (*tag == 0)
425         return ret;
426       if (ret && ret->tag && !g_str_has_prefix (ret->tag->str, tag))
427         ret = NULL;
428       return ret;
429     }
430   return NULL;
431 }
432 
433 
434 static DenemoObject *
get_chordobject(void)435 get_chordobject (void)
436 {
437   DenemoObject *curObj = get_object ();
438   if (curObj == NULL)
439     return NULL;
440   if (curObj->type != CHORD)
441     {
442       return NULL;
443     }
444   return curObj;
445 }
446 
447 static chord *
get_chord(void)448 get_chord (void)
449 {
450   DenemoObject *curObj = get_chordobject ();
451   if (curObj == NULL)
452     return NULL;
453   return (chord *) curObj->object;
454 }
455 
456 static DenemoLilyControl *
get_score(void)457 get_score (void)
458 {
459   return &Denemo.project->lilycontrol;
460 }
461 
462 
463 static note *
get_note(void)464 get_note (void)
465 {
466   DenemoProject *gui = Denemo.project;
467   DenemoObject *curObj = get_chordobject ();
468   if (curObj == NULL)
469     return NULL;
470   return findnote (curObj, gui->movement->cursor_y);
471 }
472 
473 static note *
get_strict_note(void)474 get_strict_note (void)
475 {
476   DenemoProject *gui = Denemo.project;
477   DenemoObject *curObj = get_chordobject ();
478   if (curObj == NULL)
479     return NULL;
480   return findnote_strict (curObj, gui->movement->cursor_y);
481 }
482 
483 static DenemoStaff *
get_staff(void)484 get_staff (void)
485 {
486   if (Denemo.project->movement->currentstaff == NULL)
487     return NULL;
488   return Denemo.project->movement->currentstaff->data;
489 }
490 
491 #define get_voice get_staff
492 
493 
494 //block for new type of directive
495 static clef *
get_clef(void)496 get_clef (void)
497 {
498   clef *ret = NULL;
499   DenemoObject *curObj = get_object ();
500   if (curObj && curObj->type == CLEF)
501     {
502       ret = ((clef *) curObj->object);
503     }
504   else
505     {
506       DenemoStaff *curstaff = get_staff ();
507       if (curstaff)
508         ret = &curstaff->clef;
509     }
510   return ret;
511 }
512 
513 static DenemoDirective *
get_clef_directive(gchar * tag)514 get_clef_directive (gchar * tag)
515 {
516   clef *curclef = get_clef ();
517   if (curclef == NULL || (curclef->directives == NULL))
518     return NULL;
519   return find_directive (curclef->directives, tag);
520 }
521 
522 gboolean
delete_clef_directive(gchar * tag)523 delete_clef_directive (gchar * tag)
524 {
525   clef *curclef = get_clef ();
526   if (curclef == NULL || (curclef->directives == NULL))
527     return FALSE;
528   DenemoDirective *directive = get_clef_directive (tag);
529   if (directive == NULL)
530     return FALSE;
531   return delete_directive (&curclef->directives, tag);
532 }
533 
534 // end of block for new type of directive
535 
536 
537 static keysig *
get_keysig(void)538 get_keysig (void)
539 {
540   keysig *ret = NULL;
541   DenemoObject *curObj = get_object ();
542   if (curObj && curObj->type == KEYSIG)
543     {
544       ret = ((keysig *) curObj->object);
545     }
546   else
547     {
548       DenemoStaff *curstaff = get_staff ();
549       if (curstaff)
550         ret = &curstaff->keysig;
551     }
552   return ret;
553 }
554 
555 static DenemoDirective *
get_keysig_directive(gchar * tag)556 get_keysig_directive (gchar * tag)
557 {
558   keysig *curkeysig = get_keysig ();
559   if (curkeysig == NULL || (curkeysig->directives == NULL))
560     return NULL;
561   return find_directive (curkeysig->directives, tag);
562 }
563 
564 gboolean
delete_keysig_directive(gchar * tag)565 delete_keysig_directive (gchar * tag)
566 {
567   keysig *curkeysig = get_keysig ();
568   if (curkeysig == NULL || (curkeysig->directives == NULL))
569     return FALSE;
570   DenemoDirective *directive = get_keysig_directive (tag);
571   if (directive == NULL)
572     return FALSE;
573   return delete_directive (&curkeysig->directives, tag);
574 }
575 
576 static timesig *
get_timesig(void)577 get_timesig (void)
578 {
579   timesig *ret = NULL;
580   DenemoObject *curObj = get_object ();
581   if (curObj && curObj->type == TIMESIG)
582     {
583       ret = ((timesig *) curObj->object);
584     }
585   else
586     {
587       DenemoStaff *curstaff = get_staff ();
588       if (curstaff)
589         ret = &curstaff->timesig;
590     }
591   return ret;
592 }
593 
594 static DenemoDirective *
get_timesig_directive(gchar * tag)595 get_timesig_directive (gchar * tag)
596 {
597   timesig *curtimesig = get_timesig ();
598   if (curtimesig == NULL || (curtimesig->directives == NULL))
599     return NULL;
600   return find_directive (curtimesig->directives, tag);
601 }
602 
603 gboolean
delete_timesig_directive(gchar * tag)604 delete_timesig_directive (gchar * tag)
605 {
606   timesig *curtimesig = get_timesig ();
607   if (curtimesig == NULL || (curtimesig->directives == NULL))
608     return FALSE;
609   DenemoDirective *directive = get_timesig_directive (tag);
610   if (directive == NULL)
611     return FALSE;
612   return delete_directive (&curtimesig->directives, tag);
613 }
614 
615 static tuplet *
get_tuplet(void)616 get_tuplet (void)
617 {
618   tuplet *ret = NULL;
619   DenemoObject *curObj = get_object ();
620   if (curObj && (curObj->type == TUPOPEN || curObj->type == TUPCLOSE))
621     {
622       ret = ((tuplet *) curObj->object);
623     }
624   return ret;
625 }
626 
627 static DenemoDirective *
get_tuplet_directive(gchar * tag)628 get_tuplet_directive (gchar * tag)
629 {
630   tuplet *curtuplet = get_tuplet ();
631   if (curtuplet == NULL || (curtuplet->directives == NULL))
632     return NULL;
633   return find_directive (curtuplet->directives, tag);
634 }
635 
636 gboolean
delete_tuplet_directive(gchar * tag)637 delete_tuplet_directive (gchar * tag)
638 {
639   tuplet *curtuplet = get_tuplet ();
640   if (curtuplet == NULL || (curtuplet->directives == NULL))
641     return FALSE;
642   DenemoDirective *directive = get_tuplet_directive (tag);
643   if (directive == NULL)
644     return FALSE;
645   return delete_directive (&curtuplet->directives, tag);
646 }
647 
648 static stemdirective *
get_stemdirective(void)649 get_stemdirective (void)
650 {
651   stemdirective *ret = NULL;
652   DenemoObject *curObj = get_object ();
653   if (curObj && (curObj->type == STEMDIRECTIVE))
654     {
655       ret = ((stemdirective *) curObj->object);
656     }
657   return ret;
658 }
659 
660 static DenemoDirective *
get_stemdirective_directive(gchar * tag)661 get_stemdirective_directive (gchar * tag)
662 {
663   stemdirective *curstemdirective = get_stemdirective ();
664   if (curstemdirective == NULL || (curstemdirective->directives == NULL))
665     return NULL;
666   return find_directive (curstemdirective->directives, tag);
667 }
668 
669 gboolean
delete_stemdirective_directive(gchar * tag)670 delete_stemdirective_directive (gchar * tag)
671 {
672   stemdirective *curstemdirective = get_stemdirective ();
673   if (curstemdirective == NULL || (curstemdirective->directives == NULL))
674     return FALSE;
675   DenemoDirective *directive = get_stemdirective_directive (tag);
676   if (directive == NULL)
677     return FALSE;
678   return delete_directive (&curstemdirective->directives, tag);
679 }
680 
681 static scoreheader *
get_scoreheader(void)682 get_scoreheader (void)
683 {
684   return &Denemo.project->scoreheader;
685 }
686 
687 static DenemoDirective *
get_scoreheader_directive(gchar * tag)688 get_scoreheader_directive (gchar * tag)
689 {
690   scoreheader *curscoreheader = get_scoreheader ();
691   if (curscoreheader == NULL || (curscoreheader->directives == NULL))
692     return NULL;
693   return find_directive (curscoreheader->directives, tag);
694 }
695 
696 gboolean
delete_scoreheader_directive(gchar * tag)697 delete_scoreheader_directive (gchar * tag)
698 {
699   scoreheader *curscoreheader = get_scoreheader ();
700   if (curscoreheader == NULL || (curscoreheader->directives == NULL))
701     return FALSE;
702   DenemoDirective *directive = get_scoreheader_directive (tag);
703   if (directive == NULL)
704     return FALSE;
705   return delete_directive (&curscoreheader->directives, tag);
706 }
707 
708 
709 static paper *
get_paper(void)710 get_paper (void)
711 {
712   return &Denemo.project->paper;
713 }
714 
715 static DenemoDirective *
get_paper_directive(gchar * tag)716 get_paper_directive (gchar * tag)
717 {
718   paper *curpaper = get_paper ();
719   if (curpaper == NULL || (curpaper->directives == NULL))
720     return NULL;
721   return find_directive (curpaper->directives, tag);
722 }
723 
724 gboolean
delete_paper_directive(gchar * tag)725 delete_paper_directive (gchar * tag)
726 {
727   paper *curpaper = get_paper ();
728   if (curpaper == NULL || (curpaper->directives == NULL))
729     return FALSE;
730   DenemoDirective *directive = get_paper_directive (tag);
731   if (directive == NULL)
732     return FALSE;
733   return delete_directive (&curpaper->directives, tag);
734 }
735 
736 static layout *
get_layout(void)737 get_layout (void)
738 {
739   return &Denemo.project->movement->layout;
740 }
741 
742 static DenemoDirective *
get_layout_directive(gchar * tag)743 get_layout_directive (gchar * tag)
744 {
745   layout *curlayout = get_layout ();
746   if (curlayout == NULL || (curlayout->directives == NULL))
747     return NULL;
748   return find_directive (curlayout->directives, tag);
749 }
750 
751 gboolean
delete_layout_directive(gchar * tag)752 delete_layout_directive (gchar * tag)
753 {
754   layout *curlayout = get_layout ();
755   if (curlayout == NULL || (curlayout->directives == NULL))
756     return FALSE;
757   DenemoDirective *directive = get_layout_directive (tag);
758   if (directive == NULL)
759     return FALSE;
760   return delete_directive (&curlayout->directives, tag);
761 }
762 
763 
764 static movementcontrol *
get_movementcontrol(void)765 get_movementcontrol (void)
766 {
767   return &Denemo.project->movement->movementcontrol;
768 }
769 
770 DenemoDirective *
get_movementcontrol_directive(gchar * tag)771 get_movementcontrol_directive (gchar * tag)
772 {
773   movementcontrol *curmovementcontrol = get_movementcontrol ();
774   if (curmovementcontrol == NULL || (curmovementcontrol->directives == NULL))
775     return NULL;
776   return find_directive (curmovementcontrol->directives, tag);
777 }
778 
779 gboolean
delete_movementcontrol_directive(gchar * tag)780 delete_movementcontrol_directive (gchar * tag)
781 {
782   movementcontrol *curmovementcontrol = get_movementcontrol ();
783   if (curmovementcontrol == NULL || (curmovementcontrol->directives == NULL))
784     return FALSE;
785   DenemoDirective *directive = get_movementcontrol_directive (tag);
786   if (directive == NULL)
787     return FALSE;
788   return delete_directive (&curmovementcontrol->directives, tag);
789 }
790 
791 
792 static header *
get_header(void)793 get_header (void)
794 {
795   return &Denemo.project->movement->header;
796 }
797 
798 static DenemoDirective *
get_header_directive(gchar * tag)799 get_header_directive (gchar * tag)
800 {
801   header *curheader = get_header ();
802   if (curheader == NULL || (curheader->directives == NULL))
803     return NULL;
804   return find_directive (curheader->directives, tag);
805 }
806 
807 gboolean
delete_header_directive(gchar * tag)808 delete_header_directive (gchar * tag)
809 {
810   header *curheader = get_header ();
811   if (curheader == NULL || (curheader->directives == NULL))
812     return FALSE;
813   DenemoDirective *directive = get_header_directive (tag);
814   if (directive == NULL)
815     return FALSE;
816   return delete_directive (&curheader->directives, tag);
817 }
818 
819 
820 static DenemoDirective *
get_note_directive(gchar * tag)821 get_note_directive (gchar * tag)
822 {
823   note *curnote = get_note ();
824   if (curnote == NULL || (curnote->directives == NULL))
825     return NULL;
826   return find_directive (curnote->directives, tag);
827 }
828 
829 
830 DenemoDirective *
get_note_directive_number(gint num)831 get_note_directive_number (gint num)
832 {
833   note *curnote = get_note ();
834   if (curnote == NULL || (curnote->directives == NULL))
835     return NULL;
836   return find_directive_number (curnote->directives, num);
837 }
838 
839 static DenemoDirective *
get_chord_directive(gchar * tag)840 get_chord_directive (gchar * tag)
841 {
842   DenemoObject *curObj = get_chordobject ();
843   if (curObj == NULL)
844     return NULL;
845   chord *thechord = (chord *) curObj->object;
846   if (thechord->directives == NULL)
847     return NULL;
848   return find_directive (thechord->directives, tag);
849 }
850 
851 static DenemoDirective *
get_object_directive(gchar * tag)852 get_object_directive (gchar * tag)
853 {
854   DenemoObject *curObj = get_object ();
855   if (curObj == NULL)
856     return NULL;
857   if (curObj->directives == NULL)
858     return NULL;
859   return find_directive (curObj->directives, tag);
860 }
861 
862 gboolean
delete_object_directive(gchar * tag)863 delete_object_directive (gchar * tag)
864 {
865   DenemoObject *curObj = get_object ();
866   if (curObj == NULL)
867     return FALSE;
868   if (curObj->directives == NULL)
869     return FALSE;
870   return delete_directive (&curObj->directives, tag);
871 }
872 
873 DenemoDirective *
get_score_directive(gchar * tag)874 get_score_directive (gchar * tag)
875 {
876 
877   return find_directive (Denemo.project->lilycontrol.directives, tag);
878 }
879 
880 static DenemoDirective *
get_staff_directive(gchar * tag)881 get_staff_directive (gchar * tag)
882 {
883   if (Denemo.project->movement->currentstaff == NULL)
884     return NULL;
885   DenemoStaff *curstaff = Denemo.project->movement->currentstaff->data;
886   //FIXME return NULL if not primary staff
887   if (curstaff == NULL || curstaff->staff_directives == NULL)
888     return NULL;
889   return find_directive (curstaff->staff_directives, tag);
890 }
891 
892 static DenemoDirective *
get_voice_directive(gchar * tag)893 get_voice_directive (gchar * tag)
894 {
895   if (Denemo.project->movement->currentstaff == NULL)
896     return NULL;
897   DenemoStaff *curstaff = Denemo.project->movement->currentstaff->data;
898   if (curstaff == NULL || curstaff->voice_directives == NULL)
899     return NULL;
900   return find_directive (curstaff->voice_directives, tag);
901 }
902 
903 gboolean
delete_staff_directive(gchar * tag)904 delete_staff_directive (gchar * tag)
905 {
906   if (Denemo.project->movement->currentstaff == NULL)
907     return FALSE;
908   DenemoStaff *curstaff = Denemo.project->movement->currentstaff->data;
909   if (curstaff == NULL || curstaff->staff_directives == NULL)
910     return FALSE;
911   return delete_directive (&curstaff->staff_directives, tag);
912 }
913 
914 
915 gboolean
delete_initialclef_directive(gchar * tag)916 delete_initialclef_directive (gchar * tag)
917 {
918   if (Denemo.project->movement->currentstaff == NULL)
919     return FALSE;
920   DenemoStaff *curstaff = Denemo.project->movement->currentstaff->data;
921   if (curstaff == NULL || curstaff->clef.directives == NULL)
922     return FALSE;
923   return delete_directive (&curstaff->clef.directives, tag);
924 }
925 
926 
927 gboolean
delete_voice_directive(gchar * tag)928 delete_voice_directive (gchar * tag)
929 {
930   if (Denemo.project->movement->currentstaff == NULL)
931     return FALSE;
932   DenemoStaff *curstaff = Denemo.project->movement->currentstaff->data;
933   if (curstaff == NULL || curstaff->voice_directives == NULL)
934     return FALSE;
935   return delete_directive (&curstaff->voice_directives, tag);
936 }
937 
938 gboolean
delete_note_directive(gchar * tag)939 delete_note_directive (gchar * tag)
940 {
941   note *curnote = get_note ();
942   if (curnote == NULL || (curnote->directives == NULL))
943     return FALSE;
944   DenemoDirective *directive = get_note_directive (tag);
945   if (directive == NULL)
946     return FALSE;
947   return delete_directive (&curnote->directives, tag);
948 }
949 
950 gboolean
delete_chord_directive(gchar * tag)951 delete_chord_directive (gchar * tag)
952 {
953   DenemoObject *curObj = get_chordobject ();
954   if (curObj == NULL)
955     return FALSE;
956   chord *thechord = (chord *) curObj->object;
957   if (thechord->directives == NULL)
958     return FALSE;
959   DenemoDirective *directive = get_chord_directive (tag);
960   if (directive == NULL)
961     return FALSE;
962   return delete_directive (&thechord->directives, tag);
963 }
964 
965 gboolean
delete_score_directive(gchar * tagname)966 delete_score_directive (gchar * tagname)
967 {
968   DenemoDirective *directive = get_score_directive (tagname);
969   if (directive == NULL)
970     return FALSE;
971   return delete_directive (&Denemo.project->lilycontrol.directives, tagname);
972 }
973 
974 
975 #define GET_TAG_FUNC(what)\
976 gchar *\
977 what##_directive_get_tag(gchar *tag) {\
978   DenemoDirective *directive = get_##what##_directive(tag);\
979   if(directive && directive->tag)\
980     return directive->tag->str;\
981   else directive = NULL;/* get_##what##_directive(NULL)*/;  \
982   if(directive && directive->tag)\
983     return directive->tag->str;\
984   return NULL;\
985 }
986 
987 
988 
989 #define GET_STR_FIELD_FUNC(what, field)\
990 gchar *\
991 what##_directive_get_##field(gchar *tag) {\
992   DenemoDirective *directive = get_##what##_directive(tag);\
993   if(directive && directive->field)\
994     return directive->field->str;\
995   return NULL;\
996 }
997 //typdefs to make the macros defined below pick up the right structure for staff, voice and score as chord & note do
998 typedef DenemoStaff staff;
999 typedef DenemoStaff voice;
1000 typedef DenemoLilyControl score;
1001 typedef DenemoObject object;
1002 
1003 
1004      //note I think you cannot change the graphic once you have set it.
1005 #define PUT_GRAPHIC_NAME(what, directives) gboolean \
1006 what##_directive_put_graphic(gchar *tag, gchar *value) {\
1007   what *current = get_##what();\
1008   if(current==NULL) return FALSE;\
1009   if(Denemo.project->movement->currentobject)\
1010   store_for_undo_change (Denemo.project->movement, Denemo.project->movement->currentobject->data);\
1011   if(current->directives==NULL)\
1012        create_directives (&current->directives, tag);\
1013   DenemoDirective *directive = get_##what##_directive(tag);\
1014   if(directive==NULL){\
1015     directive=new_directive(tag);\
1016     current->directives = g_list_append(current->directives, directive);\
1017     }\
1018   loadGraphicItem(value, (DenemoGraphic **)&directive->graphic);\
1019   if(directive->graphic_name)\
1020      g_string_assign(directive->graphic_name, value);\
1021   else\
1022       directive->graphic_name = g_string_new(value);\
1023   return TRUE;\
1024 }
1025 #define PUT_GRAPHIC(what) PUT_GRAPHIC_NAME(what, directives)
1026 PUT_GRAPHIC (chord);
1027 PUT_GRAPHIC (note);
1028 
1029 PUT_GRAPHIC (keysig) PUT_GRAPHIC (timesig) PUT_GRAPHIC (tuplet) PUT_GRAPHIC (stemdirective)
1030 #define PUT_STR_FIELD_FUNC_NAME(what, field, name)\
1031 gboolean \
1032 what##_directive_put_##field(gchar *tag, gchar *value) {\
1033   what *current = get_##what();\
1034   if(current==NULL) return FALSE;\
1035   if(Denemo.project->movement->currentobject)\
1036   store_for_undo_change (Denemo.project->movement, Denemo.project->movement->currentobject->data);\
1037   if(current->name==NULL)\
1038        create_directives (&current->name, tag);\
1039   DenemoDirective *directive = get_##what##_directive(tag);\
1040   if(directive==NULL){\
1041     directive=new_directive(tag);\
1042     current->name = g_list_append(current->name, directive);\
1043     }\
1044   if(directive->field)\
1045     g_string_assign(directive->field, value);\
1046   else\
1047     directive->field = g_string_new(value);\
1048   if(!Denemo.non_interactive){\
1049     widget_for_directive(directive, (void(*)())what##_directive_put_graphic);\
1050     g_object_set_data(G_OBJECT(directive->widget), "directives-pointer", &current->name);\
1051   }\
1052   return TRUE;\
1053 }
1054 #define PUT_STR_FIELD_FUNC(what, field) PUT_STR_FIELD_FUNC_NAME(what, field, directives)
1055 #define PUT_STR_FIELD_FUNCS(what, field) PUT_STR_FIELD_FUNC_NAME(what, field, staff_directives)
1056 #define PUT_STR_FIELD_FUNCV(what, field) PUT_STR_FIELD_FUNC_NAME(what, field, voice_directives)
1057   GET_TAG_FUNC (object);
1058 GET_TAG_FUNC (standalone);
1059 GET_TAG_FUNC (chord);
1060 GET_TAG_FUNC (note);
1061 GET_TAG_FUNC (staff);
1062 GET_TAG_FUNC (voice);
1063 GET_TAG_FUNC (score);
1064 GET_TAG_FUNC (clef);
1065 GET_TAG_FUNC (timesig);
1066 GET_TAG_FUNC (tuplet);
1067 GET_TAG_FUNC (stemdirective);
1068 GET_TAG_FUNC (keysig);
1069 GET_TAG_FUNC (scoreheader);
1070 GET_TAG_FUNC (header);
1071 GET_TAG_FUNC (paper);
1072 GET_TAG_FUNC (layout);
1073 GET_TAG_FUNC (movementcontrol);
1074 
1075 
1076 #undef GET_TAG_FUNC
1077 
1078 
1079 
1080 
GET_STR_FIELD_FUNC(score,midibytes)1081 GET_STR_FIELD_FUNC (score, midibytes) GET_STR_FIELD_FUNC (movementcontrol, midibytes) GET_STR_FIELD_FUNC (note, midibytes) GET_STR_FIELD_FUNC (chord, midibytes) GET_STR_FIELD_FUNC (staff, midibytes) GET_STR_FIELD_FUNC (voice, midibytes) GET_STR_FIELD_FUNC (standalone, midibytes) PUT_STR_FIELD_FUNC (note, midibytes) PUT_STR_FIELD_FUNC (chord, midibytes)
1082 
1083 //cloned for grob
1084   GET_STR_FIELD_FUNC (score, grob) GET_STR_FIELD_FUNC (movementcontrol, grob) GET_STR_FIELD_FUNC (note, grob) GET_STR_FIELD_FUNC (chord, grob) GET_STR_FIELD_FUNC (staff, grob) GET_STR_FIELD_FUNC (voice, grob) GET_STR_FIELD_FUNC (clef, grob) GET_STR_FIELD_FUNC (timesig, grob) GET_STR_FIELD_FUNC (keysig, grob) GET_STR_FIELD_FUNC (tuplet, grob) GET_STR_FIELD_FUNC (stemdirective, grob) GET_STR_FIELD_FUNC (standalone, grob) PUT_STR_FIELD_FUNC (score, grob)
1085 //PUT_STR_FIELD_FUNC(staff, grob)
1086 //PUT_STR_FIELD_FUNC(voice, grob)
1087   PUT_STR_FIELD_FUNC (note, grob) PUT_STR_FIELD_FUNC (chord, grob) PUT_STR_FIELD_FUNC (clef, grob) PUT_STR_FIELD_FUNC (timesig, grob) PUT_STR_FIELD_FUNC (keysig, grob) PUT_STR_FIELD_FUNC (tuplet, grob) PUT_STR_FIELD_FUNC (stemdirective, grob)
1088 //PUT_STR_FIELD_FUNC(standalone, grob)
1089 //end of clone for grob
1090 
1091 //this set for the "data" field is complete I think. For some reason others fields have incomplete sets of get/put functions.
1092 //In particular, the S and V versions of the macros, that enable staff and voice directives to be accessed were commented out for some reason and needed to be put back for this set.
1093   GET_STR_FIELD_FUNC (score, data)
1094   GET_STR_FIELD_FUNC (scoreheader, data)
1095   GET_STR_FIELD_FUNC (header, data)
1096   GET_STR_FIELD_FUNC (paper, data)
1097   GET_STR_FIELD_FUNC (layout, data)
1098   GET_STR_FIELD_FUNC (movementcontrol, data)
1099   GET_STR_FIELD_FUNC (note, data)
1100   GET_STR_FIELD_FUNC (chord, data)
1101   GET_STR_FIELD_FUNC (staff, data)
1102   GET_STR_FIELD_FUNC (voice, data)
1103   GET_STR_FIELD_FUNC (clef, data)
1104   GET_STR_FIELD_FUNC (timesig, data)
1105   GET_STR_FIELD_FUNC (keysig, data) GET_STR_FIELD_FUNC (tuplet, data) GET_STR_FIELD_FUNC (stemdirective, data) GET_STR_FIELD_FUNC (standalone, data)
1106 
1107 
1108   PUT_STR_FIELD_FUNC (score, data)
1109   PUT_STR_FIELD_FUNC (scoreheader, data)
1110   PUT_STR_FIELD_FUNC (header, data)
1111   PUT_STR_FIELD_FUNC (paper, data)
1112   PUT_STR_FIELD_FUNC (layout, data)
1113   PUT_STR_FIELD_FUNCS(staff, data)
1114   PUT_STR_FIELD_FUNCV(voice, data)
1115   PUT_STR_FIELD_FUNC (movementcontrol, data)
1116   PUT_STR_FIELD_FUNC (note, data) PUT_STR_FIELD_FUNC (chord, data) PUT_STR_FIELD_FUNC (clef, data) PUT_STR_FIELD_FUNC (timesig, data) PUT_STR_FIELD_FUNC (keysig, data) PUT_STR_FIELD_FUNC (tuplet, data) PUT_STR_FIELD_FUNC (stemdirective, data)
1117 //PUT_STR_FIELD_FUNC(standalone, data) // done separately below...
1118 //end of set for data
1119 
1120 
1121   GET_STR_FIELD_FUNC (chord, prefix)
1122 GET_STR_FIELD_FUNC (chord, postfix)
1123 GET_STR_FIELD_FUNC (chord, display)
1124 PUT_STR_FIELD_FUNC (chord, prefix)
1125 PUT_STR_FIELD_FUNC (chord, postfix)
1126 PUT_STR_FIELD_FUNC (chord, display)
1127 GET_STR_FIELD_FUNC (note, prefix)
1128 GET_STR_FIELD_FUNC (note, postfix)
1129 GET_STR_FIELD_FUNC (note, display)
1130 PUT_STR_FIELD_FUNC (note, prefix)
1131 PUT_STR_FIELD_FUNC (note, postfix)
1132 PUT_STR_FIELD_FUNC (note, display) GET_STR_FIELD_FUNC (standalone, prefix) GET_STR_FIELD_FUNC (standalone, postfix) GET_STR_FIELD_FUNC (standalone, display) GET_STR_FIELD_FUNC (score, prefix) GET_STR_FIELD_FUNC (score, postfix) GET_STR_FIELD_FUNC (score, display) GET_STR_FIELD_FUNC (staff, prefix) GET_STR_FIELD_FUNC (staff, postfix) GET_STR_FIELD_FUNC (staff, display) GET_STR_FIELD_FUNC (voice, prefix) GET_STR_FIELD_FUNC (voice, postfix) GET_STR_FIELD_FUNC (voice, display)
1133 #undef staff
1134 #define PUT_INT_FIELD_FUNC_NAME(what, field, name)\
1135 gboolean \
1136 what##_directive_put_##field(gchar *tag, gint value) {\
1137   what *current = get_##what();\
1138   if(current==NULL) return FALSE;\
1139   if(Denemo.project->movement->currentobject)\
1140   store_for_undo_change (Denemo.project->movement, Denemo.project->movement->currentobject->data);\
1141   if(current->name==NULL)\
1142        create_directives (&current->name, tag);\
1143   DenemoDirective *directive = get_##what##_directive(tag);\
1144   if(directive==NULL){\
1145     directive=new_directive(tag);\
1146     current->name = g_list_append(current->name, directive);\
1147     }\
1148   directive->field = value;\
1149   if(!Denemo.non_interactive){\
1150     widget_for_directive(directive, (void(*)())what##_directive_put_graphic);\
1151     g_object_set_data(G_OBJECT(directive->widget), "directives-pointer", &current->name);\
1152   }\
1153   return TRUE;\
1154 }
1155 #define PUT_INT_FIELD_FUNC(what, field)  PUT_INT_FIELD_FUNC_NAME(what, field, directives)
1156 //#define PUT_INT_FIELD_FUNCS(what, field)  PUT_INT_FIELD_FUNC_NAME(what, field, staff_directives)
1157 //#define PUT_INT_FIELD_FUNCV(what, field)  PUT_INT_FIELD_FUNC_NAME(what, field, voice_directives)
1158 #define GET_INT_FIELD_FUNC(what, field)\
1159 gint \
1160 what##_directive_get_##field(gchar *tag) {\
1161   DenemoDirective *directive = get_##what##_directive(tag);\
1162   if(directive)\
1163     return directive->field;\
1164   return 0;\
1165 }
1166 #define GET_INT_GRAPHIC_FIELD_FUNC(what, field)\
1167 gint \
1168 what##_directive_get_##field(gchar *tag) {\
1169   DenemoDirective *directive = get_##what##_directive(tag);\
1170   if(directive)\
1171     return directive->graphic->field;\
1172   return 0;\
1173 }
1174   PUT_GRAPHIC (object) PUT_INT_FIELD_FUNC (object, minpixels) GET_INT_FIELD_FUNC (object, minpixels)
1175   /* block which can be copied for new int fields */
1176   PUT_INT_FIELD_FUNC (note, minpixels) PUT_INT_FIELD_FUNC (chord, minpixels)
1177   //PUT_INT_FIELD_FUNCS(staff, minpixels)
1178   //PUT_INT_FIELD_FUNCV(voice, minpixels)
1179   //PUT_INT_FIELD_FUNC(score, minpixels)
1180   PUT_INT_FIELD_FUNC (clef, minpixels) PUT_INT_FIELD_FUNC (timesig, minpixels) PUT_INT_FIELD_FUNC (tuplet, minpixels) PUT_INT_FIELD_FUNC (stemdirective, minpixels) PUT_INT_FIELD_FUNC (keysig, minpixels)
1181   //PUT_INT_FIELD_FUNC(scoreheader, minpixels)
1182   //PUT_INT_FIELD_FUNC(header, minpixels)
1183   //PUT_INT_FIELD_FUNC(paper, minpixels)
1184   //PUT_INT_FIELD_FUNC(layout, minpixels)
1185   //PUT_INT_FIELD_FUNC(movementcontrol, minpixels)
1186   //standalone needs different code for "put" see STANDALONE_PUT* below
1187   GET_INT_FIELD_FUNC (note, minpixels)
1188 GET_INT_FIELD_FUNC (chord, minpixels)
1189 GET_INT_FIELD_FUNC (staff, minpixels)
1190 GET_INT_FIELD_FUNC (voice, minpixels)
1191 GET_INT_FIELD_FUNC (score, minpixels) GET_INT_FIELD_FUNC (clef, minpixels) GET_INT_FIELD_FUNC (keysig, minpixels) GET_INT_FIELD_FUNC (timesig, minpixels) GET_INT_FIELD_FUNC (tuplet, minpixels) GET_INT_FIELD_FUNC (stemdirective, minpixels) GET_INT_FIELD_FUNC (scoreheader, minpixels) GET_INT_FIELD_FUNC (header, minpixels) GET_INT_FIELD_FUNC (paper, minpixels) GET_INT_FIELD_FUNC (layout, minpixels) GET_INT_FIELD_FUNC (movementcontrol, minpixels) GET_INT_FIELD_FUNC (standalone, minpixels)
1192   /* end block which can be copied for new int fields */
1193   PUT_INT_FIELD_FUNC (note, override)
1194 PUT_INT_FIELD_FUNC (chord, override)
1195 GET_INT_FIELD_FUNC (note, override)
1196 GET_INT_FIELD_FUNC (chord, override)
1197 GET_INT_FIELD_FUNC (staff, override)
1198 GET_INT_FIELD_FUNC (voice, override)
1199 GET_INT_FIELD_FUNC (score, override)
1200 PUT_INT_FIELD_FUNC (note, x)
1201 PUT_INT_FIELD_FUNC (chord, x)
1202 GET_INT_FIELD_FUNC (note, x)
1203 GET_INT_FIELD_FUNC (chord, x)
1204 GET_INT_FIELD_FUNC (staff, x)
1205 GET_INT_FIELD_FUNC (voice, x)
1206 PUT_INT_FIELD_FUNC (note, y)
1207 PUT_INT_FIELD_FUNC (chord, y)
1208 GET_INT_FIELD_FUNC (note, y)
1209 GET_INT_FIELD_FUNC (chord, y)
1210 GET_INT_FIELD_FUNC (staff, y)
1211 GET_INT_FIELD_FUNC (voice, y)
1212 PUT_INT_FIELD_FUNC (note, tx)
1213 PUT_INT_FIELD_FUNC (chord, tx)
1214 GET_INT_FIELD_FUNC (note, tx)
1215 GET_INT_FIELD_FUNC (chord, tx)
1216 GET_INT_FIELD_FUNC (staff, tx)
1217 GET_INT_FIELD_FUNC (voice, tx)
1218 PUT_INT_FIELD_FUNC (note, ty)
1219 PUT_INT_FIELD_FUNC (chord, ty)
1220 GET_INT_FIELD_FUNC (note, ty)
1221 GET_INT_FIELD_FUNC (chord, ty)
1222 GET_INT_FIELD_FUNC (staff, ty)
1223 GET_INT_FIELD_FUNC (voice, ty)
1224 PUT_INT_FIELD_FUNC (note, gx)
1225 PUT_INT_FIELD_FUNC (chord, gx)
1226 GET_INT_FIELD_FUNC (note, gx)
1227 GET_INT_FIELD_FUNC (chord, gx)
1228 GET_INT_FIELD_FUNC (staff, gx)
1229 GET_INT_FIELD_FUNC (voice, gx)
1230 PUT_INT_FIELD_FUNC (note, gy)
1231 PUT_INT_FIELD_FUNC (chord, gy)
1232 GET_INT_FIELD_FUNC (note, gy)
1233 GET_INT_FIELD_FUNC (chord, gy)
1234 GET_INT_FIELD_FUNC (staff, gy)
1235 GET_INT_FIELD_FUNC (voice, gy) GET_INT_FIELD_FUNC (standalone, override) GET_INT_FIELD_FUNC (standalone, x) GET_INT_FIELD_FUNC (standalone, y) GET_INT_FIELD_FUNC (standalone, tx) GET_INT_FIELD_FUNC (standalone, ty) GET_INT_FIELD_FUNC (standalone, gx) GET_INT_FIELD_FUNC (standalone, gy) GET_INT_FIELD_FUNC (score, x) GET_INT_FIELD_FUNC (score, y) GET_INT_FIELD_FUNC (score, tx) GET_INT_FIELD_FUNC (score, ty) GET_INT_FIELD_FUNC (score, gx) GET_INT_FIELD_FUNC (score, gy)
1236   /* width and height of graphic (if any), read only */
1237   GET_INT_GRAPHIC_FIELD_FUNC (note, width)
1238 GET_INT_GRAPHIC_FIELD_FUNC (chord, width) GET_INT_GRAPHIC_FIELD_FUNC (staff, width) GET_INT_GRAPHIC_FIELD_FUNC (voice, width) GET_INT_GRAPHIC_FIELD_FUNC (standalone, width) GET_INT_GRAPHIC_FIELD_FUNC (score, width) GET_INT_GRAPHIC_FIELD_FUNC (note, height) GET_INT_GRAPHIC_FIELD_FUNC (chord, height) GET_INT_GRAPHIC_FIELD_FUNC (staff, height) GET_INT_GRAPHIC_FIELD_FUNC (voice, height) GET_INT_GRAPHIC_FIELD_FUNC (standalone, height) GET_INT_GRAPHIC_FIELD_FUNC (score, height)
1239 
1240 
1241 /* return a full path to an editscript for directive or NULL if there is none */
1242 
1243 gchar *
1244 get_editscript_filename (gchar * tag)
1245 {
1246   gchar *basename = g_strconcat (tag, ".scm", NULL);
1247   GList* dirs = NULL;
1248   dirs = g_list_append(dirs, g_build_filename (get_user_data_dir (FALSE), COMMANDS_DIR, "editscripts", NULL));
1249   dirs = g_list_append(dirs, g_build_filename (get_system_data_dir (), COMMANDS_DIR, "editscripts", NULL));
1250   return find_path_for_file(basename, dirs);
1251 }
1252 
1253 
1254 /*
1255 instead of the "activate"  "button-release-event" signal
1256 
1257 gboolean            user_function                      (GtkWidget      *widget,
1258                                                         GdkEventButton *event,
1259                                                         gpointer        user_data)      : Run Last
1260                                                         * PROBLEM cannot use gtk_widget_activate ... d-DirectiveActivate ...
1261 the look at event to see if left or right button pressed
1262 and allow advanced edit if right button.
1263 
1264 */
1265 static gboolean text_edit_directive_by_fn (DenemoDirective * directive, gpointer fn);
1266 
1267 static void
button_callback(GtkWidget * widget,GdkEventButton * event,DenemoDirective * directive)1268 button_callback (GtkWidget * widget, GdkEventButton * event, DenemoDirective * directive)
1269 {
1270   // !!!!! clicking on a staff tools menu item comes thru here - but if you break gdb here as the menu item is still up your mouse is grabbed.
1271   gboolean left = TRUE;
1272   if (event != NULL)
1273     left = !((event->button != 1));
1274   if (left && (directive->override & DENEMO_OVERRIDE_EDITOR))
1275     {
1276       GtkWidget *texteditor = (GtkWidget *) g_object_get_data (G_OBJECT (directive->widget), DENEMO_TEXTEDITOR_TAG);
1277       if (texteditor)
1278         {
1279           //FIXME position at cursor if a toplevel window
1280           gtk_widget_show_all (gtk_widget_get_toplevel (texteditor));
1281           gtk_window_present (GTK_WINDOW (gtk_widget_get_toplevel (texteditor)));
1282         }
1283     }
1284   else
1285     {
1286       gchar *script = get_action_script (directive->tag->str);
1287       if (left && script)
1288         {
1289           stage_undo (Denemo.project->movement, ACTION_STAGE_END);    //undo is a queue so this is the end :)
1290           call_out_to_guile (script);
1291           stage_undo (Denemo.project->movement, ACTION_STAGE_START);
1292         }
1293       else
1294         {
1295           if (left && (directive->override & DENEMO_OVERRIDE_TAGEDIT))
1296             script = get_editscript_filename (directive->tag->str);
1297           else
1298             script = NULL;
1299           if (script)
1300             execute_script_file (script);
1301           else
1302             {
1303               /* if there is an action of this tag with scheme script, run it again
1304                  else do text edit of the directives fields
1305                */
1306               GtkAction *action;
1307               if (left && ((action = lookup_action_from_name ((gchar *) directive->tag->str)) != NULL) && (directive->override & DENEMO_OVERRIDE_TAGEDIT))
1308                 gtk_action_activate (action);
1309               else
1310                 {
1311                   if (left && action)
1312                     {
1313                       gchar *name = (gchar *) gtk_action_get_name (action);
1314                       gint idx = lookup_command_from_name (Denemo.map, name);
1315                       if (idx > 0)
1316                         {
1317                           gpointer fn = (widget != NULL) ? g_object_get_data (G_OBJECT (widget), "fn") : NULL;
1318 
1319                           gchar *label = (gchar *) lookup_label_from_idx (Denemo.map, idx);
1320                           if (confirm (label, _("Repeat the command?\n(Hold Shift for advanced edit)")))
1321                             if(shift_held_down())
1322                                 {
1323                                 GList **directives = (GList **) g_object_get_data (G_OBJECT (widget), "directives-pointer");
1324                                 gboolean delete = !text_edit_directive (directive, fn);
1325                                 if (delete)
1326                                     {
1327                                     if (directives)
1328                                         delete_directive (directives, directive->tag->str);
1329                                       else
1330                                         g_warning ("Could not get directives list to delete from");
1331                                     }
1332                                 }
1333                             else
1334                                 gtk_action_activate (action);
1335                         }
1336                     }
1337                   else
1338                     {
1339                       gpointer fn = (widget != NULL) ? g_object_get_data (G_OBJECT (widget), "fn") : NULL;
1340                       if (fn)
1341                         {
1342                           gboolean delete = !text_edit_directive_by_fn (directive, fn);
1343                           if (delete)
1344                             {
1345                               GList **directives = (GList **) g_object_get_data (G_OBJECT (widget), "directives-pointer");
1346                               if (directives)
1347                                 delete_directive (directives, directive->tag->str);
1348                               else
1349                                 g_warning ("Could not get directives list to delete from");
1350                             }
1351                         }
1352                     }
1353                 }
1354             }
1355         }
1356     }
1357 }
1358 
1359 
1360 static void
button_activate_callback(GtkWidget * w,DenemoDirective * d)1361 button_activate_callback (GtkWidget * w, DenemoDirective * d)
1362 {
1363   button_callback (w, NULL, d);
1364 }
1365 
1366 /* return a GtkTextView which has been installed inside a scrolled window */
1367 static GtkWidget *
create_text_window(void)1368 create_text_window (void)
1369 {
1370   GtkWidget *textview = gtk_text_view_new ();
1371   GtkWidget *w = gtk_window_new (GTK_WINDOW_TOPLEVEL);
1372   gtk_window_set_title (GTK_WINDOW (w), _("Denemo Editor:Newline to update, Esc for Advanced Edit"));
1373   gtk_window_set_default_size (GTK_WINDOW (w), 600, 400);
1374   gtk_window_set_position (GTK_WINDOW (w), GTK_WIN_POS_MOUSE);
1375   g_signal_connect (G_OBJECT (w), "delete-event", G_CALLBACK (gtk_widget_hide_on_delete), w);
1376   GtkWidget *main_vbox = gtk_vbox_new (FALSE, 1);
1377   gtk_container_add (GTK_CONTAINER (w), main_vbox);
1378 
1379   GtkWidget *sw = gtk_scrolled_window_new (gtk_adjustment_new (1.0, 1.0, 2.0, 1.0, 4.0, 1.0), gtk_adjustment_new (1.0, 1.0, 2.0, 1.0, 4.0, 1.0));
1380   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
1381   gtk_box_pack_start (GTK_BOX (main_vbox), sw, TRUE, TRUE, 0);
1382   gtk_container_add (GTK_CONTAINER (sw), textview);
1383   return textview;
1384 }
1385 
1386 static void
assign_text(GtkWidget * w,gchar * text)1387 assign_text (GtkWidget * w, gchar * text)
1388 {
1389   GtkTextBuffer *textbuffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (w));
1390   if (textbuffer)
1391     gtk_text_buffer_set_text (textbuffer, text, -1);
1392 }
1393 
1394 static gchar *
get_label_text(DenemoDirective * directive,gchar * text)1395 get_label_text (DenemoDirective * directive, gchar * text)
1396 {
1397   if (directive->override & DENEMO_OVERRIDE_MARKUP)
1398     return g_strdup (text);
1399   return g_markup_escape_text (text, -1);
1400 }
1401 
1402 /* create a label.
1403 Use the display string up to the first newline, if it is long enough
1404 else use tag
1405 */
1406 static void
set_directive_graphic_label(DenemoDirective * directive)1407 set_directive_graphic_label (DenemoDirective * directive)
1408 {
1409   if(Denemo.non_interactive)
1410     return;
1411   gchar *value;
1412   if (directive->display && directive->display->len > 0)
1413     value = get_label_text (directive, directive->display->str);
1414   else
1415     value = get_label_text (directive, directive->tag->str);
1416   gchar *c;
1417   for (c = value; *c; c++)
1418     if (*c == '\n')
1419       {
1420         *c = 0;
1421         break;
1422       }
1423   if (GTK_IS_MENU_ITEM (directive->widget))
1424     gtk_menu_item_set_label_text ((GtkMenuItem *) directive->widget, value);
1425   else
1426     gtk_label_set_markup ((GtkLabel *) gtk_bin_get_child (GTK_BIN (directive->widget)), value);
1427   g_free (value);
1428 }
1429 
1430 
1431 static gboolean
editor_keypress(GtkWidget * w,GdkEventKey * event,DenemoDirective * directive)1432 editor_keypress (GtkWidget * w, GdkEventKey * event, DenemoDirective * directive)
1433 {
1434   GtkTextIter startiter, enditer;
1435   GtkTextBuffer *textbuffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (w));
1436   gtk_text_buffer_get_start_iter (textbuffer, &startiter);
1437   gtk_text_buffer_get_end_iter (textbuffer, &enditer);
1438   gchar *text = gtk_text_buffer_get_text (textbuffer, &startiter, &enditer, FALSE);
1439   if (directive->display)
1440     g_string_assign (directive->display, text);
1441   else
1442     directive->display = g_string_new (text);
1443   //if the GdkEventKey is newline, run the editscript for the directive
1444 
1445   //FIXME use switch
1446   if (event->keyval == GDK_KEY_Escape)
1447     if (!text_edit_directive (directive, "unknown"))
1448       {
1449         /* I have used "unknown" here because we would need to get the name e.g. "score" "movementcontrol" etc from fn, but this is only used for the create a script thing...
1450            g_object_get_data(G_OBJECT(directive->widget), "fn")
1451          */
1452         GList **directives_ptr = g_object_get_data (G_OBJECT (directive->widget), "directives-pointer");
1453         if (directives_ptr)
1454           delete_directive (g_object_get_data (G_OBJECT (directive->widget), "directives-pointer"), directive->tag->str);
1455         else
1456           warningdialog (_("Cannot delete via this mechanism, sorry"));
1457         return TRUE;
1458       }
1459   if (event->keyval == GDK_KEY_Return)
1460     {
1461       gchar *filename = get_editscript_filename (directive->tag->str);
1462       if (filename)
1463         execute_script_file (filename);
1464       set_directive_graphic_label (directive);
1465     }
1466   return TRUE;
1467 }
1468 
1469 static void
attach_textedit_widget(DenemoDirective * directive)1470 attach_textedit_widget (DenemoDirective * directive)
1471 {
1472   if (directive->override & DENEMO_OVERRIDE_EDITOR)
1473     {
1474       GtkWidget *texteditor = create_text_window ();
1475       //    g_signal_connect (G_OBJECT (texteditor), "key-press-event",
1476       //                G_CALLBACK (editor_keypress), directive);
1477       g_signal_connect_after (G_OBJECT (texteditor), "key-release-event", G_CALLBACK (editor_keypress), directive);
1478       if (directive->display == NULL)
1479         directive->display = g_string_new ("");
1480       assign_text (texteditor, directive->display->str);
1481       // g_object_set_data(texteditor, "gstring", directive->display);
1482       g_object_set_data (G_OBJECT (directive->widget), DENEMO_TEXTEDITOR_TAG, texteditor);
1483     }
1484 }
1485 
1486 /*
1487   widget_for_directive()
1488   if directive does not have widget:
1489 
1490      creates a widget (button or menu depending on fn) for editing/actioning directive, point directive->widget to it and attach a callback to edit/action this directive, passing fn as data to it (to say what sort of directive it is) or the directive itself (for actionscripts/editscripts).
1491 
1492 if directive is non-DenemoObject directive it  places the widget in the appropriate buttonbox/menu, the directives attached to DenemoObjects have menus created dynamically. (fn gives the type of directive: it determines where the widget goes (score or movement level, DenemoProject or DenemoMovement respectively, or in staff or voice menu))
1493 
1494      set  the label for the widget from directive->display or the tag if no display text
1495      set  the visibility for the widget from directive->override
1496 */
1497 
1498 void
widget_for_directive_menu(DenemoDirective * directive,void fn (),GtkMenu * menu)1499 widget_for_directive_menu (DenemoDirective * directive, void fn (), GtkMenu * menu)
1500 {
1501   if(Denemo.non_interactive) return;
1502   GtkWidget *box;
1503   gchar *value = "";
1504   //FIXME we don't need value now...
1505   if (directive->override & DENEMO_OVERRIDE_EDITOR)
1506     {
1507       value = directive->tag->str;
1508     }
1509   else if (directive->display)
1510     value = directive->display->str;
1511   value = get_label_text (directive, value);
1512   if (!Denemo.non_interactive && directive->widget == NULL)
1513     {
1514       //FIXME at this point you could allow the user to specify a custom button box for his directive - some property of the directive saying which button box it should be in. We could even allow the directive to create a toolitem of a toolbar or menuitem on a menu bar???
1515 
1516       if (fn == (void (*)()) score_directive_put_graphic || fn == (void (*)()) scoreheader_directive_put_graphic || fn == (void (*)()) paper_directive_put_graphic || fn == (void (*)()) layout_directive_put_graphic)
1517         box = Denemo.project->buttonbox;
1518       else if (fn == (void (*)()) movementcontrol_directive_put_graphic || fn == (void (*)()) header_directive_put_graphic)
1519         box = Denemo.project->movement->buttonbox;
1520       else
1521         box = NULL;
1522 
1523       if ((fn == (void (*)()) staff_directive_put_graphic) || (fn == (void (*)()) voice_directive_put_graphic))
1524         {
1525 #if 0
1526 voice and staff directives no longer have these popup menus, instead the staff voice editor is used.
1527 however, at least the rest of this code expects a valid GtkWidget...
1528 #endif
1529           //g_debug("Doing the staff or voice case");
1530           directive->widget = GTK_WIDGET (gtk_menu_item_new_with_label (value));        //WARNING _with_label is important
1531           attach_textedit_widget (directive);
1532           g_signal_connect (G_OBJECT (directive->widget), "button-release-event", G_CALLBACK (button_callback), directive);
1533           gtk_menu_shell_append (GTK_MENU_SHELL (menu), GTK_WIDGET (directive->widget));
1534 
1535         }
1536       else if (box)
1537         {
1538           //g_debug("Doing the score and movement cases starting from %p", directive->widget);
1539           directive->widget = GTK_WIDGET (gtk_button_new_with_label (value));
1540           gchar *tooltip;
1541           const gchar *label = get_label_for_command (directive->tag->str);
1542           const gchar *help = get_tooltip_for_command (directive->tag->str);
1543           if (label)
1544             tooltip = g_strdup_printf (_("Command: %s.\n(%s)" "\nLeft click to run the command or right click for further options"), label, help ? help : "");
1545           else
1546             tooltip = g_strdup_printf (_("This button was created for the Denemo Directive whose tag is %s." " Usually you click on it to alter the setting made or perform the action it is labelled with"), directive->tag->str);     //FIXME enable scripters to pass a tooltip in???
1547           gtk_widget_set_tooltip_text (directive->widget, tooltip);
1548           g_free (tooltip);
1549 
1550           {
1551             GtkWidget *label = gtk_bin_get_child (GTK_BIN (directive->widget));
1552             gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
1553           }
1554           attach_textedit_widget (directive);
1555           g_signal_connect (G_OBJECT (directive->widget), /*"activate" we want to use gtk_widget_activate on this */ "button-release-event", G_CALLBACK (button_callback), directive);
1556 
1557 
1558           g_signal_connect (G_OBJECT (directive->widget), "activate", G_CALLBACK (button_activate_callback), directive);
1559 
1560 
1561 
1562           if (box)
1563             {
1564               gtk_box_pack_start (GTK_BOX (box), GTK_WIDGET (directive->widget), FALSE, TRUE, 0);
1565               gtk_widget_show (box);
1566             }
1567         }
1568       else
1569         {
1570           directive->widget = gtk_menu_item_new_with_label (value);
1571           attach_textedit_widget (directive);
1572           g_signal_connect (G_OBJECT (directive->widget), "button-release-event", G_CALLBACK (button_callback), directive);
1573         }
1574       g_object_set_data (G_OBJECT (directive->widget), "directive", (gpointer) directive);
1575       g_object_set_data (G_OBJECT (directive->widget), "fn", (gpointer) fn);
1576       //GTK_WIDGET_UNSET_FLAGS(directive->widget, GTK_CAN_FOCUS);
1577       gtk_widget_set_can_focus (directive->widget, FALSE);
1578     }                           //end of no widget
1579 
1580   (directive->override & DENEMO_OVERRIDE_GRAPHIC) ? gtk_widget_show (GTK_WIDGET (directive->widget)) : gtk_widget_hide (GTK_WIDGET (directive->widget));
1581 
1582   // here handle the case where widget has a GtkTextView editing the text in value
1583   if (directive->display)
1584     {
1585       GtkWidget *texteditor = (GtkWidget *) g_object_get_data (G_OBJECT (directive->widget), DENEMO_TEXTEDITOR_TAG);
1586       if (texteditor)
1587         assign_text (texteditor, directive->display->str);
1588     }
1589   set_directive_graphic_label (directive);
1590   g_free (value);
1591 }
1592 
1593 void
widget_for_directive(DenemoDirective * directive,void fn ())1594 widget_for_directive (DenemoDirective * directive, void fn ())
1595 {
1596   if(Denemo.non_interactive) return;
1597   GtkMenu *menu = NULL;
1598   if (Denemo.project->movement)
1599     {
1600       if (fn == (void (*)()) staff_directive_put_graphic)
1601         {
1602           menu = ((DenemoStaff *) Denemo.project->movement->currentstaff->data)->staffmenu;
1603         }
1604       if (fn == (void (*)()) voice_directive_put_graphic)
1605         {
1606           menu = ((DenemoStaff *) Denemo.project->movement->currentstaff->data)->voicemenu;
1607         }
1608     }
1609   widget_for_directive_menu (directive, fn, menu);
1610 }
1611 
1612 void
widget_for_staff_directive(DenemoDirective * directive,GtkMenu * menu)1613 widget_for_staff_directive (DenemoDirective * directive, GtkMenu * menu)
1614 {
1615   return widget_for_directive_menu (directive, (void (*)()) staff_directive_put_graphic, menu);
1616 }
1617 
1618 void
widget_for_voice_directive(DenemoDirective * directive,GtkMenu * menu)1619 widget_for_voice_directive (DenemoDirective * directive, GtkMenu * menu)
1620 {
1621   return widget_for_directive_menu (directive, (void (*)()) voice_directive_put_graphic, menu);
1622 }
1623 
1624 void
widget_for_movementcontrol_directive(DenemoDirective * directive)1625 widget_for_movementcontrol_directive (DenemoDirective * directive)
1626 {
1627   return widget_for_directive_menu (directive, (void (*)()) movementcontrol_directive_put_graphic, NULL);
1628 }
1629 
1630 void
widget_for_header_directive(DenemoDirective * directive)1631 widget_for_header_directive (DenemoDirective * directive)
1632 {
1633   return widget_for_directive_menu (directive, (void (*)()) header_directive_put_graphic, NULL);
1634 }
1635 
1636 void
widget_for_layout_directive(DenemoDirective * directive)1637 widget_for_layout_directive (DenemoDirective * directive)
1638 {
1639   return widget_for_directive_menu (directive, (void (*)()) layout_directive_put_graphic, NULL);
1640 }
1641 
1642 // create a directive for non-DenemoObject directive #what
1643 // assigning the string VALUE to the field ##field
1644 // also create a button or menuitem ( if it does not already exist) as the directive->widget, this will be used to edit/action the directive
1645 // Compare this with the macros above which create the what##_directive_put_##field() without calling widget_for_directive() and so do not create a widget in the graphic field, except via the user setting graphic_name.
1646 
1647 #define PUT_GRAPHIC_WIDGET_STR(field, what, name) \
1648 gboolean \
1649 what##_directive_put_##field(gchar *tag, gchar *value) {\
1650   what *current = get_##what();\
1651   if(current==NULL) return FALSE;\
1652   if(current->name==NULL)\
1653        create_directives (&current->name, tag);\
1654   DenemoDirective *directive = get_##what##_directive(tag);\
1655   if(directive==NULL){\
1656     directive=new_directive(tag);\
1657     current->name = g_list_append(current->name, directive);\
1658     }\
1659   if(directive->field)\
1660     g_string_assign(directive->field, value);\
1661   else\
1662     directive->field = g_string_new(value);\
1663   if(!Denemo.non_interactive){\
1664     widget_for_directive(directive, (void(*)())what##_directive_put_graphic);\
1665     g_object_set_data(G_OBJECT(directive->widget), "directives-pointer", (gpointer)&current->name); \
1666   }\
1667   return TRUE;\
1668 }
1669 
1670 
1671 #define PUT_GRAPHIC_WIDGET_INT(field, what, name)\
1672 gboolean \
1673 what##_directive_put_##field(gchar *tag, gint value) {\
1674   what *current = get_##what();\
1675   if(current==NULL) return FALSE;\
1676   if(current->name==NULL)\
1677        create_directives (&current->name, tag);\
1678   DenemoDirective *directive = get_##what##_directive(tag);\
1679   if(directive==NULL){\
1680     directive=new_directive(tag);\
1681     current->name = g_list_append(current->name, directive);\
1682     }\
1683   directive->field = value;\
1684   if(!Denemo.non_interactive){\
1685     widget_for_directive(directive, (void(*)())what##_directive_put_graphic);\
1686     g_object_set_data(G_OBJECT(directive->widget), "directives-pointer", &current->name);\
1687   }\
1688   return TRUE;\
1689 }
1690 
1691 
1692 //As the above (for string and int) but for the graphic name field
1693 //FIXME this is just storing the graphic name, any bitmap of that name could be placed on the button/menu item as an icon
1694 #define PUT_GRAPHIC_WIDGET_GRAPHIC(what, name) gboolean \
1695 what##_directive_put_graphic(gchar *tag, gchar *value) {\
1696   what *current = get_##what();\
1697   if(current==NULL) return FALSE;\
1698   if(current->name==NULL)\
1699        create_directives (&current->name, tag);\
1700   DenemoDirective *directive = get_##what##_directive(tag);\
1701   if(directive==NULL){\
1702     directive=new_directive(tag);\
1703     current->name = g_list_append(current->name, directive);\
1704     }\
1705   if(directive->graphic_name==NULL) \
1706     directive->graphic_name = g_string_new(value);\
1707   else\
1708     g_string_assign(directive->graphic_name, value);\
1709   if(!Denemo.non_interactive){\
1710     widget_for_directive(directive, (void(*)())what##_directive_put_graphic);\
1711     g_object_set_data(G_OBJECT(directive->widget), "directives-pointer", &current->name);\
1712   }\
1713   return directive != NULL;\
1714 }
1715 
1716 PUT_GRAPHIC_WIDGET_GRAPHIC (score, directives)
1717 PUT_GRAPHIC_WIDGET_GRAPHIC (scoreheader, directives)
1718 PUT_GRAPHIC_WIDGET_GRAPHIC (header, directives)
1719 PUT_GRAPHIC_WIDGET_GRAPHIC (paper, directives)
1720 PUT_GRAPHIC_WIDGET_GRAPHIC (layout, directives)
1721 PUT_GRAPHIC_WIDGET_GRAPHIC (movementcontrol, directives)
1722 PUT_GRAPHIC_WIDGET_GRAPHIC (staff, staff_directives)
1723 PUT_GRAPHIC_WIDGET_GRAPHIC (voice, voice_directives)
1724 PUT_GRAPHIC_WIDGET_STR (display, score, directives)
1725 PUT_GRAPHIC_WIDGET_STR (display, scoreheader, directives)
1726 PUT_GRAPHIC_WIDGET_STR (display, header, directives)
1727 PUT_GRAPHIC_WIDGET_STR (display, paper, directives)
1728 PUT_GRAPHIC_WIDGET_STR (display, layout, directives)
1729 PUT_GRAPHIC_WIDGET_STR (display, movementcontrol, directives)
1730 PUT_GRAPHIC_WIDGET_STR (display, staff, staff_directives)
1731 PUT_GRAPHIC_WIDGET_STR (display, voice, voice_directives)
1732 PUT_GRAPHIC_WIDGET_STR (prefix, score, directives)
1733 PUT_GRAPHIC_WIDGET_STR (prefix, scoreheader, directives)
1734 PUT_GRAPHIC_WIDGET_STR (prefix, header, directives)
1735 PUT_GRAPHIC_WIDGET_STR (prefix, paper, directives)
1736 PUT_GRAPHIC_WIDGET_STR (prefix, layout, directives)
1737 PUT_GRAPHIC_WIDGET_STR (prefix, movementcontrol, directives)
1738 PUT_GRAPHIC_WIDGET_STR (prefix, staff, staff_directives)
1739 PUT_GRAPHIC_WIDGET_STR (prefix, voice, voice_directives)
1740 PUT_GRAPHIC_WIDGET_STR (postfix, score, directives)
1741 PUT_GRAPHIC_WIDGET_STR (postfix, scoreheader, directives)
1742 PUT_GRAPHIC_WIDGET_STR (postfix, header, directives)
1743 PUT_GRAPHIC_WIDGET_STR (postfix, paper, directives)
1744 PUT_GRAPHIC_WIDGET_STR (postfix, layout, directives)
1745 PUT_GRAPHIC_WIDGET_STR (postfix, movementcontrol, directives)
1746 PUT_GRAPHIC_WIDGET_STR (postfix, staff, staff_directives)
1747 PUT_GRAPHIC_WIDGET_STR (postfix, voice, voice_directives)
1748 PUT_GRAPHIC_WIDGET_STR (midibytes, score, directives)
1749 PUT_GRAPHIC_WIDGET_STR (midibytes, scoreheader, directives)
1750 PUT_GRAPHIC_WIDGET_STR (midibytes, header, directives)
1751 PUT_GRAPHIC_WIDGET_STR (midibytes, paper, directives)
1752 PUT_GRAPHIC_WIDGET_STR (midibytes, layout, directives)
1753 PUT_GRAPHIC_WIDGET_STR (midibytes, movementcontrol, directives)
1754 PUT_GRAPHIC_WIDGET_STR (midibytes, staff, staff_directives)
1755 PUT_GRAPHIC_WIDGET_STR (midibytes, voice, voice_directives)
1756 PUT_GRAPHIC_WIDGET_INT (minpixels, score, directives)
1757 PUT_GRAPHIC_WIDGET_INT (minpixels, scoreheader, directives)
1758 PUT_GRAPHIC_WIDGET_INT (minpixels, header, directives)
1759 PUT_GRAPHIC_WIDGET_INT (minpixels, paper, directives)
1760 PUT_GRAPHIC_WIDGET_INT (minpixels, layout, directives)
1761 PUT_GRAPHIC_WIDGET_INT (minpixels, movementcontrol, directives)
1762 PUT_GRAPHIC_WIDGET_INT (minpixels, staff, staff_directives)
1763 PUT_GRAPHIC_WIDGET_INT (minpixels, voice, voice_directives)
1764 PUT_GRAPHIC_WIDGET_INT (x, score, directives)
1765 PUT_GRAPHIC_WIDGET_INT (x, scoreheader, directives)
1766 PUT_GRAPHIC_WIDGET_INT (x, header, directives)
1767 PUT_GRAPHIC_WIDGET_INT (x, paper, directives)
1768 PUT_GRAPHIC_WIDGET_INT (x, layout, directives)
1769 PUT_GRAPHIC_WIDGET_INT (x, movementcontrol, directives)
1770 PUT_GRAPHIC_WIDGET_INT (x, staff, staff_directives)
1771 PUT_GRAPHIC_WIDGET_INT (x, voice, voice_directives)
1772 PUT_GRAPHIC_WIDGET_INT (y, score, directives)
1773 PUT_GRAPHIC_WIDGET_INT (y, scoreheader, directives)
1774 PUT_GRAPHIC_WIDGET_INT (y, header, directives)
1775 PUT_GRAPHIC_WIDGET_INT (y, paper, directives)
1776 PUT_GRAPHIC_WIDGET_INT (y, layout, directives)
1777 PUT_GRAPHIC_WIDGET_INT (y, movementcontrol, directives)
1778 PUT_GRAPHIC_WIDGET_INT (y, staff, staff_directives)
1779 PUT_GRAPHIC_WIDGET_INT (y, voice, voice_directives)
1780 PUT_GRAPHIC_WIDGET_INT (tx, score, directives)
1781 PUT_GRAPHIC_WIDGET_INT (tx, scoreheader, directives)
1782 PUT_GRAPHIC_WIDGET_INT (tx, header, directives)
1783 PUT_GRAPHIC_WIDGET_INT (tx, paper, directives)
1784 PUT_GRAPHIC_WIDGET_INT (tx, layout, directives)
1785 PUT_GRAPHIC_WIDGET_INT (tx, movementcontrol, directives)
1786 PUT_GRAPHIC_WIDGET_INT (tx, staff, staff_directives)
1787 PUT_GRAPHIC_WIDGET_INT (tx, voice, voice_directives)
1788 PUT_GRAPHIC_WIDGET_INT (ty, score, directives)
1789 PUT_GRAPHIC_WIDGET_INT (ty, scoreheader, directives)
1790 PUT_GRAPHIC_WIDGET_INT (ty, header, directives)
1791 PUT_GRAPHIC_WIDGET_INT (ty, paper, directives)
1792 PUT_GRAPHIC_WIDGET_INT (ty, layout, directives)
1793 PUT_GRAPHIC_WIDGET_INT (ty, movementcontrol, directives)
1794 PUT_GRAPHIC_WIDGET_INT (ty, staff, staff_directives)
1795 PUT_GRAPHIC_WIDGET_INT (ty, voice, voice_directives)
1796 PUT_GRAPHIC_WIDGET_INT (gx, score, directives)
1797 PUT_GRAPHIC_WIDGET_INT (gx, scoreheader, directives)
1798 PUT_GRAPHIC_WIDGET_INT (gx, header, directives)
1799 PUT_GRAPHIC_WIDGET_INT (gx, paper, directives)
1800 PUT_GRAPHIC_WIDGET_INT (gx, layout, directives)
1801 PUT_GRAPHIC_WIDGET_INT (gx, movementcontrol, directives)
1802 PUT_GRAPHIC_WIDGET_INT (gx, staff, staff_directives)
1803 PUT_GRAPHIC_WIDGET_INT (gx, voice, voice_directives)
1804 PUT_GRAPHIC_WIDGET_INT (gy, score, directives) PUT_GRAPHIC_WIDGET_INT (gy, scoreheader, directives) PUT_GRAPHIC_WIDGET_INT (gy, header, directives) PUT_GRAPHIC_WIDGET_INT (gy, paper, directives) PUT_GRAPHIC_WIDGET_INT (gy, layout, directives) PUT_GRAPHIC_WIDGET_INT (gy, movementcontrol, directives) PUT_GRAPHIC_WIDGET_INT (gy, staff, staff_directives) PUT_GRAPHIC_WIDGET_INT (gy, voice, voice_directives) PUT_GRAPHIC_WIDGET_INT (override, score, directives);
1805 PUT_GRAPHIC_WIDGET_INT (override, scoreheader, directives);
1806 PUT_GRAPHIC_WIDGET_INT (override, header, directives);
1807 PUT_GRAPHIC_WIDGET_INT (override, paper, directives);
1808 PUT_GRAPHIC_WIDGET_INT (override, layout, directives);
1809 PUT_GRAPHIC_WIDGET_INT (override, movementcontrol, directives);
1810 PUT_GRAPHIC_WIDGET_INT (override, staff, staff_directives);
1811 PUT_GRAPHIC_WIDGET_INT (override, voice, voice_directives);
1812 #undef PUT_GRAPHIC_WIDGET_STR
1813 #undef PUT_GRAPHIC_WIDGET_INT
1814 gboolean
standalone_directive_put_graphic(gchar * tag,gchar * value)1815 standalone_directive_put_graphic (gchar * tag, gchar * value)
1816 {
1817   DenemoDirective *directive = get_standalone_directive (tag);
1818   if (directive && directive->graphic)
1819     {
1820 
1821       // directive->graphic = NULL; FIXME should we do this...
1822       //g_string_free(directive->graphic_name, TRUE);
1823     }
1824   if (!directive)
1825     {
1826       DenemoObject *obj = lily_directive_new (" ");
1827       directive = (DenemoDirective *) obj->object;
1828       directive->tag = g_string_new (tag);
1829       object_insert (Denemo.project, obj);
1830       displayhelper (Denemo.project);
1831     }
1832   if (loadGraphicItem (value, &directive->graphic))
1833     {
1834       if (directive->graphic_name)
1835         g_string_assign (directive->graphic_name, value);
1836       else
1837         directive->graphic_name = g_string_new (value);
1838       return TRUE;
1839     }
1840   else
1841     {
1842       directive->graphic = NULL;
1843       directive->graphic_name = NULL;
1844       return FALSE;
1845     }
1846 }
1847 
1848 
1849 
1850 #define STANDALONE_PUT_STR_FIELD_FUNC(field)\
1851 gboolean \
1852 standalone_directive_put_##field(gchar *tag, gchar *value) {\
1853   DenemoDirective *directive = get_standalone_directive(tag);\
1854   if(directive && directive->field){\
1855     store_for_undo_change (Denemo.project->movement, Denemo.project->movement->currentobject->data);\
1856     g_string_assign(directive->field, value);}              \
1857   else if(directive)\
1858     directive->field = g_string_new(value);\
1859   else {\
1860     DenemoObject *obj = lily_directive_new (" ");\
1861         directive = (DenemoDirective*)obj->object;\
1862         directive->tag = g_string_new(tag);\
1863         directive->field = g_string_new(value);\
1864     object_insert(Denemo.project, obj);\
1865     displayhelper(Denemo.project);\
1866    }\
1867   return TRUE;\
1868 }
1869 
1870 STANDALONE_PUT_STR_FIELD_FUNC (prefix);
1871 STANDALONE_PUT_STR_FIELD_FUNC (postfix);
1872 STANDALONE_PUT_STR_FIELD_FUNC (display);
1873 STANDALONE_PUT_STR_FIELD_FUNC (midibytes);
1874 
1875 STANDALONE_PUT_STR_FIELD_FUNC (grob);
1876 
1877 STANDALONE_PUT_STR_FIELD_FUNC (data);
1878 
1879 
1880 
1881 
1882 #define STANDALONE_PUT_INT_FIELD_FUNC(field)\
1883 gboolean \
1884 standalone_directive_put_##field(gchar *tag, gint value) {\
1885   DenemoDirective *directive = get_standalone_directive(tag);\
1886   if(directive){\
1887     store_for_undo_change (Denemo.project->movement, Denemo.project->movement->currentobject->data);\
1888     directive->field = value;}\
1889   else {\
1890         DenemoObject *obj = lily_directive_new (" ");\
1891         directive = (DenemoDirective*)obj->object;\
1892         directive->tag = g_string_new(tag);\
1893         directive->field = value;\
1894     object_insert(Denemo.project, obj);\
1895    }\
1896   return TRUE;\
1897 }
1898 
1899 //STANDALONE_PUT_INT_FIELD_FUNC(minpixels); special case
1900 STANDALONE_PUT_INT_FIELD_FUNC (x);
1901 STANDALONE_PUT_INT_FIELD_FUNC (y);
1902 STANDALONE_PUT_INT_FIELD_FUNC (tx);
1903 STANDALONE_PUT_INT_FIELD_FUNC (ty);
1904 STANDALONE_PUT_INT_FIELD_FUNC (gx);
1905 STANDALONE_PUT_INT_FIELD_FUNC (gy);
1906 
1907 STANDALONE_PUT_INT_FIELD_FUNC (override);
1908 
put_standalone_directive(gchar * tag,gint value)1909 void put_standalone_directive (gchar *tag, gint value) {
1910   DenemoObject *obj = lily_directive_new (" ");
1911   DenemoDirective *directive = (DenemoDirective *) obj->object;
1912   directive->tag = g_string_new (tag);
1913   obj->minpixelsalloted = directive->minpixels = value;
1914   object_insert (Denemo.project, obj);
1915 }
1916 
1917 gboolean
standalone_directive_put_minpixels(gchar * tag,gint value)1918 standalone_directive_put_minpixels (gchar * tag, gint value)
1919 {
1920   DenemoDirective *directive = get_standalone_directive (tag);
1921   if (directive)
1922     {
1923       directive->minpixels = value;     //This field is not actually useful for standalone directives.
1924       DenemoObject *obj = get_object ();
1925       store_for_undo_change (Denemo.project->movement, obj);
1926       obj->minpixelsalloted = value;
1927     }
1928   else
1929     {
1930       put_standalone_directive (tag, value);
1931     }
1932   return TRUE;
1933 }
1934 
1935 
1936 
1937 static gboolean
tag_choice(GtkWidget * widget,DenemoDirective ** response)1938 tag_choice (GtkWidget * widget, DenemoDirective ** response)
1939 {
1940   if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget)))
1941     *response = g_object_get_data (G_OBJECT (widget), "choice");
1942   return TRUE;
1943 }
1944 
1945 static void
tag_none(GtkWidget * widget,DenemoDirective ** response)1946 tag_none (GtkWidget * widget, DenemoDirective ** response)
1947 {
1948   *response = NULL;
1949 }
1950 
1951 #define UNKNOWN_TAG "<Unknown Tag>"
1952 
1953 /* pack radio buttons for directive choice */
1954 static gint
pack_buttons(GtkWidget * vbox,GList * directives,DenemoDirective ** response)1955 pack_buttons (GtkWidget * vbox, GList * directives, DenemoDirective ** response)
1956 {
1957   GList *g;
1958   gint count;
1959   GtkWidget *widget = NULL, *widget2;
1960   for (count = 0, g = directives; g; g = g->next)
1961     {
1962       DenemoDirective *directive = (DenemoDirective *) g->data;
1963       if (directive->tag == NULL)
1964         directive->tag = g_string_new (UNKNOWN_TAG);
1965       count++;
1966       if (*response == NULL)
1967         *response = directive;
1968       if (widget == NULL)
1969         {
1970           widget = gtk_radio_button_new_with_label (NULL, directive->tag->str); //FIXME get_label_for_tag() and get_tooltip_for_tag() here!!!
1971           g_object_set_data (G_OBJECT (widget), "choice", directive);
1972           g_signal_connect (G_OBJECT (widget), "toggled", G_CALLBACK (tag_choice), response);
1973           gtk_box_pack_start (GTK_BOX (vbox), widget, FALSE, TRUE, 0);
1974         }
1975       else
1976         {
1977           widget2 = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON (widget), directive->tag->str);
1978           g_object_set_data (G_OBJECT (widget2), "choice", directive);
1979           g_signal_connect (G_OBJECT (widget2), "toggled", G_CALLBACK (tag_choice), response);
1980           gtk_box_pack_start (GTK_BOX (vbox), widget2, FALSE, TRUE, 0);
1981         }
1982     }
1983   return count;
1984 }
1985 
1986 
1987 /* let the user choose from a list of directives */
1988 static DenemoDirective *
select_directive(gchar * instr,GList * directives)1989 select_directive (gchar * instr, GList * directives)
1990 {
1991 
1992   GtkWidget *dialog = gtk_dialog_new_with_buttons (_("Select Directive"),
1993                                                    GTK_WINDOW (Denemo.window),
1994                                                    (GtkDialogFlags) (GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT),
1995                                                    _("_OK"), GTK_RESPONSE_ACCEPT,
1996                                                    _("_Cancel"), GTK_RESPONSE_REJECT,
1997                                                    NULL);
1998 
1999 
2000   GtkWidget *vbox = gtk_vbox_new (FALSE, 8);
2001   GtkWidget *content_area;
2002   if(g_list_length(directives)>Denemo.prefs.max_menu_size) //this doesn't avoid menu running off screen but allows the user to cancel in that case
2003     {
2004     content_area = gtk_dialog_get_action_area (GTK_DIALOG (dialog));
2005     gtk_box_pack_start (GTK_BOX (content_area), vbox, FALSE, TRUE, 0);
2006     } else
2007     {
2008     content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
2009     gtk_container_add (GTK_CONTAINER (content_area), vbox);
2010     }
2011 
2012   DenemoDirective *response = NULL;
2013 
2014 /*
2015     void                user_function                      (GtkDialog *arg0,
2016                                                         gpointer   user_data)      : Action
2017     The ::close signal is a keybinding signal which gets emitted when the user uses a keybinding to close the dialog.
2018     The default binding for this signal is the Escape key.
2019 */
2020   g_signal_connect (G_OBJECT (dialog), "close", G_CALLBACK (tag_none), &response);
2021 
2022 
2023 
2024   gint count;                   //count tagged directives
2025   GtkWidget *widget;
2026   widget = gtk_label_new (instr);
2027   gtk_box_pack_start (GTK_BOX (vbox), widget, FALSE, TRUE, 0);
2028   count = pack_buttons (vbox, directives, &response);
2029 
2030   if (count > 0)
2031     {
2032       gtk_widget_show_all (dialog);
2033       if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_REJECT)
2034         {
2035           response = NULL;
2036         }
2037     }
2038   gtk_widget_destroy (dialog);
2039   //if(response && response->tag)
2040   //g_debug("Came back with response %s\n", response->tag->str);
2041   return response;
2042 }
2043 
2044 
2045 /* let the user choose from the directives at the cursor */
2046 static void
user_select_directive_at_cursor(gchar ** what,GList *** pdirectives,DenemoDirective ** pdirective)2047 user_select_directive_at_cursor (gchar ** what, GList *** pdirectives, DenemoDirective ** pdirective)
2048 {
2049   *pdirectives = NULL;
2050   *pdirective = get_standalone_directive (NULL);
2051 
2052   if (*pdirective)
2053     return;                     //FIXME is this needed???? a return will be done anyway
2054 
2055   {
2056     tuplet *curtuplet = get_tuplet ();
2057     if (curtuplet && curtuplet->directives)
2058       {
2059         gchar *instr = get_object()->type==TUPOPEN? _("Select a directive attached to the tuplet start object"):
2060                     _("Select a directive attached to the tuplet end object");
2061         *pdirectives = &curtuplet->directives;
2062         *what = "tuplet";
2063         *pdirective = select_directive (instr, **pdirectives);
2064       }
2065   }
2066   {
2067     gchar *instr = _("Select a directive attached to the stem control object");
2068     stemdirective *curstemdir = get_stemdirective ();
2069     if (curstemdir && curstemdir->directives)
2070       {
2071         *pdirectives = &curstemdir->directives;
2072         *what = "stemdir";
2073         *pdirective = select_directive (instr, **pdirectives);
2074       }
2075 
2076   }
2077 
2078   gchar *name = NULL;
2079   note *curnote = get_note ();
2080   if (curnote != NULL)
2081     {
2082       name = mid_c_offsettolily (curnote->mid_c_offset, curnote->enshift);
2083       if (curnote->mid_c_offset == Denemo.project->movement->cursor_y)
2084         if (curnote->directives)
2085           {
2086             *pdirectives = &curnote->directives;
2087             *what = "note";
2088             gchar *instr = g_strdup_printf (_("Select a directive attached to the note \"%s\""), name);
2089             if (g_list_length (curnote->directives) == 1)
2090                 *pdirective = (DenemoDirective*)(curnote->directives->data);
2091             else
2092                 *pdirective = select_directive (instr, **pdirectives);
2093             g_free (instr);
2094             if (*pdirective)
2095               {
2096                 g_free (name);
2097                 return;
2098               }
2099           }
2100     }
2101 
2102 
2103   {
2104     // not exactly on a note, offer any chord directives
2105     gchar *instr = _("Select a directive attached to the chord");
2106     chord *curchord = get_chord ();
2107     if (curchord && curchord->directives)
2108       {
2109         *pdirectives = &curchord->directives;
2110         *what = "chord";
2111         if (g_list_length (curchord->directives) == 1)
2112             *pdirective = (DenemoDirective*)(curchord->directives->data);
2113         else
2114             *pdirective = select_directive (instr, **pdirectives);
2115       }
2116   }
2117   if (*pdirective == NULL && curnote)   //try nearest note
2118     if (curnote->directives && curnote->mid_c_offset != Denemo.project->movement->cursor_y)
2119       {
2120         *pdirectives = &curnote->directives;
2121         *what = "note";
2122         gchar *instr = g_strdup_printf (_("Select a directive attached to the note \"%s\""), name);
2123         if (g_list_length (curnote->directives) == 1)
2124             *pdirective = (DenemoDirective*)(curnote->directives->data);
2125         else
2126             *pdirective = select_directive (instr, **pdirectives);
2127         g_free (instr);
2128         if (*pdirective && (g_list_length (**pdirectives) == 1))
2129           {
2130             /* seek confirmation of the choice of this directive since it is on a note not pointed at and
2131                has been chosen automatically. */
2132             gchar *name = mid_c_offsettolily (curnote->mid_c_offset, curnote->enshift);
2133             gchar *msg = g_strdup_printf (_("Select the directive %s on note \"%s\"?"), (*pdirective)->tag->str, name);
2134 
2135             if (!confirm (_("Select Directive"), msg))
2136               *pdirective = NULL;
2137             g_free (name);
2138             g_free (msg);
2139           }
2140       }
2141   g_free (name);
2142   return;
2143 }
2144 
choose_tag_at_cursor(gchar ** ptag)2145 gboolean choose_tag_at_cursor (gchar **ptag) {
2146     gchar *what;
2147     GList **ppdirectives;
2148     DenemoDirective *pdirective;
2149     user_select_directive_at_cursor (&what, &ppdirectives, &pdirective);
2150     if (pdirective && (pdirective->tag == NULL))
2151         pdirective->tag = g_string_new ("<Unknown Tag>");
2152     *ptag = pdirective?pdirective->tag->str:NULL;
2153     return g_strcmp0 (what, "chord");
2154 }
2155 
2156 
2157 
2158 
2159 
2160 
2161 
2162 
2163 
2164 
2165 
2166 
2167 
2168 
2169 static void
populate_menu_for_directive(GtkWidget * menu,DenemoDirective * directive)2170 populate_menu_for_directive (GtkWidget * menu, DenemoDirective * directive)
2171 {
2172   GtkWidget *item = gtk_menu_item_new_with_label (directive->tag->str);
2173   gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), GTK_WIDGET (item));
2174   g_signal_connect (G_OBJECT (item), "activate", G_CALLBACK (button_activate_callback), directive);
2175   gtk_widget_show (item);
2176 
2177 }
2178 
2179 static void
populate_menu_for_directives(GtkWidget * menu,GList * directives)2180 populate_menu_for_directives (GtkWidget * menu, GList * directives)
2181 {
2182   g_object_set_data (G_OBJECT (menu), "directives", directives);
2183   //g_debug("setting directives %p for menu %p\n", directives, menu);
2184   for (; directives; directives = directives->next)
2185     {
2186       populate_menu_for_directive (menu, directives->data);
2187     }
2188 }
2189 
2190 /* callback for deactivate signal installed at startup on the NoteEditPopup menu
2191    it removes the menu items for the specific note
2192  */
2193 gboolean
unpopulate_menu(GtkWidget * menu)2194 unpopulate_menu (GtkWidget * menu)
2195 {
2196   GList *directives = g_object_get_data (G_OBJECT (menu), "directives");
2197   //g_debug("removing directives %p for menu %p\n", directives, menu);
2198   for (; directives; directives = directives->next)
2199     {
2200       DenemoDirective *directive = directives->data;
2201       //g_debug("now remove %p\n", directive->widget);
2202       if (directive->widget)
2203         gtk_container_remove (GTK_CONTAINER (menu), directive->widget);
2204     }
2205   g_object_set_data (G_OBJECT (menu), "directives", NULL);
2206   return FALSE;
2207 }
2208 
2209 // edit the object at the cursor based on its type
2210 void
edit_object_type(GtkAction * action,DenemoScriptParam * param)2211 edit_object_type (GtkAction * action, DenemoScriptParam * param)
2212 {
2213   DenemoObject *obj = get_object ();
2214   if (obj == NULL)
2215     {
2216       warningmessage (_("No object here to edit"));
2217       return;
2218     }
2219   switch (obj->type)
2220     {
2221     case LILYDIRECTIVE:
2222       edit_object_directive (NULL, NULL);
2223       return;
2224     case CLEF:
2225       {
2226         popup_menu ("/ClefEditPopup");
2227       }
2228       return;
2229     case KEYSIG:
2230       {
2231         popup_menu ("/KeyEditPopup");
2232       }
2233       return;
2234     case TIMESIG:
2235       {
2236         popup_menu ("/TimeEditPopup");
2237       }
2238       return;
2239     case CHORD:
2240       {
2241 
2242           popup_menu ("/NoteEditPopupDirectives");
2243 
2244 
2245       }
2246       return;
2247 
2248     case STEMDIRECTIVE:
2249       {
2250         GList *directives = ((stemdirective *) obj->object)->directives;
2251         if (directives)
2252           {
2253             GtkWidget *menu = gtk_menu_new ();
2254             populate_menu_for_directives (menu, directives);
2255             gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL, 0, gtk_get_current_event_time ());
2256           }
2257         else
2258           {
2259             infodialog (_("Nothing to edit on this stem direction control object - use controls in Staffs → Voices menu"));
2260           }
2261       }
2262       return;
2263     case TUPOPEN:
2264       popup_menu ("/TupletPopup");
2265       return;
2266     case TUPCLOSE:
2267       infodialog (_("This marks the end of a tuplet (that is triplets etc) - it should come in the same measure as the tuplet start marker."));
2268       return;
2269     default:
2270       warningdialog (_("No method for editing this type of object"));
2271       return;
2272     }
2273 }
2274 
2275 
2276 static gboolean
set_gstring(GtkWidget * widget,GdkEventKey * event,GString * gstr)2277 set_gstring (GtkWidget * widget, GdkEventKey * event, GString * gstr)
2278 {
2279   g_string_assign (gstr, (gchar *) gtk_entry_get_text (GTK_ENTRY (widget)));
2280   return TRUE;
2281 }
2282 
2283 static gboolean
set_int(GtkSpinButton * widget,gint * val)2284 set_int (GtkSpinButton * widget, gint * val)
2285 {
2286   *val = gtk_spin_button_get_value_as_int (widget);
2287   return TRUE;
2288 }
2289 
2290 static gboolean
set_uint(GtkSpinButton * widget,guint * val)2291 set_uint (GtkSpinButton * widget, guint * val)
2292 {
2293   *val = (guint) gtk_spin_button_get_value (widget);
2294   return TRUE;
2295 }
2296 
2297 
2298 static gchar *
quote_scheme(gchar * s)2299 quote_scheme (gchar * s)
2300 {
2301   GString *dest = g_string_new ("");
2302   gchar *c;
2303   for (c = s; *c; c++)
2304     {
2305       if (*c == '"' || *c == '\\')
2306         g_string_append_c (dest, '\\');
2307       g_string_append_c (dest, *c);
2308     }
2309   return g_string_free (dest, FALSE);
2310 }
2311 
get_script_for_directive(DenemoDirective * directive,gchar * what)2312 gchar *get_script_for_directive (DenemoDirective* directive, gchar * what)
2313  {
2314   GString *scheme = g_string_new ("");
2315   g_string_append_printf (scheme, "(let ((tag \"%s\"))\n", directive->tag->str);
2316   if (what == NULL)
2317       what = "standalone";
2318 
2319   if (!strcmp (what, "standalone"))
2320       g_string_append (scheme, "(d-Directive-standalone tag)\n");
2321 #define ADD_TEXT(field)\
2322 if(directive->field && directive->field->len)\
2323   {gchar *quote = quote_scheme(directive->field->str);\
2324    g_string_append_printf(scheme, "(d-DirectivePut-%s-%s tag \"%s\")\n",\
2325        what, #field, quote);\
2326    g_free(quote);}
2327   ADD_TEXT (prefix);
2328   ADD_TEXT (postfix);
2329   ADD_TEXT (display);
2330   ADD_TEXT (grob);
2331   ADD_TEXT (midibytes);
2332   ADD_TEXT (data);
2333  //graphic_name is exceptional, the graphic field is filled in from it
2334 if(directive->graphic_name && directive->graphic_name->len)
2335   {
2336     gchar *quote = quote_scheme(directive->graphic_name->str);
2337     g_string_append_printf(scheme, "(d-DirectivePut-%s-graphic tag \"%s\")\n",
2338        what, quote);
2339     g_free(quote);
2340    }
2341 #undef ADD_TEXT
2342 #define ADD_INTTEXT(field)\
2343 if(directive->field)\
2344   g_string_append_printf(scheme, "(d-DirectivePut-%s-%s tag %d)\n",\
2345        what, #field, directive->field);
2346   ADD_INTTEXT (minpixels);
2347   ADD_INTTEXT (override);
2348   ADD_INTTEXT (x);
2349   ADD_INTTEXT (y);
2350   ADD_INTTEXT (tx);
2351   ADD_INTTEXT (ty);
2352   ADD_INTTEXT (gx);
2353   ADD_INTTEXT (gy);
2354 
2355 #undef ADD_INTTEXT
2356   g_string_append (scheme, "(d-SetSaved #f)(d-RefreshDisplay))\n");
2357   // quote_scheme(scheme);
2358   //g_debug("Scheme is %s\n", scheme->str);
2359    return g_string_free (scheme, FALSE);
2360 }
2361 
2362 static void
create_script(DenemoDirective * directive,gchar * what)2363 create_script (DenemoDirective * directive, gchar * what)
2364 {
2365   gchar *scheme = get_script_for_directive (directive, what);
2366   appendSchemeText (scheme);
2367   g_free (scheme);
2368 }
2369 
2370 
2371 /* callback to get an upload script of name tag */
2372 #ifdef UPLOAD_TO_DENEMO_DOT_ORG
2373 static void
upload_edit_script_cb(GtkWidget * widget,gchar * tag)2374 upload_edit_script_cb (GtkWidget * widget, gchar * tag)
2375 {
2376   gchar *filename = get_editscript_filename (tag);
2377   if (filename)
2378     {
2379       GError *error = NULL;
2380       gchar *script;
2381       if (g_file_get_contents (filename, &script, NULL, &error))
2382         upload_edit_script (tag, script);
2383       g_free (script);
2384       g_free (filename);
2385     }
2386 }
2387 #endif
2388 
2389 /* callback to get an edit script of name tag into the Scheme Script window */
2390 static void
get_edit_script(GtkWidget * widget,gchar * tag)2391 get_edit_script (GtkWidget * widget, gchar * tag)
2392 {
2393   gchar *filename = get_editscript_filename (tag);
2394   if (filename)
2395     {
2396       GError *error = NULL;
2397       gchar *script;
2398       if (g_file_get_contents (filename, &script, NULL, &error))
2399         appendSchemeText (script);
2400       else
2401         g_warning (_("Could not get contents of %s"), filename);
2402       g_free (script);
2403       g_free (filename);
2404     }
2405 }
2406 
2407 
2408 /* callback to save the scheme script text buffer as an edit script of name tag in the user's local denemo directory */
2409 static void
put_edit_script(GtkWidget * widget,gchar * tag)2410 put_edit_script (GtkWidget * widget, gchar * tag)
2411 {
2412   gchar *tagscm = g_strconcat (tag, ".scm", NULL);
2413   gchar *filename = g_build_filename (get_user_data_dir (TRUE), COMMANDS_DIR, "editscripts", tagscm, NULL);
2414   if ((!g_file_test (filename, G_FILE_TEST_EXISTS)) || confirm (_("There is already an edit script for this tag"), _("Do you want to replace it?")))
2415     {
2416       gchar *scheme = (gchar *) get_script_view_text ();
2417       if (scheme && *scheme)
2418         {
2419           FILE *fp = fopen (filename, "w");
2420           if (fp)
2421             {
2422               fprintf (fp, "%s", scheme);
2423               fclose (fp);
2424               infodialog (_("Wrote edit script file to ~/.denemo/editscripts"));
2425             }
2426           g_free (scheme);
2427         }
2428     }
2429   g_free (tagscm);
2430   g_free (filename);
2431 }
2432 
2433 static gboolean
activate_directive(DenemoDirective * directive,gchar * what)2434 activate_directive (DenemoDirective * directive, gchar * what)
2435 {
2436   if (directive->widget && GTK_IS_WIDGET (directive->widget))
2437     {
2438       g_debug ("Activate");
2439       gtk_widget_activate (directive->widget);
2440       //g_signal_emit!!!!!!!!!!!!!!! what do we do!!!!!!!!!!!(directive->widget, "button-release-event");
2441       return TRUE;
2442     }
2443   return FALSE;
2444 }
2445 
2446 /* text_edit_directive
2447    textually edit the directive via a dialog.
2448    return FALSE if the user requests deletion of the directive.
2449 */
2450 static gboolean
text_edit_directive(DenemoDirective * directive,gchar * what)2451 text_edit_directive (DenemoDirective * directive, gchar * what)
2452 {
2453   gboolean ret = TRUE;
2454 #define CREATE_SCRIPT (2)
2455   DenemoDirective *clone = clone_directive (directive); //for reset
2456 
2457   GtkWidget *dialog = gtk_dialog_new_with_buttons (_("Low Level Denemo Directive Edit"),
2458                                                    GTK_WINDOW (Denemo.window),
2459                                                    (GtkDialogFlags) (GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT),
2460                                                    _("_OK"), GTK_RESPONSE_ACCEPT,
2461                                                    _("_Cancel"), GTK_RESPONSE_CANCEL,
2462                                                    NULL);
2463   gtk_window_set_title (GTK_WINDOW (dialog), _("Denemo Object Editor"));
2464 
2465   gtk_dialog_add_button (GTK_DIALOG (dialog), _("Delete Directive"), GTK_RESPONSE_REJECT);
2466   gtk_dialog_add_button (GTK_DIALOG (dialog), _("Create Script"), CREATE_SCRIPT);
2467 
2468   GtkWidget *vbox = gtk_vbox_new (FALSE, 8);
2469   GtkWidget *content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
2470   gtk_container_add (GTK_CONTAINER (content_area), vbox);
2471 
2472   GtkWidget *hbox;
2473   GString *entrycontent = g_string_new ("");
2474   GtkWidget *entrywidget;
2475   GtkWidget *label;
2476   GtkWidget *button;
2477 #define TEXTENTRY(thelabel, field) \
2478   G_GNUC_UNUSED GtkWidget *field;\
2479   hbox = gtk_hbox_new (FALSE, 8);\
2480   gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);\
2481   label = gtk_label_new (_(thelabel));\
2482   gtk_misc_set_alignment (GTK_MISC (label), 1, 0.5);\
2483   gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);\
2484   entrywidget = gtk_entry_new ();\
2485   g_string_sprintf (entrycontent, "%s", directive->field?directive->field->str:"");\
2486   gtk_entry_set_text (GTK_ENTRY (entrywidget), entrycontent->str);\
2487   gtk_box_pack_start (GTK_BOX (hbox), entrywidget, TRUE, TRUE, 0);\
2488   if(directive->field==NULL) directive->field=g_string_new("");\
2489   g_signal_connect(G_OBJECT(entrywidget), "key-release-event", G_CALLBACK(set_gstring), directive->field);\
2490   g_string_assign(entrycontent, "");
2491 
2492 #define NEWINTENTRY(thelabel, field)\
2493   hbox = gtk_hbox_new (FALSE, 8);\
2494   gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);\
2495   label = gtk_label_new (_(thelabel));\
2496   gtk_misc_set_alignment (GTK_MISC (label), 1, 0.5);\
2497   gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);\
2498   entrywidget = gtk_spin_button_new_with_range (0.0, (gdouble)G_MAXUINT, 1.0);\
2499   gtk_spin_button_set_value (GTK_SPIN_BUTTON (entrywidget), directive->field);\
2500   gtk_box_pack_start (GTK_BOX (hbox), entrywidget, TRUE, TRUE, 0);\
2501   g_signal_connect(G_OBJECT(entrywidget), "value-changed", G_CALLBACK(set_int), &directive->field);
2502 #define NEWUINTENTRY(thelabel, field)\
2503   hbox = gtk_hbox_new (FALSE, 8);\
2504   gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);\
2505   label = gtk_label_new (_(thelabel));\
2506   gtk_misc_set_alignment (GTK_MISC (label), 1, 0.5);\
2507   gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);\
2508   entrywidget = gtk_spin_button_new_with_range (0.0, (gdouble)G_MAXUINT, 1.0);\
2509   gtk_spin_button_set_value (GTK_SPIN_BUTTON (entrywidget), *(guint*)&directive->field);\
2510   gtk_box_pack_start (GTK_BOX (hbox), entrywidget, TRUE, TRUE, 0);\
2511   g_signal_connect(G_OBJECT(entrywidget), "value-changed", G_CALLBACK(set_uint), &directive->field);
2512 #define ADDINTENTRY(thelabel, fieldx, fieldy)\
2513   label = gtk_label_new (_(thelabel));\
2514   gtk_misc_set_alignment (GTK_MISC (label), 1, 0.5);\
2515   gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);\
2516   label = gtk_label_new (_(" x:"));\
2517   gtk_misc_set_alignment (GTK_MISC (label), 1, 0.5);\
2518   gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);\
2519   entrywidget = gtk_spin_button_new_with_range (-(gdouble)G_MAXINT, (gdouble)G_MAXINT, 1.0);\
2520   gtk_spin_button_set_value (GTK_SPIN_BUTTON (entrywidget), directive->fieldx);\
2521   gtk_box_pack_start (GTK_BOX (hbox), entrywidget, TRUE, TRUE, 0);\
2522   g_signal_connect(G_OBJECT(entrywidget), "value-changed", G_CALLBACK(set_int), &directive->fieldx);\
2523   label = gtk_label_new (_(" y:"));\
2524   gtk_misc_set_alignment (GTK_MISC (label), 1, 0.5);\
2525   gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);\
2526   entrywidget = gtk_spin_button_new_with_range (-(gdouble)G_MAXINT, (gdouble)G_MAXINT, 1.0);\
2527   gtk_spin_button_set_value (GTK_SPIN_BUTTON (entrywidget), directive->fieldy);\
2528   gtk_box_pack_start (GTK_BOX (hbox), entrywidget, TRUE, TRUE, 0);\
2529   g_signal_connect(G_OBJECT(entrywidget), "value-changed", G_CALLBACK(set_int), &directive->fieldy);
2530 
2531   TEXTENTRY (_("Postfix"), postfix);
2532   TEXTENTRY (_("Prefix"), prefix);
2533   TEXTENTRY (_("Display text"), display);
2534   ADDINTENTRY (_("Text Position"), tx, ty);
2535   TEXTENTRY (_("Graphic"), graphic_name);
2536   ADDINTENTRY (_("Graphic Position"), gx, gy);
2537   TEXTENTRY (_("Tag"), tag);
2538   TEXTENTRY (_("LilyPond Grob Name"), grob);
2539     TEXTENTRY (_("Scheme Data"), data);
2540   TEXTENTRY (_("MidiBytes"), midibytes);
2541   NEWINTENTRY (_("Override Mask"), override);
2542   NEWINTENTRY (_("Minimum pixel width"), minpixels);
2543   NEWUINTENTRY (_("Only Applies to Layout"), y);
2544   NEWUINTENTRY (_("Ignored by Layout"), x);
2545 #undef TEXTENTRY
2546   hbox = gtk_hbox_new (FALSE, 8);
2547   gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);
2548   button = gtk_button_new_with_label (_("Get Edit Script"));
2549   gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
2550   g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (get_edit_script), directive->tag->str);
2551   button = gtk_button_new_with_label (_("Put Edit Script"));
2552   gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
2553   g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (put_edit_script), directive->tag->str);
2554 #ifdef UPLOAD_TO_DENEMO_DOT_ORG
2555 //disabled until website can take uploading again
2556   button = gtk_button_new_with_label (_("Upload Edit Script"));
2557   gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
2558   g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (upload_edit_script_cb), directive->tag->str);
2559 #endif
2560   button = gtk_check_button_new_with_label (_("Show Current Script"));
2561   gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
2562   gtk_activatable_set_related_action (GTK_ACTIVATABLE (button), gtk_ui_manager_get_action (Denemo.ui_manager, "/MainMenu/ViewMenu/ToggleScript"));
2563 
2564   gtk_widget_show_all (dialog);
2565   gint response = gtk_dialog_run (GTK_DIALOG (dialog));
2566   //g_debug("Got response %d\n", response);
2567 
2568 
2569   if (response == GTK_RESPONSE_CANCEL || response == GTK_RESPONSE_DELETE_EVENT || response == GTK_RESPONSE_REJECT)
2570     {
2571       GtkWidget *ref_widget = directive->widget;        //not cloned
2572       directive->widget = NULL; //prevent any button being destroyed
2573       free_directive_data (directive);
2574       memcpy (directive, clone, sizeof (DenemoDirective));
2575       directive->widget = ref_widget;
2576       if (response == GTK_RESPONSE_REJECT)
2577         {
2578           ret = FALSE;          //that is it may be deleted, we ensure it has not been changed first,as the tag is used for delelet
2579         }
2580     }
2581   else
2582     {
2583       clone->widget = NULL;     //prevent any button being destroyed FIXME ???
2584       free_directive (clone);
2585       score_status (Denemo.project, TRUE);
2586     }
2587 #define REMOVEEMPTIES(field)\
2588 if(directive->field && directive->field->len==0) g_string_free(directive->field, TRUE), directive->field=NULL;
2589   REMOVEEMPTIES (postfix);
2590   REMOVEEMPTIES (prefix);
2591   REMOVEEMPTIES (display);
2592   REMOVEEMPTIES (graphic_name);
2593 
2594   //REMOVEEMPTIES(tag); don't allow NULL tag
2595 #undef REMOVEEMPTIES
2596 
2597   if (directive->tag && directive->tag->len == 0)
2598     directive->tag = g_string_new (UNKNOWN_TAG);
2599   if (directive->widget)
2600     {
2601       if (GTK_IS_WIDGET (directive->widget))
2602         widget_for_directive (directive, NULL /* no need to pass fn in as it is only needed if there is not widget, g_object_get_data(directive->widget, "fn") */ );
2603     }
2604   if (directive->graphic_name && directive->graphic)
2605     {
2606       loadGraphicItem (directive->graphic_name->str, (DenemoGraphic **) & directive->graphic);
2607     }
2608   gtk_widget_destroy (dialog);
2609   if (what && (response == CREATE_SCRIPT))
2610     create_script (directive, what);    //g_debug("(d-DirectivePut-%s \"%s\")\n", what, directive->tag->str);
2611   return ret;
2612 }
low_level_directive_edit(DenemoDirective * directive)2613 gboolean low_level_directive_edit (DenemoDirective *directive)
2614 {
2615   return text_edit_directive (directive, NULL);
2616 
2617 }
2618 #define TEXT_EDIT_IF(what)\
2619   if(fn == (void(*)())what##_directive_put_graphic)\
2620     return text_edit_directive(directive, #what);
2621 static gboolean
text_edit_directive_by_fn(DenemoDirective * directive,gpointer fn)2622 text_edit_directive_by_fn (DenemoDirective * directive, gpointer fn)
2623 {
2624   TEXT_EDIT_IF (note);
2625   TEXT_EDIT_IF (chord);
2626   TEXT_EDIT_IF (staff);
2627   TEXT_EDIT_IF (voice);
2628   TEXT_EDIT_IF (score);
2629   TEXT_EDIT_IF (clef);
2630   TEXT_EDIT_IF (timesig);
2631   TEXT_EDIT_IF (tuplet);
2632   TEXT_EDIT_IF (stemdirective);
2633   TEXT_EDIT_IF (keysig);
2634   TEXT_EDIT_IF (scoreheader);
2635   TEXT_EDIT_IF (header);
2636   TEXT_EDIT_IF (paper);
2637   TEXT_EDIT_IF (layout);
2638   TEXT_EDIT_IF (movementcontrol);
2639   TEXT_EDIT_IF (standalone);
2640   return TRUE;
2641 }
2642 
2643 #undef TEXT_EDIT_IF
2644 
2645 
2646 
2647 /* allow edit of a directive, either via script or textually if no script exists
2648    return FALSE if user confirms a request to delete the directive
2649 */
2650 static gboolean
edit_directive(DenemoDirective * directive,gchar * what)2651 edit_directive (DenemoDirective * directive, gchar * what)
2652 {
2653   gboolean ret = TRUE;
2654   gchar *filename = get_editscript_filename (directive->tag->str);
2655   if (filename == NULL)
2656     {
2657       GtkAction *action;
2658       gchar *eol;
2659       gboolean chopped = FALSE;
2660       for (eol = directive->tag->str; *eol; eol++)
2661         {
2662           if (*eol == '\n')
2663             {
2664               *eol = 0;
2665               chopped = TRUE;
2666               break;
2667             }
2668         }
2669 
2670       action = lookup_action_from_name (directive->tag->str);
2671       if (chopped)
2672         *eol = '\n';
2673       if (action && !shift_held_down())
2674         {
2675           DenemoScriptParam param;
2676           param.string = g_string_new ("edit");
2677           g_debug ("Script can look for params \"edit\" - a string to catch this");
2678           activate_script (action, &param);
2679           g_string_free (param.string, TRUE);
2680         }
2681       else
2682         { if (what || shift_held_down())
2683             {
2684                 ret = (text_edit_directive (directive, what) || !confirm (_("Directive Delete"), _("Are you sure you want to delete the directive?")));
2685                 score_status (Denemo.project, TRUE);
2686             }
2687         else
2688             edit_object();
2689         }
2690       return ret;
2691     }
2692   GError *error = (GError *) execute_script_file (filename);
2693   if (error)
2694     g_warning ("%s", error->message);
2695   g_free (filename);
2696   return ret;
2697 }
2698 
2699 
2700 /**
2701  * callback for EditDirective on directive attached to an object.
2702  */
2703 void
edit_object_directive(GtkAction * action,DenemoScriptParam * param)2704 edit_object_directive (GtkAction * action, DenemoScriptParam * param)
2705 {
2706   //g_debug("Edit directive called\n");
2707   DenemoDirective *directive;
2708   GList **directives;
2709   gchar *what = NULL;
2710   user_select_directive_at_cursor (&what, &directives, &directive);
2711 
2712   if (directive == NULL)
2713     {
2714       if (directives && *directives != NULL)
2715         infodialog (_("Cancelled"));
2716       else
2717         warningdialog (_("Use the ObjectMenu to modify this object - there are no directives here"));
2718       return;
2719     }
2720   if (directive->tag == NULL)
2721     directive->tag = g_string_new (UNKNOWN_TAG);
2722   if (!(param ? text_edit_directive (directive, what) : edit_directive (directive, what)))
2723     {
2724       if (directives && *directives)
2725         {
2726           delete_directive (directives, directive->tag->str);
2727         }
2728       else
2729         {                       //standalone directive
2730           dnm_deleteobject (Denemo.project->movement);
2731         }
2732     }
2733   if (Denemo.project->movement->currentobject)        //for standalone directive
2734     setpixelmin (Denemo.project->movement->currentobject->data);
2735 }
2736 
2737 /**
2738  * callback for DeleteDirective
2739  */
2740 void
delete_chord_or_note_directive(GtkAction * action,DenemoScriptParam * param)2741 delete_chord_or_note_directive (GtkAction * action, DenemoScriptParam * param)
2742 {
2743   //g_debug("Edit directive called\n");
2744   DenemoDirective *directive;
2745   GList **directives;
2746   gchar *what = NULL;
2747   user_select_directive_at_cursor (&what, &directives, &directive);
2748   //g_debug("Got directive %p in list %p\n", directive, directives);
2749   if (directives == NULL)
2750     {
2751       warningdialog (_("No directives here"));
2752       return;
2753     }
2754   if (directive == NULL)
2755     {
2756       warningdialog (_("No directive selected"));
2757       return;
2758     }
2759   if (directive->tag == NULL)
2760     directive->tag = g_string_new (UNKNOWN_TAG);
2761   if (confirm (_("Directive Delete"), _("Are you sure you want to delete the directive?")))
2762     delete_directive (directives, directive->tag->str);
2763   else
2764     warningdialog (_("Operation cancelled"));
2765 }
2766 
2767 static GList *all_directives = NULL;
2768 static GList *directive_types = NULL;
2769 static void
append_directives(DenemoDirective * direc,gchar * type)2770 append_directives (DenemoDirective *direc, gchar *type)
2771 {
2772     all_directives = g_list_append (all_directives, direc);
2773     directive_types = g_list_append (directive_types, type);g_print("tag %s\n", direc->tag->str);
2774 }
2775 
2776 static gint
select_system_directive(void)2777 select_system_directive (void)
2778 {
2779 
2780     g_list_foreach (Denemo.project->lilycontrol.directives, (GFunc)append_directives, "lilycontrol");
2781     g_list_foreach (Denemo.project->scoreheader.directives, (GFunc)append_directives, "scoreheader");
2782     g_list_foreach (Denemo.project->paper.directives, (GFunc)append_directives, "paper");
2783     g_list_foreach (Denemo.project->movement->header.directives, (GFunc)append_directives, "header");
2784     g_list_foreach (Denemo.project->movement->layout.directives, (GFunc)append_directives, "layout");
2785     g_list_foreach (Denemo.project->movement->movementcontrol.directives, (GFunc)append_directives, "movementcontrol");
2786     if(all_directives)
2787         {
2788             DenemoDirective *d;
2789             d = select_directive (_("Select a score or movement directive for advanced (low-level) edit.\nNote: these directives can be edited normally using Score/Movement Properties Editor from the Score or Movement menus."), all_directives);
2790             if (d)
2791                 return g_list_index (all_directives, d);
2792         }
2793     return -1;
2794 }
edit_system_directive(void)2795 void edit_system_directive (void)
2796 {
2797     gint index = select_system_directive ();
2798     if(index >= 0)
2799         {
2800             gchar *type =  g_list_nth_data (directive_types, index);
2801             DenemoDirective *directive = g_list_nth_data (all_directives, index);
2802             gboolean delete = !text_edit_directive (directive, type);
2803             if (delete)
2804                 {
2805                     GList **directives = NULL;
2806                     if (!strcmp(type, "lilycontrol"))
2807                         directives = &Denemo.project->lilycontrol.directives;
2808                     else if (!strcmp(type, "scoreheader"))
2809                         directives = &Denemo.project->scoreheader.directives;
2810                     else if (!strcmp(type, "paper"))
2811                         directives = &Denemo.project->paper.directives;
2812                     else if (!strcmp(type, "header"))
2813                         directives = &Denemo.project->movement->header.directives;
2814                     else if (!strcmp(type, "layout"))
2815                         directives = &Denemo.project->movement->layout.directives;
2816                     else if (!strcmp(type, "movementcontrol"))
2817                         directives = &Denemo.project->movement->movementcontrol.directives;
2818                     if (directives)
2819                             delete_directive (directives, directive->tag->str);
2820                     else
2821                             g_warning ("Could not get directives list to delete from");
2822                 }
2823         }
2824     g_list_free (all_directives);
2825     g_list_free (directive_types);
2826     all_directives = NULL;
2827     directive_types = NULL;
2828 }
2829 
2830 static DenemoDirective *
select_score_directive(void)2831 select_score_directive (void)
2832 {
2833   if (Denemo.project->lilycontrol.directives == NULL)
2834     return NULL;
2835   return select_directive (_("Select a score directive - use Shift for advanced edit"), Denemo.project->lilycontrol.directives);
2836 }
2837 static DenemoDirective *
select_scoreheader_directive(void)2838 select_scoreheader_directive (void)
2839 {
2840   if (Denemo.project->scoreheader.directives == NULL)
2841     return NULL;
2842   return select_directive (_("Select a score header block directive - use Shift for advanced edit"), Denemo.project->scoreheader.directives);
2843 }
2844 
2845 static DenemoDirective *
select_paper_directive(void)2846 select_paper_directive (void)
2847 {
2848   if (Denemo.project->paper.directives == NULL)
2849     return NULL;
2850   return select_directive (_("Select a score paper block directive - use Shift for advanced edit"), Denemo.project->paper.directives);
2851 }
2852 
2853 
2854 static DenemoDirective *
select_header_directive(void)2855 select_header_directive (void)
2856 {
2857   if (Denemo.project->movement->header.directives == NULL)
2858     return NULL;
2859   return select_directive (_("Select a movement header block directive - use Shift for advanced edit"), Denemo.project->movement->header.directives);
2860 }
2861 
2862 static DenemoDirective *
select_layout_directive(void)2863 select_layout_directive (void)
2864 {
2865   if (Denemo.project->movement->layout.directives == NULL)
2866     return NULL;
2867   return select_directive (_("Select a movement layout block directive - use Shift for advanced edit"), Denemo.project->movement->layout.directives);
2868 }
2869 
2870 static DenemoDirective *
select_movementcontrol_directive(void)2871 select_movementcontrol_directive (void)
2872 {
2873   if (Denemo.project->movement->movementcontrol.directives == NULL)
2874     return NULL;
2875   return select_directive (_("Select a movement control directive - use Shift for advanced edit"), Denemo.project->movement->movementcontrol.directives);
2876 }
2877 
2878 static DenemoDirective *
select_clef_directive(void)2879 select_clef_directive (void)
2880 {
2881   clef *curclef = get_clef ();
2882   if (curclef == NULL || curclef->directives == NULL)
2883     return NULL;
2884   return select_directive (_("Select a clef directive - use Shift for advanced edit"), curclef->directives);
2885 }
2886 
2887 static DenemoDirective *
select_keysig_directive(void)2888 select_keysig_directive (void)
2889 {
2890   keysig *curkeysig = get_keysig ();
2891   if (curkeysig == NULL || curkeysig->directives == NULL)
2892     return NULL;
2893   return select_directive (_("Select a key signature directive - use Shift for advanced edit"), curkeysig->directives);
2894 }
2895 
2896 static DenemoDirective *
select_timesig_directive(void)2897 select_timesig_directive (void)
2898 {
2899   timesig *curtimesig = get_timesig ();
2900   if (curtimesig == NULL || curtimesig->directives == NULL)
2901     return NULL;
2902   return select_directive (_("Select a time signature directive - use Shift for advanced edit"), curtimesig->directives);
2903 }
2904 
2905 static DenemoDirective *
select_tuplet_directive(void)2906 select_tuplet_directive (void)
2907 {
2908   tuplet *curtuplet = get_tuplet ();
2909   if (curtuplet == NULL || curtuplet->directives == NULL)
2910     return NULL;
2911   return select_directive (_("Select a time signature directive - use Shift for advanced edit"), curtuplet->directives);
2912 }
2913 
2914 static DenemoDirective *
select_stemdirective_directive(void)2915 select_stemdirective_directive (void)
2916 {
2917   stemdirective *curstemdirective = get_stemdirective ();
2918   if (curstemdirective == NULL || curstemdirective->directives == NULL)
2919     return NULL;
2920   return select_directive (_("Select a time signature directive - use Shift for advanced edit"), curstemdirective->directives);
2921 }
2922 
2923 static DenemoDirective *
select_staff_directive(void)2924 select_staff_directive (void)
2925 {
2926   if (Denemo.project->movement->currentstaff == NULL)
2927     return NULL;
2928   DenemoStaff *curstaff = Denemo.project->movement->currentstaff->data;
2929   //FIXME return NULL if not primary staff
2930   if (curstaff == NULL || curstaff->staff_directives == NULL)
2931     return NULL;
2932   return select_directive (_("Select a staff directive - use Shift for advanced edit"), curstaff->staff_directives);
2933 }
2934 
2935 static DenemoDirective *
select_voice_directive(void)2936 select_voice_directive (void)
2937 {
2938   if (Denemo.project->movement->currentstaff == NULL)
2939     return NULL;
2940   DenemoStaff *curstaff = Denemo.project->movement->currentstaff->data;
2941   if (curstaff == NULL || curstaff->voice_directives == NULL)
2942     return NULL;
2943   return select_directive (_("Select a voice directive - use Shift for advanced edit"), curstaff->voice_directives);
2944 }
2945 
2946 
2947 /**
2948  * callback for EditVoiceDirective
2949  */
2950 void
edit_voice_directive(GtkAction * action,DenemoScriptParam * param)2951 edit_voice_directive (GtkAction * action, DenemoScriptParam * param)
2952 {
2953   //g_debug("Edit directive called\n");
2954   DenemoDirective *directive = select_voice_directive ();
2955   //g_debug("Got directive %p\n", directive);
2956   if (directive == NULL)
2957     return;
2958   if (directive->tag == NULL)
2959     directive->tag = g_string_new (UNKNOWN_TAG);
2960   if (!edit_directive (directive, "voice"))
2961     delete_voice_directive (directive->tag->str);
2962   score_status (Denemo.project, TRUE);
2963 }
2964 
2965 /**
2966  * callback for EditStaffDirective
2967  */
2968 void
edit_staff_directive(GtkAction * action,DenemoScriptParam * param)2969 edit_staff_directive (GtkAction * action, DenemoScriptParam * param)
2970 {
2971   //g_debug("Edit directive called\n");
2972   DenemoDirective *directive = select_staff_directive ();
2973   //g_debug("Got directive %p\n", directive);
2974   if (directive == NULL)
2975     return;
2976   if (directive->tag == NULL)
2977     directive->tag = g_string_new (UNKNOWN_TAG);
2978   if (!edit_directive (directive, "staff"))
2979     delete_staff_directive (directive->tag->str);
2980   score_status (Denemo.project, TRUE);
2981 }
2982 
2983 /**
2984  * callback for EditClefDirective
2985  */
2986 void
edit_clef_directive(GtkAction * action,DenemoScriptParam * param)2987 edit_clef_directive (GtkAction * action, DenemoScriptParam * param)
2988 {
2989   //g_debug("Edit directive called\n");
2990   DenemoDirective *directive = select_clef_directive ();
2991   //g_debug("Got directive %p\n", directive);
2992   if (directive == NULL)
2993     return;
2994   if (directive->tag == NULL)
2995     directive->tag = g_string_new (UNKNOWN_TAG);
2996   if (!edit_directive (directive, "clef"))
2997     delete_clef_directive (directive->tag->str);
2998   score_status (Denemo.project, TRUE);
2999 }
3000 
3001 /**
3002  * callback for EditKeysigDirective
3003  */
3004 void
edit_keysig_directive(GtkAction * action,DenemoScriptParam * param)3005 edit_keysig_directive (GtkAction * action, DenemoScriptParam * param)
3006 {
3007   //g_debug("Edit directive called\n");
3008   DenemoDirective *directive = select_keysig_directive ();
3009   //g_debug("Got directive %p\n", directive);
3010   if (directive == NULL)
3011     return;
3012   if (directive->tag == NULL)
3013     directive->tag = g_string_new (UNKNOWN_TAG);
3014   if (!edit_directive (directive, "keysig"))
3015     delete_keysig_directive (directive->tag->str);
3016   score_status (Denemo.project, TRUE);
3017 }
3018 
3019 
3020 /**
3021  * callback for EditTimesigDirective
3022  */
3023 void
edit_timesig_directive(GtkAction * action,DenemoScriptParam * param)3024 edit_timesig_directive (GtkAction * action, DenemoScriptParam * param)
3025 {
3026   //g_debug("Edit directive called\n");
3027   DenemoDirective *directive = select_timesig_directive ();
3028   //g_debug("Got directive %p\n", directive);
3029   if (directive == NULL)
3030     return;
3031   if (directive->tag == NULL)
3032     directive->tag = g_string_new (UNKNOWN_TAG);
3033   if (!edit_directive (directive, "timesig"))
3034     delete_timesig_directive (directive->tag->str);
3035   score_status (Denemo.project, TRUE);
3036 }
3037 
3038 /**
3039  * callback for EditTupletDirective
3040  */
3041 void
edit_tuplet_directive(GtkAction * action,DenemoScriptParam * param)3042 edit_tuplet_directive (GtkAction * action, DenemoScriptParam * param)
3043 {
3044   //g_debug("Edit directive called\n");
3045   DenemoDirective *directive = select_tuplet_directive ();
3046   //g_debug("Got directive %p\n", directive);
3047   if (directive == NULL)
3048     return;
3049   if (directive->tag == NULL)
3050     directive->tag = g_string_new (UNKNOWN_TAG);
3051   if (!edit_directive (directive, "tuplet"))
3052     delete_tuplet_directive (directive->tag->str);
3053   score_status (Denemo.project, TRUE);
3054 }
3055 
3056 /**
3057  * callback for EditStemdirectiveDirective
3058  */
3059 void
edit_stemdirective_directive(GtkAction * action,DenemoScriptParam * param)3060 edit_stemdirective_directive (GtkAction * action, DenemoScriptParam * param)
3061 {
3062   //g_debug("Edit directive called\n");
3063   DenemoDirective *directive = select_stemdirective_directive ();
3064   //g_debug("Got directive %p\n", directive);
3065   if (directive == NULL)
3066     return;
3067   if (directive->tag == NULL)
3068     directive->tag = g_string_new (UNKNOWN_TAG);
3069   if (!edit_directive (directive, "stemdirective"))
3070     delete_stemdirective_directive (directive->tag->str);
3071   score_status (Denemo.project, TRUE);
3072 }
3073 
3074 /**
3075  * callback for EditScoreDirective
3076  */
3077 void
edit_score_directive(GtkAction * action,DenemoScriptParam * param)3078 edit_score_directive (GtkAction * action, DenemoScriptParam * param)
3079 {
3080 #define ScoreDirectives  _("ScoreDirectives")
3081 #define ScoreHeaderBlockDirectives  _("Score Header Block Directives")
3082 #define ScorePaperBlockDirectives  _("Score Paper Block Directives")
3083 #define HeaderBlockDirectives  _("Movement Header Block Directives")
3084 #define LayoutBlockDirectives  _("Layout Block Directives")
3085 
3086 #define STRINGAPPEND(field)  g_string_append_printf(options,"%s%c", field,'\0')
3087   GString *options = g_string_new ("");
3088   gchar *option;
3089   if (Denemo.project->lilycontrol.directives)
3090     STRINGAPPEND (ScoreDirectives);
3091   if (Denemo.project->scoreheader.directives)
3092     STRINGAPPEND (ScoreHeaderBlockDirectives);
3093   if (Denemo.project->paper.directives)
3094     STRINGAPPEND (ScorePaperBlockDirectives);
3095   if (Denemo.project->movement->header.directives)
3096     STRINGAPPEND (HeaderBlockDirectives);
3097   if (Denemo.project->movement->layout.directives)
3098     STRINGAPPEND (LayoutBlockDirectives);
3099 
3100   if (strlen (options->str) != options->len)
3101     {
3102       option = get_option (NULL, options->str, options->len);
3103       if (option == NULL)
3104         {
3105           g_string_free (options, TRUE);
3106           return;
3107         }
3108     }
3109   else
3110     option = options->str;
3111 #define EDITTYPE(type, what)\
3112   if(!strcmp(option, type)) {\
3113     DenemoDirective *directive = select_##what##_directive();\
3114     if(directive==NULL)\
3115       return;\
3116     if(directive->tag == NULL)\
3117       directive->tag = g_string_new(UNKNOWN_TAG);\
3118     if(!edit_directive(directive, #what))\
3119       delete_##what##_directive(directive->tag->str);\
3120   score_status (Denemo.project, TRUE);\
3121   }
3122 
3123 
3124   EDITTYPE (ScoreDirectives, score);
3125   EDITTYPE (ScoreHeaderBlockDirectives, scoreheader);
3126   EDITTYPE (ScorePaperBlockDirectives, paper);
3127   EDITTYPE (HeaderBlockDirectives, header);
3128   EDITTYPE (LayoutBlockDirectives, layout);
3129 
3130   //g_debug("option was %s\n",option);
3131   g_string_free (options, TRUE);
3132 #undef EDITTYPE
3133 #undef STRINGAPPEND
3134 }
3135 
3136 
3137 
3138 /**
3139  * callback for EditMovementDirective
3140  */
3141 void
edit_movement_directive(GtkAction * action,DenemoScriptParam * param)3142 edit_movement_directive (GtkAction * action, DenemoScriptParam * param)
3143 {
3144 #define LayoutDirectives  _("Layout Directives")
3145 #define MovementDirectives  _("Movement Directives")
3146 #define HeaderBlockDirectives  _("Movement Header Block Directives")
3147 
3148 #define STRINGAPPEND(field)  g_string_append_printf(options,"%s%c", field,'\0')
3149   GString *options = g_string_new ("");
3150   gchar *option;
3151   if (Denemo.project->movement->layout.directives)
3152     STRINGAPPEND (LayoutDirectives);
3153   if (Denemo.project->movement->movementcontrol.directives)
3154     STRINGAPPEND (MovementDirectives);
3155 
3156   if (Denemo.project->movement->header.directives)
3157     STRINGAPPEND (HeaderBlockDirectives);
3158 
3159   if (strlen (options->str) != options->len)
3160     {
3161       option = get_option (NULL, options->str, options->len);
3162       if (option == NULL)
3163         {
3164           g_string_free (options, TRUE);
3165           return;
3166         }
3167     }
3168   else
3169     option = options->str;
3170 #define EDITTYPE(type, what)\
3171   if(!strcmp(option, type)) {\
3172     DenemoDirective *directive = select_##what##_directive();\
3173     if(directive==NULL)\
3174       return;\
3175     if(directive->tag == NULL)\
3176       directive->tag = g_string_new(UNKNOWN_TAG);\
3177     if(!edit_directive(directive, #what))\
3178       delete_##what##_directive(directive->tag->str);\
3179   score_status (Denemo.project, TRUE);\
3180   }
3181 
3182 
3183 
3184   EDITTYPE (HeaderBlockDirectives, header);
3185   EDITTYPE (LayoutDirectives, layout);
3186   EDITTYPE (MovementDirectives, movementcontrol);
3187 
3188   g_string_free (options, TRUE);
3189 #undef EDITTYPE
3190 #undef STRINGAPPEND
3191 }
3192 
3193 
3194 
3195 
3196 /* block which can be copied for type of directive (minpixels is done as sample for new int fields */
PUT_INT_FIELD_FUNC(clef,x)3197 PUT_INT_FIELD_FUNC (clef, x)
3198 PUT_INT_FIELD_FUNC (clef, y)
3199 PUT_INT_FIELD_FUNC (clef, tx)
3200 PUT_INT_FIELD_FUNC (clef, ty)
3201 PUT_INT_FIELD_FUNC (clef, gx)
3202 PUT_INT_FIELD_FUNC (clef, gy)
3203 PUT_INT_FIELD_FUNC (clef, override)
3204 GET_INT_FIELD_FUNC (clef, x)
3205 GET_INT_FIELD_FUNC (clef, y) GET_INT_FIELD_FUNC (clef, tx) GET_INT_FIELD_FUNC (clef, ty) GET_INT_FIELD_FUNC (clef, gx) GET_INT_FIELD_FUNC (clef, gy) GET_INT_FIELD_FUNC (clef, override) GET_INT_GRAPHIC_FIELD_FUNC (clef, width) GET_INT_GRAPHIC_FIELD_FUNC (clef, height) PUT_GRAPHIC (clef) PUT_STR_FIELD_FUNC (clef, prefix) PUT_STR_FIELD_FUNC (clef, postfix) PUT_STR_FIELD_FUNC (clef, display) GET_STR_FIELD_FUNC (clef, prefix) GET_STR_FIELD_FUNC (clef, postfix) GET_STR_FIELD_FUNC (clef, display)
3206 /* end block which can be copied for type of directive */
3207   PUT_INT_FIELD_FUNC (keysig, x)
3208 PUT_INT_FIELD_FUNC (keysig, y)
3209 PUT_INT_FIELD_FUNC (keysig, tx)
3210 PUT_INT_FIELD_FUNC (keysig, ty)
3211 PUT_INT_FIELD_FUNC (keysig, gx)
3212 PUT_INT_FIELD_FUNC (keysig, gy)
3213 PUT_INT_FIELD_FUNC (keysig, override)
3214 GET_INT_FIELD_FUNC (keysig, x)
3215 GET_INT_FIELD_FUNC (keysig, y)
3216 GET_INT_FIELD_FUNC (keysig, tx)
3217 GET_INT_FIELD_FUNC (keysig, ty)
3218 GET_INT_FIELD_FUNC (keysig, gx)
3219 GET_INT_FIELD_FUNC (keysig, gy)
3220 GET_INT_FIELD_FUNC (keysig, override)
3221 GET_INT_GRAPHIC_FIELD_FUNC (keysig, width)
3222 GET_INT_GRAPHIC_FIELD_FUNC (keysig, height)
3223 PUT_STR_FIELD_FUNC (keysig, prefix)
3224 PUT_STR_FIELD_FUNC (keysig, postfix)
3225 PUT_STR_FIELD_FUNC (keysig, display)
3226 GET_STR_FIELD_FUNC (keysig, prefix)
3227 GET_STR_FIELD_FUNC (keysig, postfix)
3228 GET_STR_FIELD_FUNC (keysig, display)
3229 PUT_INT_FIELD_FUNC (timesig, x)
3230 PUT_INT_FIELD_FUNC (timesig, y)
3231 PUT_INT_FIELD_FUNC (timesig, tx)
3232 PUT_INT_FIELD_FUNC (timesig, ty)
3233 PUT_INT_FIELD_FUNC (timesig, gx)
3234 PUT_INT_FIELD_FUNC (timesig, gy)
3235 PUT_INT_FIELD_FUNC (timesig, override)
3236 GET_INT_FIELD_FUNC (timesig, x)
3237 GET_INT_FIELD_FUNC (timesig, y)
3238 GET_INT_FIELD_FUNC (timesig, tx)
3239 GET_INT_FIELD_FUNC (timesig, ty)
3240 GET_INT_FIELD_FUNC (timesig, gx)
3241 GET_INT_FIELD_FUNC (timesig, gy)
3242 GET_INT_FIELD_FUNC (timesig, override)
3243 GET_INT_GRAPHIC_FIELD_FUNC (timesig, width)
3244 GET_INT_GRAPHIC_FIELD_FUNC (timesig, height)
3245 PUT_STR_FIELD_FUNC (timesig, prefix)
3246 PUT_STR_FIELD_FUNC (timesig, postfix)
3247 PUT_STR_FIELD_FUNC (timesig, display)
3248 GET_STR_FIELD_FUNC (timesig, prefix)
3249 GET_STR_FIELD_FUNC (timesig, postfix)
3250 GET_STR_FIELD_FUNC (timesig, display)
3251 PUT_INT_FIELD_FUNC (tuplet, x)
3252 PUT_INT_FIELD_FUNC (tuplet, y)
3253 PUT_INT_FIELD_FUNC (tuplet, tx)
3254 PUT_INT_FIELD_FUNC (tuplet, ty)
3255 PUT_INT_FIELD_FUNC (tuplet, gx)
3256 PUT_INT_FIELD_FUNC (tuplet, gy)
3257 PUT_INT_FIELD_FUNC (tuplet, override)
3258 GET_INT_FIELD_FUNC (tuplet, x)
3259 GET_INT_FIELD_FUNC (tuplet, y)
3260 GET_INT_FIELD_FUNC (tuplet, tx)
3261 GET_INT_FIELD_FUNC (tuplet, ty)
3262 GET_INT_FIELD_FUNC (tuplet, gx)
3263 GET_INT_FIELD_FUNC (tuplet, gy)
3264 GET_INT_FIELD_FUNC (tuplet, override)
3265 GET_INT_GRAPHIC_FIELD_FUNC (tuplet, width)
3266 GET_INT_GRAPHIC_FIELD_FUNC (tuplet, height)
3267 PUT_STR_FIELD_FUNC (tuplet, prefix)
3268 PUT_STR_FIELD_FUNC (tuplet, postfix)
3269 PUT_STR_FIELD_FUNC (tuplet, display)
3270 GET_STR_FIELD_FUNC (tuplet, prefix)
3271 GET_STR_FIELD_FUNC (tuplet, postfix)
3272 GET_STR_FIELD_FUNC (tuplet, display)
3273 PUT_INT_FIELD_FUNC (stemdirective, x)
3274 PUT_INT_FIELD_FUNC (stemdirective, y)
3275 PUT_INT_FIELD_FUNC (stemdirective, tx)
3276 PUT_INT_FIELD_FUNC (stemdirective, ty)
3277 PUT_INT_FIELD_FUNC (stemdirective, gx)
3278 PUT_INT_FIELD_FUNC (stemdirective, gy)
3279 PUT_INT_FIELD_FUNC (stemdirective, override)
3280 GET_INT_FIELD_FUNC (stemdirective, x)
3281 GET_INT_FIELD_FUNC (stemdirective, y)
3282 GET_INT_FIELD_FUNC (stemdirective, tx)
3283 GET_INT_FIELD_FUNC (stemdirective, ty)
3284 GET_INT_FIELD_FUNC (stemdirective, gx)
3285 GET_INT_FIELD_FUNC (stemdirective, gy)
3286 GET_INT_FIELD_FUNC (stemdirective, override)
3287 GET_INT_GRAPHIC_FIELD_FUNC (stemdirective, width)
3288 GET_INT_GRAPHIC_FIELD_FUNC (stemdirective, height)
3289 PUT_STR_FIELD_FUNC (stemdirective, prefix)
3290 PUT_STR_FIELD_FUNC (stemdirective, postfix)
3291 PUT_STR_FIELD_FUNC (stemdirective, display)
3292 GET_STR_FIELD_FUNC (stemdirective, prefix)
3293 GET_STR_FIELD_FUNC (stemdirective, postfix)
3294 GET_STR_FIELD_FUNC (stemdirective, display)
3295 GET_INT_FIELD_FUNC (scoreheader, x)
3296 GET_INT_FIELD_FUNC (scoreheader, y)
3297 GET_INT_FIELD_FUNC (scoreheader, tx)
3298 GET_INT_FIELD_FUNC (scoreheader, ty)
3299 GET_INT_FIELD_FUNC (scoreheader, gx)
3300 GET_INT_FIELD_FUNC (scoreheader, gy)
3301 GET_INT_FIELD_FUNC (scoreheader, override)
3302 GET_INT_GRAPHIC_FIELD_FUNC (scoreheader, width)
3303 GET_INT_GRAPHIC_FIELD_FUNC (scoreheader, height)
3304 GET_STR_FIELD_FUNC (scoreheader, prefix)
3305 GET_STR_FIELD_FUNC (scoreheader, postfix)
3306 GET_STR_FIELD_FUNC (scoreheader, display)
3307 GET_INT_FIELD_FUNC (header, x)
3308 GET_INT_FIELD_FUNC (header, y)
3309 GET_INT_FIELD_FUNC (header, tx)
3310 GET_INT_FIELD_FUNC (header, ty)
3311 GET_INT_FIELD_FUNC (header, gx)
3312 GET_INT_FIELD_FUNC (header, gy)
3313 GET_INT_FIELD_FUNC (header, override)
3314 GET_INT_GRAPHIC_FIELD_FUNC (header, width)
3315 GET_INT_GRAPHIC_FIELD_FUNC (header, height)
3316 GET_STR_FIELD_FUNC (header, prefix)
3317 GET_STR_FIELD_FUNC (header, postfix)
3318 GET_STR_FIELD_FUNC (header, display)
3319 GET_INT_FIELD_FUNC (paper, x)
3320 GET_INT_FIELD_FUNC (paper, y)
3321 GET_INT_FIELD_FUNC (paper, tx)
3322 GET_INT_FIELD_FUNC (paper, ty)
3323 GET_INT_FIELD_FUNC (paper, gx)
3324 GET_INT_FIELD_FUNC (paper, gy)
3325 GET_INT_FIELD_FUNC (paper, override)
3326 GET_INT_GRAPHIC_FIELD_FUNC (paper, width)
3327 GET_INT_GRAPHIC_FIELD_FUNC (paper, height)
3328 GET_STR_FIELD_FUNC (paper, prefix)
3329 GET_STR_FIELD_FUNC (paper, postfix)
3330 GET_STR_FIELD_FUNC (paper, display)
3331 GET_INT_FIELD_FUNC (layout, x)
3332 GET_INT_FIELD_FUNC (layout, y)
3333 GET_INT_FIELD_FUNC (layout, tx)
3334 GET_INT_FIELD_FUNC (layout, ty)
3335 GET_INT_FIELD_FUNC (layout, gx)
3336 GET_INT_FIELD_FUNC (layout, gy)
3337 GET_INT_FIELD_FUNC (layout, override)
3338 GET_INT_GRAPHIC_FIELD_FUNC (layout, width)
3339 GET_INT_GRAPHIC_FIELD_FUNC (layout, height)
3340 GET_STR_FIELD_FUNC (layout, prefix)
3341 GET_STR_FIELD_FUNC (layout, postfix)
3342 GET_STR_FIELD_FUNC (layout, display)
3343 GET_INT_FIELD_FUNC (movementcontrol, x)
3344 GET_INT_FIELD_FUNC (movementcontrol, y) GET_INT_FIELD_FUNC (movementcontrol, tx) GET_INT_FIELD_FUNC (movementcontrol, ty) GET_INT_FIELD_FUNC (movementcontrol, gx) GET_INT_FIELD_FUNC (movementcontrol, gy) GET_INT_FIELD_FUNC (movementcontrol, override) GET_INT_GRAPHIC_FIELD_FUNC (movementcontrol, width) GET_INT_GRAPHIC_FIELD_FUNC (movementcontrol, height) GET_STR_FIELD_FUNC (movementcontrol, prefix) GET_STR_FIELD_FUNC (movementcontrol, postfix) GET_STR_FIELD_FUNC (movementcontrol, display)
3345 #undef STANDALONE_PUT_INT_FIELD_FUNC
3346 #undef PUT_GRAPHIC
3347 #undef PUT_INT_FIELD_FUNC
3348 #undef GET_INT_FIELD_FUNC
3349 #undef PUT_STR_FIELD_FUNC
3350 #undef GET_STR_FIELD_FUNC
3351      gchar *
3352      get_scoretitle (void)
3353 {
3354   gchar *scoretitle = NULL;
3355   GList *first = Denemo.project->movements;
3356   if (first)
3357     {
3358       DenemoMovement *si = (DenemoMovement *) first->data;
3359       if (si)
3360         {
3361           DenemoDirective *directive = find_directive (si->header.directives, "Movement-title");
3362           if (directive && directive->display)
3363             scoretitle = directive->display->str;
3364         }
3365     }
3366   return scoretitle;
3367 }
3368 
3369 #define ACTIVATE_DIRECTIVE(what)\
3370 gboolean activate_##what##_directive(gchar *tag) {\
3371   DenemoDirective *directive = get_##what##_directive(tag);\
3372   if(directive)\
3373     return activate_directive(directive, #what);\
3374   return FALSE;\
3375 }
3376 #define TEXT_EDIT_DIRECTIVE(what)\
3377 gboolean text_edit_##what##_directive(gchar *tag) {\
3378   DenemoDirective *directive = get_##what##_directive(tag);\
3379   if(directive)\
3380     return text_edit_directive(directive, #what);\
3381   return FALSE;\
3382 }\
3383 ACTIVATE_DIRECTIVE(what)
3384 
3385 TEXT_EDIT_DIRECTIVE (note);
3386 TEXT_EDIT_DIRECTIVE (chord);
3387 TEXT_EDIT_DIRECTIVE (staff);
3388 TEXT_EDIT_DIRECTIVE (voice);
3389 TEXT_EDIT_DIRECTIVE (score);
3390 TEXT_EDIT_DIRECTIVE (clef);
3391 TEXT_EDIT_DIRECTIVE (timesig);
3392 TEXT_EDIT_DIRECTIVE (tuplet);
3393 TEXT_EDIT_DIRECTIVE (stemdirective);
3394 TEXT_EDIT_DIRECTIVE (keysig);
3395 TEXT_EDIT_DIRECTIVE (scoreheader);
3396 TEXT_EDIT_DIRECTIVE (header);
3397 TEXT_EDIT_DIRECTIVE (paper);
3398 TEXT_EDIT_DIRECTIVE (layout);
3399 TEXT_EDIT_DIRECTIVE (movementcontrol);
3400 TEXT_EDIT_DIRECTIVE (standalone);
3401 
3402 
3403 #undef TEXT_EDIT_DIRECTIVE
3404 
3405 #define GET_NTH_TAG(what, name)\
3406 gchar *get_nth_##what##_tag(gint n) {\
3407   what *current = get_##what();\
3408   if(current==NULL) return NULL;\
3409   GList *g = g_list_nth(current->name, n);\
3410   if(g==NULL) return NULL;\
3411   DenemoDirective *directive = (DenemoDirective *)g->data;\
3412   return directive->tag->str;}
3413 
3414 GET_NTH_TAG (note, directives);
3415 GET_NTH_TAG (chord, directives);
3416 GET_NTH_TAG (staff, staff_directives);
3417 GET_NTH_TAG (voice, voice_directives);
3418 GET_NTH_TAG (score, directives);
3419 GET_NTH_TAG (clef, directives);
3420 GET_NTH_TAG (timesig, directives);
3421 GET_NTH_TAG (tuplet, directives);
3422 GET_NTH_TAG (stemdirective, directives);
3423 GET_NTH_TAG (keysig, directives);
3424 GET_NTH_TAG (scoreheader, directives);
3425 GET_NTH_TAG (header, directives);
3426 GET_NTH_TAG (paper, directives);
3427 GET_NTH_TAG (layout, directives);
3428 GET_NTH_TAG (movementcontrol, directives);
3429 #undef GET_NTH_TAG
3430 
get_nth_strict_note_tag(gint n)3431 gchar *get_nth_strict_note_tag(gint n)
3432     {
3433       note *current = get_strict_note();
3434       if(current==NULL) return NULL;
3435       GList *g = g_list_nth(current->directives, n);
3436       if(g==NULL) return NULL;
3437       DenemoDirective *directive = (DenemoDirective *)g->data;
3438       if (directive->tag==NULL) directive->tag = g_string_new (UNKNOWN_TAG);
3439       return directive->tag->str;
3440   }
3441 
strict_note_directive_get_tag(gchar * tag)3442 const gchar *strict_note_directive_get_tag (gchar *tag)
3443     {
3444       note *current = get_strict_note();
3445       if(current==NULL) return NULL;
3446       GList *g = current->directives;
3447       for(;g; g=g->next)
3448           {
3449             DenemoDirective *directive = (DenemoDirective *)g->data;
3450             if(tag == NULL)
3451                 return directive->tag?directive->tag->str:NULL;
3452             if (directive->tag && !strcmp (directive->tag->str, tag))
3453                 return tag;
3454           }
3455       return NULL;
3456     }
3457 
3458 
3459 /* gets the directive at the cursor a further call on the same object gets the next directive unless called on another object of the same type
3460  * which causes it to reset to the first directive */
get_next_directive_at_cursor(void)3461 DenemoDirective *get_next_directive_at_cursor (void)
3462 {
3463   GList *directives = NULL;
3464   DenemoDirective *directive = NULL;
3465   note *current = get_strict_note();
3466   if(current)
3467     {static GList *last;
3468         directives = current->directives;
3469         if(directives)
3470             {
3471                 if(last && (g_list_position(directives, last)>=0))
3472                 {
3473                     last = last->next;
3474                     if(!last) last = directives;
3475                 } else
3476                 last = directives;
3477             directive =  last->data;
3478             }
3479     }
3480   if(directives==NULL)
3481     {
3482        chord *curchord = get_chord ();
3483        if(curchord)
3484            {static GList *last;
3485             directives = curchord->directives;
3486             if(directives)
3487                 {
3488                     if(last && (g_list_position(directives, last)>=0))
3489                     {
3490                         last = last->next;
3491                         if(!last) last = directives;
3492                     } else
3493                     last = directives;
3494                 directive =  last->data;
3495                 }
3496            }
3497     }
3498   if(directives==NULL)
3499     {
3500         DenemoObject *currentobject = get_object ();
3501         if (currentobject)
3502             {static GList *last;
3503                 if(currentobject->type == LILYDIRECTIVE)
3504                     {
3505                        directive = currentobject->object;
3506                     } else {
3507                         gpointer obj = currentobject->object;
3508                         directives = (currentobject->type==KEYSIG)?((keysig*)obj)->directives:
3509                         (currentobject->type==TIMESIG)?((timesig*)obj)->directives:
3510                         (currentobject->type==CLEF)?((clef*)obj)->directives:
3511                         (currentobject->type==STEMDIRECTIVE)?((stemdirective*)obj)->directives:
3512                         (currentobject->type==TUPOPEN)?((tuplet*)obj)->directives:
3513                         (currentobject->type==TUPCLOSE)?((tuplet*)obj)->directives:NULL;
3514 
3515                         if(directives)
3516                             {
3517                                 if(last && (g_list_position(directives, last)>=0))
3518                                 {
3519                                     last = last->next;
3520                                     if(!last) last = directives;
3521                                 } else
3522                                 last = directives;
3523                             directive = last->data;
3524                             }
3525                     }
3526             }
3527     }
3528     return directive;
3529 }
3530 
move_to_front(GList * directives,gchar * tag)3531 static GList *move_to_front (GList *directives, gchar *tag)
3532 {
3533     GList *el;
3534     gpointer data = NULL;
3535     for (el = directives;el;el=el->next)
3536     {
3537         DenemoDirective *directive = el->data;
3538         if (!(g_strcmp0 (tag, (gchar*) directive->tag->str)))
3539             {
3540                 data = el->data;
3541                 directives = g_list_remove (directives, data);
3542                 break;
3543             }
3544     }
3545     if(data)
3546         return g_list_prepend (directives, data);
3547     return NULL;
3548 }
3549 #define REORDER_TAG(what, name)\
3550 gboolean prioritize_##what##_tag (gchar *tag) {\
3551   what *current = get_##what();\
3552   if(current==NULL) return FALSE;\
3553   GList *g = move_to_front (current->name, tag);\
3554   if(g==NULL) return FALSE;\
3555   current->name = g;\
3556   return TRUE;}
3557 
3558 REORDER_TAG (note, directives);
3559 REORDER_TAG (chord, directives);
3560 REORDER_TAG (staff, staff_directives);
3561 REORDER_TAG (voice, voice_directives);
3562 REORDER_TAG (score, directives);
3563 REORDER_TAG (clef, directives);
3564 REORDER_TAG (timesig, directives);
3565 REORDER_TAG (tuplet, directives);
3566 REORDER_TAG (stemdirective, directives);
3567 REORDER_TAG (keysig, directives);
3568 REORDER_TAG (scoreheader, directives);
3569 REORDER_TAG (header, directives);
3570 REORDER_TAG (paper, directives);
3571 REORDER_TAG (layout, directives);
3572 REORDER_TAG (movementcontrol, directives);
3573 #undef REORDER_TAG
3574