/****************************************************************************************/
/*											*/
/* This program is free software; you can redistribute it and/or modify it under the	*/
/* terms of the GNU General Public License as published by the Free Software		*/
/* Foundation; either version 2 of the License, or (at your option) any later version.	*/
/*											*/
/* This program is distributed in the hope that it will be useful, but WITHOUT ANY	*/
/* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A	*/
/* PARTICULAR PURPOSE. See the GNU General Public License for more details.		*/
/*											*/
/* You should have received a copy of the GNU General Public License along with this	*/
/* program; (See "LICENSE.GPL"). If not, write to the Free Software Foundation, Inc.,	*/
/* 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.				*/
/*											*/
/*--------------------------------------------------------------------------------------*/
/*											*/
/*		Joerg Anders, TU Chemnitz, Fakultaet fuer Informatik, GERMANY		*/
/*		ja@informatik.tu-chemnitz.de						*/
/*											*/
/*											*/
/****************************************************************************************/

// <GFI date="2001/03/29" mail="gilles.filippini@free.fr">
// WITH_OLDLILY trick implemented to be able to coop with old LilyPond syntax
// </GFI>

#include "config.h"
#if GCC_MAJ_VERS > 2
#include <istream>
#else
#include <istream.h>
#endif
#include <stdlib.h> //  esigra: needed for mkstemp when --without-libs
#include <kfiledialog.h>
#include <kmessagebox.h>
#include <klocale.h>
#include <qregexp.h>
#include <qcheckbox.h>
#include <qcombobox.h>
#include <qspinbox.h>
#include <qslider.h>
#include "lilyexport.h"
#include "mainframewidget.h"
#include "resource.h"
#include "clef.h"
#include "filehandler.h"
#include "keysig.h"
#include "timesig.h"
#include "sign.h"
#include "rest.h"
#include "chord.h"
#include "voice.h"
#include "staff.h"
#include "uiconnect.h"
#include "chorddiagram.h"
#include "layout.h"

#define LILY_ERR_DRUM_STAFF        1
#define LILY_ERR_IRREGULAER        2
#define LILY_ERR_NOTE_128          3
#define LILY_ERR_NOTE_COUNT        4
#define LILY_ERR_NOTE_MIXED_TIES   5
#define LILY_ERR_SLURES_IN_GRACES  6
#define LILY_ERR_VAR_TRILLS        7
#define LILY_ERR_BRACKET_DISCONT   8
#define LILY_ERR_PIANO_DISCONT     9
#define LILY_ERR_CONT_OUTSIDE     10

#define MEASURES_PER_LINE 2

#define EDGE_TEXT_NOT_SET 0
#define EDGE_TEXT_TR 1
#define EDGE_TEXT_EMPTY 2

#define BODY_DEFAULT 0

QRegExp NLilyExport::nonAlphas_("[^A-Za-z]");
QRegExp NLilyExport::digits_("[0-9]");
QRegExp NLilyExport::whiteSpaces_(" ");
QRegExp NLilyExport::relSyms("[<>]");
QRegExp NLilyExport::starOnly("^ *[-\\*] *$");

NLilyExport::NLilyExport() {
#if GCC_MAJ_VERS > 2
	os_ = new ostringstream();
#else
	os_ = new ostrstream(buffer_, 128);
#endif
	noStrongPizzMsg_ = false;
}

