From 8e8f4bf5305e6d0e9663370dae30b5ba8b30529a Mon Sep 17 00:00:00 2001 From: Rodrigo Braz Monteiro Date: Sun, 16 Mar 2008 06:41:23 +0000 Subject: [PATCH] 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. --- aegilib/aegilib.vcproj | 72 +++--- aegilib/include/aegilib/action.h | 2 + aegilib/include/aegilib/actionlist.h | 3 + aegilib/include/aegilib/deltacoder.h | 54 +++++ aegilib/include/aegilib/gorgontime.h | 7 + aegilib/include/aegilib/model.h | 5 +- aegilib/include/aegilib/section_entry.h | 3 + aegilib/src/action.cpp | 31 ++- aegilib/src/formats/format_ass_dialogue.cpp | 37 ++- aegilib/src/formats/format_ass_dialogue.h | 34 +-- .../src/formats/format_ass_dialogue_delta.cpp | 195 ++++++++++++++++ .../src/formats/format_ass_dialogue_delta.h | 53 +++++ aegilib/src/model.cpp | 28 ++- aegilib/src/stdint.h | 221 ++++++++++++++++++ 14 files changed, 669 insertions(+), 76 deletions(-) create mode 100644 aegilib/include/aegilib/deltacoder.h create mode 100644 aegilib/src/formats/format_ass_dialogue_delta.cpp create mode 100644 aegilib/src/formats/format_ass_dialogue_delta.h create mode 100644 aegilib/src/stdint.h diff --git a/aegilib/aegilib.vcproj b/aegilib/aegilib.vcproj index 3506ce6d2..d1ce38260 100644 --- a/aegilib/aegilib.vcproj +++ b/aegilib/aegilib.vcproj @@ -224,6 +224,10 @@ RelativePath=".\include\aegilib\colour.h" > + + @@ -317,34 +321,6 @@ RelativePath=".\include\aegilib\format.h" > - - - - - - - - - - - - - - @@ -357,6 +333,46 @@ RelativePath=".\include\aegilib\format_manager.h" > + + + + + + + + + + + + + + + + + + + + entry; + shared_ptr delta; const String section; int lineNumber; public: ActionModify(shared_ptr entry,int line,const String §ion); + ActionModify(shared_ptr delta,int line,const String §ion); virtual ~ActionModify() {} ActionPtr GetAntiAction(const Model &model) const; diff --git a/aegilib/include/aegilib/actionlist.h b/aegilib/include/aegilib/actionlist.h index d29abdd43..0ce99fd10 100644 --- a/aegilib/include/aegilib/actionlist.h +++ b/aegilib/include/aegilib/actionlist.h @@ -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(); diff --git a/aegilib/include/aegilib/deltacoder.h b/aegilib/include/aegilib/deltacoder.h new file mode 100644 index 000000000..1c7490336 --- /dev/null +++ b/aegilib/include/aegilib/deltacoder.h @@ -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 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 DeltaCoderPtr; + +}; diff --git a/aegilib/include/aegilib/gorgontime.h b/aegilib/include/aegilib/gorgontime.h index c1260bed1..5e96f69e7 100644 --- a/aegilib/include/aegilib/gorgontime.h +++ b/aegilib/include/aegilib/gorgontime.h @@ -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; } }; }; diff --git a/aegilib/include/aegilib/model.h b/aegilib/include/aegilib/model.h index 389250a9d..221bd30ee 100644 --- a/aegilib/include/aegilib/model.h +++ b/aegilib/include/aegilib/model.h @@ -36,7 +36,6 @@ #pragma once #include #include -#include #include #include "actionlist.h" #include "section.h" @@ -58,7 +57,7 @@ namespace Gorgonsub { friend class Action; typedef std::list ViewList; - typedef std::stack > ActionStack; + typedef std::list ActionStack; typedef shared_ptr 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""); diff --git a/aegilib/include/aegilib/section_entry.h b/aegilib/include/aegilib/section_entry.h index 4db3c7fa8..6a9ca61a0 100644 --- a/aegilib/include/aegilib/section_entry.h +++ b/aegilib/include/aegilib/section_entry.h @@ -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); diff --git a/aegilib/src/action.cpp b/aegilib/src/action.cpp index 4ea45f3f1..0ef58f2a1 100644 --- a/aegilib/src/action.cpp +++ b/aegilib/src/action.cpp @@ -114,19 +114,36 @@ void ActionRemove::Execute(Model &model) ///////////////////////////// Modify line ///////////////////////////// -/////////////// -// Constructor +//////////////// +// Constructors ActionModify::ActionModify(shared_ptr data,int line,const String &sName) : entry(data), lineNumber(line), section(sName) {} +ActionModify::ActionModify(shared_ptr _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; } diff --git a/aegilib/src/formats/format_ass_dialogue.cpp b/aegilib/src/formats/format_ass_dialogue.cpp index 7b36ab2ff..1b09d02a3 100644 --- a/aegilib/src/formats/format_ass_dialogue.cpp +++ b/aegilib/src/formats/format_ass_dialogue.cpp @@ -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); diff --git a/aegilib/src/formats/format_ass_dialogue.h b/aegilib/src/formats/format_ass_dialogue.h index bd269e06e..f88b0fa29 100644 --- a/aegilib/src/formats/format_ass_dialogue.h +++ b/aegilib/src/formats/format_ass_dialogue.h @@ -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; + array text; // 0 = text, 1 = style, 2 = actor, 3 = effect array 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; } }; }; diff --git a/aegilib/src/formats/format_ass_dialogue_delta.cpp b/aegilib/src/formats/format_ass_dialogue_delta.cpp new file mode 100644 index 000000000..e8ab51de7 --- /dev/null +++ b/aegilib/src/formats/format_ass_dialogue_delta.cpp @@ -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 +#endif + +using namespace Gorgonsub; + + +//////////////////////////////////// +// Encode delta between two entries +VoidPtr DialogueASSDeltaCoder::EncodeDelta(VoidPtr _from,VoidPtr _to) const +{ + // Cast pointers + shared_ptr from = static_pointer_cast (_from); + shared_ptr to = static_pointer_cast (_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 > delta (new std::vector(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 > (_delta))->front(); + int mask = *((short*) data); + shared_ptr to = static_pointer_cast (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 > delta (new std::vector(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 > (_delta))->front(); + shared_ptr to = static_pointer_cast (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 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; + } + } +} diff --git a/aegilib/src/formats/format_ass_dialogue_delta.h b/aegilib/src/formats/format_ass_dialogue_delta.h new file mode 100644 index 000000000..c8b58e91d --- /dev/null +++ b/aegilib/src/formats/format_ass_dialogue_delta.h @@ -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 to) const; + + public: + VoidPtr EncodeDelta(VoidPtr from,VoidPtr to) const; + VoidPtr EncodeReverseDelta(VoidPtr from,VoidPtr to) const; + void ApplyDelta(VoidPtr delta,VoidPtr object) const; + }; + +}; diff --git a/aegilib/src/model.cpp b/aegilib/src/model.cpp index d8dd0875c..f5fe33b42 100644 --- a/aegilib/src/model.cpp +++ b/aegilib/src/model.cpp @@ -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""; } diff --git a/aegilib/src/stdint.h b/aegilib/src/stdint.h new file mode 100644 index 000000000..739c89e7e --- /dev/null +++ b/aegilib/src/stdint.h @@ -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 + +// For Visual Studio 6 in C++ mode wrap 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 +#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 +#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 ]