/* lyparserfuncs.c * utility functions invoked by the * mudela parser */ /* For Denemo, a gtk+ frontend to GNU Lilypond * (c) 2000-2005 Matthew Hiller */ /*#define DEBUG 1*/ #include "chordops.h" #include #include "lyparserfuncs.h" #include "objops.h" #include "processstaffname.h" #include "utils.h" #include /*#include "lyparser.h"*/ #include "contexts.h" #include "staffops.h" #include "calculatepositions.h" #include "measureops.h" #include "exportmudela.h" #include "commandfuncs.h" #include "articulations.h" gboolean g_string_equal (const GString * v, const GString * v2); /* RECURSIVE return the first object in object list CUROBJ of type thetype before any CHORD type, following branches made for references to identifiers * static DenemoObject * first_node_context (objnode * curobj, gint thetype) { while (curobj) { if (((DenemoObject *) curobj->data)->type == MUSIC_IDENTIFIER) { DenemoObject *mud = first_node_context (br (curobj), thetype); if (mud) return mud; } if (((DenemoObject *) curobj->data)->type == thetype) return (DenemoObject *) curobj->data; if (((DenemoObject *) curobj->data)->type == CHORD) return NULL; curobj = curobj->next; } return NULL; } /* return the first object in measure curmeasure of type thetype before any CHORD type * static DenemoObject * first_context (measurenode * curmeasure, gint thetype) { objnode *curobj = (objnode *) curmeasure->data; return first_node_context (curobj, thetype); } * static void set_initial_staffcontext (DenemoStaff * curstaffstruct, DenemoScore *si) { measurenode *firstmeasure = curstaffstruct->measures; DenemoObject *obj; g_assert (firstmeasure); if ((obj = first_context (firstmeasure, CLEF)) || (obj = first_context (firstmeasure, INITIAL_CLEF))) { * DENEMO treats CLEF as clef change, so make the initial clef a different type obj->type = (DenemoObjType) INITIAL_CLEF; setpixelmin (obj); different object different width curstaffstruct->sclef = ((clef *) obj->object)->type; find_leftmost_staffcontext (curstaffstruct, si); fixnoteheights (curstaffstruct); find_xes_in_all_measures (si); core dumps } if ((obj = first_context (firstmeasure, KEYSIG)) || (obj = first_context (firstmeasure, INITIAL_KEYSIG))) { obj->type = (DenemoObjType) INITIAL_KEYSIG; setpixelmin (obj); curstaffstruct->skey = ((keysig *) obj->object)->number; initkeyaccs (curstaffstruct->skeyaccs, curstaffstruct->skey); } if ((obj = first_context (firstmeasure, TIMESIG)) || (obj = first_context (firstmeasure, INITIAL_TIMESIG))) { obj->type = (DenemoObjType) INITIAL_TIMESIG; setpixelmin (obj); curstaffstruct->stime1 = ((timesig *) obj->object)->time1; curstaffstruct->stime2 = ((timesig *) obj->object)->time2; } } */ /* void set_initial_staffcontexts (DenemoScore *si) { staffnode *curstaff = si->thescore; si->maxkeywidth = G_MININT; for (; curstaff; curstaff = curstaff->next) { set_initial_staffcontext ((DenemoStaff *) curstaff->data, si); } } */ void setstaffname (DenemoScore * si, gchar * str) { DenemoStaff *curstaffstruct = (DenemoStaff *) si->currentstaff->data; g_string_assign (curstaffstruct->lily_name, str); set_denemo_name (curstaffstruct->lily_name, curstaffstruct->denemo_name); g_free (str); } enum clefs cleftypefromname (gchar * str) { enum clefs ret = DENEMO_TREBLE_CLEF; if (g_strcasecmp (str, "treble") == 0) ret = DENEMO_TREBLE_CLEF; else if (g_strcasecmp (str, "bass") == 0) ret = DENEMO_BASS_CLEF; else if (g_strcasecmp (str, "alto") == 0) ret = DENEMO_ALTO_CLEF; else if (g_strcasecmp (str, "\"g_8\"") == 0) ret = DENEMO_G_8_CLEF; else if (g_strcasecmp (str, "tenor") == 0) ret = DENEMO_TENOR_CLEF; else if (g_strcasecmp (str, "soprano") == 0) ret = DENEMO_SOPRANO_CLEF; g_free (str); return ret; } void set_clef (DenemoScore * si, gchar * str) { ((DenemoStaff *) si->currentstaff->data)->sclef = cleftypefromname (str); } void set_key (DenemoScore * si, struct twoints t) { DenemoStaff *curstaffstruct = (DenemoStaff *) si->currentstaff->data; if (t.b) { /* Minor key */ curstaffstruct->skey = t.a - 3; curstaffstruct->skey_isminor = TRUE; } else { curstaffstruct->skey = t.a; curstaffstruct->skey_isminor = FALSE; } initkeyaccs (curstaffstruct->skeyaccs, curstaffstruct->skey); } void set_time (DenemoScore * si, struct twoints t) { DenemoStaff *curstaffstruct = (DenemoStaff *) si->currentstaff->data; curstaffstruct->stime1 = t.a; curstaffstruct->stime2 = t.b; } struct twoints twointer (gint a, gint b) { struct twoints ret; ret.a = a; ret.b = b; return ret; } /* This is basically the inverse to determinekey in * exportmudela.c */ gint keynametonumber (gchar * str) { if (g_strcasecmp (str, "ces") == 0) return -7; else if (g_strcasecmp (str, "ges") == 0) return -6; else if (g_strcasecmp (str, "des") == 0) return -5; else if (g_strcasecmp (str, "aes") == 0) return -4; else if (g_strcasecmp (str, "ees") == 0) return -3; else if (g_strcasecmp (str, "bes") == 0) return -2; else if (g_strcasecmp (str, "f") == 0) return -1; else if (g_strcasecmp (str, "c") == 0) return 0; else if (g_strcasecmp (str, "g") == 0) return 1; else if (g_strcasecmp (str, "d") == 0) return 2; else if (g_strcasecmp (str, "a") == 0) return 3; else if (g_strcasecmp (str, "e") == 0) return 4; else if (g_strcasecmp (str, "b") == 0) return 5; else if (g_strcasecmp (str, "fis") == 0) return 6; else if (g_strcasecmp (str, "cis") == 0) return 7; else if (g_strcasecmp (str, "gis") == 0) return 8; else if (g_strcasecmp (str, "dis") == 0) return 9; else if (g_strcasecmp (str, "ais") == 0) return 10; else return 0; /* Defaults to c minor/major */ g_free (str); } gint mutointernalduration (gint muduration) { gint ret = 0; while (muduration > 1) { ret++; muduration >>= 1; } return ret; } gint pitchtomid_c_offset (gchar name, gint octave) { return 7 * (octave - 1) + (name - 'a' + 5) % 7; } void addtonewrapper (DenemoObject * curmudelaobj, gchar tonetype, gint enshift, gint octave, struct twoints duration, gint dclef) { gint mid_c_offset = pitchtomid_c_offset (tonetype, octave); if (tonetype != 'r') addtone (curmudelaobj, mid_c_offset, enshift, dclef); ((chord *) curmudelaobj->object)->baseduration = duration.a; ((chord *) curmudelaobj->object)->numdots = duration.b; set_basic_numticks (curmudelaobj); } void set_tone_option (DenemoObject * curmudelaobj, gchar * option) { if (!strcmp (option, "fermata")) ((chord *) curmudelaobj->object)->ornamentlist = insert_ornament_list (FERMATA, ((chord *) curmudelaobj->object)->ornamentlist); else if (!strcmp (option, "trill")) ((chord *) curmudelaobj->object)->ornamentlist = insert_ornament_list (TRILL, ((chord *) curmudelaobj->object)->ornamentlist); else if (!strcmp (option, "turn")) ((chord *) curmudelaobj->object)->ornamentlist = insert_ornament_list (TURN, ((chord *) curmudelaobj->object)->ornamentlist); else if (!strcmp (option, "mordent")) ((chord *) curmudelaobj->object)->ornamentlist = insert_ornament_list (MORDENT, ((chord *) curmudelaobj->object)->ornamentlist); else if (!strcmp (option, "accent")) ((chord *) curmudelaobj->object)->ornamentlist = insert_ornament_list (D_ACCENT, ((chord *) curmudelaobj->object)->ornamentlist); else if (!strcmp (option, "staccato")) ((chord *) curmudelaobj->object)->ornamentlist = insert_ornament_list (STACCATO, ((chord *) curmudelaobj->object)->ornamentlist); else if (!strcmp (option, "staccatissimo")) ((chord *) curmudelaobj->object)->ornamentlist = insert_ornament_list (STACCATISSIMO, ((chord *) curmudelaobj->object)->ornamentlist); else if (!strcmp (option, "tenuto")) ((chord *) curmudelaobj->object)->ornamentlist = insert_ornament_list (TENUTO, ((chord *) curmudelaobj->object)->ornamentlist); } /* typedef struct Keyword_ent { gchar *str; gint type; } Keyword_ent; static Keyword_ent the_key_tab[] = { {"alias", ALIAS}, {"apply", APPLY}, {"arpeggio", ARPEGGIO}, {"autochange", AUTOCHANGE}, {"spanrequest", SPANREQUEST}, {"commandspanrequest", COMMANDSPANREQUEST}, {"simultaneous", SIMULTANEOUS}, {"sequential", SEQUENTIAL}, {"accepts", ACCEPTS}, {"alternative", ALTERNATIVE}, {"bar", BAR}, {"breathe", BREATHE}, {"char", CHAR_T}, {"chordmodifiers", CHORDMODIFIERS}, {"chords", CHORDS}, {"clef", CLEF_}, underscore added for denemo name clash {"cm", CM_T}, {"consists", CONSISTS}, {"consistsend", CONSISTSEND}, {"context", CONTEXT}, {"default", DEFAULT}, {"denies", DENIES}, {"duration", DURATION}, {"dynamicscript", DYNAMICSCRIPT}, {"grobdescriptions", GROBDESCRIPTIONS}, {"figures", FIGURES}, {"grace", GRACE}, {"glissando", GLISSANDO}, {"header", HEADER}, {"in", IN_T}, {"lyrics", LYRICS}, {"key", KEY}, {"mark", MARK}, {"pitch", PITCH}, {"time", TIME_T}, {"times", TIMES}, {"midi", MIDI}, {"mm", MM_T}, {"name", NAME}, {"pitchnames", PITCHNAMES}, {"notes", NOTES}, {"outputproperty", OUTPUTPROPERTY}, {"override", OVERRIDE}, {"set", SET}, {"rest", REST}, {"revert", REVERT}, {"partial", PARTIAL}, {"paper", PAPER}, {"penalty", PENALTY}, {"property", PROPERTY}, {"pt", PT_T}, {"relative", RELATIVE}, {"remove", REMOVE}, {"repeat", REPEAT}, {"addlyrics", ADDLYRICS}, {"partcombine", PARTCOMBINE}, {"score", SCORE}, {"script", SCRIPT}, {"stylesheet", STYLESHEET}, {"skip", SKIP}, {"tempo", TEMPO}, {"translator", TRANSLATOR}, {"transpose", TRANSPOSE}, {"type", TYPE}, {"unset", UNSET}, {"layout", LAYOUT}, {0, 0} }; gint lookup_keyword (gchar * str) { int i; for (i = 0; the_key_tab[i].str; i++) { if (!strcmp (the_key_tab[i].str, str)) return the_key_tab[i].type; very inefficient! } return -1; } */ /* sets si->currentstaff to the first staff in si->thescore with lily_name * NAME or NULL if none. * sets si->currentstaffnum to correspond */ static void findstaff (GString * name, DenemoScore * si) { DenemoStaff *curstaffstruct; if (si->thescore) for (si->currentstaff = si->thescore, si->currentstaffnum = 0; si->currentstaff; si->currentstaff = si->currentstaff->next, si->currentstaffnum++) { curstaffstruct = (DenemoStaff *) (si->currentstaff->data); if (g_string_equal (curstaffstruct->staff_name, name)) return; } si->currentstaff = NULL; si->currentstaffnum = g_list_length (si->thescore); /*set to insert at end */ } /* set si->currentstaff to the insertion point for voice named NAME in staff * STAFFCTX, return TRUE if voice already exists else FALSE. * sets si->currentstaffnum to correspond */ static gboolean findvoice (GString * name, GList * staffctx, DenemoScore * si) { DenemoStaff *curstaffstruct; DenemoStaff *staffctxstruct; if (si->thescore) if (staffctx) { staffctxstruct = (DenemoStaff *) (staffctx->data); for (si->currentstaff = si->thescore, si->currentstaffnum = 1; si->currentstaff && (staffctx != si->currentstaff); si->currentstaff = si->currentstaff->next, si->currentstaffnum++) /* move to primary voice in current staff */ ; curstaffstruct = (DenemoStaff *) (si->currentstaff->data); if (curstaffstruct->lily_name->len == 0) { /* no voice here yet */ curstaffstruct->lily_name = name; curstaffstruct->voicenumber = 1; return TRUE; } while (g_string_equal (curstaffstruct->staff_name, staffctxstruct->staff_name)) { /* still in same staff */ /* found the voice */ if (g_string_equal (curstaffstruct->lily_name, name)) return TRUE; if (!si->currentstaff->next) return FALSE; si->currentstaff = si->currentstaff->next, si->currentstaffnum++; } si->currentstaff = si->currentstaff->prev, si->currentstaffnum--; /* just come off this staff, go back one */ return FALSE; } /* FIXME these cases - no staffs or no staff context */ si->currentstaff = NULL; si->currentstaffnum = 0; return FALSE; } static void anewstaff (DenemoScore * si, GString * staffname, GString * voicename) { DenemoStaff *thestaffstruct = (DenemoStaff *) g_malloc0 (sizeof (DenemoStaff)); thestaffstruct->sclef = DENEMO_TREBLE_CLEF; thestaffstruct->stime1 = 4; thestaffstruct->stime2 = 4; thestaffstruct->no_of_lines = 5; thestaffstruct->staff_name = staffname; thestaffstruct->denemo_name = g_string_new (""); thestaffstruct->lily_name = voicename; thestaffstruct->midi_instrument = g_string_new ("acoustic grand"); if (si->thescore) { si->thescore = g_list_insert (si->thescore, thestaffstruct, si->currentstaffnum); si->currentstaff = g_list_nth (si->thescore, si->currentstaffnum); si->currentstaffnum++; } else { /* FIXME for some bizarre reason si->currentstaffnum is set to 1 in init_score but zero elsewhere? */ si->currentstaffnum = 1; si->thescore = si->currentstaff = g_list_append (NULL, thestaffstruct); } } /* traverse G a GList of object nodes returning the first of type T or NULL if none GList * findtok (GList * g, int t) { while (g && ntype (g) != t) g = g->next; return g; } */ /* put separate chords into a tones list of a chord and return that, * amalgamating the user_strings * static DenemoObject * generate_chord (GList * chordnode) { GList *g; GList *firstchord = findtok (chordnode, CHORD); gchar *str; * collect up the user strings here * if (firstchord == NULL) { g_warning ("<> without any notes"); return (DenemoObject *) chordnode->data; * FIXME return everything * } for (str = NULL, g = chordnode; g; g = g->next) { if (str && u_str (g)) str = g_strconcat (str, u_str (g), NULL); else if (!str) str = u_str (g); } u_str (firstchord) = str; for (g = firstchord->next; g; g = g->next) { if (ntype (g) == CHORD) { addtone ((DenemoObject *) firstchord->data, ((note *) (((chord *) (((DenemoObject *) g->data)->object))-> tones->data))->mid_c_offset, ((note *) (((chord *) (((DenemoObject *) g->data)->object))-> tones->data))->enshift, 0); } * FIXME memory leak * } return (DenemoObject *) firstchord->data; } */ /* RECURSIVE: generate_chords_and_sequentials() * called within a SEQUENTIAL it detects <> and { } music. * The <> are chords are in lilypond style ie SIMULTANEOUS nodes * this function turns them into tones lists * belonging to a chord structure in denemo style * the { } are things like repeats etc, inline these * Note we don't cope with new contexts being created... */ // static int create_score (DenemoScore * si, GList * top); // // static void // generate_chords_and_sequentials (DenemoScore * si, GList * g) // { // GList *chordnode; // // for (chordnode = br (g); chordnode; chordnode = chordnode->next) // { // if (ntype (chordnode) == SIMULTANEOUS) // { // gchar *str = u_str (chordnode); // gchar *str2 = u_post_str (chordnode); // chordnode->data = generate_chord (br (chordnode)); // u_str (chordnode) = // g_strconcat (str, u_str (chordnode), str2, NULL); // /* FIXME memory leak */ // } // else if (ntype (chordnode) == SEQUENTIAL) // { // /*create a text node for the u_str, one for the u_post_str and // in between link in the create_score(br(chordnode) */ // GList *temp = br (chordnode); // generate_chords_and_sequentials (si, chordnode); // u_str (temp) = g_strconcat (u_str (chordnode), u_str (temp), NULL); // (chordnode->prev)->next = NULL; // g_list_concat (chordnode->prev, temp); // temp = g_list_last (temp); // u_str (temp) = // g_strconcat (u_str (temp), u_post_str (chordnode), NULL); // chordnode->prev = NULL; // g_list_concat (temp, chordnode->next); // /* FIXME memory leak of chordnode itself */ // } // } // } // // // // /* RECURSIVE: perform the guts of end_of_first_measure() qv, going inside // MUSIC_IDENTIFIERS - assume such a thing does not cross a tuplet or grace */ // static GList * // recursive_end_of_first_measure (GList * theobjs, gint * ptime1, gint * ptime2, // gint * pticks_so_far, gint * ptickspermeasure, // gint * pnumerator, gint * pdenominator) // { // // objnode *curobjnode; // DenemoObject *theobj; // gint basic_ticks_in_tuplet_group = 0; // gint basic_ticks_in_grace_group = 0; // gboolean in_tuplet = FALSE; // gboolean in_grace = FALSE; // for (curobjnode = theobjs; curobjnode; curobjnode = curobjnode->next) // { // theobj = (DenemoObject *) curobjnode->data; // theobj->starttick = // *pticks_so_far + (basic_ticks_in_tuplet_group * *pnumerator // / *pdenominator) + basic_ticks_in_grace_group; // // switch (theobj->type) // { // case PARTIAL: // case CHORD: // // if (in_tuplet) // { // set_tuplefied_numticks (theobj, *pnumerator, *pdenominator); // basic_ticks_in_tuplet_group += theobj->basic_durinticks; // } // else if (in_grace) // { // set_grace_numticks (theobj, 8); // basic_ticks_in_grace_group += theobj->basic_durinticks; // } // else // { // set_tuplefied_numticks (theobj, 1, 1); // set_grace_numticks (theobj, 1); // if (theobj->type == PARTIAL) // { // theobj->durinticks = *ptickspermeasure - theobj->durinticks; // /* FIXME need to handle the FRACTION multiplier which is not // being passed through at the moment */ // } // *pticks_so_far += theobj->durinticks; // } // break; // // case TUPOPEN: // // in_tuplet = TRUE; // *pnumerator = ((tupopen *) theobj->object)->numerator; // *pdenominator = ((tupopen *) theobj->object)->denominator; // basic_ticks_in_tuplet_group = 0; /* Probably gratuitous */ // break; // case TUPCLOSE: // // in_tuplet = FALSE; // *pticks_so_far += ((basic_ticks_in_tuplet_group * *pnumerator) // / *pdenominator); // *pnumerator = 1; // *pdenominator = 1; // basic_ticks_in_tuplet_group = 0; // break; // case GRACE_START: // // in_grace = TRUE; // basic_ticks_in_grace_group = 0; // break; // case GRACE_END: // // in_grace = FALSE; // /* *pticks_so_far += basic_ticks_in_grace_group; */ // basic_ticks_in_grace_group = 0; // break; // case INITIAL_TIMESIG: // case TIMESIG: // *ptime1 = ((timesig *) theobj->object)->time1; // *ptime2 = ((timesig *) theobj->object)->time2; // *ptickspermeasure = *ptime1 * WHOLE_NUMTICKS / *ptime2; // break; // case MUSIC_IDENTIFIER: // { // GList *ret = // recursive_end_of_first_measure ((((nodeid *) (curobjnode)-> // data)->id), ptime1, ptime2, // pticks_so_far, ptickspermeasure, // pnumerator, pdenominator); // if (ret) // { // g_warning ("Measure finishes inside a music_identifier\n"); // return ret; // /** bar finished inside the MUSIC_IDENTIFIER */ // } // } // break; // default: // break; // } // // theobj->starttickofnextnote = // *pticks_so_far + (basic_ticks_in_tuplet_group * *pnumerator // / *pdenominator) + basic_ticks_in_grace_group; // if (*pticks_so_far >= *ptickspermeasure) // break; // } // return curobjnode; // } // // /* return the node in g at which one measure is complete in terms // of ticks. On entering, assume timesig of (*ptime1) / (*ptime2), any // change in the timesig changes these. // If end of measure, or incomplete measure return NULL // This function has been ripped off of settickvalsinmeasure() in // measureops.cpp, it side-effects the ticks fields of the objs in // the list, in the same manner as will that function when called. // */ // static GList * // end_of_first_measure (GList * theobjs, gint * ptime1, gint * ptime2) // { // gint numerator = 1, denominator = 1; /* varies if in tuplet etc */ // gint ticks_so_far = 0; // gint tickspermeasure = *ptime1 * WHOLE_NUMTICKS / *ptime2; // return recursive_end_of_first_measure (theobjs, ptime1, ptime2, // &ticks_so_far, &tickspermeasure, // &numerator, &denominator); // // // } // // /* attach the measures in BRANCH to the MEASURES_LIST, by counting ticks // * return the measures list built up */ // static GList * // break_into_measures (GList * branch, GList * measures_list) // { // GList *barline; // GList *rest; // gint time1 = 4, time2 = 4; /*default timesig */ // barline = end_of_first_measure (branch, &time1, &time2); // if (barline) // { // rest = barline->next; // if (rest) // rest->prev = NULL; // barline->next = NULL; // } // else // rest = NULL; // measures_list = g_list_append (measures_list, branch); // while (rest) // { // barline = end_of_first_measure (rest, &time1, &time2); // if (barline) // { // measures_list = g_list_append (measures_list, rest); // rest = barline->next; // if (rest) // rest->prev = NULL; // barline->next = NULL; // } // else // { // measures_list = g_list_append (measures_list, rest); // rest = NULL; // // } // } // return measures_list; // } // // static GList *staffctx = NULL, *voicectx = NULL, *lyricsctx = // NULL, *figuresctx = NULL; // // /* create_score: Recursively traverse the GList TOP which represents a // score block of the input lily file. Create denemo structures to enable // it to be edited graphically // */ // static int // create_score (DenemoScore * si, GList * top) // { // GList *g; // // DenemoStaff *curstaffstruct; // #if DEBUG // g_print // ("The parse tree from this node downwards looks" // " like this\n*************************************\n"); // for (g = top; g; g = g->next) // { // g_print ("node type = %d string = %s\n", // ((nodegeneric *) g->data)->type, // ((nodegeneric *) g->data)->user_string); // } // g_print ("\n*************************************\n"); // #endif // // for (g = top; g; (g = g->next)) // { // #if DEBUG // g_print ("Handling: node type = %d string = %s\n", // ((nodegeneric *) g->data)->type, // ((nodegeneric *) g->data)->user_string); // #endif // switch (ntype (g)) // { // case NOTES: // #if DEBUG // g_print ("Found notes\n"); // #endif // break; // case figuredbasscontext: // case staffcontext: // findstaff (gstr (g), si); /*sets si->currentstaffnum */ // staffctx = si->currentstaff; // if (!staffctx) // { // si->currentstaff = si->thescore; // anewstaff (si, gstr (g), g_string_new ("")); // staffctx = si->currentstaff = g_list_last (si->thescore); // staffstruct (staffctx)->voicenumber = 1; // } // si->currentprimarystaff = staffctx; // if (ntype (g) == figuredbasscontext) // { // staff_info *staffs = // (staff_info *) g_malloc0 (sizeof (staff_info)); // if (staffctx->prev == NULL) // { // parser_error ("Figured Bass not preceded by a bass staff ", // 0); // return -1; // } // staffs->main_staff = (DenemoStaff *) (staffctx->prev->data); // staffs->related_staff = (DenemoStaff *) (staffctx->data); // si->has_figures = staffs; // ((DenemoStaff *) (staffctx->data))->no_of_lines = 0; // } // break; // // case voicecontext: // // if (!findvoice (gstr (g), staffctx, si)) // { // anewstaff (si, staffstruct (staffctx)->staff_name, gstr (g)); // voicectx = si->currentstaff; // set_denemo_name (gstr (g), staffstruct (voicectx)->denemo_name); // staffstruct (voicectx)->voicenumber = 2; // } // voicectx = si->currentstaff; // break; // // case endcontext: // if (voicectx) // { // voicectx = NULL; // } // else // staffctx = NULL; // break; // case MUSIC_IDENTIFIER: // #define id(g) (((nodeid*)(g)->data)->id) // if (create_score (si, id (g))) // return -1; // break; // case SIMULTANEOUS: // if (create_score (si, br (g))) // return -1; // break; // // case SCORE: // parser_error ("Score block inside a score block", 0); // return -1; // break; // // case DENEMO_MEASURES: // case SEQUENTIAL: // /* first find out if we have voice and staff contexts, // if not create use/create // default staff structures */ // if (!staffctx) // { /* use/create the first staff structure in si->thescore */ // if (si->thescore) // { // /* if we have a named voice context create a staff context // for it otherwise insert it as a voice in the first staff // */ // staffctx = voicectx = g_list_last (si->thescore); // } // else // { // anewstaff (si, g_string_new ("dummyname"), // g_string_new ("dummyname")); // staffctx = voicectx = si->currentstaff; // } // } // else // { /* there is a staff context */ // if (!voicectx) // voicectx = staffctx; // } // si->currentstaff = voicectx; // curstaffstruct = staffstruct (voicectx); // if (ntype (g) == SEQUENTIAL) // { // generate_chords_and_sequentials (si, g); // // curstaffstruct->measures = // break_into_measures (br (g), curstaffstruct->measures); // br (g) = (GList *) & (curstaffstruct->measures); // /* nasty - we store the address // of the GList* pointer. This is so that if // editing in denemo adds a new bar at the beginning we // will not find ourselves pointing to the second bar. Or, // worse if the first bar got deleted. We are not yet tackling // the case where the staff gets deleted. We should probably // store the name and prevent that // being changed uncontrollably */ // ntype (g) = DENEMO_MEASURES; // } // else // { /* these measures are already in another staff */ // curstaffstruct->measures = *(measurenode **) br (g); // curstaffstruct->is_parasite = (measurenode **) br (g); // } // break; // // // default: // break; // } // } // return 0; // // } // // int // create_score_from_lily (DenemoScore * si, GList * top) // { // staffctx = NULL; // voicectx = NULL; // lyricsctx = NULL; // figuresctx = NULL; // return create_score (si, top); // } // // // /* this function seems to be missing from the glib library, // although in the headers */ // gboolean // g_string_equal (const GString * v, const GString * v2) // { // if ((!v) || (!v2) || (v->len != v2->len)) // return FALSE; // return !strcmp (v->str, v2->str); /* not general case of embedded 0 bytes */ // } // // // // /***************** functions for managing display of lily text ***************/ // // static void // string_edited (GtkTextBuffer * buffer, gpointer data) // { // GtkTextIter start, end; // gchar *text; // DenemoScore *si = (DenemoScore *) data; // gtk_text_buffer_get_bounds (buffer, &start, &end); // text = gtk_text_iter_get_text (&start, &end); // if (si->curlilynode == NULL) // { // g_warning ("Attempt to edit nonexistent node - ignored\n"); // return; // } // if (u_str (si->curlilynode)) // g_free (u_str (si->curlilynode)); // /* else big memory leak - check all lilynodes // xsuser_strings are mallocced strings */ // u_str (si->curlilynode) = text; // } // // // void // lily_text_change (DenemoGUI * gui) // { // static gboolean text_is_readonly = FALSE; // g_signal_handler_block (G_OBJECT (gui->textbuffer), gui->sigid); // if (ntype (gui->si->curlilynode) == DENEMO_MEASURES) // { // gtk_widget_hide (gui->textview); // gtk_widget_show (gui->musicdatabutton); // text_is_readonly = TRUE; // } // else // { // if (text_is_readonly) // { // gtk_widget_show (gui->textview); // gtk_widget_hide (gui->musicdatabutton); // } // text_is_readonly = FALSE; // if (ntype (gui->si->curlilynode) == endcontext) // gtk_text_buffer_set_text (gui->textbuffer, // g_strdup ("<>"), -1); // if (!u_str (gui->si->curlilynode)) // u_str (gui->si->curlilynode) = generate_lily (gui->si->curlilynode); // gtk_text_buffer_set_text (gui->textbuffer, u_str (gui->si->curlilynode), -1); // // } // // g_signal_handler_unblock (G_OBJECT (gui->textbuffer), gui->sigid); // } // // // void // set_text_node (GtkWidget * button, DenemoGUI* gui) // { // /* FIXME: the next line can coredump when you have multiple score blocks // and you have destroyed the textwindow and switched scores... // there are a series of fields like these that need to be file-wide // not score block wide */ // if (!gui->textwindow) // create_text_display (gui); // if (gui->si->currentobject) // gui->si->curlilynode = gui->si->currentobject; // lily_text_change (gui); // } // /*void updatescoreinfo (DenemoScore *si);*/ // /* this is missing from header */ // void // next_score (GtkWidget * button, DenemoGUI * gui) // { // GList *g = gui->si->scoreblocks; // if (g == NULL) // return; // /* copy the si to the last in the list si->next, // then copy the first to si, and then move the first to the last */ // memcpy (g_list_last (g)->data, gui, sizeof (DenemoGUI)); // memcpy (gui, g->data, sizeof (DenemoGUI)); // g = g_list_append (g, g->data); /* put it on the end */ // g = g_list_delete_link (g, g); /* and remove it from the beginning */ // gui->si->scoreblocks = g; // updatescoreinfo (gui->si); // } // // void // toggle_top_node (GtkWidget * button, DenemoGUI * gui) // { // if (gui->si->lily_file->next == NULL) // return; /* all in one node */ // if (GTK_WIDGET_VISIBLE (gui->scorearea)) /* not in toplevel */ // { // if (gui->si->lily_file) // gui->si->curlilynode = gui->si->lily_file; // gtk_widget_hide (gui->scorearea); // if (!GTK_WIDGET_IS_SENSITIVE (gui->textview)) // { // gtk_widget_set_sensitive (gui->textview, TRUE); // gtk_widget_set_sensitive (gui->scorearea, FALSE); // } // } // else // gtk_widget_show (gui->scorearea); // lily_text_change (gui); // } // static void // node_text_next (GtkWidget * win, gpointer data) // { // DenemoGUI *gui = (DenemoGUI *) data; // if (gui->si->curlilynode == gui->si->currentobject) // { // cursorright (gui->si); // gui->si->curlilynode = gui->si->currentobject; // gtk_widget_draw (gui->scorearea, NULL); // /* so cursor is seen to move in score */ // } // else if (gui->si->curlilynode->next) // { // gui->si->curlilynode = gui->si->curlilynode->next; // } // #if DEBUG // g_print ("next node has node type = %d string = %s\n", // ntype (gui->si->curlilynode), u_str (gui->si->curlilynode)); // #endif // lily_text_change (gui); // } // // static void // node_text_previous (GtkWidget * win, gpointer data) // { // DenemoGUI *gui = (DenemoGUI*) data; // /* if(si->curlilynode == NULL) si->curlilynode = lily_file; */ // if (gui->si->curlilynode == gui->si->currentobject) // { // cursorleft (gui->si); // gui->si->curlilynode = gui->si->currentobject; // gtk_widget_draw (gui->scorearea, NULL); // /* so cursor is seen to move in score */ // } // else if (gui->si->curlilynode->prev) // { // gui->si->curlilynode = gui->si->curlilynode->prev; // } // // #if DEBUG // g_print ("next node has node type = %d string = %s\n", // ntype (gui->si->curlilynode), u_str (gui->si->curlilynode)); // #endif // lily_text_change (gui); // } // // // static void // toggle_window (GtkWidget * widget, gpointer data) // { // DenemoGUI *gui = (DenemoGUI *) data; // /* printf("toggling display\n"); */ // if (GTK_WIDGET_IS_SENSITIVE (gui->textview)) // { // gtk_widget_set_sensitive (gui->textview, FALSE); // gtk_widget_set_sensitive (gui->scorearea, TRUE); // } // else // { // gtk_widget_set_sensitive (gui->textview, TRUE); // gtk_widget_set_sensitive (gui->scorearea, FALSE); // } // // } // // /* create a textwindow to display the nodes in scoreinfo lily_file // */ // void // create_text_display (DenemoGUI * gui) // { // GtkWidget *main_vbox; // static GtkWidget *second_window = NULL; // GtkWidget *hbox; // GtkWidget *sw; // GtkWidget *togglebutton, *topbutton, *prevbutton, *nextbutton, // *reloadbutton; // // main_vbox = gtk_bin_get_child ((GtkBin *) gui->window); // gui->textwindow = gtk_vbox_new (FALSE, 1); // gtk_container_add (GTK_CONTAINER (main_vbox), gui->textwindow); // gtk_widget_show (gui->textwindow); // main_vbox = gui->textwindow; // if (!second_window) // { // second_window = gtk_window_new (GTK_WINDOW_TOPLEVEL); // gtk_window_set_title (GTK_WINDOW (second_window), // "Lilypond Mode Functions"); // gtk_window_set_default_size (GTK_WINDOW (second_window), 100, 75); // gtk_widget_show (second_window); // // hbox = gtk_hbox_new (FALSE, 1); // gtk_container_add (GTK_CONTAINER (second_window), hbox); // gtk_widget_show (hbox); // /* the reload node button */ // reloadbutton = gtk_button_new_with_label ("Reload"); // g_signal_connect (G_OBJECT (reloadbutton), "clicked", // (GtkSignalFunc) reload_lily_file, gui); // gtk_box_pack_start (GTK_BOX (hbox), reloadbutton, TRUE, FALSE, 0); // gtk_widget_show (reloadbutton); // /* the edit button */ // togglebutton = gtk_button_new_with_label ("Toggle window"); // gtk_widget_set_size_request (togglebutton, -1, 20); // g_signal_connect (G_OBJECT (togglebutton), "clicked", // (GtkSignalFunc) toggle_window, gui); // gtk_box_pack_start (GTK_BOX (hbox), togglebutton, TRUE, FALSE, 0); // gtk_widget_show (togglebutton); // // /* the top node button */ // topbutton = gtk_button_new_with_label ("Toplevel <-> Music Data"); // gtk_widget_set_size_request (topbutton, -1, 20); // g_signal_connect (G_OBJECT (topbutton), "clicked", // (GtkSignalFunc) toggle_top_node, gui); // gtk_box_pack_start (GTK_BOX (hbox), topbutton, TRUE, FALSE, 0); // gtk_widget_show (topbutton); // // // /* the previous node button */ // prevbutton = gtk_button_new_with_label ("<-"); // gtk_widget_set_size_request (prevbutton, -1, 20); // g_signal_connect (G_OBJECT (prevbutton), "clicked", // (GtkSignalFunc) node_text_previous, gui); // gtk_box_pack_start (GTK_BOX (hbox), prevbutton, TRUE, FALSE, 0); // gtk_widget_show (prevbutton); // /* the next node button */ // nextbutton = gtk_button_new_with_label ("->"); // gtk_widget_set_size_request (nextbutton, -1, 20); // g_signal_connect (G_OBJECT (nextbutton), "clicked", // (GtkSignalFunc) node_text_next, gui); // gtk_box_pack_start (GTK_BOX (hbox), nextbutton, TRUE, FALSE, 0); // gtk_widget_show (nextbutton); // /* the music data button */ // gui->musicdatabutton = // gtk_button_new_with_label ("music data - edit graphically"); // gtk_widget_set_size_request (gui->musicdatabutton, -1, 20); // /* could have signal here to go to current object? */ // gtk_box_pack_start (GTK_BOX (hbox), gui->musicdatabutton, TRUE, // FALSE, 0); // gtk_widget_show (gui->musicdatabutton); // // } // /******* the text to edit ***********/ // sw = gtk_scrolled_window_new (NULL, NULL); // gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw), // GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); // // gtk_container_add (GTK_CONTAINER (main_vbox), sw); // gtk_widget_show (sw); // // // gui->textview = gtk_text_view_new (); // gtk_widget_set_sensitive (gui->textview, FALSE); // gtk_container_add (GTK_CONTAINER (sw), gui->textview); // gui->textbuffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (gui->textview)); // gui->si->curlilynode = gui->si->lily_file; // gtk_text_buffer_set_text (gui->textbuffer, u_str (gui->si->curlilynode), -1); // gui->sigid = g_signal_connect (G_OBJECT (gui->textbuffer), "changed", // (GtkSignalFunc) string_edited, gui); // gtk_widget_show (gui->textview); // }