void NLilyExport::exportStaffs(QString fname, QList<NStaff> *stafflist, exportFrm *expWin, NMainFrameWidget *mainWidget) {
	int i, j;
	double wh;
	int k, str;
	badmeasure *bad;
	NVoice *voice_elem;
	NStaff *staff_elem;
	int voice_count;
	QString staffName, staffLabel, s;
	NClef *clef;
	int staff_count;
	bool header_written = false;
	bool bracket_problem_reported = false;
	bool piano_problem_reported = false;
	bool contBars, discontBars;

	exportDialog_ = expWin;

	if (fname.isNull() || fname.isEmpty())
		return;

	out_.open(fname);
	if (!out_) {
		*os_ << "error opening file " << fname << '\0';
#if GCC_MAJ_VERS > 2
		KMessageBox::sorry
			(0, QString(os_->str().c_str()), kapp->makeStdCaption(i18n("???")));
#else
		KMessageBox::sorry
			(0, QString(os_->str()), kapp->makeStdCaption(i18n("???")));
#endif
		return;
	}
	out_.setf(ios::showpoint);
	staff_count = stafflist->count();
	lastLilyPondfile_ = fname;
	staffarray_ = new staffdescr[staff_count];
	noteBody_ = BODY_DEFAULT;
	for (i = 0; i < staff_count; i++) {
		staffarray_[i].lyrics_count = 0;
		if (NResource::staffSelExport_ != 0) {
			staffarray_[i].is_selected = NResource::staffSelExport_[i];
		}
		else {
			staffarray_[i].is_selected = true;
		}
	}
	badlist_.setAutoDelete(true);
	badlist_.clear();
	drum_problem_written_ = false;
	va_problem_written_ = false;
	out_ << "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%" << endl;
	out_ << "%                                  %" << endl;
	out_ << "%   LilyPond output generated by   %" << endl;
	out_ << "%           \"noteedit\"             %" << endl;
	out_ << "%                                  %" << endl;
	out_ << "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%" << endl << endl;
	if (!exportDialog_->lilyVoice->isChecked()) {
		out_ << "\\include \"paper" << exportDialog_->lilyFont->currentText() << ".ly\"" << endl << endl;
	}
	if (exportDialog_->lilyDrumNotes->isChecked()) {
		out_ << "bcr = {" << endl << "\\context Thread = xcircle" << endl << "\\property Voice.NoteHead \\set #'style = #'cross" << endl << '}' << endl;
		out_ << "bdf = {" << endl << "\\context Thread = xdefault" << endl << "\\property Voice.NoteHead \\set #'style = #'default" << endl << '}' << endl;
		out_ << "bcc = {" << endl << "\\context Thread = xcircle" << endl << "\\property Voice.NoteHead \\set #'style = #'xcircle" << endl << '}' << endl;
		out_ << "btr = {" << endl << "\\context Thread = xtriangle" << endl << "\\property Voice.NoteHead \\set #'style = #'triangle" << endl << '}' << endl << endl;
	}
	if (NResource::lilyProperties_.lilyVersion2) {
		out_ << "flat = \\markup { \\raise #0.4 \\smaller \\musicglyph #\"accidentals--2\" }" << endl;
		out_ << "sharp = \\markup { \\raise #0.6 \\smaller \\musicglyph #\"accidentals-2\" }" << endl;
		out_ << "textcodaysym = \\markup { \\hspace #1 \\raise #1.1 \\musicglyph #\"scripts-coda\"}" << endl;
	}
	else {
		out_ << "#(define flat '((raise . 0.2) (font-relative-size . -1) (music (named \"accidentals--1\"))))" << endl;
		out_ << "#(define sharp '((raise . 0.4) (font-relative-size . -1) (music (named \"accidentals-1\"))))" << endl;
		out_ << "#(define note '(columns (music \"noteheads-2\" ((kern . -0.1) ))))" << endl;
		out_ << "#(define quarter-head `(columns ,note ((kern . -0.1) )))" << endl;
	}
	out_ << endl;


	if (!mainWidget->scTitle_.isEmpty() && !mainWidget->scTitle_.isNull()) {
		if (!header_written) {
			header_written = true;
			out_ << endl << "\\header {" << endl;
		}
		out_ << "\ttitle = \"" << mainWidget->scTitle_ << '"';
		if (NResource::lilyProperties_.lilySemicolons) out_ << ";";
		out_ << endl;
	}
	if (!mainWidget->scAuthor_.isEmpty() && !mainWidget->scAuthor_.isNull()) {
		if (!header_written) {
			header_written = true;
			out_ << endl << "\\header {" << endl;
		}
		out_ << "\tcomposer = \"" << mainWidget->scAuthor_ << '"';
		if (NResource::lilyProperties_.lilySemicolons) out_ << ";";
		out_ << endl;
	}
	if (!mainWidget->scCopyright_.isEmpty() && !mainWidget->scCopyright_.isNull()) {
		if (!header_written) {
			header_written = true;
			out_ << endl << "\\header {" << endl;
		}
		out_ << "\tcopyright = \"" << mainWidget->scCopyright_ << '"';
		if (NResource::lilyProperties_.lilySemicolons) out_ << ";";
		out_ << endl;
	}
	if (header_written) {
		out_ << '}' << endl << endl;
	}
	for (i = 0, staff_elem = stafflist->first(); staff_elem; staff_elem = stafflist->next(), i++) {
		if (!staffarray_[i].is_selected) continue; 
		voice_count = staff_elem->voiceCount();
		if (voice_count == 1) {
			if (staff_elem->staffName_.isEmpty() || staff_elem->staffName_.isNull()) {
				staffLabel.sprintf("Staff%c", i + 'A');
			}
			else {
				staffLabel = staff_elem->staffName_ + s.sprintf("%c", i + 'A');
			}
			removeExceptsFromString(&staffLabel, false);
			out_ << staffLabel;
			out_ << " = \\notes\\relative c";
			voice_elem = staff_elem->getVoiceNr(0);
			clef = voice_elem->getFirstClef();
			switch (clef->getSubType()) {
				case DRUM_BASS_CLEF:
				case DRUM_CLEF: lastLine_ = -3; str = 0; break;
				case TENOR_CLEF: lastLine_ = 3; str = 1; break;
				case ALTO_CLEF: lastLine_ = 4; str = 1; break;
				case BASS_CLEF: lastLine_ = 3; str = 0; break;
				case TREBLE_CLEF: lastLine_ = -2; str = 1; break;
			} 
			for (k = 0; k < str; k++) out_ << '\'';
			out_ << " {" << endl << '\t';
			if (exportDialog_->lilyBeam->isChecked()) {
				out_ << "\\property Voice.autoBeaming = ##f" << endl << '\t';
			}
			if (exportDialog_->lilyTies->isChecked()) {
				out_ << "\\property Thread.sparseTies = ##t" << endl << '\t';
			}
			if (!voice_elem->getStaff()->staffName_.isNull() && !voice_elem->getStaff()->staffName_.isEmpty()) {
				out_ << "\\property Staff.instrument = #\"" << staff_elem->staffName_ << '"' << endl << '\t';
			}
			voice_elem->prepareForWriting();
			staff_elem->actualClef_.change(clef);
			depth_ = 1;
			writeVoice(i, 0,voice_elem);
			out_ << "}" << endl;
		}
		else {
			voice_elem = staff_elem->getVoiceNr(0);
			clef = voice_elem->getFirstClef();
			for (j = 0; j < voice_count; j++) {
				voice_elem = staff_elem->getVoiceNr(j);
				if (staff_elem->staffName_.isNull() || staff_elem->staffName_.isEmpty()) {
					staffLabel.sprintf("Staff%cVoice%c", i + 'A', j + 'A');
				}
				else {
					staffLabel = staff_elem->staffName_ + s.sprintf("%cVoice%c", i + 'A', j + 'A');
				}
				removeExceptsFromString(&staffLabel, false);
				out_ << staffLabel;
				out_ << " = \\notes\\relative c";
				switch (clef->getSubType()) {
					case DRUM_BASS_CLEF:
					case DRUM_CLEF: lastLine_ = -3; str = 0; break;
					case TENOR_CLEF: lastLine_ = 3; str = 1; break;
					case ALTO_CLEF: lastLine_ = 4; str = 1; break;
					case BASS_CLEF: lastLine_ = 3; str = 0; break;
					case TREBLE_CLEF: lastLine_ = -2; str = 1; break;
				} 
				for (k = 0; k < str; k++) out_ << '\'';
				out_ << " {";
				if (!(exportDialog_->lilyStem->isChecked())) {
					switch(j) {
						case 0: out_ << " \\voiceOne "; break;
						case 1: out_ << " \\voiceTwo "; break;
						case 2: out_ << " \\voiceThree "; break;
						case 3: out_ << " \\voiceFour "; break;
					}
				}
				out_ <<  endl << '\t';
				if (exportDialog_->lilyBeam->isChecked()) {
					out_ << "\\property Voice.noAutoBeaming = ##t" << endl << '\t';
				}
				if (exportDialog_->lilyTies->isChecked()) {
					out_ << "\\property Thread.sparseTies = ##t" << endl << '\t';
				}
				voice_elem->prepareForWriting();
				staff_elem->actualClef_.change(clef);
				depth_ = 1;
				writeVoice(i, j, voice_elem);
				if (j < 0) out_ << endl;
				out_ << "}" << endl;
			}
			if (staff_elem->staffName_.isNull() || staff_elem->staffName_.isEmpty()) {
				staffLabel.sprintf("Staff%c", i + 'A');
			}
			else {
				staffLabel = staff_elem->staffName_ + s.sprintf("%c", i + 'A');
			}
			removeExceptsFromString(&staffLabel, false);
			out_ << staffLabel << " = \\simultaneous {" << endl;
			if (!staff_elem->staffName_.isNull() && !staff_elem->staffName_.isEmpty()) {
				out_ << "\t\\property Staff.instrument = #\"" << staff_elem->staffName_ << '"' << endl;
			}
			for (j = 0, voice_elem = staff_elem->getVoiceNr(0); j < voice_count; j++) {
				if (staff_elem->staffName_.isNull() || staff_elem->staffName_.isEmpty()) {
					staffLabel.sprintf("Staff%cVoice%c", i + 'A', j + 'A');
				}
				else {
					staffLabel = staff_elem->staffName_ + s.sprintf("%cVoice%c", i + 'A', j + 'A');
				}
				removeExceptsFromString(&staffLabel, false);
				out_ << "\t\\context Voice=\"" << staffLabel << "\" " <<  "\\" << staffLabel << endl;
			}
			out_ << "}" << endl;
		}
		if (staff_elem->staffName_.isNull() || staff_elem->staffName_.isEmpty()) {
			staffLabel.sprintf("Staff%c", i + 'A');
		}
		else {
			staffLabel = staff_elem->staffName_ + s.sprintf("%c", i + 'A');
		}
		removeExceptsFromString(&staffLabel, false);
		if (staffarray_[i].lyrics_count) {
			out_ << staffLabel << "Text = \\lyrics ";
			writeLyrics(i, voice_elem);
		}
	}
	if (!exportDialog_->lilyVoice->isChecked()) {
		out_ << "\\score {" << endl;
		out_ << "\t\\simultaneous {" << endl;
		out_ << "\t\t\\property Score.skipBars = ##t" << endl;
		if (NResource::lilyProperties_.lilyVersion2) {
			out_ << "\t\t\\property Score.melismaBusyProperties = #'(melismaBusy slurMelismaBusy tieMelismaBusy)" << endl;
		}
		depth_ = 2;
	
		if (continuedOutsideAGroup(mainWidget, staff_count)) {
			bad = new badmeasure(LILY_ERR_CONT_OUTSIDE, 1, /* dummy */ 1, /* dummy */ 1, /* dummy */ 1 /* dummy */);
			badlist_.append(bad);
		}
		for (i = 0, staff_elem = stafflist->first(); staff_elem; staff_elem = stafflist->next(), i++) {
			if (!staffarray_[i].is_selected) continue;
			for (k = 0; k < staff_count; k++) {
				if (mainWidget->bracketMatrix_[k].valid) {
					if (mainWidget->bracketMatrix_[k].beg == i) {
						analyseGroup(&(mainWidget->bracketMatrix_[k]), mainWidget, staff_count, &contBars, &discontBars);
						tabsOut();
						if (contBars) {
							out_ << "\\context StaffGroup";
							if (NResource::lilyProperties_.lilyVersion2) {
								out_ << "<< ";
							}
							else {
								out_ << '<' <<' ';
							}
							out_ << endl;
						}
						else {
							out_ << "\\context ChoirStaff" << endl;
							if (NResource::lilyProperties_.lilyVersion2) {
								out_ << "<< ";
							}
							else {
								 out_ << '<' << ' ';
							}
							out_ << endl;
							if (!discontBars && !bracket_problem_reported) {
								bad = new badmeasure(LILY_ERR_BRACKET_DISCONT, 1, /* dummy */ 1, /* dummy */ 1, /* dummy */ 1 /* dummy */);
								badlist_.append(bad);
								bracket_problem_reported = true;
							}
						}
						depth_++;
					}
				}
			}
			for (k = 0; k < staff_count; k++) {
				if (mainWidget->braceMatrix_[k].valid) {
					if (mainWidget->braceMatrix_[k].beg == i) {
						tabsOut();
						out_ << "\\context PianoStaff \\notes" << endl;
						if (NResource::lilyProperties_.lilyVersion2) {
							out_ << "<< ";
						}
						else {
							out_ << '<' <<' ';
						}
						out_ << endl;
						depth_++;
						if (!piano_problem_reported) {
							analyseGroup(&(mainWidget->braceMatrix_[k]), mainWidget, staff_count, &contBars, &discontBars);
							if (!contBars) {
								bad = new badmeasure(LILY_ERR_PIANO_DISCONT, 1, /* dummy */ 1, /* dummy */ 1, /* dummy */ 1 /* dummy */);
								badlist_.append(bad);
								piano_problem_reported = true;
							}
						}
					}
				}
			}
			if (staff_elem->staffName_.isNull() || staff_elem->staffName_.isEmpty()) {
				staffLabel.sprintf("Staff%c", i + 'A');
				staffName.sprintf("Staff%c", i + 'A');
			}
			else {
				staffLabel = staff_elem->staffName_ + s.sprintf("%c", i + 'A');
				staffName = staff_elem->staffName_;
			}
			removeExceptsFromString(&staffLabel, false);

			tabsOut();
			if (staffarray_[i].lyrics_count) {
				out_ << "\\addlyrics " << endl; tabsOut();
			}
	                out_ << "\\context Staff=\"" << staffName << "\" ";
			out_ << '\\' << staffLabel << endl;
			if (staffarray_[i].lyrics_count) {
				tabsOut();
				out_ << "\\context Lyrics=\"" << staffName << "Text\" \\" << staffLabel << "Text" << endl;
			}
			for (k = 0; k < staff_count; k++) {
				if (mainWidget->bracketMatrix_[k].valid) {
					if (mainWidget->bracketMatrix_[k].end == i) {
						depth_--;
						tabsOut();
						if (NResource::lilyProperties_.lilyVersion2) {
							out_ << ">>" << endl;
						}
						else {
							out_ << '>' << endl;
						}
					}
				}
			}
			for (k = 0; k < staff_count; k++) {
				if (mainWidget->braceMatrix_[k].valid) {
					if (mainWidget->braceMatrix_[k].end == i) {
						depth_--;
						tabsOut();
						if (NResource::lilyProperties_.lilyVersion2) {
							out_ << ">>" << endl;
						}
						else {
							out_ << '>' << endl;
						}
					}
				}
			}
		}
	
	
		out_ << "\t}" << endl;
	        out_ << "\t\\paper {" << endl;
		if (exportDialog_->lilyLand->isChecked()) {
			out_ << "\t\torientation = \"landscape\"" << endl;
			if (NResource::lilyProperties_.lilySemicolons) out_ << ";";
		}
		if (sscanf(exportDialog_->lilyWidth->text(), "%lf", &wh) != 1) {
			wh = 250.0;
		}
	        out_ << "\t\tlinewidth = " << wh << " \\mm";
		if (NResource::lilyProperties_.lilySemicolons) out_ << ";";
		out_ << endl;
		if (sscanf(exportDialog_->lilyHeight->text(), "%lf", &wh) != 1) {
			wh = 160.0;
		}
	        out_ << "\t\ttextheight = " << wh << " \\mm";
		if (NResource::lilyProperties_.lilySemicolons) out_ << ";";
		out_ << endl;
	        out_ << "\t}" << endl;
		out_ << "}" << endl;
	}
	out_.close();
	delete [] staffarray_;
	if (!badlist_.isEmpty()) {
		QString output;
		output = i18n
			("Noteedit has exported the score to LilyPond but there are some\n"
			 "problems which will probably prevent successful LilyPond output.\n");
		output += i18n("-----------------------------------------------------\n");
		for (bad = badlist_.first(); bad; bad = badlist_.next()) {
			switch (bad->kind) {
				case LILY_ERR_NOTE_128:
				output += i18n
				( "Staff %1, measure %2: 128th in mesaure; minimum is 64th\n").arg(bad->track).arg(bad->measure);
					break;
				case LILY_ERR_IRREGULAER:
				output += i18n
				( "Staff %1 has irregular keysig. This cannot be expressed in LilyPond\n").arg(bad->track);
					break;
				case LILY_ERR_NOTE_COUNT:
				output += i18n
				( "Staff %1, measure %2: has %3 128th, should be: %4\n").
					arg(bad->track).arg(bad->measure).arg(bad->realcount).arg(bad->shouldbe);
					break;
				case LILY_ERR_VAR_TRILLS:
				output += i18n
				( "Staff %1, measure %2: LilyPond less than 1.5.2 cannot deal with variable length trills (wavelines)\n").
				arg(bad->track).arg(bad->measure);
					break;
				case LILY_ERR_NOTE_MIXED_TIES:
				output += i18n 
				( "Staff %1, measure %2: Only a subset of notes in a chord has ties!\n").arg(bad->track).arg(bad->measure);
					break;
				case LILY_ERR_DRUM_STAFF:
					output += i18n
						("Staff %1 contains drum staff. Note! The LilyPond export is not quite correct!\n")
						.arg(bad->track);
					break;
				case LILY_ERR_SLURES_IN_GRACES:
					output += i18n
						("Staff %1: This version of LilyPond cannot deal with slures in graces\n")
						.arg(bad->track);
					break;
				case LILY_ERR_BRACKET_DISCONT:
					output += i18n
						("A bracket with partial continued partial discountinued bar rules cannot be expressed in LilyPond\n");
					break;
				case LILY_ERR_PIANO_DISCONT:
					output += i18n
						("A piano staff without continued bar rules cannot be expressed in LilyPond\n");
					break;
				case LILY_ERR_CONT_OUTSIDE:
					output += i18n
						("Continued bar rule outside brace or bracket cannot be expressed in LilyPond\n");
					break;
			}
		}
		NResource::exportWarning_->setOutput(i18n ("LilyPond produced. But there are some problems."), &output);
		NResource::exportWarning_->show();
	}
}



