Added a delta coder specific for ASS dialogue entries that seems (from very simple tests) to work. Warning: code not for the faint of heart.

Originally committed to SVN as r2069.
This commit is contained in:
Rodrigo Braz Monteiro 2008-03-16 06:41:23 +00:00
parent 072d747921
commit 8e8f4bf530
14 changed files with 669 additions and 76 deletions

View file

@ -224,6 +224,10 @@
RelativePath=".\include\aegilib\colour.h"
>
</File>
<File
RelativePath=".\include\aegilib\deltacoder.h"
>
</File>
<File
RelativePath=".\src\exception.cpp"
>
@ -317,34 +321,6 @@
RelativePath=".\include\aegilib\format.h"
>
</File>
<File
RelativePath=".\src\formats\format_ass.cpp"
>
</File>
<File
RelativePath=".\src\formats\format_ass.h"
>
</File>
<File
RelativePath=".\src\formats\format_ass_dialogue.cpp"
>
</File>
<File
RelativePath=".\src\formats\format_ass_dialogue.h"
>
</File>
<File
RelativePath=".\src\formats\format_ass_plain.h"
>
</File>
<File
RelativePath=".\src\formats\format_ass_style.cpp"
>
</File>
<File
RelativePath=".\src\formats\format_ass_style.h"
>
</File>
<File
RelativePath=".\include\aegilib\format_handler.h"
>
@ -357,6 +333,46 @@
RelativePath=".\include\aegilib\format_manager.h"
>
</File>
<Filter
Name="ASS"
>
<File
RelativePath=".\src\formats\format_ass.cpp"
>
</File>
<File
RelativePath=".\src\formats\format_ass.h"
>
</File>
<File
RelativePath=".\src\formats\format_ass_dialogue.cpp"
>
</File>
<File
RelativePath=".\src\formats\format_ass_dialogue.h"
>
</File>
<File
RelativePath=".\src\formats\format_ass_dialogue_delta.cpp"
>
</File>
<File
RelativePath=".\src\formats\format_ass_dialogue_delta.h"
>
</File>
<File
RelativePath=".\src\formats\format_ass_plain.h"
>
</File>
<File
RelativePath=".\src\formats\format_ass_style.cpp"
>
</File>
<File
RelativePath=".\src\formats\format_ass_style.h"
>
</File>
</Filter>
</Filter>
<Filter
Name="Actions"

View file

