1 /* contexts.cpp
2  * Context finders: functions that find the current clef, key, and time
3  * signature contexts for the measures being displayed
4  *
5  * These functions are also invoked when a staff is created
6  *
7  *
8  * for Denemo, a gtk+ frontend to GNU Lilypond
9  * (c) 1999-2005 Matthew Hiller, Adam Tee
10  */
11 
12 #include "command/contexts.h"
13 #include "display/drawingprims.h"
14 #include "command/object.h"
15 #include "command/staff.h"
16 #include "command/measure.h"
17 
18 /**
19  * This function finds the first DenemoObject of type thetype *before* measure
20  * curmeasure. It returns NULL if it was unable to find such a DenemoObject
21  *
22  * @param curmeasure the current measure to search
23  * @param thetype type of DenemoObject to find
24  * @return the first DenemoObject of type the type
25  */
26 static DenemoObject *
find_measure_context(measurenode * curmeasure,DenemoObjType thetype)27 find_measure_context (measurenode * curmeasure, DenemoObjType thetype)
28 {
29   objnode *curobj;
30   if (curmeasure && curmeasure->prev)
31     curmeasure = curmeasure->prev;
32   else
33     return NULL;
34 
35   curobj = measure_last_obj_node (curmeasure);
36   while (1)
37     {
38       while (!curobj)
39         {                       /* Cycle back to preceding measure */
40           if (!curmeasure->prev)
41             return NULL;        /* That is, we've fallen off the beginnig */
42           curmeasure = curmeasure->prev;
43           curobj = measure_last_obj_node (curmeasure);
44         }
45       if (((DenemoObject *) curobj->data)->type == thetype)
46         return (DenemoObject *) curobj->data;
47       else
48         curobj = curobj->prev;
49     }
50 }
51 
52 
53 
54 /**
55  * This function finds the first DenemoObject of type thetype before si->currentobject
56  * It returns NULL if it was unable to find such a DenemoObject
57  * @param si the DenemoMovement with si->currentobject and si->currentmeasure set
58  * @param thetype type of DenemoObject to find
59  * @return the first DenemoObject of type thetype
60  */
61 static DenemoObject *
find_context_of_object(DenemoMovement * si,DenemoObjType thetype)62 find_context_of_object (DenemoMovement * si, DenemoObjType thetype)
63 {
64   objnode *curobj = si->currentobject;
65   measurenode *curmeasure = si->currentmeasure;
66   if (curmeasure == NULL)
67     return NULL;
68   if (curobj == NULL)
69       while (curmeasure->prev)
70             {
71               curmeasure = curmeasure->prev;
72               curobj = measure_last_obj_node (curmeasure);
73               if (curobj)
74                 break;
75             }
76 
77    if (curobj == NULL || curmeasure == NULL)
78     return NULL;
79 
80   while (curobj)
81     {
82       if (((DenemoObject *) curobj->data)->type == thetype)
83         return (DenemoObject *) curobj->data;
84       else
85         curobj = curobj->prev;
86       if (curobj == NULL)
87         {                       /* go back to preceding measure */
88           while (curmeasure->prev)
89             {
90               curmeasure = curmeasure->prev;
91               curobj = measure_last_obj_node (curmeasure);
92               if (curobj)
93                 break;
94             }
95         }
96     }
97   return NULL;
98 }
99 
100 
101 DenemoObject *
get_clef_before_object(objnode * obj)102 get_clef_before_object (objnode * obj)
103 {
104   DenemoObject *ret;
105   objnode *curobj = Denemo.project->movement->currentobject;
106   Denemo.project->movement->currentobject = obj;
107   ret = find_context_of_object (Denemo.project->movement, CLEF);
108   Denemo.project->movement->currentobject = curobj;
109   return ret;
110 }
111 
112 /* find the clef in which the currentobject lies */
113 gint
find_prevailing_clef(DenemoMovement * si)114 find_prevailing_clef (DenemoMovement * si)
115 {
116     return ((clef*)get_prevailing_context (CLEF))->type;
117 /*
118   DenemoStaff *curstaff = ((DenemoStaff *) si->currentstaff->data);
119   DenemoObject *obj = find_context_of_object (si, CLEF);
120 //g_debug("prevailing clef %d\n",  obj? ((clef *) obj->object)->type:curstaff->clef.type);
121   return obj ? ((clef *) obj->object)->type : curstaff->clef.type;
122   * */
123 }
124 
125 /* returns a pointer to a CLEF TIMESIG or KEYSIG structure which holds the information on the prevailing context for the current object */
126 gpointer
get_prevailing_context(DenemoObjType type)127 get_prevailing_context (DenemoObjType type)
128 {
129   DenemoStaff *curstaff = ((DenemoStaff *) Denemo.project->movement->currentstaff->data);
130   gpointer *obj;
131   switch (type)
132     {
133     case CLEF:
134       obj = (gpointer)(Denemo.project->movement->currentobject?((DenemoObject*)Denemo.project->movement->currentobject->data)->clef:((DenemoMeasure*)Denemo.project->movement->currentmeasure->data)->clef);
135       break;
136     case KEYSIG:
137       obj = (gpointer)(Denemo.project->movement->currentobject?((DenemoObject*)Denemo.project->movement->currentobject->data)->keysig:((DenemoMeasure*)Denemo.project->movement->currentmeasure->data)->keysig);
138 
139       break;
140     case TIMESIG:
141       obj = (gpointer)((DenemoMeasure*)Denemo.project->movement->currentmeasure->data)->timesig;
142 
143       break;
144     default:
145       g_critical ("Wrong type in call to get_prevailing_context");
146       obj = NULL;
147       break;
148     }
149   return obj;
150 }
151 
152 /**
153  * Finds the first occurrences of the clef, keysig and timesig of the
154  * current staff  inserting them into the passed CURSTAFFSTRUCT
155  *
156  * @param curstaffstruct the current staff
157  * @param si the scoreinfo structure
158  * @return none
159  */
160 void
find_leftmost_staffcontext(DenemoStaff * curstaffstruct,DenemoMovement * si)161 find_leftmost_staffcontext (DenemoStaff * curstaffstruct, DenemoMovement * si)
162 {
163   measurenode *leftmeasure = g_list_nth (curstaffstruct->themeasures,
164                                          si->leftmeasurenum - 1);
165   DenemoObject *obj;
166 
167   if ((obj = find_measure_context (leftmeasure, CLEF)))
168     curstaffstruct->leftmost_clefcontext = ((clef *) obj->object);
169   else
170     curstaffstruct->leftmost_clefcontext = &curstaffstruct->clef;
171   if ((obj = find_measure_context (leftmeasure, KEYSIG)))
172     curstaffstruct->leftmost_keysig = (keysig *) obj->object;
173   else
174     curstaffstruct->leftmost_keysig = &curstaffstruct->keysig;
175 
176   // initkeyaccs (curstaffstruct->leftmost_keysig->accs,
177   //           curstaffstruct->leftmost_keysig->number);
178 
179   si->maxkeywidth = MAX (si->maxkeywidth, draw_key (NULL, 0, 0, curstaffstruct->leftmost_keysig->number, 0, 0, FALSE, curstaffstruct->leftmost_keysig));
180   if ((obj = find_measure_context (leftmeasure, TIMESIG)))
181     {
182       curstaffstruct->leftmost_timesig = (timesig *) obj->object;
183     }
184   else
185     {
186       curstaffstruct->leftmost_timesig = &curstaffstruct->timesig;
187     }
188   if ((obj = find_measure_context (leftmeasure, STEMDIRECTIVE)))
189     curstaffstruct->leftmost_stem_directive = ((stemdirective *) obj->object)->type;
190   else
191     curstaffstruct->leftmost_stem_directive = DENEMO_STEMBOTH;
192 }
193 
194 /**
195  * Finds the first occurrences of the clef, keysig and timesig of the
196  * across the entir score
197  * @param si the scoreinfo structure
198  * @return none
199  */
200 void
find_leftmost_allcontexts(DenemoMovement * si)201 find_leftmost_allcontexts (DenemoMovement * si)
202 {
203   staffnode *curstaff = si->thescore;
204 
205   si->maxkeywidth = G_MININT;
206   for (; curstaff; curstaff = curstaff->next)
207     {
208       find_leftmost_staffcontext ((DenemoStaff *) curstaff->data, si);
209 
210     }
211 }
212