void NLilyExport::writeVoice(int staff_nr,  int voice_nr, NVoice *voi) {
	NMusElement *elem, *specialElem;
	char *hiddenRepeat = "\\repeat \"volta\" 2 {";
	int total = 0, i;
	bool first;
	bool AfterFirstBar = false;
	char *pendingVolSig = 0;
	int pending_tempo = -1;
	unsigned int pending_segnos_rirads_accels = 0;
#define PENDING_SEGNO		  (1 << 0)
#define PENDING_DAL_SEGNO	  (1 << 1)
#define PENDING_DAL_SEGNO_AL_FINE (1 << 2)
#define PENDING_DAL_SEGNO_AL_CODA (1 << 3)
#define PENDING_FINE		  (1 << 4)
#define PENDING_CODA		  (1 << 5)
#define PENDING_RITARDANDO	  (1 << 6)
#define PENDING_ACCELERANDO	  (1 << 7)
#define SOME_SIGNS_WITH_TEXT	 (PENDING_DAL_SEGNO | PENDING_DAL_SEGNO_AL_FINE | PENDING_DAL_SEGNO_AL_CODA | PENDING_FINE | PENDING_RITARDANDO | PENDING_ACCELERANDO)
	int acr;
	int saveLine;
	int LineBeforeSPE1;
	bool lastElemIsBar = false;
	bool prevElemIsBar = false;
	bool repeatOpenSeen = false;
	bool specialEnding2Seen = false;
	bool intuplet = false, inbeam = false;
	bool inGrace = false, strokenGrace = false;
	bool slur_problem_written = false;
	long lastBarPos = 0;
	long currentPos;
	long PosOfHiddenRepeat = -1;
	bool repeatOpenAtBeginMissing = false;
	int length;
	int part;
	NClef *clef;
	NKeySig *key;
	NTimeSig *timesig;
	NNote *note;
	NChord *chord;
	NChordDiagram *diag;
	NSign *sign;
	int counter = 0;
	int measure_counter = 0;
	int kind, count;
	NStaff *actual_staff;
	int dynEndPos = 0;
	char *lastDynSym = 0;
	bool textpropset = false;
	bool fatTextWritten = false;
	int edgetext = EDGE_TEXT_NOT_SET;
	int trillendpos = 0;
	int trilledNotes = 0;
	int vaendpos = 0;
	int c4Line;
	int restlen;
	int octaviation = 0;

	countof128th_ = 128;
	currentNumerator_ = currentDenominator_ = 4;
	barNr_ = 1;
	badmeasure *bad;
	

	lastLength_ = 1000;
	lastDotted_ = 0;
	actualStemPolicy_ = STEM_UNSET;
	actual_staff = voi->getStaff();
	actual_staff->actualKeysig_.resetAtBar();
	elem = voi->getCurrentPosition();
	if (elem == 0) return;
	if (!voi->isFirstVoice()) {
		actual_staff->resetSpecialElement();
	}
	do {
		lastElemIsBar = false;
		if (!voi->isFirstVoice()) {
			while (specialElem = actual_staff->checkSpecialElement(elem->getXpos())) {
				switch (specialElem->getType()) {
					case T_KEYSIG: actual_staff->actualKeysig_.change((NKeySig *) specialElem); break;
					case T_CLEF: c4Line = actual_staff->actualClef_.lineOfC4();
						     actual_staff->actualClef_.change((NClef *) specialElem);
						     lastLine_ += actual_staff->actualClef_.lineOfC4() - c4Line;
						     break; 
				}
			}
		}
		switch (elem->getType()) {
			case T_CHORD: if (PosOfHiddenRepeat < 0) {
					if (acr = voi->determineAnacrusis()) {
						out_ << "\\partial " << (128 / acr);
						if (NResource::lilyProperties_.lilySemicolons) out_ << ";";
						out_ << endl << '\t';
					}
					PosOfHiddenRepeat = out_.tellp();
					out_ << hiddenRepeat << endl << '\t';
				     }
				     prevElemIsBar = false;
				     part = elem->getSubType(); 
				     if (!(elem->status_ & STAT_GRACE)) {
				     	total += (elem->status_ & STAT_TUPLET) ? elem->getPlaytime() * part / elem->getNumNotes() : part;
				     }
				     switch (elem->status_ & DOT_MASK) {
					case 1: total += part / 2; break;
					case 2: total += 3 * part / 4; break;
				     }
				     if ((elem->status_ & STAT_TUPLET) && !intuplet) {
					intuplet = true;
					out_ << "\\times " << ((int) elem->getPlaytime()) << '/' << ((int) elem->getNumNotes()) << " { ";
				     }
				     if (total > MULTIPLICATOR*countof128th_ && voi->isFirstVoice()) {
					total = 0;
					bad = new badmeasure(LILY_ERR_NOTE_COUNT, (staff_nr + 1), barNr_, total / 3, countof128th_);
					badlist_.append(bad);
				     }
				     chord = (NChord *) elem;
				     if (chord->countOfLyricsLines() > staffarray_[staff_nr].lyrics_count) {
					staffarray_[staff_nr].lyrics_count = chord->countOfLyricsLines();
				     }
				     if (chord->getSubType() < NOTE64_LENGTH) {
					part = NOTE64_LENGTH;	
					bad = new badmeasure(LILY_ERR_NOTE_128, (staff_nr + 1), barNr_, total / 3, countof128th_);
					badlist_.append(bad);
				     }
				     if (chordHasMixedTies(elem->getNoteList())) {
					bad = new badmeasure(LILY_ERR_NOTE_MIXED_TIES, (staff_nr + 1), barNr_, total / 3, countof128th_);
					badlist_.append(bad);
				     }
				     if ((diag = elem->getChordChordDiagram()) != 0) {
					if (!NResource::lilyProperties_.lilyVersion2  && !fatTextWritten) {
						fatTextWritten = true;
						out_ << "\\fatText ";
					}
				     }
				     if ((pending_segnos_rirads_accels & SOME_SIGNS_WITH_TEXT) && !fatTextWritten) {
				     	fatTextWritten = true;
					out_ << "\\fatText ";
				     }
				     if (chord->trill_) {
					trilledNotes = voi->findNoteCountTillTrillEnd(chord);
					if (!NResource::lilyProperties_.lilyVersion2) {
				        	if (NResource::lilyProperties_.lilyVarTrills) {
							if (!textpropset) {
								textpropset = true;
								out_ << endl;
								tabsOut();
								out_ << "\\property Voice.TextSpanner \\set #'type = #'trill" << endl;
							}
							if (chord->trill_ > 0 && edgetext != EDGE_TEXT_TR) {
								edgetext = EDGE_TEXT_TR;
								out_ << endl;
								tabsOut();
								out_ << "\\property Voice.TextSpanner \\set #'edge-text = #'((line (music \"scripts-trill\") \" \") . \"\")" << endl;
								tabsOut();
							}
							else if (chord->trill_ < 0 && edgetext != EDGE_TEXT_EMPTY) {
								edgetext = EDGE_TEXT_EMPTY;
								out_ << endl;
								tabsOut();
								out_ << "\\property Voice.TextSpanner \\set #'edge-text = #'(\"\")" << endl;
								tabsOut();
							}
						}
						else {
							trilledNotes = 0;
							bad = new badmeasure(LILY_ERR_VAR_TRILLS, (staff_nr + 1), barNr_, total / 3, countof128th_);
							badlist_.append(bad);
						}
					}
				     }
				     if (hasContraryStems(elem->getNoteList()) && exportDialog_->lilyStem->isChecked()) {
					if (chord->status_ & STAT_STEM_UP) {
						if (actualStemPolicy_ != STEM_DIR_UP) {
#ifndef WITH_OLDLILY
							out_ << "\\stemUp ";
#else
							out_ << "\\stemup ";
#endif	// WITH_OLDLILY
							actualStemPolicy_ = STEM_DIR_UP;
						}
					}
					else {
						if (actualStemPolicy_ != STEM_DIR_DOWN) {
#ifndef WITH_OLDLILY
							out_ << "\\stemDown ";
#else
							out_ << "\\stemdown ";
#endif	// WITH_OLDLILY
							actualStemPolicy_ = STEM_DIR_DOWN;
						}
					}
				     }
				     else if (actualStemPolicy_ != STEM_UNSET) {
#ifndef WITH_OLDLILY
					out_ << "\\stemBoth ";
#else
					out_ << "\\stemboth ";
#endif	// WITH_OLDLILY
					actualStemPolicy_ = STEM_UNSET;
				     }
				     if (elem->status_ & STAT_GRACE) {
					if (!slur_problem_written && elem->status_ & STAT_SLURED && !NResource::lilyProperties_.lilySluresInGraces) {
						bad = new badmeasure(LILY_ERR_SLURES_IN_GRACES, (staff_nr + 1), barNr_, total / 3, countof128th_);
						badlist_.append(bad);
						slur_problem_written = true;
					}
					if  (!inGrace) {
						inGrace = true;
						strokenGrace = true;
						out_ << "\\grace { ";
						if (elem->getSubType() != INTERNAL_MARKER_OF_STROKEN_GRACE) {
							strokenGrace = false;
							out_ << "[ ";
						}
					}
				     }
				     else {
					if (inGrace) {
						slur_problem_written = false;
						inGrace = false;
						if (!strokenGrace) {
							strokenGrace = false;
							out_ << "] ";
						}
						out_ << "} ";
					}
					else if (!NResource::lilyProperties_.lilyVersion2 && exportDialog_->lilyBeam->isChecked()) {
						if ((elem->status_ & STAT_BEAMED) && !inbeam) {
							out_ << "[ "; inbeam = true;
				     		}
					}
				     }
				     if (!NResource::lilyProperties_.lilyVersion2 && pending_tempo >= 0) {
				     	if (pending_tempo >= 0) {
					   	out_ << "\\tempo 4.=" << pending_tempo << ' ';
						pending_tempo = -1;
					}
				     }
				     if (chord->va_ != 0) {
					vaendpos = chord->getVaEnd();
					if (chord->va_> 0) {
						octaviation = 1;
						lastLine_ -= 7;
						out_ << "#(set-octavation 1) ";
					}
					else {
						octaviation = -1;
						lastLine_ += 7;
						out_ << "#(set-octavation -1) ";
					}
				     }
				     if (elem->getNoteList()->count() > 1) out_ << "< ";
				     first = true;
			  	     for (note = elem->getNoteList()->first(); note; note = elem->getNoteList()->next()) {
					     if (first) {
					        if (!NResource::lilyProperties_.lilyVersion2 && (chord->status_ & STAT_PART_OF_SLUR)) {
							out_ << ") ";
					        }
					     }
					     if (exportDialog_->lilyDrumNotes->isChecked() && !drum_problem_written_ && (note->status & BODY_MASK)) {
						drum_problem_written_ = true;
						bad = new badmeasure(LILY_ERR_DRUM_STAFF, staff_nr +1, 3 /* dummy */, total / 3, countof128th_);
						badlist_.append(bad);
					     }
					     if (exportDialog_->lilyDrumNotes->isChecked() && noteBody_ != (note->status & BODY_MASK)) {
						switch (noteBody_ = (note->status & BODY_MASK)) {
							case STAT_BODY_CROSS:
							case STAT_BODY_CROSS2:
								out_ << "\\bcr "; break;
							case STAT_BODY_CIRCLE_CROSS:
							case STAT_BODY_RECT:
								out_ << "\\bcc "; break;
							case STAT_BODY_TRIA:
								 out_ << "\\btr "; break;
							default:
								 out_ << "\\bdf "; break;
						}
					      }
					     pitchOut(note, &(actual_staff->actualClef_));
					     if ((elem->status_ & STAT_GRACE) && (elem->getSubType() == INTERNAL_MARKER_OF_STROKEN_GRACE)) {
						length = WHOLE_LENGTH / (NOTE8_LENGTH);
					     }
					     else {
						length = WHOLE_LENGTH / part;
					     }
					     if (first) {
						first = false;
					        if ((!NResource::lilyProperties_.lilyVersion2 || elem->getNoteList()->count() < 2) && (length != lastLength_ || lastDotted_ != (elem->status_ & DOT_MASK))) {
						   if (part == DOUBLE_WHOLE_LENGTH) {
							out_ << "\\breve";
						   }
						   else {
						   	out_ << length;
						   }
						   lastLength_ = length;
						   switch (elem->status_ & DOT_MASK) {
							case 1:	out_ << "."; break;
							case 2:	out_ << ".."; break;
						   }
						   lastDotted_ = elem->status_ & DOT_MASK;
					        }
						if (!NResource::lilyProperties_.lilyVersion2 && elem->status_ & STAT_ARPEGG) {
							out_ << "\\arpeggio ";
						}
						if (elem->status_ & STAT_STACC) {
							out_ << "-.";
					        }
						if (elem->status_ & STAT_SFORZ) {
							out_ << "-^";
						}
						if (elem->status_ & STAT_PORTA) {
							out_ << "--";
						}
						if (elem->status_ & STAT_STPIZ) {
							if (!noStrongPizzMsg_)
								KMessageBox::sorry
									(0,
									 i18n("Sorry, strong Pizzicato is not available under LilyPoint. Take musixtex, to enjoy this feature."),
									 kapp->makeStdCaption(i18n("???"))
									);
							noStrongPizzMsg_ = true;
						}
						if (elem->status_ & STAT_SFZND) {
							out_ << "->";
						}
						if (elem->status_ & STAT_FERMT) {
							out_ << "\\fermata";
						}
						if (chord->trill_ > 0 && trilledNotes == 0) {
							out_ << "\\trill ";
						}
						else if (chord->trill_ < 0 && trilledNotes == 0) {
							out_ << "\\prall ";
						}
						if (trillendpos != 0 && chord->getBbox()->right() > trillendpos) {
							trillendpos = 0;
							if (NResource::lilyProperties_.lilyVersion2) {
								out_ << "#(ly:export (make-span-event 'TextSpanEvent STOP)) ";
							}
							else {
								out_ <<  " \\spanrequest \\stop \"text\" ";
							}
						}
						if (chord->trill_ != 0 && trilledNotes > 0) {
							trillendpos = chord->getTrillEnd();
							if (NResource::lilyProperties_.lilyVersion2) {
								out_ << "#(ly:export (make-span-event 'TextSpanEvent START)) ";
							}
							else {
								out_ << " \\spanrequest \\start \"text\" ";
							}
						}
						if (!NResource::lilyProperties_.lilyVersion2) {
							if (lastDynSym && chord->getBbox()->right() >  dynEndPos) {
								out_ << lastDynSym;
								lastDynSym = 0;
								dynEndPos = 0;
							}
							if (chord->dynamic_) {
								out_ << (chord->dynamicAlign_ ? " \\cr  " : " \\decr ");
								dynEndPos = chord->getDynamicEnd();
								lastDynSym = (char *) (chord->dynamicAlign_ ? " \\rc " : " \\rced ");
							}
						}
						if (chord->status2_ & STAT2_PEDAL_ON) {
							if (NResource::lilyProperties_.lilyVersion2) {
								out_ << "\\sustainDown ";
							}
							else {
								out_ << " \\spanrequest \\start \"Sustain\" ";
							}
						}
						if (chord->status2_ & STAT2_PEDAL_OFF) {
							if (NResource::lilyProperties_.lilyVersion2) {
								out_ << "\\sustainUp ";
							}
							else {
								out_ << " \\spanrequest \\stop \"Sustain\" ";
							}
						}
						if (!NResource::lilyProperties_.lilyVersion2) {
							if (pendingVolSig) {
								switch (exportDialog_->lilyVol->currentItem()) {
									case 1: out_ << '^' << pendingVolSig; break;
									case 2: out_  << pendingVolSig; break;
								}
								pendingVolSig = 0;
							}
							if (pending_tempo >= 0) {
						   		out_ << "^#`(columns , quarter-head \" = " << pending_tempo << "\") ";
						   		pending_tempo = -1;
							}
							if (pending_segnos_rirads_accels & PENDING_SEGNO) {
								out_ << "^\\segno ";
								pending_segnos_rirads_accels &= (~(PENDING_SEGNO));
							}
							if (pending_segnos_rirads_accels & PENDING_DAL_SEGNO) {
								out_ << "^#'(large \"D.S.\") ";
								pending_segnos_rirads_accels &= (~(PENDING_DAL_SEGNO));
							}
							if (pending_segnos_rirads_accels & PENDING_DAL_SEGNO_AL_FINE) {
								out_ << "^#'(large \"D.S. al Fine\") ";
								pending_segnos_rirads_accels &= (~(PENDING_DAL_SEGNO_AL_FINE));
							}
							if (pending_segnos_rirads_accels & PENDING_FINE) {
								out_ << "^#'(Large \"Fine\") ";
								pending_segnos_rirads_accels &= (~(PENDING_FINE));
							}
							if (pending_segnos_rirads_accels & PENDING_DAL_SEGNO_AL_CODA) {
								out_ << "^#'(large \"D.S. al    \" (music \"scripts-coda\")) ";
								pending_segnos_rirads_accels &= (~(PENDING_DAL_SEGNO_AL_CODA));
							}
							if (pending_segnos_rirads_accels & PENDING_CODA) {
								out_ << "^#'(large (music \"scripts-coda\")) ";
								pending_segnos_rirads_accels &= (~(PENDING_CODA));
							}
							if (pending_segnos_rirads_accels & PENDING_RITARDANDO) {
								out_ << "^#'(large \"ritard.\") ";
								pending_segnos_rirads_accels &= (~(PENDING_RITARDANDO));
							}
							if (pending_segnos_rirads_accels & PENDING_ACCELERANDO) {
								out_ << "^#'(large \"accel.\") ";
								pending_segnos_rirads_accels &= (~(PENDING_ACCELERANDO));
							}
						}
						saveLine = lastLine_;
						if (chord->status_ & STAT_SLURED) {
						   out_ << " ( ";
						}
					     }
				     	     out_ << ' ';
				     }
				     if (diag != 0) {
					writeChordName(diag->getChordName());
				     }
				     if (elem->getNoteList()->count() > 1) {
				     	out_ << "> ";
				        if (NResource::lilyProperties_.lilyVersion2 && (length != lastLength_ || lastDotted_ != (elem->status_ & DOT_MASK))) {
						if (part == DOUBLE_WHOLE_LENGTH) {
							out_ << "\\breve";
						   }
						   else {
						   	out_ << length;
						   }
						   lastLength_ = length;
						   switch (elem->status_ & DOT_MASK) {
							case 1:	out_ << "."; break;
							case 2:	out_ << ".."; break;
						   }
						   lastDotted_ = elem->status_ & DOT_MASK;
					        }
				     }
				     if (NResource::lilyProperties_.lilyVersion2) {
					if (pendingVolSig) {
						switch (exportDialog_->lilyVol->currentItem()) {
							case 1: out_ << '^' << pendingVolSig; break;
							case 2: out_  << pendingVolSig; break;
						}
						pendingVolSig = 0;
					}
					if (elem->status_ & STAT_ARPEGG) {
						out_ << "\\arpeggio ";
					}
					if (pending_segnos_rirads_accels & PENDING_SEGNO) {
						out_ << "^\\segno ";
						pending_segnos_rirads_accels &= (~(PENDING_SEGNO));
					}
					if (pending_segnos_rirads_accels & PENDING_DAL_SEGNO) {
						out_ << "^\\markup{\\large D.S.} ";
						pending_segnos_rirads_accels &= (~(PENDING_DAL_SEGNO));
					}
					if (pending_segnos_rirads_accels & PENDING_DAL_SEGNO_AL_FINE) {
						out_ << "^\\markup{\\large D.S. al Fine} ";
						pending_segnos_rirads_accels &= (~(PENDING_DAL_SEGNO_AL_FINE));
					}
					if (pending_segnos_rirads_accels & PENDING_FINE) {
						out_ << "^\\markup{\\large Fine} ";
						pending_segnos_rirads_accels &= (~(PENDING_FINE));
					}
					if (pending_segnos_rirads_accels & PENDING_DAL_SEGNO_AL_CODA) {
						out_ << "^\\markup{\\large D.S. al \\textcodaysym}";
						pending_segnos_rirads_accels &= (~(PENDING_DAL_SEGNO_AL_CODA));
					}
					if (pending_segnos_rirads_accels & PENDING_CODA) {
						out_ << "^\\coda ";
						pending_segnos_rirads_accels &= (~(PENDING_CODA));
					}
					if (pending_segnos_rirads_accels & PENDING_RITARDANDO) {
						out_ << "^\\markup{\\large ritard.} ";
						pending_segnos_rirads_accels &= (~(PENDING_RITARDANDO));
					}
					if (pending_segnos_rirads_accels & PENDING_ACCELERANDO) {
						out_ << "^\\markup{\\large accel.} ";
						pending_segnos_rirads_accels &= (~(PENDING_ACCELERANDO));
					}
					if (chord->status_ & STAT_PART_OF_SLUR) {
						out_ << ") ";
					}
					if (!inGrace && exportDialog_->lilyBeam->isChecked()) {
						if ((elem->status_ & STAT_BEAMED) && !inbeam) {
							out_ << "[ "; inbeam = true;
						}
					}
					if (lastDynSym && chord->getBbox()->right() >  dynEndPos) {
						out_ << lastDynSym;
						lastDynSym = 0;
						dynEndPos = 0;
					}
					if (chord->dynamic_) {
						out_ << (chord->dynamicAlign_ ? " \\<  " : " \\> ");
						dynEndPos = chord->getDynamicEnd();
						lastDynSym = " \\! ";
					}
				     }
				     if (vaendpos != 0 && chord->getBbox()->right() > vaendpos) {
					vaendpos = 0;
					if (octaviation > 0) {
						saveLine += 7;
					}
					else {
						saveLine -= 7;
					}
					octaviation = 0;
					out_ << "#(set-octavation 0) ";
				     }
				     if (exportDialog_->lilyBeam->isChecked()) {
				     	if (elem->lastBeamed()) {
						out_ << "] "; inbeam = false;
				     	}
				     }
				     if (hasATie(elem->getNoteList())) {
					out_ << "~ ";
				     }
				     lastLine_ = saveLine;
				     if (elem->status_ & STAT_LAST_TUPLET) {
					intuplet = false;
					out_ << " } ";
				     }
				     break;
			case T_REST: if (PosOfHiddenRepeat < 0) {
					if (acr = voi->determineAnacrusis()) {
						out_ << "\\partial " << (128 / acr);
						if (NResource::lilyProperties_.lilySemicolons) out_ << ";";
						out_ << endl << '\t';
					}
					PosOfHiddenRepeat = out_.tellp();
					out_ << hiddenRepeat << endl << '\t';
				     }
				     if (NResource::lilyProperties_.lilyVersion2 && vaendpos != 0 && chord->getBbox()->right() > vaendpos) {
						vaendpos = 0;
						if (octaviation > 0) {
							lastLine_ += 7;
						}
						else {
							lastLine_ -= 7;
						}
						octaviation = 0;
						out_ << "#(set-octavation 0) ";
				     }
				     prevElemIsBar = false;
				     part = elem->getSubType(); 
				     if (part == MULTIREST) {
					total = MULTIPLICATOR*countof128th_;
				     }
				     else {
				        restlen = (elem->status_ & STAT_TUPLET) ? elem->getPlaytime() * part / elem->getNumNotes() : part;
				     	total += restlen;
				     }
				     switch (elem->status_ & DOT_MASK) {
					case 1: restlen += part / 2; total += part / 2; break;
					case 2: restlen += 3 * part / 4; total += 3 * part / 4; break;
				     }
				     if ((diag = elem->getChordChordDiagram()) != 0) {
					if (!fatTextWritten) {
						fatTextWritten = true;
						out_ << "\\fatText ";
					}
				     }
				     if ((pending_segnos_rirads_accels & SOME_SIGNS_WITH_TEXT) && !fatTextWritten) {
				     	fatTextWritten = true;
					out_ << "\\fatText ";
				     }
				     if (inGrace) {
					inGrace = false;
					if (!strokenGrace) {
						strokenGrace = false;
						out_ << "] ";
					}
					out_ << "} ";
				     }
				     if ((elem->status_ & STAT_TUPLET) && !intuplet) {
					intuplet = true;
					out_ << "\\times " << ((int) elem->getPlaytime()) << '/' << ((int) elem->getNumNotes()) << " { ";
				     }
				     if (total > MULTIPLICATOR*countof128th_ && voi->isFirstVoice()) {
					total = 0;
					bad = new badmeasure(LILY_ERR_NOTE_COUNT, (staff_nr + 1), barNr_, total / 3, countof128th_);
					badlist_.append(bad);
				     }
				     if (pendingVolSig) {
						switch (exportDialog_->lilyVol->currentItem()) {
							case 1: out_ << '^' << pendingVolSig; break;
							case 2: out_  << pendingVolSig; break;
						}
						pendingVolSig = 0;
				     }
				     if (NResource::lilyProperties_.lilyVersion2 && pending_tempo >= 0) {
					out_ << "\\tempo 4.=" << pending_tempo << ' ';
					pending_tempo = -1;
				     }
				     if (part == MULTIREST) {
					lastDotted_ = lastLength_ = 1111; /* invalidate */
					out_ << 'R' << currentDenominator_ << '*' <<
						(currentNumerator_ * ((NRest *)elem)->getMultiRestLength());
				     }
				     else if (restlen == MULTIPLICATOR*countof128th_) {
				        length = WHOLE_LENGTH / part;
				     	out_ << 'R';
					out_ << length;
					lastDotted_ = lastLength_ = 1111; /* invalidate */
					switch (elem->status_ & DOT_MASK) {
						case 1: out_ << "."; break;
						case 2: out_ << ".."; break;
					}
				     }
				     else {
				     	out_ << ((elem->status_ & STAT_HIDDEN) ? "s" : "r");
				     	length = WHOLE_LENGTH / part;
				     	if (length != lastLength_  || lastDotted_ != (elem->status_ & DOT_MASK)) {
						out_ << length;
						lastLength_ = length;
				     		switch (elem->status_ & DOT_MASK) {
							case 1:	out_ << "."; break;
							case 2:	out_ << ".."; break;
				     		}
						lastDotted_ = elem->status_ & DOT_MASK;
				     	}
				      }
				     if (!NResource::lilyProperties_.lilyVersion2) {
					if (pendingVolSig) {
						switch (exportDialog_->lilyVol->currentItem()) {
							case 1: out_ << '^' << pendingVolSig; break;
							case 2: out_  << pendingVolSig; break;
						}
						pendingVolSig = 0;
					}
					if (pending_tempo >= 0) {
				   		out_ << "^#`(columns , quarter-head \" = " << pending_tempo << "\") ";
				   		pending_tempo = -1;
					}
				     }
				     if (diag != 0) {
					writeChordName(diag->getChordName());
				     }
				     out_ << ' ';
				     if (NResource::lilyProperties_.lilyVersion2) {
					if (pending_segnos_rirads_accels & PENDING_SEGNO) {
						out_ << "^\\segno ";
						pending_segnos_rirads_accels &= (~(PENDING_SEGNO));
					}
					if (pending_segnos_rirads_accels & PENDING_DAL_SEGNO) {
						out_ << "^\\markup{\\large D.S.} ";
						pending_segnos_rirads_accels &= (~(PENDING_DAL_SEGNO));
					}
					if (pending_segnos_rirads_accels & PENDING_DAL_SEGNO_AL_FINE) {
						out_ << "^\\markup{\\large D.S. al Fine} ";
						pending_segnos_rirads_accels &= (~(PENDING_DAL_SEGNO_AL_FINE));
					}
					if (pending_segnos_rirads_accels & PENDING_FINE) {
						out_ << "^\\markup{\\large Fine} ";
						pending_segnos_rirads_accels &= (~(PENDING_FINE));
					}
					if (pending_segnos_rirads_accels & PENDING_DAL_SEGNO_AL_CODA) {
						out_ << "^\\markup{\\large D.S. al \\textcodaysym}";
						pending_segnos_rirads_accels &= (~(PENDING_DAL_SEGNO_AL_CODA));
					}
					if (pending_segnos_rirads_accels & PENDING_CODA) {
						out_ << "^\\coda ";
						pending_segnos_rirads_accels &= (~(PENDING_CODA));
					}
					if (pending_segnos_rirads_accels & PENDING_RITARDANDO) {
						out_ << "^\\markup{\\large ritard.} ";
						pending_segnos_rirads_accels &= (~(PENDING_RITARDANDO));
					}
					if (pending_segnos_rirads_accels & PENDING_ACCELERANDO) {
						out_ << "^\\markup{\\large accel.} ";
						pending_segnos_rirads_accels &= (~(PENDING_ACCELERANDO));
					}
				     }
				     else {
					     if (pending_segnos_rirads_accels & PENDING_SEGNO) {
						out_ << "^\\segno ";
						pending_segnos_rirads_accels &= (~(PENDING_SEGNO));
					     }
					     if (pending_segnos_rirads_accels & PENDING_DAL_SEGNO) {
						out_ << "^#'(large \"D.S.\") ";
						pending_segnos_rirads_accels &= (~(PENDING_DAL_SEGNO));
					     }
					     if (pending_segnos_rirads_accels & PENDING_DAL_SEGNO_AL_FINE) {
						out_ << "^#'(large \"D.S. al Fine\") ";
						pending_segnos_rirads_accels &= (~(PENDING_DAL_SEGNO_AL_FINE));
					     }
					     if (pending_segnos_rirads_accels & PENDING_FINE) {
						out_ << "^#'(Large \"Fine\") ";
						pending_segnos_rirads_accels &= (~(PENDING_FINE));
					     }
					     if (pending_segnos_rirads_accels & PENDING_DAL_SEGNO_AL_CODA) {
						out_ << "^#'(large \"D.S. al    \" (music \"scripts-coda\")) ";
						pending_segnos_rirads_accels &= (~(PENDING_DAL_SEGNO_AL_CODA));
					     }
					     if (pending_segnos_rirads_accels & PENDING_CODA) {
						out_ << "^#'(large (music \"scripts-coda\")) ";
						pending_segnos_rirads_accels &= (~(PENDING_CODA));
					     }
					     if (pending_segnos_rirads_accels & PENDING_RITARDANDO) {
						out_ << "^#'(large \"ritard.\") ";
						pending_segnos_rirads_accels &= (~(PENDING_RITARDANDO));
					     }
					     if (pending_segnos_rirads_accels & PENDING_ACCELERANDO) {
						out_ << "^#'(large \"accel.\") ";
						pending_segnos_rirads_accels &= (~(PENDING_ACCELERANDO));
					     }
				     }
				     if (elem->status_ & STAT_LAST_TUPLET) {
					intuplet = false;
					out_ << " } ";
				     }
				     break;
			case T_KEYSIG: key = (NKeySig *) elem;
				     prevElemIsBar = false;
				     if (inGrace) {
					inGrace = false;
					if (!strokenGrace) {
						strokenGrace = false;
						out_ << "] ";
					}
					out_ << "} ";
				     }
				     if (key->isRegular(&kind, &count)) {
					if (count || barNr_ > 1) {
						out_ << "\\key " << LilyPondKeyName(kind, count) << " \\major";
						if (NResource::lilyProperties_.lilySemicolons) out_ << ";";
						out_ << endl; tabsOut();
					}
				     }
				     else {
					bad = new badmeasure(LILY_ERR_IRREGULAER, (staff_nr + 1), barNr_, total / 3, countof128th_);
					badlist_.append(bad);
				     }
				     break;
			case T_TIMESIG: timesig = (NTimeSig *) elem;
					if (inGrace) {
						inGrace = false;
						if (!strokenGrace) {
							strokenGrace = false;
							out_ << "] ";
						}
						out_ << "} ";
					}
					if (prevElemIsBar) {
						out_.seekp(lastBarPos);
					}
					countof128th_ = timesig->numOf128th();
					currentNumerator_ = timesig->getNumerator();
					currentDenominator_ = timesig->getDenominator();
					out_ << "\\time " << timesig->getNumerator() << '/'
					                  << timesig->getDenominator();
					    		  if (NResource::lilyProperties_.lilySemicolons) out_ << ";";
					out_ << ' ';
					if (prevElemIsBar) {
						lastBarPos = out_.tellp();
						out_ << "| ";
						prevElemIsBar = true;
					}
					out_ << endl; tabsOut();
				     break;
			case T_CLEF: if (inGrace) {
					inGrace = false;
					if (!strokenGrace) {
						strokenGrace = false;
						out_ << "] ";
					}
					out_ << "} ";
				     }
				     clef = (NClef *) elem;
				     prevElemIsBar = false;
			             out_ << "\\clef ";
				     switch (clef->getSubType()) {
					 case DRUM_CLEF:  out_ << "percussion"; if (NResource::lilyProperties_.lilySemicolons) out_ << ";"; break;
				         case TREBLE_CLEF: out_ << "violin"; if (NResource::lilyProperties_.lilySemicolons) out_ << ";"; break;
					 case TENOR_CLEF: out_ << "tenor"; if (NResource::lilyProperties_.lilySemicolons) out_ << ";"; break;
					 case ALTO_CLEF: out_ << "alto"; if (NResource::lilyProperties_.lilySemicolons) out_ << ";"; break;
					 case DRUM_BASS_CLEF: out_ << "percussion"; if (NResource::lilyProperties_.lilySemicolons) out_ << ";"; break;
					 case BASS_CLEF: out_ << "bass"; if (NResource::lilyProperties_.lilySemicolons) out_ << ";"; break;
				     }
				     out_ << endl; tabsOut();
				     c4Line = actual_staff->actualClef_.lineOfC4();
				     actual_staff->actualClef_.change(clef);
				     lastLine_ += actual_staff->actualClef_.lineOfC4() - c4Line;
				     break;
			case T_SIGN: if (inGrace) {
					inGrace = false;
					if (!strokenGrace) {
						strokenGrace = false;
						out_ << "] ";
					}
					out_ << "} ";
				     }
				     switch (elem->getSubType ()) {
				     	case END_BAR:
					case SIMPLE_BAR: 
						if (AfterFirstBar && total != MULTIPLICATOR*countof128th_ && voi->isFirstVoice()) {
							bad = new badmeasure(LILY_ERR_NOTE_COUNT, (staff_nr + 1), barNr_, total / 3, countof128th_);
							badlist_.append(bad);
						}
						total = 0;
						if (specialEnding2Seen) {
#ifndef WITH_OLDLILY
							if (!NResource::lilyProperties_.lilyVersion2) {
								lastLine_ = LineBeforeSPE1;
							}
#endif	// WITH_OLDLILY
							specialEnding2Seen = false;
							counter = 0;
							if (lastElemIsBar) {
								out_.seekp(lastBarPos);
								out_ << "| " << endl;
							}
							depth_--; out_ << endl; tabsOut();
							out_ << "}" << endl; depth_--; tabsOut();
							out_ << "}" << endl; tabsOut();
							lastLength_ = 1000; // invalidate
							break;
						}
						lastElemIsBar = true;
						lastBarPos = out_.tellp();
						out_ << "| ";
						prevElemIsBar = true;
						if (exportDialog_->lilyMeasure->isChecked()) {
							if (((++measure_counter) % exportDialog_->lilyMeasureVal->value()) == 0) {
								out_ << "\\break ";
							 }
						}
						if (((++counter) % MEASURES_PER_LINE) == 0) {
							out_ << "  % " << ((NSign *) elem)->getBarNr();
							out_ << endl; tabsOut();
						}
						barNr_ = ((NSign *) elem)->getBarNr();
						AfterFirstBar = true;
						break;
					case DOUBLE_BAR: 
						if (AfterFirstBar && total != MULTIPLICATOR*countof128th_ && voi->isFirstVoice()) {
							bad = new badmeasure(LILY_ERR_NOTE_COUNT, (staff_nr + 1), barNr_, total / 3, countof128th_);
							badlist_.append(bad);
						}
						total = 0;
						if (specialEnding2Seen) {
#ifndef WITH_OLDLILY
							if (!NResource::lilyProperties_.lilyVersion2) {
								lastLine_ = LineBeforeSPE1;
							}
#endif	// WITH_OLDLILY
							specialEnding2Seen = false;
							counter = 0;
							if (lastElemIsBar) {
								out_.seekp(lastBarPos);
								out_ << "| " << endl;
							}
							depth_--; out_ << endl; tabsOut();
							out_ << "}" << endl; depth_--; tabsOut();
							out_ << "}" << endl; tabsOut();
							lastLength_ = 1000; // invalidate
							break;
						}
						lastElemIsBar = true;
						lastBarPos = out_.tellp();
						out_ << "\\bar \"||\" ";
						prevElemIsBar = true;
						if (exportDialog_->lilyMeasure->isChecked()) {
							if (((++measure_counter) % exportDialog_->lilyMeasureVal->value()) == 0) {
								out_ << "\\break ";
							 }
						}
						if (((++counter) % MEASURES_PER_LINE) == 0) {
							out_ << "  % " << ((NSign *) elem)->getBarNr();
							out_ << endl; tabsOut();
						}
						barNr_ = ((NSign *) elem)->getBarNr();
						AfterFirstBar = true;
						break;
					case REPEAT_OPEN:
				     		prevElemIsBar = false;
						if (AfterFirstBar && total != MULTIPLICATOR*countof128th_ && voi->isFirstVoice()) {
							bad = new badmeasure(LILY_ERR_NOTE_COUNT, (staff_nr + 1), barNr_, total / 3, countof128th_);
							badlist_.append(bad);
						}
						total = 0;
						if (specialEnding2Seen) {
#ifndef WITH_OLDLILY
							if (!NResource::lilyProperties_.lilyVersion2) {
								lastLine_ = LineBeforeSPE1;
							}
#endif	// WITH_OLDLILY
							specialEnding2Seen = false;
							counter = 0;
							if (lastElemIsBar) {
								out_.seekp(lastBarPos);
								out_ << "| " << endl;
							}
							depth_--; out_ << endl; tabsOut();
							out_ << "}" << endl; depth_--; tabsOut();
							out_ << "}" << endl; tabsOut();
							lastLength_ = 1000; // invalidate
						}
						repeatOpenSeen = true;
						specialEnding2Seen = false;
						++measure_counter; ++counter;
						out_ << endl; tabsOut(); counter = 0;
						out_ << "\\repeat \"volta\" 2 {" << endl; depth_++; tabsOut();
						barNr_ = ((NSign *) elem)->getBarNr();
						AfterFirstBar = true;
						lastLength_ = 1000; // invalidate
						break;
					case REPEAT_CLOSE:
				     		prevElemIsBar = false;
						if (AfterFirstBar && total != MULTIPLICATOR*countof128th_ && voi->isFirstVoice()) {
							bad = new badmeasure(LILY_ERR_NOTE_COUNT, (staff_nr + 1), barNr_, total / 3, countof128th_);
							badlist_.append(bad);
						}
						total = 0;
						if (!repeatOpenSeen) {
							repeatOpenAtBeginMissing = true;
						}
						repeatOpenSeen = true;
						if (lastElemIsBar) {
							out_.seekp(lastBarPos);
							out_ << "| " << endl;
						}
						if (exportDialog_->lilyMeasure->isChecked()) {
							if (((++measure_counter) % exportDialog_->lilyMeasureVal->value()) == 0) {
								out_ << "\\break ";
							 }
						}
						if (repeatOpenSeen) depth_--; out_ << endl; tabsOut();
						out_ << "}" << endl; tabsOut();
						counter = 0;
						barNr_ = ((NSign *) elem)->getBarNr();
						AfterFirstBar = true;
						lastLength_ = 1000; // invalidate
						break;
				
					case REPEAT_OPEN_CLOSE:
				     		prevElemIsBar = false;
						if (AfterFirstBar && total != MULTIPLICATOR*countof128th_ && voi->isFirstVoice()) {
							bad = new badmeasure(LILY_ERR_NOTE_COUNT, (staff_nr + 1), barNr_, total / 3, countof128th_);
							badlist_.append(bad);
						}
						total = 0;
						if (!repeatOpenSeen) {
							repeatOpenAtBeginMissing = true;
						}
						if (lastElemIsBar) {
							out_.seekp(lastBarPos);
							out_ << "| " << endl;
						}
						if (repeatOpenSeen) depth_--; out_ << endl; tabsOut();
						out_ << "}" << endl; tabsOut();
						counter = 0;

						if (!repeatOpenSeen) {
							repeatOpenAtBeginMissing = true;
						}
						repeatOpenSeen = true;
						specialEnding2Seen = false;
						++measure_counter; ++counter;
						out_ << endl; tabsOut(); counter = 0;
						out_ << "\\repeat \"volta\" 2 {" << endl; depth_++; tabsOut();
						barNr_ = ((NSign *) elem)->getBarNr();
						AfterFirstBar = true;
						lastLength_ = 1000; // invalidate
						if (exportDialog_->lilyMeasure->isChecked()) {
							if (((++measure_counter) % exportDialog_->lilyMeasureVal->value()) == 0) {
								out_ << "\\break ";
							 }
						}
						break;
					case SPECIAL_ENDING1: 
				     		prevElemIsBar = false;
						if (lastElemIsBar) {
							out_.seekp(lastBarPos);
							out_ << "| " << endl;
						}
						depth_--; out_ << endl; tabsOut();
						out_ << "}" << endl; tabsOut();
						out_ << "\\alternative {" << endl; depth_++; tabsOut();
						out_ << "{" << endl; depth_++; tabsOut(); counter = 0;
						LineBeforeSPE1 = lastLine_;
						lastLength_ = 1000; // invalidate
						break;
					case SPECIAL_ENDING2:
				     		prevElemIsBar = false;
						counter = 0;
						out_ << "{" << endl; depth_++; tabsOut(); 
						specialEnding2Seen = true;
						lastLength_ = 1000; // invalidate
#ifndef WITH_OLDLILY
						if (!NResource::lilyProperties_.lilyVersion2) {
							lastLine_ = LineBeforeSPE1;
						}
#endif	// WITH_OLDLILY
						break;
					case TEMPO_SIGNATURE:
				     		prevElemIsBar = false;
						sign = (NSign *) elem;
						pending_tempo = sign->getTempo();
						break;
					case VOLUME_SIG:
				     		prevElemIsBar = false;
						sign = (NSign *) elem;
						switch(sign->getVolType()) {
							case V_PPPIANO : pendingVolSig = "\\ppp "; break;
							case V_PPIANO  : pendingVolSig = "\\pp "; break;
							case V_PIANO   : pendingVolSig = "\\p "; break;
							case V_MPIANO  : pendingVolSig = "\\mp "; break;
							case V_FORTE   : pendingVolSig = "\\f "; break;
							case V_FFORTE  : pendingVolSig = "\\ff "; break;
							case V_FFFORTE : pendingVolSig = "\\fff "; break;
							default        : pendingVolSig = "\\mf "; break;
						}
						break;
#ifdef XXX
					case PROGRAM_CHANGE:
				     		prevElemIsBar = false;
						sign = (NSign *) elem;
						out_ << "midi " << staff_nr << " 1: 0 \"program=" << sign->getProgram() << "\"";
						if (NResource::lilyProperties_.lilySemicolons) out_ << ";";
						break;
#endif
					case SEGNO:
						pending_segnos_rirads_accels |= PENDING_SEGNO;
						break;
					case DAL_SEGNO:
						pending_segnos_rirads_accels |= PENDING_DAL_SEGNO;
						break;
					case DAL_SEGNO_AL_FINE:
						pending_segnos_rirads_accels |= PENDING_DAL_SEGNO_AL_FINE;
						break;
					case DAL_SEGNO_AL_CODA:
						pending_segnos_rirads_accels |= PENDING_DAL_SEGNO_AL_CODA;
						break;
					case CODA:
						pending_segnos_rirads_accels |= PENDING_CODA;
						break;
					case RITARDANDO:
						pending_segnos_rirads_accels |= PENDING_RITARDANDO;
						break;
					case ACCELERANDO:
						pending_segnos_rirads_accels |= PENDING_ACCELERANDO;
						break;
				     }
				     break;
		}
		elem = voi->getNextPosition();
	}
	while (elem);
	if (voice_nr == 0 && total > MULTIPLICATOR*countof128th_ && voi->isFirstVoice()) {
		bad = new badmeasure(LILY_ERR_NOTE_COUNT, (staff_nr + 1), barNr_, total / 3, countof128th_);
		badlist_.append(bad);
	}
	if (lastElemIsBar) {
		out_.seekp(lastBarPos);
		out_ << endl;
		tabsOut();
		out_ << "\\bar \"|.\"";
		if (NResource::lilyProperties_.lilySemicolons) out_ << ";";
		out_ << endl;
	}
	if (!repeatOpenAtBeginMissing) {
		currentPos = out_.tellp();
		out_.seekp(PosOfHiddenRepeat);
		for (i = 0; i < strlen(hiddenRepeat); i++) out_ << ' ';
		out_.seekp(currentPos);
	}
	if (voice_nr > 0) out_ << endl;
}

