home *** CD-ROM | disk | FTP | other *** search
- /* ---------------------------------------------------------------------------
-
- 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://home.sprynet.com/sprynet/funduc or
- http://ourworld.compuserve.com/homepages/funduc
-
- ----------------------------------------------------------------------------*/
-
- // 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
-
- /////////////////////////////////////////////////////////////////////////////
- // 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);
- 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_iCurrentOffset = 0;
-
- }
-
- CHexviewView::~CHexviewView()
- {
- delete m_cfBoldFont;
- }
-
- /////////////////////////////////////////////////////////////////////////////
- // CHexviewView drawing
-
- void CHexviewView::OnDraw(CDC* pDC)
- {
- CHexviewDoc* pDoc = GetDocument();
- ASSERT_VALID(pDoc);
-
- DispData(pDC, m_iFirstLine, pDoc->TotalFileLength(), m_cfFixedFont,
- m_iWndLines, m_iFontHeight, m_iCurrentOffset, m_iFontWidth);
- }
-
- void CHexviewView::DispData(CDC* pDC, int iFirstLine, int iTotalLines, CFont *cfFixedFont,
- int iWndLines, int iFontHeight, int iCurrentOffset, int iFontWidth)
- {
-
- CFont *pOldFont = pDC->SelectObject(cfFixedFont);
- CRect rcWnd;
- GetClientRect(&rcWnd);
-
- // compute the start point
- int iOffset = iFirstLine * 16 + iCurrentOffset;
- int iRemaining = iTotalLines - iOffset;
- int iLine = 0;
- CHexviewDoc* pDoc = GetDocument();
- BYTE *pData = pDoc->AdjustPointerAbsolute(0);
- if (!pData)
- {
- pDC->TextOut(0, 0, "No data", 7);
- }
- else
- {
- char buf[80], buf2[80];
- 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 ((iCount > 0) && isprint(*p))
- {
- sprintf(&buf[strlen(buf)], "%c", *p);
- }
- else if (iCount > 0)
- {
- strcat(buf, ".");
- }
- else
- {
- strcat(buf, " ");
- }
- iCount--;
- p++;
- }
- 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(m_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();
- }
- }
- }
-
- void CHexviewView::UpdateScrollSizes()
- {
- // UpdateScrollSizes() is called when it is necessary to adjust the
- // scrolling range or page/line sizes. There are two occassions
- // where this is necessary: (1) when a new row is added-- see
- // UpdateRow()-- and (2) when the window size changes-- see OnSize().
- CRect rectClient;
- GetClientRect(&rectClient);
-
- CClientDC dc(this);
- TEXTMETRIC tm;
- dc.GetTextMetrics(&tm);
- m_iFontHeight = tm.tmHeight + tm.tmExternalLeading;
- m_iFontWidth = tm.tmMaxCharWidth;
-
- CSize sz;
- sz.cx = m_iFontWidth * 80;
- CHexviewDoc* pDoc = GetDocument();
- sz.cy = m_iViewHeight = (pDoc->BlockLength(m_iCurrentOffset) + 15) / 16;
-
- m_iLastLine = m_iViewHeight;
-
- // The vert scrolling range is the total display height of all
- // of the rows.
- CSize sizeTotal(sz.cx,
- m_iFontHeight * (min(m_iViewHeight, INT_MAX / m_iFontHeight - 1)));
-
- m_iWndLines = max(1, (rectClient.bottom/m_iFontHeight));
- // The vertical per-page scrolling distance is equal to the
- // how many rows can be displayed in the current window, less
- // one row for paging overlap.
- CSize sizePage(sz.cx, m_iWndLines * m_iFontHeight);
-
- // The vertical per-line scrolling distance is equal to the
- // height of the row.
- CSize sizeLine(sz.cx, m_iFontHeight);
-
- SetScrollSizes(MM_TEXT, sizeTotal, sizePage, sizeLine);
-
- if (sizePage.cy >= sizeTotal.cy)
- {
- m_iFirstLine = 0;
- SetScrollPos(SB_VERT, 0, TRUE);
- }
- else
- {
- int iPos = 0;
- if ((m_iLastLine - m_iWndLines) * m_iFontHeight) // No divide by 0
- iPos = (m_iViewHeight * m_iFirstLine) / (m_iLastLine - m_iWndLines) * m_iFontHeight;
- SetScrollPos(SB_VERT, iPos, TRUE);
- }
- }
-
- /////////////////////////////////////////////////////////////////////////////
- // CHexviewView printing
-
- BOOL CHexviewView::OnPreparePrinting(CPrintInfo* pInfo)
- {
- // default preparation
- return DoPreparePrinting(pInfo);
- }
-
- void CHexviewView::OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo)
- {
- TEXTMETRIC tm;
- pDC->GetTextMetrics(&tm);
- int nPageHeight = pDC->GetDeviceCaps(VERTRES);
- m_iFontHeight = tm.tmHeight + tm.tmExternalLeading;
- m_iWndLines = nPageHeight / m_iFontHeight;
-
- CHexviewDoc* pDoc = GetDocument();
- ASSERT_VALID(pDoc);
- m_iFirstLine = 0;
- int nTotalLines = (pDoc->TotalFileLength() + 15) / 16;
- pInfo->SetMaxPage((nTotalLines + m_iWndLines - 1) / m_iWndLines);
- }
-
- void CHexviewView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
- {
- UpdateScrollSizes();
- }
-
- /////////////////////////////////////////////////////////////////////////////
- // CHexviewView diagnostics
-
- #ifdef _DEBUG
- void CHexviewView::AssertValid() const
- {
- CScrollView::AssertValid();
- }
-
- void CHexviewView::Dump(CDumpContext& dc) const
- {
- CScrollView::Dump(dc);
- }
-
- CHexviewDoc* CHexviewView::GetDocument() // non-debug version is inline
- {
- ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CHexviewDoc)));
- return (CHexviewDoc*)m_pDocument;
- }
- #endif //_DEBUG
-
- /////////////////////////////////////////////////////////////////////////////
- // CHexviewView message handlers
-
- void CHexviewView::OnDestroy()
- {
- delete m_cfFixedFont;
- CScrollView::OnDestroy();
- }
-
- void CHexviewView::OnPrepareDC(CDC* pDC, CPrintInfo* pInfo)
- {
- // TODO: Add your specialized code here and/or call the base class
-
- CScrollView::OnPrepareDC(pDC, pInfo);
- CPoint pt = pDC->GetViewportOrg();
- pt.y = 0;
- pDC->SetViewportOrg(pt);
-
- }
-
- void CHexviewView::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
- {
- switch (nSBCode)
- {
- case SB_TOP:
- m_iFirstLine = 0;
- break;
-
- case SB_BOTTOM:
- m_iFirstLine = m_iLastLine;
- break;
-
- case SB_LINEUP:
- m_iFirstLine--;
- break;
-
- case SB_PAGEUP:
- m_iFirstLine -= m_iWndLines;
- break;
-
- case SB_LINEDOWN:
- m_iFirstLine++;
- break;
-
- case SB_PAGEDOWN:
- m_iFirstLine += m_iWndLines;
- break;
-
- case SB_THUMBPOSITION:
- case SB_THUMBTRACK:
- m_iFirstLine = (nPos * m_iLastLine) / (m_iFontHeight * m_iViewHeight);
- break;
-
- default:
- return;
- }
-
- if (m_iFirstLine >= m_iLastLine - m_iWndLines)
- {
- m_iFirstLine = m_iLastLine - m_iWndLines;
- }
- if (m_iFirstLine < 0) m_iFirstLine = 0;
- if (m_iWndLines >= m_iLastLine)
- {
- m_iFirstLine = 0;
- }
-
- int iPos = 0;
- if (m_iWndLines < m_iLastLine)
- iPos = (m_iViewHeight * m_iFirstLine) / (m_iLastLine - m_iWndLines) * m_iFontHeight;
- TRACE("First Line: %d, Last Line: %d, Window lines: %d, Position: %d\n",
- m_iFirstLine, m_iLastLine, m_iWndLines, iPos);
- SetScrollPos(SB_VERT, iPos, TRUE);
- Invalidate(FALSE);
- }
-
- void CHexviewView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
- {
- // TODO: Add your message handler code here and/or call default
-
- switch (nChar)
- {
- case VK_HOME:
- OnVScroll(SB_TOP, 0, NULL);
- break;
-
- case VK_END:
- OnVScroll(SB_BOTTOM, 0, NULL);
- break;
-
- case VK_UP:
- OnVScroll(SB_LINEUP, 0, NULL);
- break;
-
- case VK_DOWN:
- OnVScroll(SB_LINEDOWN, 0, NULL);
- break;
-
- case VK_PRIOR:
- OnVScroll(SB_PAGEUP, 0, NULL);
- break;
-
- case VK_NEXT:
- OnVScroll(SB_PAGEDOWN, 0, NULL);
- break;
-
- default:
- CScrollView::OnKeyDown(nChar, nRepCnt, nFlags);
- break;
- }
- }
-
- void CHexviewView::OnPrint(CDC* pDC, CPrintInfo* pInfo)
- {
- TEXTMETRIC tm;
- pDC->GetTextMetrics(&tm);
- int nPageHeight = pDC->GetDeviceCaps(VERTRES);
- int iFontHeight = tm.tmHeight + tm.tmExternalLeading;
- int iFontWidth = tm.tmMaxCharWidth;
- int iWndLines = nPageHeight / iFontHeight;
- int iFirstLine = (pInfo->m_nCurPage -1) * iWndLines;
- // Print the rows for the current page.
-
- int yTopOfPage = (pInfo->m_nCurPage -1) * iWndLines
- * iFontHeight;
-
- CHexviewDoc* pDoc = GetDocument();
- ASSERT_VALID(pDoc);
-
- DispData(pDC, iFirstLine, pDoc->TotalFileLength(), m_cfFixedFont,
- iWndLines, iFontHeight, 0, iFontWidth);
- }
-
- void CHexviewView::OnSize(UINT nType, int cx, int cy)
- {
- UpdateScrollSizes();
- CScrollView::OnSize(nType, cx, cy);
- }
-
-
- void CHexviewView::OnViewNextblock()
- {
- CHexviewDoc* pDoc = GetDocument();
- ASSERT_VALID(pDoc);
- if (pDoc->GetNextBlock(m_iCurrentOffset))
- {
- m_iFirstLine = 0;
- m_iLastLine = (pDoc->BlockLength(m_iCurrentOffset) + 15) / 16;
- SetScrollPos(SB_VERT, 0, TRUE);
- UpdateScrollSizes();
- Invalidate();
- }
- }
-
- void CHexviewView::OnViewPreviousblock()
- {
- CHexviewDoc* pDoc = GetDocument();
- ASSERT_VALID(pDoc);
- if (pDoc->GetPrevBlock(m_iCurrentOffset))
- {
- m_iFirstLine = 0;
- m_iLastLine = (pDoc->BlockLength(m_iCurrentOffset) + 15) / 16;
- SetScrollPos(SB_VERT, 0, TRUE);
- UpdateScrollSizes();
- Invalidate();
- }
- }
-
- void CHexviewView::OnUpdateViewNextblock(CCmdUI* pCmdUI)
- {
- CHexviewDoc* pDoc = GetDocument();
- ASSERT_VALID(pDoc);
- int iCurrentOffset = m_iCurrentOffset;
- pCmdUI->Enable(pDoc->GetNextBlock(iCurrentOffset));
- }
-
- void CHexviewView::OnUpdateViewPreviousblock(CCmdUI* pCmdUI)
- {
- CHexviewDoc* pDoc = GetDocument();
- ASSERT_VALID(pDoc);
- int iCurrentOffset = m_iCurrentOffset;
- pCmdUI->Enable(pDoc->GetPrevBlock(iCurrentOffset));
- }
-
-
- void CHexviewView::OnViewGoto()
- {
- CGotoDlg dlgGoto;
- CHexviewDoc* pDoc = GetDocument();
- ASSERT_VALID(pDoc);
-
- if (pDoc->m_lStartOffset != -1) // Show the initial offset
- dlgGoto.m_lNewOffset = pDoc->m_lStartOffset;
- else // Show the top of current block
- dlgGoto.m_lNewOffset = m_iCurrentOffset;
- if (dlgGoto.DoModal() == IDOK)
- {
- // Bogus offset
- if (dlgGoto.m_lNewOffset > pDoc->TotalFileLength())
- {
- m_iFirstLine = 0;
- }
- else
- {
- // Find the right block
- while (dlgGoto.m_lNewOffset > m_iCurrentOffset + pDoc->BlockLength(m_iCurrentOffset))
- {
- pDoc->GetNextBlock(m_iCurrentOffset);
- }
- m_iFirstLine = (dlgGoto.m_lNewOffset - m_iCurrentOffset) / 16;
- m_iLastLine = (pDoc->BlockLength(m_iCurrentOffset) + 15) / 16;
- UpdateScrollSizes();
- }
- Invalidate();
- }
- }
-