diff --git a/uppsrc/TextDiffCtrl/DiffCtrl.cpp b/uppsrc/TextDiffCtrl/DiffCtrl.cpp index 8546ed417..56273940a 100644 --- a/uppsrc/TextDiffCtrl/DiffCtrl.cpp +++ b/uppsrc/TextDiffCtrl/DiffCtrl.cpp @@ -1,182 +1,192 @@ -#include "TextDiffCtrl.h" - -namespace Upp { - -#define IMAGECLASS DiffImg -#define IMAGEFILE -#include - -TextDiffCtrl::TextDiffCtrl() -{ - left.Gutter(30); - right.NoGutter(); - Horz(left, right); - left.WhenScroll = right.ScrollWhen(left); - right.WhenScroll = left.ScrollWhen(right); - right.HideSb(); - left.WhenLeftDouble = Proxy(WhenLeftLine); - right.WhenLeftDouble = Proxy(WhenRightLine); -} - -static bool SmallDiff(const char *s1, const char *s2) -{ - for(;;) { - while(*s1 && (byte)*s1 <= ' ') - s1++; - while(*s2 && (byte)*s2 <= ' ') - s2++; - if(!*s1 || !*s2) - return !*s1 && !*s2; - if(*s1 != *s2) - return false; - while(*s1 && *s1 == *s2) - s1++, s2++; - if((byte)s1[-1] <= ' ') - continue; - if((byte)*s1 > ' ' || (byte)*s2 > ' ') - return false; - } -} - -void TextDiffCtrl::Set(Stream& l, Stream& r) -{ - Vector ll = GetLineMap(l); - Vector rl = GetLineMap(r); - Array sections = CompareLineMaps(ll, rl); - -// Point left_pos = left.GetPos(); -// Point right_pos = right.GetPos(); -// int sb_pos = left.GetSb(); - - int outln = 0; - left.SetCount(0); - right.SetCount(0); - int firstdiff = -1; - for(int i = 0; i < sections.GetCount(); i++) { - const TextSection& sec = sections[i]; - bool diff = !sec.same; - if(firstdiff < 0 && diff) - firstdiff = outln; - int maxcount = max(sec.count1, sec.count2); - left.AddCount(maxcount); - int l; - for(l = 0; l < sec.count1; l++) { - int level = (diff ? l < sec.count2 && SmallDiff(ll[sec.start1 + l], rl[sec.start2 + l]) ? 1 : 2 : 0); - left.Set(outln + l, ll[sec.start1 + l], diff, sec.start1 + l + 1, level); - } - for(; l < maxcount; l++) - left.Set(outln + l, Null, diff, Null, 2); - right.AddCount(maxcount); - for(l = 0; l < sec.count2; l++) { - int level = (diff ? l < sec.count1 && SmallDiff(rl[sec.start2 + l], ll[sec.start1 + l]) ? 1 : 2 : 0); - right.Set(outln + l, rl[sec.start2 + l], diff, sec.start2 + l + 1, level); - } - for(; l < maxcount; l++) - right.Set(outln + l, Null, diff, Null, 2); - outln += maxcount; - } - if(firstdiff >= 0) - left.SetSb(max(firstdiff - 2, 0)); - left.ClearSelection(); - right.ClearSelection(); -} - -void TextDiffCtrl::Set(const String& l, const String& r) -{ - StringStream sl(l); - StringStream sr(r); - Set(sl, sr); -} - -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); - } -} - -Event&, const WString&> DiffDlg::WhenHighlight; - -static void sDoHighlight(Vector& hl, const WString& ln, const String *path) -{ - DiffDlg::WhenHighlight(*path, hl, ln); -} - -DiffDlg::DiffDlg() -{ - Add(diff.SizePos()); - Sizeable().Zoomable(); - diff.InsertFrameLeft(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(); - diff.left.WhenHighlight = callback1(sDoHighlight, &editfile); - diff.right.WhenHighlight = callback1(sDoHighlight, &editfile); -} - -void FileDiff::Open() -{ - if(!fs.ExecuteOpen()) - return; - String f = ~fs; - 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(FileSel& fs_) -: fs(fs_) -{ - r.Height(EditField::GetStdHeight()); - Icon(DiffImg::Diff()); - diff.InsertFrameRight(r); - r <<= THISBACK(Open); -} - -FileSel& DiffFs() { - static FileSel fs; - ONCELOCK { - fs.Type("Patch file (*.diff, *.patch)", "*.diff *.patch"); - fs.AllFilesType(); - } - return fs; -} - -}; +#include "TextDiffCtrl.h" + +namespace Upp { + +#define IMAGECLASS DiffImg +#define IMAGEFILE +#include + +TextDiffCtrl::TextDiffCtrl() +{ + left.Gutter(30); + right.NoGutter(); + Horz(left, right); + left.WhenScroll = right.ScrollWhen(left); + right.WhenScroll = left.ScrollWhen(right); + right.HideSb(); + left.WhenLeftDouble = THISBACK(GetLeftLine); + right.WhenLeftDouble = THISBACK(GetRightLine); +} + +void TextDiffCtrl::GetLeftLine(int number, int line) +{ + WhenLeftLine(number); +} + +void TextDiffCtrl::GetRightLine(int number, int line) +{ + WhenRightLine(number); +} + +static bool SmallDiff(const char *s1, const char *s2) +{ + for(;;) { + while(*s1 && (byte)*s1 <= ' ') + s1++; + while(*s2 && (byte)*s2 <= ' ') + s2++; + if(!*s1 || !*s2) + return !*s1 && !*s2; + if(*s1 != *s2) + return false; + while(*s1 && *s1 == *s2) + s1++, s2++; + if((byte)s1[-1] <= ' ') + continue; + if((byte)*s1 > ' ' || (byte)*s2 > ' ') + return false; + } +} + +void TextDiffCtrl::Set(Stream& l, Stream& r) +{ + Vector ll = GetLineMap(l); + Vector rl = GetLineMap(r); + Array sections = CompareLineMaps(ll, rl); + +// Point left_pos = left.GetPos(); +// Point right_pos = right.GetPos(); +// int sb_pos = left.GetSb(); + + int outln = 0; + left.SetCount(0); + right.SetCount(0); + int firstdiff = -1; + for(int i = 0; i < sections.GetCount(); i++) { + const TextSection& sec = sections[i]; + bool diff = !sec.same; + if(firstdiff < 0 && diff) + firstdiff = outln; + int maxcount = max(sec.count1, sec.count2); + left.AddCount(maxcount); + int l; + for(l = 0; l < sec.count1; l++) { + int level = (diff ? l < sec.count2 && SmallDiff(ll[sec.start1 + l], rl[sec.start2 + l]) ? 1 : 2 : 0); + left.Set(outln + l, ll[sec.start1 + l], diff, sec.start1 + l + 1, level, diff && l < sec.count2 ? rl[sec.start2 + l] : Null, sec.start1 + l + 1, true); + } + for(; l < maxcount; l++) + left.Set(outln + l, Null, diff, Null, 2, Null, Null, true); + right.AddCount(maxcount); + for(l = 0; l < sec.count2; l++) { + int level = (diff ? l < sec.count1 && SmallDiff(rl[sec.start2 + l], ll[sec.start1 + l]) ? 1 : 2 : 0); + right.Set(outln + l, rl[sec.start2 + l], diff, sec.start2 + l + 1, level, diff && l < sec.count1 ? ll[sec.start1 + l] : Null, sec.start2 + l + 1, false); + } + for(; l < maxcount; l++) + right.Set(outln + l, Null, diff, Null, 2, Null, Null, false); + outln += maxcount; + } + if(firstdiff >= 0) + left.SetSb(max(firstdiff - 2, 0)); + left.ClearSelection(); + right.ClearSelection(); +} + +void TextDiffCtrl::Set(const String& l, const String& r) +{ + StringStream sl(l); + StringStream sr(r); + Set(sl, sr); +} + +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); + } +} + +Event&, const WString&> DiffDlg::WhenHighlight; + +static void sDoHighlight(Vector& hl, const WString& ln, const String *path) +{ + DiffDlg::WhenHighlight(*path, hl, ln); +} + +DiffDlg::DiffDlg() +{ + Add(diff.SizePos()); + Sizeable().Zoomable(); + diff.InsertFrameLeft(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(); + diff.left.WhenHighlight = callback1(sDoHighlight, &editfile); + diff.right.WhenHighlight = callback1(sDoHighlight, &editfile); +} + +void FileDiff::Open() +{ + if(!fs.ExecuteOpen()) + return; + String f = ~fs; + 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(FileSel& fs_) +: fs(fs_) +{ + r.Height(EditField::GetStdHeight()); + Icon(DiffImg::Diff()); + diff.InsertFrameRight(r); + r <<= THISBACK(Open); +} + +FileSel& DiffFs() { + static FileSel fs; + ONCELOCK { + fs.Type("Patch file (*.diff, *.patch)", "*.diff *.patch"); + fs.AllFilesType(); + } + return fs; +} + +}; diff --git a/uppsrc/TextDiffCtrl/TextCtrl.cpp b/uppsrc/TextDiffCtrl/TextCtrl.cpp index 3ef213cd4..e14f48a99 100644 --- a/uppsrc/TextDiffCtrl/TextCtrl.cpp +++ b/uppsrc/TextDiffCtrl/TextCtrl.cpp @@ -13,7 +13,7 @@ TextCompareCtrl::TextCompareCtrl() number_bg = WhiteGray(); SetFrame(FieldFrame()); AddFrame(scroll); - SetFont(CourierZ(14), CourierZ(10)); + SetFont(CourierZ(10), CourierZ(10)); scroll.NoAutoHide(); scroll.WhenScroll = THISBACK(SelfScroll); maxwidth = 0; @@ -23,6 +23,10 @@ TextCompareCtrl::TextCompareCtrl() gutter_fg = SGreen; cursor = anchor = Null; gutter_capture = false; + show_line_number = true; + show_white_space = true; + show_diff_highlight = true; + change_paper_color = true; } int TextCompareCtrl::GetLineNo(int y, int& ii) @@ -69,7 +73,7 @@ void TextCompareCtrl::LeftDouble(Point pt, dword keyflags) int ii; int i = GetLineNo(pt.y, ii); if(!IsNull(i)) - WhenLeftDouble(i - 1); + WhenLeftDouble(i - 1, ii); } void TextCompareCtrl::MouseMove(Point pt, dword flags) @@ -213,27 +217,35 @@ void TextCompareCtrl::Paint(Draw& draw) draw.DrawRect(gx + gutter_width - 2, ty, 2, by - ty, Black); } - for(int i = first_line; i <= last_line; i++) { - const Line& l = lines[i]; - int y = i * letter.cy - offset.cy; - draw.DrawRect(0, y, number_width, letter.cy, number_bg); - if(!IsNull(l.number)) - draw.DrawText(0, y + number_yshift, FormatInt(l.number), number_font, l.diff ? LtBlue() : SColorText()); + int n_width = show_line_number ? number_width : 0; + if(show_line_number) { + for(int i = first_line; i <= last_line; i++) { + const Line& l = lines[i]; + int y = i * letter.cy - offset.cy; + Color paper = IsNull(l.number) ? LtGray() : l.diff ? l.left ? Blend(LtRed(), White(), 230) : Blend(LtGreen(), White(), 230) : SColorPaper(); + Color ink = l.diff ? l.left ? Red(): Green() : Gray(); + draw.DrawRect(0, y, n_width, letter.cy, paper); + draw.DrawRect(n_width - 1, y, 1, letter.cy, Gray()); + if(!IsNull(l.number)) + draw.DrawText(0, y + number_yshift, FormatInt(l.number_diff), number_font, ink); + } } - draw.Clip(number_width, 0, sz.cx - gutter_width - number_width, sz.cy); + draw.Clip(n_width, 0, sz.cx - gutter_width - n_width, sz.cy); + int sell, selh; GetSelection(sell, selh); for(int i = first_line; i <= last_line; i++) { const Line& l = lines[i]; int y = i * letter.cy - offset.cy; Color ink = SColorText(); - Color paper = IsNull(l.number) ? SGray() : l.diff ? SColorInfo() : SColorPaper(); + Color paper = IsNull(l.number) ? LtGray() : l.diff ? l.left ? Blend(LtRed(), White(), 230) : Blend(LtGreen(), White(), 230) : SColorPaper(); bool sel = l.number >= sell && l.number <= selh; if(sel) { ink = SColorHighlightText; paper = SColorHighlight; } draw.DrawRect(0, y, sz.cx, letter.cy, paper); + WString ln = l.text.ToWString(); if(ln.GetCount() > 20000) ln.Trim(20000); @@ -247,24 +259,66 @@ void TextCompareCtrl::Paint(Draw& draw) h.chr = ln[i]; h.font = StdFont(); } - if(!sel) + + if(!sel) { WhenHighlight(hln, ln); + + WString ln_diff = l.text_diff.ToWString(); + ln_diff = ExpandTabs(ln_diff); + + int diff_start = -1, diff_end = -1; + for(int i = 0; i < ln.GetCount(); ++i) { + LineEdit::Highlight& h = hln[i]; + if (change_paper_color) + h.paper = paper; + if(show_diff_highlight + && (diff_start == -1) + && (i < ln_diff.GetCount() && (h.chr != ln_diff[i]))) + diff_start = i; + } + if(show_diff_highlight && (diff_start >= 0)) { + for(int i = ln.GetCount(), j = ln_diff.GetCount(); i >= 0 && j >=0; --i, --j) { + if(ln[i] != ln_diff[j]) { + diff_end = i; + break; + } + } + for(int i = diff_start; i <= diff_end; ++i) { + LineEdit::Highlight& h = hln[i]; + h.paper = l.left ? Blend(LtRed(), White(), 192) : Blend(LtGreen(), White(), 128); + } + } + if(show_white_space) { + for(int i = ln.GetCount(); i >= 0; --i) { + LineEdit::Highlight& h = hln[i]; + if (ln[i] == 0) + continue; + if(ln[i] == 32) + h.paper = l.left ? Red() : Green(); + else + break; + } + } + } + int x = 0; int a = StdFont().GetAscent(); - for(int i = 0; i < hln.GetCount(); i++) { + for(int i = 0; i < hln.GetCount() - 1; ++i) { Font fnt = font; LineEdit::Highlight& h = hln[i]; fnt.Bold(h.font.IsBold()); fnt.Italic(h.font.IsItalic()); fnt.Underline(h.font.IsUnderline()); - draw.DrawText(number_width - offset.cx + x, y + a - fnt.GetAscent(), &h.chr, fnt, h.ink, 1); - x += font[h.chr]; + int width = fnt[h.chr]; + draw.DrawRect(n_width - offset.cx + x, y, width, fnt.GetCy(), h.paper); + draw.DrawText(n_width - offset.cx + x, y, &h.chr, fnt, h.ink, 1); + x += width; } } int lcy = lcnt * letter.cy - offset.cy; draw.DrawRect(0, lcy, sz.cx, sz.cy - lcy, SGray()); draw.End(); - draw.DrawRect(0, lcy, number_width, sz.cy - lcy, number_bg); + draw.DrawRect(0, lcy, n_width, sz.cy - lcy, number_bg); } void TextCompareCtrl::TabSize(int t) @@ -294,7 +348,9 @@ void TextCompareCtrl::SetFont(Font f) void TextCompareCtrl::Layout() { - scroll.Set(scroll, (scroll.GetReducedViewSize() - Size(number_width + gutter_width, 0)) / letter, Size(maxwidth, lines.GetCount())); + int n_width = show_line_number ? number_width : 0; + + scroll.Set(scroll, (scroll.GetReducedViewSize() - Size(n_width + gutter_width, 0)) / letter, Size(maxwidth, lines.GetCount())); Refresh(); } @@ -318,7 +374,7 @@ void TextCompareCtrl::AddCount(int c) Layout(); } -void TextCompareCtrl::Set(int line, String text, bool diff, int number, int level) +void TextCompareCtrl::Set(int line, String text, bool diff, int number, int level, String text_diff, int number_diff, bool left) { Line& l = lines.At(line); int tl = MeasureLength(text.ToWString()); @@ -328,6 +384,9 @@ void TextCompareCtrl::Set(int line, String text, bool diff, int number, int leve l.text = text; l.diff = diff; l.level = level; + l.text_diff = text_diff; + l.number_diff = number_diff; + l.left = left; if(rl) UpdateWidth(); else if(tl > maxwidth) { diff --git a/uppsrc/TextDiffCtrl/TextDiff.cpp b/uppsrc/TextDiffCtrl/TextDiff.cpp index db3cf75d2..ac8c3a14b 100644 --- a/uppsrc/TextDiffCtrl/TextDiff.cpp +++ b/uppsrc/TextDiffCtrl/TextDiff.cpp @@ -22,7 +22,7 @@ Vector GetLineMap(Stream& stream) while(!stream.IsEof()) { String s = stream.GetLine(); const char *p = s, *e = s.End(), *f = e; - while(e > p && (byte)e[-1] <= ' ') + while(e > p && (byte)e[-1] != 9 && (byte)e[-1] < ' ') e--; if(e == p) emp++; diff --git a/uppsrc/TextDiffCtrl/TextDiffCtrl.h b/uppsrc/TextDiffCtrl/TextDiffCtrl.h index 3d62b7be2..834211a67 100644 --- a/uppsrc/TextDiffCtrl/TextDiffCtrl.h +++ b/uppsrc/TextDiffCtrl/TextDiffCtrl.h @@ -1,232 +1,258 @@ -#ifndef _TextDiffCtrl_TextDiffCtrl_h -#define _TextDiffCtrl_TextDiffCtrl_h - -#include - -namespace Upp { - -#define IMAGECLASS DiffImg -#define IMAGEFILE -#include - -class TextSection -{ -public: - TextSection(int start1, int count1, int start2, int count2, bool same) - : start1(start1), count1(count1), start2(start2), count2(count2), same(same) {} - -public: - int start1; - int count1; - int start2; - int count2 : 31; - unsigned same : 1; -}; - -Array CompareLineMaps(const Vector& l1, const Vector& l2); -Vector GetLineMap(Stream& stream); -Vector GetFileLineMap(const String& path); -Vector GetStringLineMap(const String &s); - -class TextCompareCtrl : public Ctrl { -public: - virtual void Paint(Draw& draw); - virtual void Layout(); - virtual void MouseWheel(Point pt, int zdelta, dword keyflags); - virtual void MouseMove(Point pt, dword keyflags); - virtual void LeftDown(Point pt, dword keyflags); - virtual void LeftDouble(Point pt, dword keyflags); - virtual void LeftUp(Point pt, dword keyflags); - virtual void RightDown(Point p, dword keyflags); - virtual bool Key(dword key, int repcnt); - -private: - void SelfScroll(); - void PairScroll(TextCompareCtrl *ctrl); - void UpdateWidth(); - WString ExpandTabs(const wchar *line) const; - int MeasureLength(const wchar *line) const; - bool GetSelection(int& l, int& h); - void DoSelection(int y, bool shift); - void Copy(); - int GetLineNo(int y, int& yy); - -private: - struct Line { - Line() : number(Null), level(0) {} - int number; - bool diff; - String text; - int level; - }; - Array lines; - int maxwidth; - ScrollBars scroll; - Font font; - Font number_font; - Color number_bg; - Color gutter_fg; - Color gutter_bg; - Size letter; - int tabsize; - int number_width; - int number_yshift; - int gutter_width; - int cursor; - int anchor; - bool gutter_capture; - - typedef TextCompareCtrl CLASSNAME; - -public: - Event<> WhenScroll; - Event WhenLeftDouble; - Event&, const WString&> WhenHighlight; - - void SetCount(int c); - void AddCount(int c); - int GetCount() const { return lines.GetCount(); } - - void SetFont(Font f, Font nf); - void SetFont(Font f); - Font GetFont() const { return font; } - Font GetNumberFont() const { return number_font; } - - void NumberBgColor(Color bg) { number_bg = bg; Refresh(); } - Color GetNumberBgColor() const { return number_bg; } - - void ShowSb(bool ssb) { scroll.ShowY(ssb); } - void HideSb() { ShowSb(false); } - - void Gutter(int size) { gutter_width = size; Refresh(); } - void NoGutter() { gutter_width = 0; Refresh(); } - - void TabSize(int t); - int GetTabSize() const { return tabsize; } - - void Set(int line, String text, bool diff, int number, int level); - String GetText(int line) const { return lines[line].text; } - bool GetDiff(int line) const { return lines[line].diff; } - int GetNumber(int line) const { return lines[line].number; } - - Point GetPos() const; - void SetPos(Point pos); - - int GetSb() const { return scroll.Get().y; } - void SetSb(int y) { scroll.Set(0, y); } - - void ClearSelection() { cursor = Null; Refresh(); } - void SetSelection(int l, int h) { cursor = l; anchor = h; } - - Event<> ScrollWhen(TextCompareCtrl& pair) { return THISBACK1(PairScroll, &pair); } - - TextCompareCtrl(); -}; - -struct TextDiffCtrl : public Splitter { - TextCompareCtrl left; - TextCompareCtrl right; - - void Set(Stream& l, Stream& r); - void Set(const String& l, const String& r); - void InsertFrameLeft(CtrlFrame& f) { left.InsertFrame(0, f); } - void InsertFrameRight(CtrlFrame& f) { right.InsertFrame(0, f); } - void AddFrameLeft(CtrlFrame& f) { left.AddFrame(f); } - void AddFrameRight(CtrlFrame& f) { right.AddFrame(f); } - void SetFont(Font f, Font nf) { left.SetFont(f, nf); right.SetFont(f, nf); } - void SetFont(Font f) { left.SetFont(f); right.SetFont(f); } - - Event WhenLeftLine; - Event WhenRightLine; - - TextDiffCtrl(); -}; - -struct DiffDlg : public TopWindow { - TextDiffCtrl diff; - FrameTop p; - DataPusher l; - Button write; - String editfile; - String extfile; - - typedef DiffDlg CLASSNAME; - - void Write(); - void Execute(const String& f); - - static Event&, const WString&> WhenHighlight; - - DiffDlg(); -}; - -FileSel& DiffFs(); - -struct FileDiff : DiffDlg { - FrameTop r; - - virtual void Open(); - void Execute(const String& f); - - typedef FileDiff CLASSNAME; - - String GetExtPath() const { return ~r; } - - FileDiff(FileSel& fs); - - FileSel& fs; -}; - -struct PatchDiff : FileDiff { - PatchDiff(FileSel& fs) : FileDiff(fs) {} - - virtual void Open(); - - void Copy(FileIn& in, FileIn& oin, int& l, int ln, int n); - void LoadDiff(const char *fn); -}; - -class DirDiffDlg : public TopWindow { - Splitter files_diff; - ParentCtrl files_pane; - FileList files; - - SelectDirButton seldir1; - WithDropChoice dir1; - SelectDirButton seldir2; - WithDropChoice dir2; - Option hidden; - Button compare; - Label info; - - FrameTop left, right; - EditString lfile, rfile; - Button copyleft, copyright; - - void GatherFilesDeep(Index& files, const String& base, const String& path); - void Compare(); - void ClearFiles(); - void File(); - void Copy(bool left); - -public: - TextDiffCtrl diff; - - typedef DirDiffDlg CLASSNAME; - - void SetFont(Font fnt) { diff.SetFont(fnt); } - void Dir1(const String& dir) { dir1 <<= dir; } - void Dir2(const String& dir) { dir2 <<= dir; } - void Dir1AddList(const String& dir) { dir1.AddList(dir); } - void Dir2AddList(const String& dir) { dir2.AddList(dir); } - - String GetLeftFile() const { return ~lfile; } - String GetRightFile() const { return ~rfile; } - - DirDiffDlg(); -}; - - -}; - -#endif +#ifndef _TextDiffCtrl_TextDiffCtrl_h +#define _TextDiffCtrl_TextDiffCtrl_h + +#include + +namespace Upp { + +#define IMAGECLASS DiffImg +#define IMAGEFILE +#include + +class TextSection +{ +public: + TextSection(int start1, int count1, int start2, int count2, bool same) + : start1(start1), count1(count1), start2(start2), count2(count2), same(same) {} + +public: + int start1; + int count1; + int start2; + int count2 : 31; + unsigned same : 1; +}; + +Array CompareLineMaps(const Vector& l1, const Vector& l2); +Vector GetLineMap(Stream& stream); +Vector GetFileLineMap(const String& path); +Vector GetStringLineMap(const String &s); + +class TextCompareCtrl : public Ctrl { +public: + virtual void Paint(Draw& draw); + virtual void Layout(); + virtual void MouseWheel(Point pt, int zdelta, dword keyflags); + virtual void MouseMove(Point pt, dword keyflags); + virtual void LeftDown(Point pt, dword keyflags); + virtual void LeftDouble(Point pt, dword keyflags); + virtual void LeftUp(Point pt, dword keyflags); + virtual void RightDown(Point p, dword keyflags); + virtual bool Key(dword key, int repcnt); + +private: + void SelfScroll(); + void PairScroll(TextCompareCtrl *ctrl); + void UpdateWidth(); + WString ExpandTabs(const wchar *line) const; + int MeasureLength(const wchar *line) const; + bool GetSelection(int& l, int& h); + void DoSelection(int y, bool shift); + void Copy(); + int GetLineNo(int y, int& yy); + +private: + struct Line { + Line() : number(Null), level(0) {} + int number; + bool diff; + String text; + int level; + String text_diff; + int number_diff; + bool left; + }; + Array lines; + int maxwidth; + ScrollBars scroll; + Font font; + Font number_font; + Color number_bg; + Color gutter_fg; + Color gutter_bg; + Size letter; + int tabsize; + int number_width; + int number_yshift; + int gutter_width; + int cursor; + int anchor; + bool gutter_capture; + bool show_line_number; + bool show_white_space; + bool show_diff_highlight; + bool change_paper_color; + + typedef TextCompareCtrl CLASSNAME; + +public: + Event<> WhenScroll; + Callback2 WhenLeftDouble; + Event&, const WString&> WhenHighlight; + + void SetCount(int c); + void AddCount(int c); + int GetCount() const { return lines.GetCount(); } + + void SetFont(Font f, Font nf); + void SetFont(Font f); + Font GetFont() const { return font; } + Font GetNumberFont() const { return number_font; } + + void NumberBgColor(Color bg) { number_bg = bg; Refresh(); } + Color GetNumberBgColor() const { return number_bg; } + + void AutoHideSb(bool ssb=true){ scroll.AutoHide(ssb); } + void ShowSb(bool ssb) { scroll.ShowY(ssb); } + void HideSb() { ShowSb(false); } + + void Gutter(int size) { gutter_width = size; Refresh(); } + void NoGutter() { gutter_width = 0; Refresh(); } + + void TabSize(int t); + int GetTabSize() const { return tabsize; } + + void Set(int line, String text, bool diff, int number, int level, String text_diff, int number_diff, bool left); + String GetText(int line) const { return lines[line].text; } + bool GetDiff(int line) const { return lines[line].diff; } + int GetNumber(int line) const { return lines[line].number; } + int GetNumberDiff(int line) const { return lines[line].number_diff; } + + Point GetPos() const; + void SetPos(Point pos); + + int GetSb() const { return scroll.Get().y; } + void SetSb(int y) { scroll.Set(0, y); } + + void ClearSelection() { cursor = Null; Refresh(); } + void SetSelection(int l, int h) { cursor = l; anchor = h; } + + void ShowLineNumber(bool sln) { show_line_number = sln; Refresh(); } + void HideLineNumber() { ShowLineNumber(false); } + + void ShowWhiteSpace(bool sws) { show_white_space = sws; Refresh(); } + void HideWhiteSpace() { ShowWhiteSpace(false); } + + void DiffHighlight(bool dh) { show_diff_highlight = dh; Refresh(); } + void NoDiffHighlight() { DiffHighlight(false); } + + void ChangePaperColor(bool cpc) { change_paper_color = cpc; Refresh(); } + void NoChangePaperColor() { ChangePaperColor(false); } + + Event<> ScrollWhen(TextCompareCtrl& pair) { return THISBACK1(PairScroll, &pair); } + + TextCompareCtrl(); +}; + +struct TextDiffCtrl : public Splitter { + TextCompareCtrl left; + TextCompareCtrl right; + + typedef TextDiffCtrl CLASSNAME; + + void Set(Stream& l, Stream& r); + void Set(const String& l, const String& r); + void InsertFrameLeft(CtrlFrame& f) { left.InsertFrame(0, f); } + void InsertFrameRight(CtrlFrame& f) { right.InsertFrame(0, f); } + void AddFrameLeft(CtrlFrame& f) { left.AddFrame(f); } + void AddFrameRight(CtrlFrame& f) { right.AddFrame(f); } + void SetFont(Font f, Font nf) { left.SetFont(f, nf); right.SetFont(f, nf); } + void SetFont(Font f) { left.SetFont(f); right.SetFont(f); } + + void GetLeftLine(int number, int line); + void GetRightLine(int number, int line); + + Callback1 WhenLeftLine; + Callback1 WhenRightLine; + + TextDiffCtrl(); +}; + +struct DiffDlg : public TopWindow { + TextDiffCtrl diff; + FrameTop p; + DataPusher l; + Button write; + String editfile; + String extfile; + + typedef DiffDlg CLASSNAME; + + void Write(); + void Execute(const String& f); + + static Event&, const WString&> WhenHighlight; + + DiffDlg(); +}; + +FileSel& DiffFs(); + +struct FileDiff : DiffDlg { + FrameTop r; + + virtual void Open(); + void Execute(const String& f); + + typedef FileDiff CLASSNAME; + + String GetExtPath() const { return ~r; } + + FileDiff(FileSel& fs); + + FileSel& fs; +}; + +struct PatchDiff : FileDiff { + PatchDiff(FileSel& fs) : FileDiff(fs) {} + + virtual void Open(); + + void Copy(FileIn& in, FileIn& oin, int& l, int ln, int n); + void LoadDiff(const char *fn); +}; + +class DirDiffDlg : public TopWindow { + Splitter files_diff; + ParentCtrl files_pane; + FileList files; + + SelectDirButton seldir1; + WithDropChoice dir1; + SelectDirButton seldir2; + WithDropChoice dir2; + Option hidden; + Button compare; + Label info; + + FrameTop left, right; + EditString lfile, rfile; + Button copyleft, copyright; + + void GatherFilesDeep(Index& files, const String& base, const String& path); + void Compare(); + void ClearFiles(); + void File(); + void Copy(bool left); + +public: + TextDiffCtrl diff; + + typedef DirDiffDlg CLASSNAME; + + void SetFont(Font fnt) { diff.SetFont(fnt); } + void Dir1(const String& dir) { dir1 <<= dir; } + void Dir2(const String& dir) { dir2 <<= dir; } + void Dir1AddList(const String& dir) { dir1.AddList(dir); } + void Dir2AddList(const String& dir) { dir2.AddList(dir); } + + String GetLeftFile() const { return ~lfile; } + String GetRightFile() const { return ~rfile; } + + DirDiffDlg(); +}; + + +}; + +#endif