void NLilyExport::writeChordName(QString chordname) {
	QRegExp reg = QRegExp("#");
	if (NResource::lilyProperties_.lilyVersion2) {
		chordname.replace (reg, "\\sharp ");
		reg = QRegExp("b");
		chordname.replace (reg, "\\flat ");
		out_ << "^\\markup{\\bold " << chordname << "} ";
	}
	else {
		chordname.replace (reg, "$\\\\sharp$");
		reg = QRegExp("b");
		chordname.replace (reg, "$\\\\flat$");
		out_ << "^#'(bold \"" << chordname << "\") ";
	}
}

void NLilyExport::writeLyrics(int voice_nr, NVoice *voi) {
	NMusElement *elem;
	NChord *chord;
	QString *ps, s;
	int lyline;
	int counter;

	if (staffarray_[voice_nr].lyrics_count > 1) {
		out_ << "{" << endl << "\t\\simultaneous {" << endl << "\t\t";
		depth_ = 2;
	}
	else {
		out_ << "{" << endl << '\t';
		depth_ = 1;
	}
	
	for (lyline = 0; lyline < staffarray_[voice_nr].lyrics_count; lyline++) {
		counter = 0;
		voi->prepareForWriting();
		out_ << "{" << endl; depth_++; tabsOut();
		elem = voi->getCurrentPosition();
		while (elem) {
			switch (elem->getType()) {
			case T_SIGN:
				if (elem->getSubType() & BAR_SYMS) {
					if (((++counter) % MEASURES_PER_LINE) == 0) {
						out_ << endl; tabsOut();
					}
				}
				break;
			case T_CHORD:
				chord = (NChord *) elem;
				ps = chord->getLyrics(lyline);
				if (!ps) {
					out_ << " _ ";
				}
				else if (ps->find(starOnly) != -1) {
					out_ << " _ ";
				}
				else {
					s = QString(*ps);
					s.replace(relSyms, "");
					s.replace(whiteSpaces_, "_");
					removeExceptsFromString(&s, true);
					switch(exportDialog_->lilyOutputCoding->currentItem()) {
						case 1: out_ << s.latin1() << ' ';
							break;
						case 2: out_ << s.unicode() << ' ';
							break;
						case 3: out_ << s.utf8() << ' ';
							break;
						default: NResource::germanUmlautsToTeX(&s);
							out_ << s << ' ';
							break;
					}
				}
				break;
			}
			elem = voi->getNextPosition();
		}
		depth_--;
		out_ << '}' << endl; tabsOut();
	}
	if (staffarray_[voice_nr].lyrics_count > 1) {
		out_ << '}' << endl;
	}
	out_ << '}' << endl;
}


