mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-08-29 06:12:59 -06:00
TextDiffCtrl: Line differences now shown (thanks Coolman)
git-svn-id: svn://ultimatepp.org/upp/trunk@10553 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
parent
a1d9192520
commit
6d6bc38d15
4 changed files with 527 additions and 432 deletions
|
|
@ -1,182 +1,192 @@
|
|||
#include "TextDiffCtrl.h"
|
||||
|
||||
namespace Upp {
|
||||
|
||||
#define IMAGECLASS DiffImg
|
||||
#define IMAGEFILE <TextDiffCtrl/Diff.iml>
|
||||
#include <Draw/iml_source.h>
|
||||
|
||||
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<String> ll = GetLineMap(l);
|
||||
Vector<String> rl = GetLineMap(r);
|
||||
Array<TextSection> 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 String&, Vector<LineEdit::Highlight>&, const WString&> DiffDlg::WhenHighlight;
|
||||
|
||||
static void sDoHighlight(Vector<LineEdit::Highlight>& 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 <TextDiffCtrl/Diff.iml>
|
||||
#include <Draw/iml_source.h>
|
||||
|
||||
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<String> ll = GetLineMap(l);
|
||||
Vector<String> rl = GetLineMap(r);
|
||||
Array<TextSection> 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 String&, Vector<LineEdit::Highlight>&, const WString&> DiffDlg::WhenHighlight;
|
||||
|
||||
static void sDoHighlight(Vector<LineEdit::Highlight>& 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;
|
||||
}
|
||||
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ Vector<String> 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++;
|
||||
|
|
|
|||
|
|
@ -1,232 +1,258 @@
|
|||
#ifndef _TextDiffCtrl_TextDiffCtrl_h
|
||||
#define _TextDiffCtrl_TextDiffCtrl_h
|
||||
|
||||
#include <CtrlLib/CtrlLib.h>
|
||||
|
||||
namespace Upp {
|
||||
|
||||
#define IMAGECLASS DiffImg
|
||||
#define IMAGEFILE <TextDiffCtrl/Diff.iml>
|
||||
#include <Draw/iml_header.h>
|
||||
|
||||
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<TextSection> CompareLineMaps(const Vector<String>& l1, const Vector<String>& l2);
|
||||
Vector<String> GetLineMap(Stream& stream);
|
||||
Vector<String> GetFileLineMap(const String& path);
|
||||
Vector<String> 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<Line> 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<int> WhenLeftDouble;
|
||||
Event<Vector<LineEdit::Highlight>&, 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<int> WhenLeftLine;
|
||||
Event<int> WhenRightLine;
|
||||
|
||||
TextDiffCtrl();
|
||||
};
|
||||
|
||||
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);
|
||||
|
||||
static Event<const String&, Vector<LineEdit::Highlight>&, const WString&> WhenHighlight;
|
||||
|
||||
DiffDlg();
|
||||
};
|
||||
|
||||
FileSel& DiffFs();
|
||||
|
||||
struct FileDiff : DiffDlg {
|
||||
FrameTop<DataPusher> 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<EditString> dir1;
|
||||
SelectDirButton seldir2;
|
||||
WithDropChoice<EditString> dir2;
|
||||
Option hidden;
|
||||
Button compare;
|
||||
Label info;
|
||||
|
||||
FrameTop<ParentCtrl> left, right;
|
||||
EditString lfile, rfile;
|
||||
Button copyleft, copyright;
|
||||
|
||||
void GatherFilesDeep(Index<String>& 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 <CtrlLib/CtrlLib.h>
|
||||
|
||||
namespace Upp {
|
||||
|
||||
#define IMAGECLASS DiffImg
|
||||
#define IMAGEFILE <TextDiffCtrl/Diff.iml>
|
||||
#include <Draw/iml_header.h>
|
||||
|
||||
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<TextSection> CompareLineMaps(const Vector<String>& l1, const Vector<String>& l2);
|
||||
Vector<String> GetLineMap(Stream& stream);
|
||||
Vector<String> GetFileLineMap(const String& path);
|
||||
Vector<String> 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<Line> 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<int, int> WhenLeftDouble;
|
||||
Event<Vector<LineEdit::Highlight>&, 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<int> WhenLeftLine;
|
||||
Callback1<int> WhenRightLine;
|
||||
|
||||
TextDiffCtrl();
|
||||
};
|
||||
|
||||
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);
|
||||
|
||||
static Event<const String&, Vector<LineEdit::Highlight>&, const WString&> WhenHighlight;
|
||||
|
||||
DiffDlg();
|
||||
};
|
||||
|
||||
FileSel& DiffFs();
|
||||
|
||||
struct FileDiff : DiffDlg {
|
||||
FrameTop<DataPusher> 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<EditString> dir1;
|
||||
SelectDirButton seldir2;
|
||||
WithDropChoice<EditString> dir2;
|
||||
Option hidden;
|
||||
Button compare;
|
||||
Label info;
|
||||
|
||||
FrameTop<ParentCtrl> left, right;
|
||||
EditString lfile, rfile;
|
||||
Button copyleft, copyright;
|
||||
|
||||
void GatherFilesDeep(Index<String>& 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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue