213 lines
5.8 KiB
C++
213 lines
5.8 KiB
C++
//=============================================================================
|
|
// MuseScore
|
|
// Music Composition & Notation
|
|
//
|
|
// Copyright (C) 2011 Werner Schweer
|
|
//
|
|
// This program is free software; you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License version 2
|
|
// as published by the Free Software Foundation and appearing in
|
|
// the file LICENCE.GPL
|
|
//=============================================================================
|
|
|
|
#include "segmentlist.h"
|
|
#include "segment.h"
|
|
#include "score.h"
|
|
|
|
namespace Ms {
|
|
|
|
//---------------------------------------------------------
|
|
// clone
|
|
//---------------------------------------------------------
|
|
|
|
SegmentList SegmentList::clone() const
|
|
{
|
|
SegmentList dl;
|
|
Segment* s = _first;
|
|
for (int i = 0; i < _size; ++i) {
|
|
Segment* ns = s->clone();
|
|
dl.push_back(ns);
|
|
s = s->next();
|
|
}
|
|
dl.check();
|
|
return dl;
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// check
|
|
//---------------------------------------------------------
|
|
|
|
#ifndef NDEBUG
|
|
void SegmentList::check()
|
|
{
|
|
int n = 0;
|
|
Segment* f = 0;
|
|
Segment* l = 0;
|
|
for (Segment* s = _first; s; s = s->next()) {
|
|
if (f == 0)
|
|
f = s;
|
|
l = s;
|
|
++n;
|
|
}
|
|
for (Segment* s = _first; s; s = s->next()) {
|
|
switch (s->segmentType()) {
|
|
case Segment::Type::Invalid:
|
|
case Segment::Type::BeginBarLine:
|
|
case Segment::Type::Clef:
|
|
case Segment::Type::KeySig:
|
|
case Segment::Type::Ambitus:
|
|
case Segment::Type::TimeSig:
|
|
case Segment::Type::StartRepeatBarLine:
|
|
case Segment::Type::BarLine:
|
|
case Segment::Type::ChordRest:
|
|
case Segment::Type::Breath:
|
|
case Segment::Type::EndBarLine:
|
|
case Segment::Type::TimeSigAnnounce:
|
|
case Segment::Type::KeySigAnnounce:
|
|
break;
|
|
default:
|
|
qFatal("SegmentList::check: invalid segment type 0x%x", int(s->segmentType()));
|
|
break;
|
|
}
|
|
Segment* ss = s->next();
|
|
while (ss) {
|
|
if (s == ss) {
|
|
qFatal("SegmentList::check: segment twice in list");
|
|
}
|
|
ss = ss->next();
|
|
}
|
|
}
|
|
if (f != _first) {
|
|
qFatal("SegmentList::check: bad first");
|
|
}
|
|
if (l != _last) {
|
|
qFatal("SegmentList::check: bad last");
|
|
}
|
|
if (f->prev())
|
|
qFatal("SegmentList::check: first has prev");
|
|
if (l->next())
|
|
qFatal("SegmentList::check: last has next");
|
|
if (n != _size) {
|
|
qFatal("SegmentList::check: counted %d but _size is %d", n, _size);
|
|
_size = n;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
//---------------------------------------------------------
|
|
// insert
|
|
/// Insert Segment \a e before Segment \a el.
|
|
//---------------------------------------------------------
|
|
|
|
void SegmentList::insert(Segment* e, Segment* el)
|
|
{
|
|
if (el == 0)
|
|
push_back(e);
|
|
else if (el == first())
|
|
push_front(e);
|
|
else {
|
|
++_size;
|
|
e->setNext(el);
|
|
e->setPrev(el->prev());
|
|
el->prev()->setNext(e);
|
|
el->setPrev(e);
|
|
}
|
|
check();
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// remove
|
|
//---------------------------------------------------------
|
|
|
|
void SegmentList::remove(Segment* e)
|
|
{
|
|
#ifndef NDEBUG
|
|
check();
|
|
bool found = false;
|
|
for (Segment* s = _first; s; s = s->next()) {
|
|
if (e == s) {
|
|
found = true;
|
|
break;
|
|
}
|
|
}
|
|
if (!found) {
|
|
qFatal("segment %p %s not in list", e, e->subTypeName());
|
|
}
|
|
#endif
|
|
--_size;
|
|
if (e == _first) {
|
|
_first = _first->next();
|
|
if (_first)
|
|
_first->setPrev(0);
|
|
if (e == _last)
|
|
_last = 0;
|
|
}
|
|
else if (e == _last) {
|
|
_last = _last->prev();
|
|
if (_last)
|
|
_last->setNext(0);
|
|
}
|
|
else {
|
|
e->prev()->setNext(e->next());
|
|
e->next()->setPrev(e->prev());
|
|
}
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// push_back
|
|
//---------------------------------------------------------
|
|
|
|
void SegmentList::push_back(Segment* e)
|
|
{
|
|
++_size;
|
|
e->setNext(0);
|
|
if (_last)
|
|
_last->setNext(e);
|
|
else
|
|
_first = e;
|
|
e->setPrev(_last);
|
|
_last = e;
|
|
check();
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// push_front
|
|
//---------------------------------------------------------
|
|
|
|
void SegmentList::push_front(Segment* e)
|
|
{
|
|
++_size;
|
|
e->setPrev(0);
|
|
if (_first)
|
|
_first->setPrev(e);
|
|
else
|
|
_last = e;
|
|
e->setNext(_first);
|
|
_first = e;
|
|
check();
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// firstCRSegment
|
|
//---------------------------------------------------------
|
|
|
|
Segment* SegmentList::firstCRSegment() const
|
|
{
|
|
return first(Segment::Type::ChordRest);
|
|
}
|
|
|
|
//---------------------------------------------------------
|
|
// first
|
|
//---------------------------------------------------------
|
|
|
|
Segment* SegmentList::first(Segment::Type types) const
|
|
{
|
|
for (Segment* s = _first; s; s = s->next()) {
|
|
if (s->segmentType() & types)
|
|
return s;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
}
|
|
|