void NLilyExport::removeExceptsFromString(QString *str, bool onlyDigits) {
	int l = str->length();
	int digit;
	QChar c, c2;
	while ((l = str->find(digits_)) >= 0) {
		c = str->at(l);
		digit = c.digitValue ();
		c2 = QChar('A' + digit);
		str->replace(l, 1, &c2, 1);
	}
	if (onlyDigits) return;
	str->replace(nonAlphas_, "X");
		
}
		
char *NLilyExport::LilyPondKeyName(int kind, int count) {
	char *err = "LilyPondKeyName: internal error";
	if (kind == STAT_CROSS) {
		switch (count) {
			case 0: return "c";
			case 1: return "g";
			case 2: return "d";
			case 3: return "a";
			case 4: return "e";
			case 5: return "b";
			case 6: return "fis";
			default: NResource::abort(err, 1);
		}
	}
	switch (count) {
		case 0: return "c";
		case 1: return "f";
		case 2: return "bes";
		case 3: return "es";
		case 4: return "as";
		case 5: return "des";
		case 6: return "ges";
		default: NResource::abort(err, 2);
	}
	return "";
}

void NLilyExport::pitchOut( const NNote *note, NClef *ac_clef) {
	int octave;
	int linediff;
	char notename;

	linediff = note->line - lastLine_;
	notename = ac_clef->line2Name(note->line, &octave, true, false);
	out_ << notename;
	switch (note->offs) {
		case 1: out_ << "is"; break;
		case -1: if (notename == 'e' || notename == 'a')
				out_ << 's';
			     else 
				out_ << "es";
			 break;
		case 2: out_ << "isis"; break;
		case -2: if (notename == 'e' || notename == 'a')
				out_ << "ses";
			     else 
				out_ << "eses";
			 break;
	}
	while (linediff > 3)
    	{
        	out_ << '\'';
          	linediff -= 7;
	}
	while (linediff < -3)
	{
        	out_ << ',';
        	linediff += 7;
	}
	if (note->status & STAT_FORCE) {
		out_ << '!';
	}
	lastLine_ = note->line;
}

