/* ---------------------------------------------------------------------------
This code can be used as you wish but without warranties as to performance
of merchantability or any other warranties whether expressed or implied.
Written by Mike Funduc, Funduc Software Inc. 8/1/96
To download the code and more useful utilities (including Search and
Replace for Windows 95/NT, 3.1x) go to:
http://www.funduc.com
----------------------------------------------------------------------------*/
// hexviewView.cpp : implementation of the CHexviewView class
//
#include "stdafx.h"
#include "hexview.h"
#include "hexviewDoc.h"
#include "hexviewView.h"
#include "gotodlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
extern BOOL bDBCS;
/////////////////////////////////////////////////////////////////////////////
// CHexviewView
IMPLEMENT_DYNCREATE(CHexviewView, CScrollView)
BEGIN_MESSAGE_MAP(CHexviewView, CScrollView)
//{{AFX_MSG_MAP(CHexviewView)
ON_WM_DESTROY()
ON_WM_VSCROLL()
ON_WM_KEYDOWN()
ON_WM_SIZE()
ON_COMMAND(ID_VIEW_NEXTBLOCK, OnViewNextblock)
ON_COMMAND(ID_VIEW_PREVIOUSBLOCK, OnViewPreviousblock)
ON_UPDATE_COMMAND_UI(ID_VIEW_NEXTBLOCK, OnUpdateViewNextblock)
ON_UPDATE_COMMAND_UI(ID_VIEW_PREVIOUSBLOCK, OnUpdateViewPreviousblock)
ON_COMMAND(ID_VIEW_GOTO, OnViewGoto)
//}}AFX_MSG_MAP
// Standard printing commands
ON_COMMAND(ID_FILE_PRINT, CScrollView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_DIRECT, CScrollView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_PREVIEW, CScrollView::OnFilePrintPreview)
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CHexviewView construction/destruction
CHexviewView::CHexviewView()
{
m_cfFixedFont = new(CFont);
if (bDBCS)
m_cfFixedFont->CreateStockObject(SYSTEM_FIXED_FONT);
else
m_cfFixedFont->CreateStockObject(ANSI_FIXED_FONT);
m_cfBoldFont = new CFont;
// try and create the new font for the list box
// it should be the same as the old but without the BOLD weight
LOGFONT oldFont;
m_cfFixedFont->GetObject(sizeof(LOGFONT), &oldFont);
oldFont.lfUnderline = TRUE;
m_cfBoldFont->CreateFontIndirect(&oldFont);
m_cfPrintFont = NULL;
m_cfPrintBoldFont = NULL;
m_iCurrentOffset = 0;
}
CHexviewView::~CHexviewView()
{
delete m_cfBoldFont;
delete m_cfPrintFont;
delete m_cfPrintBoldFont;
}
/////////////////////////////////////////////////////////////////////////////
// CHexviewView drawing
void CHexviewView::OnDraw(CDC* pDC)
{
CHexviewDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
DispData(pDC, m_iFirstLine, pDoc->TotalFileLength(), m_cfFixedFont,
m_cfBoldFont, m_iWndLines, m_iFontHeight, m_iCurrentOffset, m_iFontWidth);
}
void CHexviewView::DispData(CDC* pDC, int iFirstLine, int iTotalLines,
CFont *cfFixedFont, CFont *cfBoldFont,
int iWndLines, int iFontHeight, int iCurrentOffset,
int iFontWidth, int iLine)
{
CFont *pOldFont = pDC->SelectObject(cfFixedFont);
CRect rcWnd;
GetClientRect(&rcWnd);
// compute the start point
int iOffset = iFirstLine * 16 + iCurrentOffset;
int iRemaining = iTotalLines - iOffset;
CHexviewDoc* pDoc = GetDocument();
BYTE *pData = pDoc->AdjustPointerAbsolute(0);
bool bIgnoreThisChar = false;
int x=0;
if (!pData)
{
pDC->TextOut(0, 0, "No data", 7);
}
else
{
char buf[100], buf2[100];
while ((iRemaining > 0) && (iLine < iWndLines))
{
sprintf(buf, "%8.8lX ", iOffset);
BYTE *p = pData + iOffset;
int iCount = iRemaining;
for (int i = 0; i < 16; i++)
{
if (iCount > 0)
{
sprintf(&buf[strlen(buf)],
"%2.2X ",
*p);
}
else
{
strcat(buf, " ");
}
iCount--;
p++;
}
strcat(buf, " ");
p = pData + iOffset;
iCount = iRemaining;
for (i = 0; i < 16; i++)
{
// If bIgnoreThisChar is true, this is that case that last line endded
// with lead byte of double byte char and the value of this tail byte
// is in the range of lead byte. Yuk!
// If this is double byte char, need to deal with it now!
// IsDBCSLeadByte() may return TRUE for tail byte if its value is
// in the range of lead bytes'
if ((bDBCS) && (IsDBCSLeadByte(*p)) && !bIgnoreThisChar)
{
sprintf(&buf[strlen(buf)], "%c%c", *p, *(p + 1));
iCount-=2;
p+=2;
i++;
if (i >= 16)
bIgnoreThisChar = true;
continue;
}
if ((iCount > 0) && isprint(*p) && !bIgnoreThisChar)
{
sprintf(&buf[strlen(buf)], "%c", *p);
}
else if (iCount > 0)
{
strcat(buf, ".");
}
else
{
strcat(buf, " ");
}
bIgnoreThisChar = false;
iCount--;
p++;
}
// Need to blank out rest of this line
// This is to make all lines same length, otherwise, list control will have junk displayed.
#define LINE_LENGTH 78
if ((i = strlen(buf)) < LINE_LENGTH)
{
memset(&buf[i], ' ', LINE_LENGTH-i);
buf[LINE_LENGTH]=0;
}
if ((iOffset + 16 >= pDoc->m_lStartOffset) && (iOffset < pDoc->m_lEndOffset))
{
strcpy(buf2, buf);
CSize szExtent;
int nStartOnLine = max(0, pDoc->m_lStartOffset - iOffset);
int nItemsOnLine = min(pDoc->m_lEndOffset, iOffset + 16) - max(pDoc->m_lStartOffset, iOffset);
// Characters before highlight
pDC->TextOut(0, iLine * iFontHeight, buf, nStartOnLine * 3 + 10);
szExtent = pDC->GetTextExtent(buf, nStartOnLine * 3 + 10);
memcpy(buf, buf2 + nStartOnLine * 3 + 10, (16 - nStartOnLine) * 3 + 2);
buf[(16 - nStartOnLine) * 3 + 2] = 0;
pDC->SelectObject(cfBoldFont);
// Highlight characters
pDC->TextOut(szExtent.cx, iLine * iFontHeight, buf, nItemsOnLine * 3);
szExtent += pDC->GetTextExtent(buf, nItemsOnLine * 3);
pDC->SelectObject(cfFixedFont);
strcpy(buf, buf2 + (nStartOnLine + nItemsOnLine) * 3 + 10);
// Characters after highlight
pDC->TextOut(szExtent.cx, iLine * iFontHeight, buf, strlen(buf));
pDC->MoveTo(0, (iLine + 1) * iFontHeight);
}
else // Just a regular line
pDC->TextOut(0, iLine * iFontHeight, buf, strlen(buf));
iOffset += 16;
iRemaining -= 16;
iLine++;
}
if (iLine < iWndLines)
{
CRect rc = rcWnd;
rc.top = iLine * iFontHeight;
pDC->ExtTextOut(0, iLine * iFontHeight, ETO_OPAQUE,
&rc, "", 0, NULL);
}
}
pDC->SelectObject(pOldFont);
}
void CHexviewView::OnInitialUpdate()
{
CDC *pDC = GetDC();
CFont *pOldFont = pDC->SelectObject(m_cfFixedFont);
pDC->SelectObject(pOldFont);
CHexviewDoc* pDoc = GetDocument();
m_iLastLine = 0;
m_iWndLines = 0;
m_iFirstLine = 0;
CScrollView::OnInitialUpdate();
UpdateScrollSizes();
if (pDoc->m_lStartOffset > -1)
{
if (pDoc->m_lStartOffset > pDoc->TotalFileLength())
{
m_iFirstLine = 0;
pDoc->m_lStartOffset = pDoc->m_lEndOffset = -1;
}
else
{
while (pDoc->m_lStartOffset > m_iCurrentOffset + pDoc->BlockLength(m_iCurrentOffset))
{
pDoc->GetNextBlock(m_iCurrentOffset);
}
m_iFirstLine = (pDoc->m_lStartOffset - m_iCurrentOffset) / 16;
m_iLastLine = (pDoc->BlockLength(m_iCurrentOffset) + 15) / 16;
UpdateScrollSizes();
}
}