//--------------------------------------------------------------------
// $Id: vbindiff.cpp 4759 2008-07-26 03:19:24Z cjm $
//--------------------------------------------------------------------
//
// Visual Binary Diff
// Copyright 1995-2008 by Christopher J. Madsen
//
// Visual display of differences in binary files
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of
// the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//--------------------------------------------------------------------
#include "config.h"
#include <ctype.h>
#include <limits.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
#include <iostream>
#include <sstream>
#include <map>
#include <string>
#include <vector>
using namespace std;
#include "GetOpt/GetOpt.hpp"
#include "ConWin.hpp"
#include "FileIO.hpp"
const char titleString[] =
"\nVBinDiff " PACKAGE_VERSION "\nCopyright 1995-2008 Christopher J. Madsen";
void exitMsg(int status, const char* message);
void usage(bool showHelp=true, int exitStatus=0);
//====================================================================
// Type definitions:
typedef unsigned char Byte;
typedef unsigned short Word;
typedef Byte Command;
enum LockState { lockNeither = 0, lockTop, lockBottom };
//--------------------------------------------------------------------
// Strings:
typedef string String;
typedef String::size_type StrIdx;
typedef String::iterator StrItr;
typedef String::const_iterator StrConstItr;
//--------------------------------------------------------------------
// Vectors:
typedef vector<String> StrVec;
typedef StrVec::iterator SVItr;
typedef StrVec::const_iterator SVConstItr;
typedef StrVec::size_type VecSize;
//--------------------------------------------------------------------
// Map:
typedef map<VecSize, String> StrMap;
typedef StrMap::value_type SMVal;
typedef StrMap::iterator SMItr;
typedef StrMap::const_iterator SMConstItr;
//====================================================================
// Constants:
const Command cmmMove = 0x80;
const Command cmmMoveSize = 0x03;
const Command cmmMoveForward = 0x04;
const Command cmmMoveTop = 0x08;
const Command cmmMoveBottom = 0x10;
const Command cmmMoveByte = 0x00; // Move 1 byte
const Command cmmMoveLine = 0x01; // Move 1 line
const Command cmmMovePage = 0x02; // Move 1 page
const Command cmmMoveAll = 0x03; // Move to beginning or end
const Command cmmMoveBoth = cmmMoveTop|cmmMoveBottom;
const Command cmgGoto = 0x04; // Commands 4-7
const Command cmgGotoTop = 0x01;
const Command cmgGotoBottom = 0x02;
const Command cmgGotoBoth = cmgGotoTop|cmgGotoBottom;
const Command cmgGotoMask = ~cmgGotoBoth;
const Command cmNothing = 0;
const Command cmNextDiff = 1;
const Command cmQuit = 2;
const Command cmEditTop = 8;
const Command cmEditBottom = 9;
const Command cmUseTop = 10;
const Command cmUseBottom = 11;
const Command cmToggleASCII = 12;
const Command cmFind = 16; // Commands 16-19
const short leftMar = 11; // Starting column of hex display
const short leftMar2 = 61; // Starting column of ASCII display
const int lineWidth = 16; // Number of bytes displayed per line
const int promptHeight = 4; // Height of prompt window
const int inWidth = 10; // Width of input window (excluding border)
const int screenWidth = 80;
const int maxPath = 260;
const VecSize maxHistory = 2000;
const char hexDigits[] = "0123456789ABCDEF";
#include "tables.h" // ASCII and EBCDIC tables
//====================================================================
// Class Declarations:
void showEditPrompt();
void showPrompt();
class Difference;
union FileBuffer
{
Byte line[1][lineWidth];
Byte buffer[lineWidth];
}; // end FileBuffer
class FileDisplay
{
friend class Difference;
protected:
int bufContents;
FileBuffer* data;
const Difference* diffs;
File file;
char fileName[maxPath];
FPos offset;
ConWindow win;
bool writable;
int yPos;
public:
FileDisplay();
~FileDisplay();
void init(int y, const Difference* aDiff=NULL,
const char* aFileName=NULL);
void resize();
void shutDown();
void display();
bool edit(const FileDisplay* other);
const Byte* getBuffer() const { return data->buffer; };
void move(int step) { moveTo(offset + step); };
void moveTo(FPos newOffset);
bool moveTo(const Byte* searchFor, int searchLen);
void moveToEnd(FileDisplay* other);
bool setFile(const char* aFileName);
protected:
void setByte(short x, short y, Byte b);
}; // end FileDisplay
class Difference
{
friend void FileDisplay::display();
protected:
FileBuffer* data;
const FileDisplay* file1;
const FileDisplay* file2;
int numDiffs;
public:
Difference(const FileDisplay* aFile1, const FileDisplay* aFile2);
~Difference();
int compute();
int getNumDiffs() const { return numDiffs; };
void resize();
}; // end Difference
class InputManager
{
private:
char* buf; // The editing buffer
const char* restrict; // If non-NULL, only allow these chars
StrVec& history; // The history vector to use
StrMap historyOverlay; // Overlay of modified history entries
VecSize historyPos; // The current offset into history[]
int maxLen; // The size of buf (not including NUL)
int len; // The current length of the string
int i; // The current cursor position
bool upcase; // Force all characters to uppercase?
bool splitHex; // Entering space-separated hex bytes?
bool insert; // False for overstrike mode
public:
InputManager(char* aBuf, int aMaxLen, StrVec& aHistory);
bool run();
void setCharacters(const char* aRestriction) { restrict = aRestriction; };
void setSplitHex(bool val) { splitHex = val; };
void setUpcase(bool val) { upcase = val; };
private:
bool normalize(int pos);
void useHistory(int delta);
}; // end InputManager
//====================================================================
// Global Variables:
String lastSearch;
StrVec hexSearchHistory, textSearchHistory, positionHistory;
ConWindow promptWin,inWin;
FileDisplay file1, file2;
Difference diffs(&file1, &file2);
const char* displayTable = asciiDisplayTable;
const char* program_name; // Name under which this program was invoked
LockState lockState = lockNeither;
bool singleFile = false;
int numLines = 9; // Number of lines of each file to display
int bufSize = numLines * lineWidth;
int linesBetween = 1; // Number of lines of padding between files
// The number of bytes to move for each possible step size:
// See cmmMoveByte, cmmMoveLine, cmmMovePage
int steps[4] = {1, lineWidth, bufSize-line