void NLilyExport::analyseGroup(layoutDef *group, NMainFrameWidget *mainWidget, int staffCount, bool *continuedBars, bool *discontinuedBars) {
	int i, j;
	*continuedBars = false;
	*discontinuedBars = true;

	for (i = 0; i < staffCount; i++) {
		if (mainWidget->barCont_[i].valid && mainWidget->barCont_[i].beg == group->beg &&  mainWidget->barCont_[i].end == group->end) {
			*continuedBars = true;
		}
	}
	for (i = group->beg; i <= group->end; i++) {
		for (j = 0; j < staffCount; j++) {
			if (mainWidget->barCont_[j].valid && mainWidget->barCont_[j].beg <= i && mainWidget->barCont_[j].end > i) {
				*discontinuedBars = false;
			}
			else {
			}
		}
	}
}

bool NLilyExport::continuedOutsideAGroup(NMainFrameWidget *mainWidget, int staffCount) {
	int i, j;
	bool *contList;
	bool continuedInside;

	contList = (bool *) alloca(staffCount * sizeof(bool));
	for (i = 0; i < staffCount; i++) {
		contList[i] = false;
		for (j = 0; j < staffCount; j++) {
			if (mainWidget->barCont_[j].valid && mainWidget->barCont_[j].beg <= i && mainWidget->barCont_[j].end > i) {
				contList[i] = true;
			}
		}
	}
	for (i = 0; i < staffCount; i++) {
		if (!contList[i]) continue;
		continuedInside = false;
		for (j = 0; j < staffCount; j++) {
			if (mainWidget->braceMatrix_[j].valid && i >= mainWidget->braceMatrix_[j].beg && i <= mainWidget->braceMatrix_[j].end) {
				continuedInside = true;
			}
		}
		for (j = 0; j < staffCount; j++) {
			if (mainWidget->bracketMatrix_[j].valid && i >= mainWidget->bracketMatrix_[j].beg && i <= mainWidget->bracketMatrix_[j].end) {
				continuedInside = true;
			}
		}
		if (!continuedInside) return true;
	}
	return false;
}


bool NLilyExport::hasATie(QList<NNote> *notelist) {
	NNote *note;
	for (note = notelist->first(); note; note = notelist->next()) {
		if (note->status & STAT_TIED) return true;
	}
	return false;
}

bool NLilyExport::hasContraryStems(QList<NNote> *notelist) {
	int stemdir = STEM_UNSET;
	NNote *note;
	for (note = notelist->first(); note; note = notelist->next()) {
		if (note->line > 4 && stemdir == STEM_DIR_UP) return true;
		if (note->line <= 4 && stemdir == STEM_DIR_DOWN) return true;
		stemdir = note->line > 4 ? STEM_DIR_DOWN : STEM_DIR_UP;
	}
	return false;
}

bool NLilyExport::chordHasMixedTies(QList<NNote> *notelist) {
	bool hasTie = false;
	NNote *note;
	for (note = notelist->first(); note; note = notelist->next()) {
		if (note->status & STAT_TIED) {hasTie = true; continue;}
		if (hasTie) return true;
	}
	return false;
}

void NLilyExport::tabsOut() {
	int i;
	for (i = 0; i < depth_; i++) out_ << '\t';
}
