/**************************************************************************** PROJECT: MusixTeX PreProcessor FILE : notename.cc AUTHOR : J. C. Nieuwenhuizen copyright (c) FlowerSoft 1995 --*/ #define max(a,b) ( ( ( a ) > ( b ) ) ? (a) : ( b ) ) #define min(a,b) ( ( ( a ) < ( b ) ) ? (a) : ( b ) ) #include #include "key.h" #include "notename.h" #include "inote.h" #include "init.h" #include "staff.h" #include "mpp.h" #if 0 char signString[ 8 ][ 3 ] = { "<", "_", "=", "^", ">", "==", "", "" }; #else char signString[ 8 ][ 4 ] = { "dfl", "fl", "na", "sh", "dsh", "dna", 0, 0 }; #endif char signSpacing[ 8 ][ 5 ] = { "\\hsk", "\\hsk", "\\hsk", "\\hsk", "\\hsk", "\\hsk", "", "" }; /**************************************************************************** class NoteName --*/ NoteName::NoteName( int p ) : Token( "" ), height( 0 ), offset( 0 ), pitch( p ), sign( PLAIN ), staff( NOSTAFF ) { } NoteName::NoteName( const char* name ) : Token( name ), height( 0 ), offset( 0 ), pitch( 0 ), sign( PLAIN ), staff( NOSTAFF ) { _getFrom( char2istream( name ) ); } NoteName::NoteName( const char* name, int p, int h, int o ) : Token( name ), height( h ), offset( o ), pitch( p ), sign( PLAIN ), staff( NOSTAFF ) { } NoteName::NoteName( const NoteName& noteName ) : Token( noteName.name ), height( noteName.height ), offset( noteName.offset ), pitch( noteName.pitch ), sign( noteName.sign ), staff( noteName.staff ) { } NoteName::NoteName( istream& is ) : Token( "" ), height( 0 ), offset( 0 ), pitch( 0 ), sign( PLAIN ), staff( NOSTAFF ) { _getFrom( is ); } NoteName::NoteName( Staff& s ) : Token( "" ), height( 0 ), offset( 0 ), pitch( 0 ), sign( PLAIN ), staff( s ) { getFrom( staff ); } NoteName::~NoteName() { } //#ifndef __TOKENCHARPTR inline NoteName& NoteName::operator =( const NoteName& noteName ) { name = noteName.name; height = noteName.height; offset = noteName.offset; pitch = noteName.pitch; sign = noteName.sign; return *this; } //#endif void NoteName::operator ++() { pitch++; } void NoteName::operator --() { pitch--; } int NoteName::comparePitch( const Object& noteName, void* pitch ) { if ( noteName == NOOBJECT ) return 0; return ( ( (NoteName&)noteName ).pitch == *(int*)pitch ); } int NoteName::getPitch() const { return pitch; } const char* NoteName::getSign() const { return signString[ sign - FLATFLAT ]; } const char* NoteName::getSpacing() const { return signSpacing[ sign - FLATFLAT ]; } NoteName& NoteName::_getFrom( istream& is ) { ;// monitor << "NoteName::_getFrom" << endl; Octave octave( is ); int octavate = octave; if ( staff != NOSTAFF ) octavate += staff.octavate; String s; s = Token::_getFrom( is ); if ( isupper( s[0] ) ) // octavate -= 2; octavate -= 1; // changed for version 0.44 s.lower(); NoteName *noteName; if ( (noteName = ¬eNames.firstNoteName( Token::compare, (void*)(const char*)s ) ) == ZERO ) { if ( !s.len() ) s = String( (char)is.peek() ); if ( staff != NOSTAFF ) staff.error( quoteString( "NoteName::execute: noteName not found", s ) ); else error( quoteString( "noteName not found", s ), __FILE__, __LINE__ ); } *this = *noteName; if ( ( staff != NOSTAFF ) && ( sign == INVALID ) ) staff.warning( quoteString( "NoteName::execute: invalid sign with note", name ) ); if ( pitch >= 0 ) pitch += octavate * 7; if ( staff != NOSTAFF ) pitch += staff.transpose; return *noteName; } int NoteName::getFrom( Staff& staff ) { ;// monitor << "NoteName::_getFrom" << endl; // yak Sign forceSign = getSignFrom( staff ); NoteName& noteName = _getFrom( *staff.is ); if ( forceSign != PLAIN ) if ( forceSign != Sign( offset ) ) staff.warning( quoteString( "illegal sign with note", name ) ); // rest or ghost / spacing if ( pitch < 0 ) sign = PLAIN; else { if ( ( sign != PLAIN ) && ( staff != NOOBJECT ) && staff.key ) { // sustain sign for this bar staff.key->sustain( noteName.pitch, sign ); if ( forceSign != PLAIN ) staff.warning( quoteString( "sign ignored with note", name ) ); } else if ( forceSign != PLAIN ) sign = forceSign; } return 0; } // yak NESTED_IN( NoteName )Sign NoteName::getSignFrom( Staff& staff ) { int i = 0; char s[ 81 ]; istream& is = *staff.is; char c = is.peek(); while ( ( i < 79 ) && ( ( c == '@' ) || ( c == '=' ) || ( c == '#' ) || ( c == 'x' ) ) && !is.eof() && ( c != (char)EOF ) ) { is.get( c ); s[ i++ ] = c; c = is.peek(); } s[ i++ ] = '\0'; s[ i ] = '\0'; int j = s[ 0 ] + 256 * s[ 1 ]; Sign forceSign = PLAIN; switch ( j ) { case 0 : break; case '@' : forceSign = FLAT; break; case '=' : forceSign = NATURAL; break; case '#' : forceSign = SHARP; break; case '@' * '@' : forceSign = FLATFLAT; break; case '=' * '=' : forceSign = NATURALNATURAL; break; case 'x' : case '#' * '#' : forceSign = SHARPSHARP; break; default: staff.warning( quoteString( "invalid sign", s ) ); break; } return forceSign; } void NoteName::printOn( ostream& os ) const { ;// monitor << "NoteName::printOn" << endl; char noteChar; int octavate; if ( pitch < 0 ) { if ( pitch == -1 ) noteChar = 'p'; else noteChar = 's'; octavate = 0; } else { int aToAPitch = pitch + ( 'c' - 'a' ); noteChar = 'a' + aToAPitch % 7; octavate = aToAPitch / 7 - 4; } if ( octavate < 0 ) { noteChar = toupper( noteChar ); octavate += 2; } os << '!'; os << String( '`', -octavate ); os << String( '\'', octavate ); os << noteChar; } // only called by Key, in strokes of five void NoteName::sustain( Sign forcedSign ) { static int i = 0; #if 0 switch ( forcedSign ) { case FLAT : switch( Sign( i + FLATFLAT ) ) { case FLAT : sign = PLAIN; break; case NATURAL : sign = NATURAL; break; case SHARP : sign = SHARP; break; } break; case NATURAL : switch( Sign( i + FLATFLAT ) ) { case FLAT : sign = FLAT; break; case NATURAL : sign = PLAIN; break; case SHARP : sign = SHARP; break; } break; case SHARP : switch( Sign( i + FLATFLAT ) ) { case FLAT : sign = FLAT; break; case NATURAL : sign = NATURAL; break; case SHARP : sign = PLAIN; break; } break; } #else /* or */ if ( i + FLATFLAT == forcedSign ) sign = PLAIN; else //?? { switch ( i + FLATFLAT ) { case FLAT : break; case NATURAL : break; case SHARP : break; } sign = Sign( i + FLATFLAT ); } #endif i = ++i % 5; // called in strokes of three (five) } int NoteName::validCharacter( const char c ) const { return ( Token::validCharacter( c ) && isalpha( c ) ); } //-- class NoteName // /**************************************************************************** class Octave --*/ const int Octave::central = 4; Octave::Octave( istream& is ) : Token( "" ), octavate( 0 ) { getFrom( is ); } Octave::~Octave() { } Octave::operator int() const { return central + octavate; } int Octave::getFrom( istream& is ) { char c = is.peek(); while ( validCharacter( c ) ) { is.get( c ); if ( c == '\'' ) octavate++; else if ( c == '`' ) octavate--; c = is.peek(); } return 0; } int Octave::validCharacter( const char c ) const { return ( Token::validCharacter( c ) && ( ( c == '\'' ) || ( c == '`' ) ) ); } //-- class Octave //