The RGDiff project parses the output from a standard command line Diff program and presents the results in a graphical manner. It re-uses the GNU Diff program by "shelling out" using the WIN32 CreateProcess() function.
The techniques used could easily be incorporated into other programs requiring Diff functionality.
This article explains how the above is done in more detail. Running RGDiff
RGDiff needs the GNU WIN32 diff.exe program to be in the same directory as RGDiff.exe. The directory should be writeable as RGDiff needs to create some temporary files.
RGDiff is statically linked with MFC because it is a standalone tool and MFC70.dll is probably not as widely distributed as MFC42.dll. I know this is probably not true among CodeProject members, but just to be on the safe side... Background
Whenever I have used Microsoft's WinDiff, I could not help but be frustrated by its "Zebra Stripes". I have used other GUI Diff tools, and found that a side by side approach helps me understand the differences between the files much better. I had a look around the WWW and couldn't find anything that was free and did what I wanted, I therefore decided to have a go at writing my own.
My first decision was whether to write my own Diff algorithm or rip off somebody else's. I looked at Diff algorithms, the WinDiff code, and the GNU Diff code, and found them all impenetrable in the time I had available :-(
I therefore decided that the only realistic approach for me was to use an existing command line Diff utility as a spawned process, which is a common design pattern on *nix. The GNU Diff utility seemed like a good start, and with programmers like Richard Stallman behind it, I felt that it might take me a while to improve on their algorithms! (A man's gotta know his limitations).
The GNU WIN32 Project provides a compiled diff.exe (and a lot of other useful stuff), and I have included diff.exe as part of both downloads. The above page provides details of how to get the source code if the reader should require that. Techniques Used
This project uses standard WIN32/MFC techniques as follows: Spawn a process and capture the results SDI application with multiple windows Splitter windows Owner draw list boxes Specialized list boxes Registry access Comparing Files
This is where Diff is used to compare 2 files. The command and output will be something like the following:
The lines we are interested in are the ones without < or > signs at the start, as these are simply to help a human see which lines come from which file. The other lines tell us what the differences between the files are, or put another way, what we need to do to either file to make it the same as the other. It is these lines that we parse out and use to build the visual display.
The results above are interpreted as follows: 1,2d0 means delete lines 1-2 of file 1; or, if changing file 2 into file 1, append lines 1-2 of file 1 after line 0 of file 2. 8c6,7 means change line 8 of file 1 to read as lines 6-7 of file 2; or, if changing file 2 into file 1, change lines 6-7 of file 2 to read as line 8 of file 1. 15a15,20 means append lines 15-20 of file 2 after line 15 of file 1; or, if changing file 2 into file 1, delete lines 15-20 of file 2.
The GNU Diff documentation fully describes the way the results should be interpreted. Comparing Directories
Comparing 2 files is good, but being able to recurse sub-directories like WinDiff is better. Luckily diff.exe provides command line options to allow this. The command and output will be something like the following:
C:\Code\DIFF>diff --recursive --report-identical-files --brief dir1 dir2 Files dir1\file1.cpp and dir2\file1.cpp are identical Files dir1\file2.cpp and dir2\file2.cpp differ Only in dir1: file3.cpp Only in dir2: file4.cpp
The command line options are mostly self explanatory, but --brief tells Diff to only summarize each file. If this was omitted, a full Diff report for each file would be produced, taking longer. The above command executes very quickly, although I have only tried it on medium size projects of 200 or so files, with 20 or so sub-directories.
The results are parsed to produce a summary report just like with WinDiff. Double clicking a file then invokes Diff again to compare those 2 files, and a detailed report is displayed the same, as if the user had just chosen to compare those 2 files.
Note that because file names can contain the sequence " and " , some care is required when parsing the results. The Scrolling Views
I have chosen to implement each view as an owner-draw list box. This allows me to customize the display to a great extent and I think they look OK. One problem is that when 2 files are displayed side by side in detail mode, I want them to keep in step when either one is scrolled. I achieve this by capturing all messages and when a scroll message is received, I first send it to the other list box. This works fine but can look a little odd sometimes as one view moves slightly after the other. Future Direction
I am fairly pleased that RGDiff provides a useful, yet minimal implementation without too much effort expended. However the following are a few things that I think could improve RGDiff: Birds eye view in the left margin, like WinDiff Merge functionality (one at a time, or en-masse) Better synchronized scrolling between views, in detail view Better remembering of recently used files, like CodeProject front end to WinDiff History
1.0.0.3 - 3rd March 2003 - Initial Version About Rob Groves
Software developer using C/C++, ASP, .NET and SQL Server/Oracle relational databases.