ultimatepp/uppsrc/ide/Diff.cpp
cxl 7fd2c2230b TheIDE now can work with diff/patch files
git-svn-id: svn://ultimatepp.org/upp/trunk@984 f0d560ea-af0d-0410-9eb7-867de7ffcac7
2009-03-19 21:56:29 +00:00

303 lines
5.5 KiB
C++

#include "ide.h"
struct DiffDlg : public TopWindow {
TextDiffCtrl diff;
FrameTop<StaticRect> p;
DataPusher l;
Button write;
String editfile;
String extfile;
typedef DiffDlg CLASSNAME;
void Write();
void Execute(const String& f);
DiffDlg();
};
INITBLOCK {
RegisterGlobalConfig("diff");
}
void DiffDlg::Execute(const String& f)
{
editfile = f;
l <<= editfile;
Title(editfile);
String h;
{
LoadFromGlobal(h, "diff");
StringStream ss(h);
SerializePlacement(ss);
}
TopWindow::Execute();
{
StringStream ss;
SerializePlacement(ss);
h = ss;
StoreToGlobal(h, "diff");
}
}
void DiffDlg::Write()
{
if(PromptYesNo("Do you want to overwrite&[* " + DeQtf(editfile) + "] ?")) {
SaveFile(editfile, extfile);
Break(IDOK);
}
}
DiffDlg::DiffDlg()
{
Add(diff.SizePos());
Sizeable().Zoomable();
diff.AddFrameLeft(p);
int cy = EditField::GetStdHeight();
p.Height(cy);
p.Add(l.VSizePos().HSizePos(0, 6 * cy));
p.Add(write.VSizePos().RightPos(0, 6 * cy));
write <<= THISBACK(Write);
write.SetLabel("Overwrite <-");
l.SetReadOnly();
}
struct FileDiff : DiffDlg {
FrameTop<DataPusher> r;
virtual void Open();
void Execute(const String& f);
typedef FileDiff CLASSNAME;
FileDiff();
};
void FileDiff::Open()
{
if(!AnySourceFs().ExecuteOpen())
return;
String f = ~AnySourceFs();
r <<= f;
diff.Set(LoadFile(editfile), extfile = LoadFile(f));
}
void FileDiff::Execute(const String& f)
{
editfile = f;
Open();
if(IsNull(r))
return;
DiffDlg::Execute(f);
}
FileDiff::FileDiff()
{
r.Height(EditField::GetStdHeight());
Icon(IdeImg::Diff());
diff.AddFrameRight(r);
r <<= THISBACK(Open);
}
void Ide::Diff()
{
if(IsNull(editfile))
return;
FileDiff dlg;
dlg.Execute(editfile);
}
FileSel& DiffFs() {
static FileSel fs;
ONCELOCK {
fs.Type("Patch file (*.diff, *.patch)", "*.diff *.patch");
fs.AllFilesType();
}
return fs;
}
struct PatchDiff : FileDiff {
virtual void Open();
void Copy(FileIn& in, FileIn& oin, int& l, int ln, int n);
void LoadDiff(const char *fn);
};
void PatchDiff::Copy(FileIn& in, FileIn& oin, int& l, int ln, int n)
{
if(ln < l)
throw CParser::Error("");
while(l < ln) {
if(oin.IsEof())
throw CParser::Error("");
extfile << oin.GetLine() << "\r\n";
l++;
}
l += n;
while(n--)
oin.GetLine();
}
void PatchDiff::LoadDiff(const char *fn)
{
try {
FileIn in(fn);
FileIn oin(editfile);
extfile.Clear();
int l = 1;
String s = in.GetLine();
if(IsDigit(*s)) {
in.Seek(0);
while(!in.IsEof()) {
s = in.GetLine();
if(IsDigit(*s)) {
CParser p(s);
int ln = p.ReadNumber();
int n = 0;
if(p.Char('a'))
ln++;
else {
n = p.Char(',') ? p.ReadNumber() - ln + 1 : 1;
if(!p.Char('c'))
p.PassChar('d');
}
Copy(in, oin, l, ln, n);
}
else
if(*s == '>') {
if(s[1] != ' ')
throw CParser::Error("");
extfile << s.Mid(2) << "\r\n";
}
else
if(*s != '<' && *s != '-')
throw CParser::Error("");
}
}
else {
for(;;) {
if(in.IsEof())
throw CParser::Error("");
if(in.GetLine().Mid(0, 4) == "+++ ")
break;
}
while(!in.IsEof()) {
String s = in.GetLine();
if(*s == '@') {
CParser p(s);
p.PassChar2('@', '@');
p.PassChar('-');
int ln = p.ReadNumber();
int n = 1;
if(p.Char(','))
n = p.ReadNumber();
Copy(in, oin, l, ln, n);
}
else
if(*s == '+' || *s == ' ')
extfile << s.Mid(1) << "\r\n";
else
if(*s != '-')
throw CParser::Error("");
}
}
while(!oin.IsEof())
extfile << oin.GetLine() << "\r\n";
}
catch(CParser::Error&) {
Exclamation("Invalid file format!");
extfile = LoadFile(fn);
}
}
void PatchDiff::Open()
{
if(!DiffFs().ExecuteOpen())
return;
String f = ~DiffFs();
r <<= f;
LoadDiff(f);
diff.Set(LoadFile(editfile), extfile);
}
void Ide::Patch()
{
if(IsNull(editfile))
return;
PatchDiff dlg;
dlg.Execute(editfile);
}
struct SvnDiff : DiffDlg {
FrameTop<DropList> r;
void Load();
void Execute(const String& f);
typedef SvnDiff CLASSNAME;
SvnDiff();
};
void SvnDiff::Execute(const String& f)
{
editfile = f;
String log = Sys("svn log " + f);
if(log.IsVoid()) {
Exclamation("Error executing 'svn log'");
return;
}
StringStream ss(log);
while(!ss.IsEof()) {
String l = ss.GetLine();
if(l[0] == 'r') {
Vector<String> h = Split(l, '|');
if(h.GetCount() > 3) {
String rev = TrimBoth(h[0]);
String s = rev;
Vector<String> t = Split(h[2], ' ');
if(t.GetCount() > 1)
s << ' ' << t[0];
s << ' ' << TrimBoth(h[1]);
while(!ss.IsEof()) {
l = ss.GetLine();
if(l.GetCount()) {
if(l[0] != '-')
s << ": " << l;
break;
}
}
r.Add(rev, s);
}
}
}
if(r.GetCount() == 0) {
Exclamation("No parsable history for the file");
return;
}
r.SetIndex(0);
Load();
DiffDlg::Execute(f);
}
void SvnDiff::Load()
{
diff.Set(LoadFile(editfile), extfile = Sys("svn cat " + editfile + '@' + AsString(~r)));
}
SvnDiff::SvnDiff()
{
r.Height(EditField::GetStdHeight());
r.SetDropLines(32);
Icon(IdeImg::SvnDiff());
diff.AddFrameRight(r);
r <<= THISBACK(Load);
}
void Ide::SvnHistory()
{
if(IsNull(editfile))
return;
SvnDiff dlg;
dlg.Execute(editfile);
}