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