1 #ifndef _TextDiffCtrl_TextDiffCtrl_h
2 #define _TextDiffCtrl_TextDiffCtrl_h
3 
4 #include <CtrlLib/CtrlLib.h>
5 
6 namespace Upp {
7 
8 #define IMAGECLASS DiffImg
9 #define IMAGEFILE <TextDiffCtrl/Diff.iml>
10 #include <Draw/iml_header.h>
11 
12 class TextSection
13 {
14 public:
TextSection(int start1,int count1,int start2,int count2,bool same)15 	TextSection(int start1, int count1, int start2, int count2, bool same)
16 		: start1(start1), count1(count1), start2(start2), count2(count2), same(same) {}
17 
18 public:
19 	int      start1;
20 	int      count1;
21 	int      start2;
22 	int      count2 : 31;
23 	unsigned same   : 1;
24 };
25 
26 Array<TextSection> CompareLineMaps(const Vector<String>& l1, const Vector<String>& l2);
27 Vector<String>     GetLineMap(Stream& stream);
28 Vector<String>     GetFileLineMap(const String& path);
29 Vector<String>     GetStringLineMap(const String &s);
30 
31 class TextCompareCtrl : public Ctrl {
32 public:
33 	virtual void   Paint(Draw& draw);
34 	virtual void   Layout();
35 	virtual void   MouseWheel(Point pt, int zdelta, dword keyflags);
36 	virtual void   MouseMove(Point pt, dword keyflags);
37 	virtual void   LeftDown(Point pt, dword keyflags);
38 	virtual void   LeftDouble(Point pt, dword keyflags);
39 	virtual void   LeftUp(Point pt, dword keyflags);
40 	virtual void   RightDown(Point p, dword keyflags);
41 	virtual bool   Key(dword key, int repcnt);
42 
43 private:
44 	void           SelfScroll();
45 	void           PairScroll(TextCompareCtrl *ctrl);
46 	void           UpdateWidth();
47 	WString        ExpandTabs(const wchar *line) const;
48 	int            MeasureLength(const wchar *line) const;
49 	bool           GetSelection(int& l, int& h);
50 	void           DoSelection(int y, bool shift);
51 	void           Copy();
52 	int            GetLineNo(int y, int& yy);
53 	int            GetMatchLen(const wchar *s1, const wchar *s2, int len);
54 	bool           LineDiff(bool left, Vector<LineEdit::Highlight>& hln, Color eq_color,
55 	                        const wchar *s1, int l1, int h1,
56 	                        const wchar *s2, int l2, int h2, int depth);
57 
58 private:
59 	struct Line {
LineLine60 		Line() : number(Null), level(0) {}
61 		int    number;
62 		bool   diff;
63 		String text;
64 		int    level;
65 		String text_diff;
66 		int    number_diff;
67 	};
68 	Array<Line>    lines;
69 	int            maxwidth;
70 	ScrollBars     scroll;
71 	Font           font;
72 	Font           number_font;
73 	Color          number_bg;
74 	Color          gutter_fg;
75 	Color          gutter_bg;
76 	Size           letter;
77 	int            tabsize;
78 	int            number_width;
79 	int            number_yshift;
80 	int            gutter_width;
81 	int            cursor;
82 	int            anchor;
83 	bool           gutter_capture;
84 	bool           show_line_number;
85 	bool           show_white_space;
86 	bool           show_diff_highlight;
87 	bool           change_paper_color;
88 	bool           left = false;
89 
90 	typedef TextCompareCtrl CLASSNAME;
91 
92 public:
93 	Event<>        WhenScroll;
94 	Callback2<int, int> WhenLeftDouble;
95 	Event<Vector<LineEdit::Highlight>&, const WString&> WhenHighlight;
96 
97 	void           SetCount(int c);
98 	void           AddCount(int c);
GetCount()99 	int            GetCount() const { return lines.GetCount(); }
100 
101 	void           SetFont(Font f, Font nf);
102 	void           SetFont(Font f);
GetFont()103 	Font           GetFont() const { return font; }
GetNumberFont()104 	Font           GetNumberFont() const { return number_font; }
105 
NumberBgColor(Color bg)106 	void           NumberBgColor(Color bg)  { number_bg = bg; Refresh(); }
GetNumberBgColor()107 	Color          GetNumberBgColor() const { return number_bg; }
108 
109 	void           AutoHideSb(bool ssb=true){ scroll.AutoHide(ssb); }
ShowSb(bool ssb)110 	void           ShowSb(bool ssb)         { scroll.ShowY(ssb); }
HideSb()111 	void           HideSb()                 { ShowSb(false); }
112 
Gutter(int size)113 	void           Gutter(int size)         { gutter_width = size; Refresh(); }
NoGutter()114 	void           NoGutter()               { gutter_width = 0; Refresh(); }
115 
116 	void           TabSize(int t);
GetTabSize()117 	int            GetTabSize() const { return tabsize; }
118 
119 	void           Set(int line, String text, bool diff, int number, int level, String text_diff, int number_diff);
GetText(int line)120 	String         GetText(int line) const { return lines[line].text; }
GetDiff(int line)121 	bool           GetDiff(int line) const { return lines[line].diff; }
GetNumber(int line)122 	int            GetNumber(int line) const { return lines[line].number; }
GetNumberDiff(int line)123 	int            GetNumberDiff(int line) const { return lines[line].number_diff; }
124 
125 	Point          GetPos() const;
126 	void           SetPos(Point pos);
127 
GetSb()128 	int            GetSb() const { return scroll.Get().y; }
SetSb(int y)129 	void           SetSb(int y)  { scroll.Set(0, y); }
130 
ClearSelection()131 	void           ClearSelection()           { cursor = Null; Refresh(); }
SetSelection(int l,int h)132 	void           SetSelection(int l, int h) { cursor = l; anchor = h; }
133 
ShowLineNumber(bool sln)134 	void           ShowLineNumber(bool sln)   { show_line_number = sln; Refresh(); }
HideLineNumber()135 	void           HideLineNumber()           { ShowLineNumber(false); }
136 
ShowWhiteSpace(bool sws)137 	void           ShowWhiteSpace(bool sws)   { show_white_space = sws; Refresh(); }
HideWhiteSpace()138 	void           HideWhiteSpace()           { ShowWhiteSpace(false); }
139 
DiffHighlight(bool dh)140 	void           DiffHighlight(bool dh)     { show_diff_highlight = dh; Refresh(); }
NoDiffHighlight()141 	void           NoDiffHighlight()          { DiffHighlight(false); }
142 
ChangePaperColor(bool cpc)143 	void           ChangePaperColor(bool cpc) { change_paper_color = cpc; Refresh(); }
NoChangePaperColor()144 	void           NoChangePaperColor()       { ChangePaperColor(false); }
145 
SetLeft()146 	void           SetLeft()                  { left = true; }
147 
ScrollWhen(TextCompareCtrl & pair)148 	Event<>        ScrollWhen(TextCompareCtrl& pair) { return THISBACK1(PairScroll, &pair); }
149 
150 	TextCompareCtrl();
151 };
152 
153 struct TextDiffCtrl : public Splitter {
154 	TextCompareCtrl left;
155 	TextCompareCtrl right;
156 
157 	typedef TextDiffCtrl CLASSNAME;
158 
159 	void Set(Stream& l, Stream& r);
160 	void Set(const String& l, const String& r);
InsertFrameLeftTextDiffCtrl161 	void InsertFrameLeft(CtrlFrame& f)                     { left.InsertFrame(0, f); }
InsertFrameRightTextDiffCtrl162 	void InsertFrameRight(CtrlFrame& f)                    { right.InsertFrame(0, f); }
AddFrameLeftTextDiffCtrl163 	void AddFrameLeft(CtrlFrame& f)                        { left.AddFrame(f); }
AddFrameRightTextDiffCtrl164 	void AddFrameRight(CtrlFrame& f)                       { right.AddFrame(f); }
SetFontTextDiffCtrl165 	void SetFont(Font f, Font nf)                          { left.SetFont(f, nf); right.SetFont(f, nf); }
SetFontTextDiffCtrl166 	void SetFont(Font f)                                   { left.SetFont(f); right.SetFont(f); }
167 
168 	void GetLeftLine(int number, int line);
169 	void GetRightLine(int number, int line);
170 
171 	Callback1<int> WhenLeftLine;
172 	Callback1<int> WhenRightLine;
173 
174 	TextDiffCtrl();
175 };
176 
177 struct DiffDlg : public TopWindow {
178 	TextDiffCtrl         diff;
179 	FrameTop<StaticRect> p;
180 	DataPusher           l;
181 	Button               write;
182 	String               editfile;
183 	String               extfile;
184 
185 	typedef DiffDlg CLASSNAME;
186 
187 	void Write();
188 	void Execute(const String& f);
189 
190 	static Event<const String&, Vector<LineEdit::Highlight>&, const WString&> WhenHighlight;
191 
192 	DiffDlg();
193 };
194 
195 FileSel& DiffFs();
196 
197 struct FileDiff : DiffDlg {
198 	FrameTop<DataPusher> r;
199 
200 	virtual void Open();
201 	void Execute(const String& f);
202 
203 	typedef FileDiff CLASSNAME;
204 
GetExtPathFileDiff205 	String GetExtPath() const { return ~r; }
206 
207 	FileDiff(FileSel& fs);
208 
209 	FileSel& fs;
210 
211 	void Execute(const String& lpath, const String& rpath);
212 };
213 
214 class DirDiffDlg : public TopWindow {
215 public:
216 	virtual bool HotKey(dword key);
217 
218 private:
219 	Splitter                   files_diff;
220 	ParentCtrl                 files_pane;
221 	FileList                   files;
222 
223 	SelectDirButton            seldir1;
224 	WithDropChoice<EditString> dir1;
225 	SelectDirButton            seldir2;
226 	WithDropChoice<EditString> dir2;
227 	Option                     hidden;
228 	Button                     compare;
229 	Label                      info;
230 
231 	Option                     removed, added, modified;
232 	EditString				   find;
233 	Button					   clearFind;
234 
235 	FrameTop<ParentCtrl>       left, right;
236 	EditString                 lfile, rfile;
237 	Button                     copyleft, copyright;
238 
239 	enum { NORMAL_FILE, DELETED_FILE, NEW_FILE, FAILED_FILE, PATCHED_FILE };
240 
241 	Array<Tuple<String, String, String, int>> list;
242 
243 	static bool FileEqual(const String& f1, const String& f2, int& n);
244 
245 	void GatherFilesDeep(Index<String>& files, const String& base, const String& path);
246 	void Compare();
247 	void ShowResult();
248 	void ClearFiles();
249 	void File();
250 	void Copy(bool left);
251 	FileList::File MakeFile(int i);
252 
253 	friend class PatchDiff;
254 
255 public:
256 	Function<Image(const char *path)> WhenIcon;
257 
258 	TextDiffCtrl               diff;
259 
260 	typedef DirDiffDlg CLASSNAME;
261 
SetFont(Font fnt)262 	void SetFont(Font fnt)                      { diff.SetFont(fnt); }
Dir1(const String & dir)263 	void Dir1(const String& dir)                { dir1 <<= dir; }
Dir2(const String & dir)264 	void Dir2(const String& dir)                { dir2 <<= dir; }
Dir1AddList(const String & dir)265 	void Dir1AddList(const String& dir)         { dir1.AddList(dir); }
Dir2AddList(const String & dir)266 	void Dir2AddList(const String& dir)         { dir2.AddList(dir); }
267 
GetLeftFile()268 	String GetLeftFile() const                  { return ~lfile; }
GetRightFile()269 	String GetRightFile() const                 { return ~rfile; }
270 
271 	DirDiffDlg();
272 };
273 
274 struct Patch {
275 	struct Chunk {
276 		int            line;
277 		Vector<String> orig;
278 		Vector<String> patch;
279 		String         src;
280 	};
281 
282 	VectorMap<String, Array<Chunk>> file;
283 	String  common_path;
284 	String  target_dir;
285 
286 	static int MatchLen(const String& a, const String& b);
287 	int        MatchCount(const char *dir);
288 	bool       Load0(Stream& in, Progress& pi);
289 
290 public:
291 	bool Load(Stream& in, Progress& pi);
292 	bool Load(const char *fn, Progress& pi);
293 	bool MatchFiles(const Vector<String>& dir, Progress& pi);
SetTargetDirPatch294 	void SetTargetDir(const char *dir) { target_dir = AppendFileName(dir, common_path); }
295 
GetCountPatch296 	int    GetCount() const            { return file.GetCount(); }
GetTargetDirPatch297 	String GetTargetDir() const        { return target_dir; }
GetFilePatch298 	String GetFile(int i) const        { return file.GetKey(i); }
GetPathPatch299 	String GetPath(int i) const        { return AppendFileName(target_dir, file.GetKey(i)); }
300 	String GetPatch(int i) const;
301 	String GetPatchedFile(int i) const;
302 };
303 
304 class PatchDiff : public DirDiffDlg {
305 	Patch  patch;
306 	String file_path;
307 	String patched_file;
308 
309 	EditString patch_file;
310 	EditString target_dir;
311 	Label      failed;
312 
313 	OpenFileButton  selfile;
314 	SelectDirButton seldir;
315 
316 	int             failed_count = 0;
317 
318 	void File();
319 	int  GetFileIndex() const;
320 
321 public:
322 	bool Open(const char *patch_path, const Vector<String>& target_dirs);
323 
324 	PatchDiff();
325 };
326 
327 };
328 
329 #endif
330