@ -89,11 +89,13 @@ namespace Gorgonsub {
class ActionModify : public Action {
private:
shared_ptr<SectionEntry> entry;
shared_ptr<void> delta;
const String section;
int lineNumber;
public:
ActionModify(shared_ptr<SectionEntry> entry,int line,const String &section);
ActionModify(shared_ptr<void> delta,int line,const String &section);
virtual ~ActionModify() {}
ActionPtr GetAntiAction(const Model &model) const;

View file

@ -64,6 +64,9 @@ namespace Gorgonsub {
public:
~ActionList();
String GetName() const { return actionName; }
String GetOwner() const { return owner; }
void AddAction(const ActionPtr action);
void Finish();

View file

@ -0,0 +1,54 @@
// Copyright (c) 2008, Rodrigo Braz Monteiro
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of the Aegisub Group nor the names of its contributors
// may be used to endorse or promote products derived from this software
// without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// -----------------------------------------------------------------------------
//
// AEGISUB/GORGONSUB
//
// Website: http://www.aegisub.net
// Contact: mailto:amz@aegisub.net
//
#pragma once
#include "tr1.h"
namespace Gorgonsub {
// Void pointer prototyle
typedef shared_ptr<void> VoidPtr;
// Deltacoder interface
class DeltaCoder {
public:
virtual ~DeltaCoder() {}
virtual VoidPtr EncodeDelta(VoidPtr from,VoidPtr to) const = 0;
virtual VoidPtr EncodeReverseDelta(VoidPtr delta,VoidPtr object) const = 0;
virtual void ApplyDelta(VoidPtr delta,VoidPtr object) const = 0;
};
typedef shared_ptr<DeltaCoder> DeltaCoderPtr;
};

View file

@ -52,6 +52,13 @@ namespace Gorgonsub {
String GetString(int ms_precision,int h_precision) const;
void Parse(const String &data);
bool operator == (const Time &par) const { return ms == par.ms; }
bool operator != (const Time &par) const { return ms != par.ms; }
bool operator < (const Time &par) const { return ms < par.ms; }
bool operator > (const Time &par) const { return ms > par.ms; }
bool operator <= (const Time &par) const { return ms <= par.ms; }
bool operator >= (const Time &par) const { return ms >= par.ms; }
};
};

View file

@ -36,7 +36,6 @@
#pragma once
#include <list>
#include <vector>
#include <stack>
#include <wx/wfstream.h>
#include "actionlist.h"
#include "section.h"
@ -58,7 +57,7 @@ namespace Gorgonsub {
friend class Action;
typedef std::list<ViewPtr> ViewList;
typedef std::stack<ActionListPtr,std::list<ActionListPtr> > ActionStack;
typedef std::list<ActionListPtr> ActionStack;
typedef shared_ptr<Format> FormatPtr;
private:
@ -71,6 +70,8 @@ namespace Gorgonsub {
void ProcessActionList(const ActionList &actionList,int type=0);
String GetUndoMessage(const String owner=L"") const;
String GetRedoMessage(const String owner=L"") const;
bool CanUndo(const String owner=L"") const;
bool CanRedo(const String owner=L"") const;
void Undo(const String owner=L"");

View file

@ -36,6 +36,7 @@
#pragma once
#include "gorgonstring.h"
#include "tr1.h"
#include "deltacoder.h"
namespace Gorgonsub {
@ -79,6 +80,8 @@ namespace Gorgonsub {
virtual String GetDefaultGroup() const =0;
virtual SectionEntryPtr Clone() const =0;
virtual DeltaCoderPtr GetDeltaCoder() const { return DeltaCoderPtr(); }
static const SectionEntryPlainPtr GetAsPlain(const SectionEntryPtr &ptr);
static const SectionEntryDialoguePtr GetAsDialogue(const SectionEntryPtr &ptr);
static const SectionEntryDialogueConstPtr GetAsDialogue(const SectionEntryConstPtr &ptr);

View file

@ -114,19 +114,36 @@ void ActionRemove::Execute(Model &model)
///////////////////////////// Modify line /////////////////////////////
///////////////
// Constructor
////////////////
// Constructors
ActionModify::ActionModify(shared_ptr<SectionEntry> data,int line,const String &sName)
: entry(data), lineNumber(line), section(sName) {}
ActionModify::ActionModify(shared_ptr<void> _delta,int line,const String &sName)
: delta(_delta), lineNumber(line), section(sName) {}
/////////////////////////////////
// Create anti-action for insert
ActionPtr ActionModify::GetAntiAction(const Model &model) const
{
// Get section and original line
SectionPtr sect = GetSection(model,section);
SectionEntryPtr entry = sect->GetEntry(lineNumber);
return ActionPtr(new ActionModify(entry,lineNumber,section));
SectionEntryPtr oldEntry = sect->GetEntry(lineNumber);
// Try to get a delta
DeltaCoderPtr deltaCoder = oldEntry->GetDeltaCoder();
if (deltaCoder) {
VoidPtr _delta;
if (entry) _delta = deltaCoder->EncodeDelta(entry,oldEntry);
else _delta = deltaCoder->EncodeReverseDelta(delta,oldEntry);
return ActionPtr(new ActionModify(_delta,lineNumber,section));
}
// Store the whole original line
else {
return ActionPtr(new ActionModify(oldEntry,lineNumber,section));
}
}
@ -140,5 +157,9 @@ void ActionModify::Execute(Model &model)
SectionPtr sect = GetSection(model,sectionName);
// Modify the line
sect->GetEntryRef(lineNumber) = entry;
if (delta) {
SectionEntryPtr &ref = sect->GetEntryRef(lineNumber);
ref->GetDeltaCoder()->ApplyDelta(delta,ref);
}
else sect->GetEntryRef(lineNumber) = entry;
}

View file

@ -97,12 +97,12 @@ bool DialogueASS::Parse(wxString rawData, int version)
}
// Get times
start.Parse(tkn.GetString());
end.Parse(tkn.GetString());
time[0].Parse(tkn.GetString());
time[1].Parse(tkn.GetString());
// Get style and actor
style = tkn.GetString(true);
actor = tkn.GetString(true);
text[1] = tkn.GetString(true);
text[2] = tkn.GetString(true);
// Get margins
for (int i=0;i<3;i++) margin[i] = tkn.GetInt();
@ -124,10 +124,10 @@ bool DialogueASS::Parse(wxString rawData, int version)
}
// Get effect
effect = temp;
text[3] = temp;
// Get text
text = tkn.GetTheRest();
text[0] = tkn.GetTheRest();
}
catch (...) {
@ -156,14 +156,14 @@ String DialogueASS::ToText(int version) const
else final += _T("Marked=0,");
// Write times, style and actor
final += start.GetString(2,1) + _T(",") + end.GetString(2,1) + _T(",") + style + _T(",") + actor + _T(",");
final += time[0].GetString(2,1) + _T(",") + time[1].GetString(2,1) + _T(",") + text[1] + _T(",") + text[2] + _T(",");
// Write margins
if (version <= 1) final += wxString::Format(_T("%04i,%04i,%04i,"),margin[0],margin[1],margin[2]);
else final += wxString::Format(_T("%04i,%04i,%04i,%04i,"),margin[0],margin[1],margin[2],margin[3]);
// Write effect and text
final += effect + _T(",") + text;
final += text[3] + _T(",") + text[0];
// Return final
return final;
@ -177,7 +177,7 @@ String DialogueASS::ToText(int version) const
if (!isComment) size++; // Comment->Dialogue
if (version == 0) size += 8; // "Marked=0"
else if (version == 2) size += 5; // Fourth margin
size += style.Length() + actor.Length() + effect.Length() + text.Length();
for (size_t i=0;i<4;i++) size += text[i].Length();
// Allocate string
wxString final;
@ -197,17 +197,16 @@ String DialogueASS::ToText(int version) const
else WriteText(buffer,_T("Marked=0,"),9,pos);
// Write times
wxString tempStr = start.GetString(2,1);
WriteText(buffer,&tempStr[0],10,pos);
WriteChar(buffer,_T(','),pos);
tempStr = end.GetString(2,1);
WriteText(buffer,&tempStr[0],10,pos);
WriteChar(buffer,_T(','),pos);
for (size_t i=0;i<2;i++) {
wxString tempStr = time[i].GetString(2,1);
WriteText(buffer,&tempStr[0],10,pos);
WriteChar(buffer,_T(','),pos);
}
// Write style and actor
WriteText(buffer,&style[0],style.Length(),pos);
WriteText(buffer,&text[1][0],text[1].Length(),pos);
WriteChar(buffer,_T(','),pos);
WriteText(buffer,&actor[0],actor.Length(),pos);
WriteText(buffer,&text[2][0],text[2].Length(),pos);
WriteChar(buffer,_T(','),pos);
// Write margins
@ -219,9 +218,9 @@ String DialogueASS::ToText(int version) const
}
// Write effect and text
WriteText(buffer,&effect[0],effect.Length(),pos);
WriteText(buffer,&text[3][0],text[3].Length(),pos);
WriteChar(buffer,_T(','),pos);
WriteText(buffer,&text[0],text.Length(),pos);
WriteText(buffer,&text[0][0],text[0].Length(),pos);
// Write terminator
WriteText(buffer,_T("\0"),1,pos);

View file

@ -36,18 +36,18 @@
#pragma once
#include "gorgonstring.h"
#include "section_entry_dialogue.h"
#include "format_ass_dialogue_delta.h"
#include "serialize.h"
namespace Gorgonsub {
// Dialogue
class DialogueASS : public SectionEntryDialogue, public SerializeText {
friend class DialogueASSDeltaCoder;
private:
String text;
String style;
String effect;
String actor;
Time start,end;
array<Time,2> time;
array<String,4> text; // 0 = text, 1 = style, 2 = actor, 3 = effect
array<short,4> margin;
int layer;
bool isComment;
@ -63,6 +63,7 @@ namespace Gorgonsub {
// Basic features
String GetDefaultGroup() const { return L"Events"; }
SectionEntryPtr Clone() const { return SectionEntryPtr(new DialogueASS(*this)); }
DeltaCoderPtr GetDeltaCoder() const { return DeltaCoderPtr(new DialogueASSDeltaCoder()); }
// Capabilities
bool HasText() const { return true; }
@ -71,25 +72,26 @@ namespace Gorgonsub {
bool HasMargins() const { return true; }
// Read accessors
const String& GetText() const { return text; }
Time GetStartTime() const { return start; }
Time GetEndTime() const { return end; }
Time GetStartTime() const { return time[0]; }
Time GetEndTime() const { return time[1]; }
bool IsComment() const { return isComment; }
int GetLayer() const { return layer; }
int GetMargin(int n) const { return margin.at(n); }
const String& GetStyle() const { return style; }
const String& GetActor() const { return actor; }
const String& GetUserField() const { return effect; }
const String& GetText() const { return text[0]; }
const String& GetStyle() const { return text[1]; }
const String& GetActor() const { return text[2]; }
const String& GetUserField() const { return text[3]; }
// Write acessors
void SetText(const String &setText) { text = setText; }
void SetStartTime(Time setStart) { start = setStart; }
void SetEndTime(Time setEnd) { end = setEnd; }
void SetStartTime(Time setStart) { time[0] = setStart; }
void SetEndTime(Time setEnd) { time[1] = setEnd; }
void SetComment(bool _isComment) { isComment = _isComment; }
void SetLayer(int _layer) { layer = _layer; }
void SetMargin(int _margin,int value) { margin.at(_margin) = value; }
void SetStyle(const String &_style) { style = _style; }
void SetUserField(const String &userField) { effect = userField; }
void SetText(const String &setText) { text[0] = setText; }
void SetStyle(const String &style) { text[1] = style; }
void SetActor(const String &actor) { text[2] = actor; }
void SetUserField(const String &userField) { text[3] = userField; }
};
};

View file

@ -0,0 +1,195 @@
// Copyright (c) 2008, Rodrigo Braz Monteiro
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of the Aegisub Group nor the names of its contributors
// may be used to endorse or promote products derived from this software
// without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// -----------------------------------------------------------------------------
//
// AEGISUB/GORGONSUB
//
// Website: http://www.aegisub.net
// Contact: mailto:amz@aegisub.net
//
#include "format_ass_dialogue_delta.h"
#include "format_ass_dialogue.h"
#ifdef _MSC_VER
#include "../stdint.h"
#else
#include <stdint.h>
#endif
using namespace Gorgonsub;
////////////////////////////////////
// Encode delta between two entries
VoidPtr DialogueASSDeltaCoder::EncodeDelta(VoidPtr _from,VoidPtr _to) const
{
// Cast pointers
shared_ptr<DialogueASS> from = static_pointer_cast<DialogueASS> (_from);
shared_ptr<DialogueASS> to = static_pointer_cast<DialogueASS> (_to);
// Determine changes
unsigned short mask = 0;
if (from->isComment != to->isComment) mask |= 0x0001;
if (from->layer != to->layer) mask |= 0x0002;
if (from->time[0] != to->time[0]) mask |= 0x0004;
if (from->time[1] != to->time[1]) mask |= 0x0008;
for (size_t i=0;i<4;i++) {
if (from->margin[i] != to->margin[i]) mask |= 0x0010 << i;
if (from->text[i] != to->text[i]) mask |= 0x0100 << i;
}
// Calculate final size and allocate
size_t size = 2 + (mask & 0x0002)*4 + (mask & 0x0004)*4 + (mask & 0x0008)*4;
for (size_t i=0;i<4;i++) {
if (mask & (0x0010 << i)) size += 2;
if (mask & (0x0100 << i)) size += (to->text[i].Length()+1)*2;
}
shared_ptr<std::vector<char> > delta (new std::vector<char>(size));
// Write data
char *final = &delta->front();
GetDelta(mask,final,to);
// Return delta
return delta;
}
////////////////////////////
// Calculates reverse delta
VoidPtr DialogueASSDeltaCoder::EncodeReverseDelta(VoidPtr _delta,VoidPtr object) const
{
// Get mask
char *data = &(static_pointer_cast<std::vector<char> > (_delta))->front();
int mask = *((short*) data);
shared_ptr<DialogueASS> to = static_pointer_cast<DialogueASS> (object);
// Calculate final size and allocate
size_t size = 2 + (mask & 0x0002)*4 + (mask & 0x0004)*4 + (mask & 0x0008)*4;
for (size_t i=0;i<4;i++) {
size += (mask & (0x0010 << i)) * 2 + (mask & (0x0100 << i)) * (to->text[i].Length()+1)*2;
}
shared_ptr<std::vector<char> > delta (new std::vector<char>(size));
// Write data
char *final = &delta->front();
GetDelta(mask,final,to);
return delta;
}
///////////////////////////
// Applies delta to a line
void DialogueASSDeltaCoder::ApplyDelta(VoidPtr _delta,VoidPtr object) const
{
// Process parameters
char *data = &(static_pointer_cast<std::vector<char> > (_delta))->front();
shared_ptr<DialogueASS> to = static_pointer_cast<DialogueASS> (object);
// Read mask
int mask = *((int16_t*) data);
data += 2;
// Toggle comment
if (mask & 0x0001) to->isComment = !to->isComment;
// Read layer
if (mask & 0x0002) {
to->layer = *((int32_t*) data);
data += 4;
}
// Read times
for (size_t i=0;i<2;i++) {
if (mask & (0x0004 << i)) {
to->time[i].SetMS(*((int32_t*) data));
data += 4;
}
}
// Read margins
for (size_t i=0;i<4;i++) {
if (mask & (0x0010 << i)) {
to->margin[i] = *((int16_t*) data);
data += 2;
}
}
// Read text fields
for (size_t i=0;i<4;i++) {
if (mask & (0x0100 << i)) {
to->text[i] = wxString((wchar_t*) data);
data += (to->text[i].Length() + 1)*2;
}
}
}
///////////////////////////
// Actually get delta data
void DialogueASSDeltaCoder::GetDelta(int mask,char *final,shared_ptr<DialogueASS> to) const
{
// Write mask
*((uint16_t*) final) = mask;
final += 2;
// Write layer
if (mask & 0x0002) {
*((int32_t*) final) = to->layer;
final += 4;
}
// Write times
for (size_t i=0;i<2;i++) {
if (mask & (0x0004 << i)) {
*((int32_t*) final) = to->time[i].GetMS();
final += 4;
}
}
// Write margins
for (size_t i=0;i<4;i++) {
if (mask & (0x0010 << i)) {
*((int16_t*) final) = to->margin[i];
final += 2;
}
}
// Write text fields
for (size_t i=0;i<4;i++) {
if (mask & (0x0100 << i)) {
size_t len = (to->text[i].Length() + 1)*2;
memcpy(final,to->text[i].c_str(),len);
final += len-2;
*(final++) = 0;
*(final++) = 0;
final += len;
}
}
}

View file

@ -0,0 +1,53 @@
// Copyright (c) 2008, Rodrigo Braz Monteiro
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of the Aegisub Group nor the names of its contributors
// may be used to endorse or promote products derived from this software
// without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// -----------------------------------------------------------------------------
//
// AEGISUB/GORGONSUB
//
// Website: http://www.aegisub.net
// Contact: mailto:amz@aegisub.net
//
#pragma once
#include "deltacoder.h"
namespace Gorgonsub {
// Delta coder
class DialogueASS;
class DialogueASSDeltaCoder : public DeltaCoder {
private:
void GetDelta(int mask,char *dst,shared_ptr<DialogueASS> to) const;
public:
VoidPtr EncodeDelta(VoidPtr from,VoidPtr to) const;
VoidPtr EncodeReverseDelta(VoidPtr from,VoidPtr to) const;
void ApplyDelta(VoidPtr delta,VoidPtr object) const;
};
};

View file

@ -81,8 +81,8 @@ void Model::ProcessActionList(const ActionList &_actionList,int type)
// Insert into undo stack
if (actions->undoAble) {
stack->push(undo);
if (type == 0) redoStack = ActionStack();
stack->push_back(undo);
if (type == 0) redoStack.clear();
}
// Notify listeners
@ -179,8 +179,8 @@ size_t Model::GetSectionCount() const
void Model::Clear()
{
sections.clear();
undoStack = ActionStack();
redoStack = ActionStack();
undoStack.clear();
redoStack.clear();
}
@ -222,8 +222,24 @@ void Model::ActivateStack(ActionStack &stack,bool isUndo,const String &owner)
(void) owner;
// Process list
ProcessActionList(*stack.top(),isUndo?1:2);
ProcessActionList(*stack.back(),isUndo?1:2);
// Pop original
stack.pop();
stack.pop_back();
}
//////////////////////////
// Get undo/redo messages
String Model::GetUndoMessage(const String owner) const
{
(void) owner;
if (CanUndo()) return undoStack.back()->GetName();
return L"";
}
String Model::GetRedoMessage(const String owner) const
{
(void) owner;
if (CanRedo()) return redoStack.back()->GetName();
return L"";
}

221
aegilib/src/stdint.h Normal file
View file

@ -0,0 +1,221 @@
// ISO C9x compliant stdint.h for Miscrosoft Visual Studio
// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124
//
// Copyright (c) 2006 Alexander Chemeris
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// 3. The name of the author may be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
///////////////////////////////////////////////////////////////////////////////
#ifdef _MSC_VER
#ifndef _MSC_STDINT_H_ // [
#define _MSC_STDINT_H_
#if _MSC_VER > 1000
#pragma once
#endif
#include <limits.h>
// For Visual Studio 6 in C++ mode wrap <wchar.h> include with 'extern "C++" {}'
// or compiler give many errors like this:
// error C2733: second C linkage of overloaded function 'wmemchr' not allowed
#if (_MSC_VER < 1300) && defined(__cplusplus)
extern "C++" {
#endif
# include <wchar.h>
#if (_MSC_VER < 1300) && defined(__cplusplus)
}
#endif
// 7.18.1 Integer types
// 7.18.1.1 Exact-width integer types
typedef __int8 int8_t;
typedef __int16 int16_t;
typedef __int32 int32_t;
typedef __int64 int64_t;
typedef unsigned __int8 uint8_t;
typedef unsigned __int16 uint16_t;
typedef unsigned __int32 uint32_t;
typedef unsigned __int64 uint64_t;
// 7.18.1.2 Minimum-width integer types
typedef int8_t int_least8_t;
typedef int16_t int_least16_t;
typedef int32_t int_least32_t;
typedef int64_t int_least64_t;
typedef uint8_t uint_least8_t;
typedef uint16_t uint_least16_t;
typedef uint32_t uint_least32_t;
typedef uint64_t uint_least64_t;
// 7.18.1.3 Fastest minimum-width integer types
typedef int8_t int_fast8_t;
typedef int16_t int_fast16_t;
typedef int32_t int_fast32_t;
typedef int64_t int_fast64_t;
typedef uint8_t uint_fast8_t;
typedef uint16_t uint_fast16_t;
typedef uint32_t uint_fast32_t;
typedef uint64_t uint_fast64_t;
// 7.18.1.4 Integer types capable of holding object pointers
#ifdef _WIN64 // [
typedef __int64 intptr_t;
typedef unsigned __int64 uintptr_t;
#else // _WIN64 ][
typedef int intptr_t;
typedef unsigned int uintptr_t;
#endif // _WIN64 ]
// 7.18.1.5 Greatest-width integer types
typedef int64_t intmax_t;
typedef uint64_t uintmax_t;
// 7.18.2 Limits of specified-width integer types
#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [ See footnote 220 at page 257 and footnote 221 at page 259
// 7.18.2.1 Limits of exact-width integer types
#define INT8_MIN _I8_MIN
#define INT8_MAX _I8_MAX
#define INT16_MIN _I16_MIN
#define INT16_MAX _I16_MAX
#define INT32_MIN _I32_MIN
#define INT32_MAX _I32_MAX
#define INT64_MIN _I64_MIN
#define INT64_MAX _I64_MAX
#define UINT8_MAX _UI8_MAX
#define UINT16_MAX _UI16_MAX
#define UINT32_MAX _UI32_MAX
#define UINT64_MAX _UI64_MAX
// 7.18.2.2 Limits of minimum-width integer types
#define INT_LEAST8_MIN INT8_MIN
#define INT_LEAST8_MAX INT8_MAX
#define INT_LEAST16_MIN INT16_MIN
#define INT_LEAST16_MAX INT16_MAX
#define INT_LEAST32_MIN INT32_MIN
#define INT_LEAST32_MAX INT32_MAX
#define INT_LEAST64_MIN INT64_MIN
#define INT_LEAST64_MAX INT64_MAX
#define UINT_LEAST8_MAX UINT8_MAX
#define UINT_LEAST16_MAX UINT16_MAX
#define UINT_LEAST32_MAX UINT32_MAX
#define UINT_LEAST64_MAX UINT64_MAX
// 7.18.2.3 Limits of fastest minimum-width integer types
#define INT_FAST8_MIN INT8_MIN
#define INT_FAST8_MAX INT8_MAX
#define INT_FAST16_MIN INT16_MIN
#define INT_FAST16_MAX INT16_MAX
#define INT_FAST32_MIN INT32_MIN
#define INT_FAST32_MAX INT32_MAX
#define INT_FAST64_MIN INT64_MIN
#define INT_FAST64_MAX INT64_MAX
#define UINT_FAST8_MAX UINT8_MAX
#define UINT_FAST16_MAX UINT16_MAX
#define UINT_FAST32_MAX UINT32_MAX
#define UINT_FAST64_MAX UINT64_MAX
// 7.18.2.4 Limits of integer types capable of holding object pointers
#ifdef _WIN64 // [
# define INTPTR_MIN INT64_MIN
# define INTPTR_MAX INT64_MAX
# define UINTPTR_MAX UINT64_MAX
#else // _WIN64 ][
# define INTPTR_MIN INT32_MIN
# define INTPTR_MAX INT32_MAX
# define UINTPTR_MAX UINT32_MAX
#endif // _WIN64 ]
// 7.18.2.5 Limits of greatest-width integer types
#define INTMAX_MIN INT64_MIN
#define INTMAX_MAX INT64_MAX
#define UINTMAX_MAX UINT64_MAX
// 7.18.3 Limits of other integer types
#ifdef _WIN64 // [
# define PTRDIFF_MIN _I64_MIN
# define PTRDIFF_MAX _I64_MAX
#else // _WIN64 ][
# define PTRDIFF_MIN _I32_MIN
# define PTRDIFF_MAX _I32_MAX
#endif // _WIN64 ]
#define SIG_ATOMIC_MIN INT_MIN
#define SIG_ATOMIC_MAX INT_MAX
#ifndef SIZE_MAX // [
# ifdef _WIN64 // [
# define SIZE_MAX _UI64_MAX
# else // _WIN64 ][
# define SIZE_MAX _UI32_MAX
# endif // _WIN64 ]
#endif // SIZE_MAX ]
// WCHAR_MIN and WCHAR_MAX are also defined in <wchar.h>
#ifndef WCHAR_MIN // [
# define WCHAR_MIN 0
#endif // WCHAR_MIN ]
#ifndef WCHAR_MAX // [
# define WCHAR_MAX _UI16_MAX
#endif // WCHAR_MAX ]
#define WINT_MIN 0
#define WINT_MAX _UI16_MAX
#endif // __STDC_LIMIT_MACROS ]
// 7.18.4 Limits of other integer types
#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260
// 7.18.4.1 Macros for minimum-width integer constants
#define INT8_C(val) val
#define INT16_C(val) val
#define INT32_C(val) val##L
#define INT64_C(val) val##i64
#define UINT8_C(val) val
#define UINT16_C(val) val
#define UINT32_C(val) val##UL
#define UINT64_C(val) val##Ui64
// 7.18.4.2 Macros for greatest-width integer constants
#define INTMAX_C INT64_C
#define UINTMAX_C UINT64_C
#endif // __STDC_CONSTANT_MACROS ]
#endif // _MSC_STDINT_H_ ]
#endif // _MSC_VER ]