+ s = ''
+ if header.has_key (key):
+ s = header[key] + "\n"
+ header [key] = s + a
+
+def wordwrap(a, v):
+ linelen = len (v) - v.rfind ('\n')
+ if linelen + len (a) > 80:
+ v = v + '\n'
+ return v + a + ' '
+
+def stuff_append (stuff, idx, a):
+ if not stuff:
+ stuff.append (a)
+ else:
+ stuff [idx] = wordwrap(a, stuff[idx])
+
+# ignore wordwrap since we are adding to the previous word
+def stuff_append_back(stuff, idx, a):
+ if not stuff:
+ stuff.append (a)
+ else:
+ point = len(stuff[idx])-1
+ while stuff[idx][point] is ' ':
+ point = point - 1
+ point = point +1
+ stuff[idx] = stuff[idx][:point] + a + stuff[idx][point:]
+
+def voices_append(a):
+ if current_voice_idx < 0:
+ select_voice ('default', '')
+ stuff_append (voices, current_voice_idx, a)
+
+# word wrap really makes it hard to bind beams to the end of notes since it
+# pushes out whitespace on every call. The _back functions do an append
+# prior to the last space, effectively tagging whatever they are given
+# onto the last note
+def voices_append_back(a):
+ if current_voice_idx < 0:
+ select_voice ('default', '')
+ stuff_append_back(voices, current_voice_idx, a)
+
+def repeat_prepend():
+ global repeat_state
+ if current_voice_idx < 0:
+ select_voice ('default', '')
+ if not using_old:
+ repeat_state[current_voice_idx] = 't'
+
+
+def lyrics_append(a):
+ a = re.sub ('#', '\\#', a) # latex does not like naked #'s
+ a = re.sub ('"', '\\"', a) # latex does not like naked "'s
+ a = ' \\line { "' + a + '" }\n'
+ stuff_append (lyrics, current_lyric_idx, a)
+
+# break lyrics to words and put "'s around words containing numbers and '"'s
+def fix_lyric(str):
+ ret = ''
+ while str != '':
+ m = re.match('[ \t]*([^ \t]*)[ \t]*(.*$)', str)
+ if m:
+ word = m.group(1)
+ str = m.group(2)
+ word = re.sub('"', '\\"', word) # escape "
+ if re.match('.*[0-9"\(]', word):
+ word = re.sub('_', ' ', word) # _ causes probs inside ""
+ ret = ret + '\"' + word + '\" '
+ else:
+ ret = ret + word + ' '
+ else:
+ return (ret)
+ return (ret)
+
+def slyrics_append(a):
+ a = re.sub ( '_', ' _ ', a) # _ to ' _ '
+ a = re.sub ( '([^-])-([^-])', '\\1- \\2', a) # split words with "-" unless was originally "--"
+ a = re.sub ( '\\\\- ', '-', a) # unless \-
+ a = re.sub ( '~', '_', a) # ~ to space('_')
+ a = re.sub ( '\*', '_ ', a) # * to to space
+ a = re.sub ( '#', '\\#', a) # latex does not like naked #'s
+ if re.match('.*[0-9"\(]', a): # put numbers and " and ( into quoted string
+ a = fix_lyric(a)
+ a = re.sub ( '$', ' ', a) # insure space between lines
+ __main__.lyric_idx = lyric_idx + 1
+ if len(slyrics[current_voice_idx]) <= lyric_idx:
+ slyrics[current_voice_idx].append(a)
+ else:
+ v = slyrics[current_voice_idx][lyric_idx]
+ slyrics[current_voice_idx][lyric_idx] = wordwrap(a, slyrics[current_voice_idx][lyric_idx])
+
+
+def try_parse_header_line (ln, state):
+ global length_specified
+ m = re.match ('^([A-Za-z]): *(.*)$', ln)
+
+ if m:
+ g =m.group (1)
+ a = m.group (2)
+ if g == 'T': #title
+ a = re.sub('[ \t]*$','', a) #strip trailing blanks
+ if header.has_key('title'):
+ if a:
+ if len(header['title']):
+ # the non-ascii character
+ # in the string below is a
+ # punctuation dash. (TeX ---)
+ header['title'] = header['title'] + ' â ' + a
+ else:
+ header['subtitle'] = a
+ else:
+ header['title'] = a
+ if g == 'M': # Meter
+ if a == 'C':
+ if not state.common_time:
+ state.common_time = 1
+ voices_append (" \\override Staff.TimeSignature #'style = #'C\n")
+ a = '4/4'
+ if a == 'C|':
+ if not state.common_time:
+ state.common_time = 1
+ voices_append ("\\override Staff.TimeSignature #'style = #'C\n")
+ a = '2/2'
+ if not length_specified:
+ set_default_len_from_time_sig (a)
+ else:
+ length_specified = 0
+ if not a == 'none':
+ voices_append ('\\time %s' % a)
+ state.next_bar = ''
+ if g == 'K': # KEY
+ a = check_clef(a)
+ if a:
+ m = re.match ('^([^ \t]*) *([^ ]*)( *)(.*)$', a) # separate clef info
+ if m:
+ # there may or may not be a space
+ # between the key letter and the mode
+ # convert the mode to lower-case before comparing
+ mode = m.group(2)[0:3].lower();
+ if key_lookup.has_key(mode):
+ # use the full mode, not only the first three letters
+ key_info = m.group(1) + m.group(2).lower()
+ clef_info = a[m.start(4):]
+ else:
+ key_info = m.group(1)
+ clef_info = a[m.start(2):]
+ __main__.global_key = compute_key (key_info)
+ k = lily_key (key_info)
+ if k:
+ voices_append ('\\key %s' % k)
+ check_clef(clef_info)
+ else:
+ __main__.global_key = compute_key (a)
+ k = lily_key (a)
+ if k:
+ voices_append ('\\key %s \\major' % k)
+ if g == 'N': # Notes
+ header ['footnotes'] = header['footnotes'] + '\\\\\\\\' + a
+ if g == 'O': # Origin
+ header ['origin'] = a
+ if g == 'X': # Reference Number
+ header ['crossRefNumber'] = a
+ if g == 'A': # Area
+ header ['area'] = a
+ if g == 'H': # History
+ header_append ('history', a)
+ if g == 'B': # Book
+ header ['book'] = a
+ if g == 'C': # Composer
+ if header.has_key('composer'):
+ if a:
+ header['composer'] = header['composer'] + '\\\\\\\\' + a
+ else:
+ header['composer'] = a
+ if g == 'S':
+ header ['subtitle'] = a
+ if g == 'L': # Default note length
+ set_default_length (ln)
+ if g == 'V': # Voice
+ voice = re.sub (' .*$', '', a)
+ rest = re.sub ('^[^ \t]* *', '', a)
+ if state.next_bar:
+ voices_append(state.next_bar)
+ state.next_bar = ''
+ select_voice (voice, rest)
+ if g == 'W': # Words
+ lyrics_append(a)
+ if g == 'w': # vocals
+ slyrics_append (a)
+ if g == 'Q': #tempo
+ try_parse_q (a)
+ return ''
+ return ln
+
+# we use in this order specified accidental, active accidental for bar,
+# active accidental for key
+def pitch_to_lilypond_name (name, acc, bar_acc, key):
+ s = ''
+ if acc == UNDEF:
+ if not nobarlines:
+ acc = bar_acc
+ if acc == UNDEF:
+ acc = key
+ if acc == -1:
+ s = 'es'
+ elif acc == 1:
+ s = 'is'
+
+ if name > 4:
+ name = name -7
+ return(chr (name + ord('c')) + s)
+
+
+def octave_to_lilypond_quotes (o):
+ o = o + 2
+ s =''
+ if o < 0:
+ o = -o
+ s=','
+ else:
+ s ='\''
+
+ return s * o