home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 1998 January / Pcwk0198.iso / Zadarmo / HEXVIEW / SRC / HEXVIEWV.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1996-08-04  |  14.7 KB  |  543 lines

  1. /* ---------------------------------------------------------------------------
  2.  
  3.    This code can be used as you wish but without warranties as to performance 
  4.    of merchantability or any other warranties whether expressed or implied.
  5.    
  6.      Written by Mike Funduc, Funduc Software Inc. 8/1/96
  7.  
  8.      To download the code and more useful utilities (including Search and
  9.      Replace for Windows 95/NT, 3.1x) go to:
  10.      http://home.sprynet.com/sprynet/funduc  or
  11.      http://ourworld.compuserve.com/homepages/funduc
  12.  
  13. ----------------------------------------------------------------------------*/
  14.  
  15. // hexviewView.cpp : implementation of the CHexviewView class
  16. //
  17.  
  18. #include "stdafx.h"
  19. #include "hexview.h"
  20.  
  21. #include "hexviewDoc.h"
  22. #include "hexviewView.h"
  23. #include "gotodlg.h"
  24.  
  25. #ifdef _DEBUG
  26. #define new DEBUG_NEW
  27. #undef THIS_FILE
  28. static char THIS_FILE[] = __FILE__;
  29. #endif
  30.  
  31. /////////////////////////////////////////////////////////////////////////////
  32. // CHexviewView
  33.  
  34. IMPLEMENT_DYNCREATE(CHexviewView, CScrollView)
  35.  
  36. BEGIN_MESSAGE_MAP(CHexviewView, CScrollView)
  37.     //{{AFX_MSG_MAP(CHexviewView)
  38.     ON_WM_DESTROY()
  39.     ON_WM_VSCROLL()
  40.     ON_WM_KEYDOWN()
  41.     ON_WM_SIZE()
  42.     ON_COMMAND(ID_VIEW_NEXTBLOCK, OnViewNextblock)
  43.     ON_COMMAND(ID_VIEW_PREVIOUSBLOCK, OnViewPreviousblock)
  44.     ON_UPDATE_COMMAND_UI(ID_VIEW_NEXTBLOCK, OnUpdateViewNextblock)
  45.     ON_UPDATE_COMMAND_UI(ID_VIEW_PREVIOUSBLOCK, OnUpdateViewPreviousblock)
  46.     ON_COMMAND(ID_VIEW_GOTO, OnViewGoto)
  47.     //}}AFX_MSG_MAP
  48.     // Standard printing commands
  49.     ON_COMMAND(ID_FILE_PRINT, CScrollView::OnFilePrint)
  50.     ON_COMMAND(ID_FILE_PRINT_DIRECT, CScrollView::OnFilePrint)
  51.     ON_COMMAND(ID_FILE_PRINT_PREVIEW, CScrollView::OnFilePrintPreview)
  52. END_MESSAGE_MAP()
  53.  
  54. /////////////////////////////////////////////////////////////////////////////
  55. // CHexviewView construction/destruction
  56.  
  57. CHexviewView::CHexviewView()
  58. {
  59.     m_cfFixedFont = new(CFont);
  60.     m_cfFixedFont->CreateStockObject(ANSI_FIXED_FONT);
  61.     m_cfBoldFont = new CFont;
  62.         // try and create the new font for the list box
  63.     // it should be the same as the old but without the BOLD weight
  64.     LOGFONT oldFont;
  65.     m_cfFixedFont->GetObject(sizeof(LOGFONT), &oldFont);
  66.     
  67.     oldFont.lfUnderline = TRUE;
  68.  
  69.     m_cfBoldFont->CreateFontIndirect(&oldFont);
  70.  
  71.     m_iCurrentOffset = 0;
  72.  
  73. }
  74.  
  75. CHexviewView::~CHexviewView()
  76. {
  77.     delete m_cfBoldFont;
  78. }
  79.  
  80. /////////////////////////////////////////////////////////////////////////////
  81. // CHexviewView drawing
  82.  
  83. void CHexviewView::OnDraw(CDC* pDC)
  84. {
  85.     CHexviewDoc* pDoc = GetDocument();
  86.     ASSERT_VALID(pDoc);
  87.  
  88.     DispData(pDC, m_iFirstLine, pDoc->TotalFileLength(), m_cfFixedFont,
  89.                             m_iWndLines, m_iFontHeight, m_iCurrentOffset, m_iFontWidth);
  90. }
  91.  
  92. void CHexviewView::DispData(CDC* pDC, int iFirstLine, int iTotalLines, CFont *cfFixedFont,
  93.                             int iWndLines, int iFontHeight, int iCurrentOffset, int iFontWidth)
  94. {
  95.  
  96.     CFont *pOldFont = pDC->SelectObject(cfFixedFont);
  97.     CRect rcWnd;
  98.     GetClientRect(&rcWnd);
  99.  
  100.     // compute the start point
  101.     int iOffset = iFirstLine * 16 + iCurrentOffset;
  102.     int iRemaining = iTotalLines - iOffset;
  103.     int iLine = 0;
  104.     CHexviewDoc* pDoc = GetDocument();
  105.     BYTE *pData = pDoc->AdjustPointerAbsolute(0);
  106.     if (!pData) 
  107.     {
  108.         pDC->TextOut(0, 0, "No data", 7);
  109.     } 
  110.     else 
  111.     {
  112.         char buf[80], buf2[80];
  113.         while ((iRemaining > 0) && (iLine < iWndLines)) 
  114.         {
  115.             sprintf(buf, "%8.8lX  ", iOffset);
  116.             BYTE *p = pData + iOffset;
  117.             int iCount = iRemaining;
  118.             for (int i = 0; i < 16; i++) 
  119.             {
  120.                 if (iCount > 0) 
  121.                 {
  122.                     sprintf(&buf[strlen(buf)],
  123.                             "%2.2X ",
  124.                             *p);
  125.                 } 
  126.                 else 
  127.                 {
  128.                     strcat(buf, "   ");
  129.                 }
  130.                 iCount--;
  131.                 p++;
  132.             }
  133.             strcat(buf, "  ");
  134.             p = pData + iOffset;
  135.             iCount = iRemaining;
  136.             for (i = 0; i < 16; i++) 
  137.             {
  138.                 if ((iCount > 0) && isprint(*p)) 
  139.                 {
  140.                     sprintf(&buf[strlen(buf)], "%c", *p);
  141.                 } 
  142.                 else if (iCount > 0) 
  143.                 {
  144.                     strcat(buf, ".");
  145.                 } 
  146.                 else 
  147.                 {
  148.                     strcat(buf, " ");
  149.                 }
  150.                 iCount--;
  151.                 p++;
  152.             }
  153.             if ((iOffset + 16 >= pDoc->m_lStartOffset) && (iOffset < pDoc->m_lEndOffset))
  154.             {
  155.                 strcpy(buf2, buf);
  156.                 CSize szExtent;
  157.                 int nStartOnLine = max(0, pDoc->m_lStartOffset - iOffset);
  158.                 int nItemsOnLine = min(pDoc->m_lEndOffset, iOffset + 16) - max(pDoc->m_lStartOffset, iOffset);
  159.                 // Characters before highlight
  160.                 pDC->TextOut(0, iLine * iFontHeight, buf, nStartOnLine * 3 + 10);
  161.                 szExtent = pDC->GetTextExtent(buf, nStartOnLine * 3 + 10);
  162.                 memcpy(buf, buf2 + nStartOnLine * 3 + 10, (16 - nStartOnLine) * 3 + 2);
  163.                 buf[(16 - nStartOnLine) * 3 + 2] = 0;
  164.                 pDC->SelectObject(m_cfBoldFont);
  165.                 // Highlight characters
  166.                 pDC->TextOut(szExtent.cx, iLine * iFontHeight, buf, nItemsOnLine * 3);
  167.                 szExtent += pDC->GetTextExtent(buf, nItemsOnLine * 3);
  168.                 pDC->SelectObject(cfFixedFont);
  169.                 strcpy(buf, buf2 + (nStartOnLine + nItemsOnLine) * 3 + 10);
  170.                 // Characters after highlight
  171.                 pDC->TextOut(szExtent.cx, iLine * iFontHeight, buf, strlen(buf));
  172.                 pDC->MoveTo(0, (iLine + 1) * iFontHeight);
  173.             }
  174.             else  // Just a regular line
  175.                 pDC->TextOut(0, iLine * iFontHeight, buf, strlen(buf));
  176.             iOffset += 16;
  177.             iRemaining -= 16;
  178.             iLine++;
  179.         }
  180.         if (iLine < iWndLines) 
  181.         {
  182.             CRect rc = rcWnd;
  183.             rc.top = iLine * iFontHeight;
  184.             pDC->ExtTextOut(0, iLine * iFontHeight, ETO_OPAQUE,
  185.                             &rc, "", 0, NULL);
  186.         }
  187.     }
  188.     pDC->SelectObject(pOldFont);
  189. }
  190.  
  191. void CHexviewView::OnInitialUpdate()
  192. {
  193.     CDC *pDC = GetDC();
  194.     CFont *pOldFont = pDC->SelectObject(m_cfFixedFont);
  195.     pDC->SelectObject(pOldFont);
  196.     CHexviewDoc* pDoc = GetDocument();
  197.     m_iLastLine = 0;
  198.     m_iWndLines = 0;
  199.     m_iFirstLine = 0;
  200.  
  201.     CScrollView::OnInitialUpdate();
  202.  
  203.     UpdateScrollSizes();
  204.     if (pDoc->m_lStartOffset > -1)
  205.     {
  206.         if (pDoc->m_lStartOffset > pDoc->TotalFileLength())
  207.         {
  208.             m_iFirstLine = 0;
  209.             pDoc->m_lStartOffset = pDoc->m_lEndOffset = -1;
  210.         }
  211.         else
  212.         {
  213.             while (pDoc->m_lStartOffset > m_iCurrentOffset + pDoc->BlockLength(m_iCurrentOffset))
  214.             {
  215.                 pDoc->GetNextBlock(m_iCurrentOffset);
  216.             }
  217.             m_iFirstLine = (pDoc->m_lStartOffset - m_iCurrentOffset) / 16;
  218.             m_iLastLine = (pDoc->BlockLength(m_iCurrentOffset) + 15) / 16;
  219.             UpdateScrollSizes();
  220.         }
  221.     }
  222. }
  223.  
  224. void CHexviewView::UpdateScrollSizes()
  225. {
  226.     // UpdateScrollSizes() is called when it is necessary to adjust the
  227.     // scrolling range or page/line sizes.  There are two occassions
  228.     // where this is necessary:  (1) when a new row is added-- see
  229.     // UpdateRow()-- and (2) when the window size changes-- see OnSize().
  230.     CRect rectClient;
  231.     GetClientRect(&rectClient);
  232.  
  233.     CClientDC dc(this);
  234.     TEXTMETRIC tm;
  235.     dc.GetTextMetrics(&tm);
  236.     m_iFontHeight = tm.tmHeight + tm.tmExternalLeading;
  237.     m_iFontWidth = tm.tmMaxCharWidth;
  238.  
  239.     CSize sz;
  240.     sz.cx = m_iFontWidth * 80;
  241.     CHexviewDoc* pDoc = GetDocument();
  242.     sz.cy = m_iViewHeight = (pDoc->BlockLength(m_iCurrentOffset) + 15) / 16;
  243.  
  244.     m_iLastLine = m_iViewHeight;
  245.  
  246.     // The vert scrolling range is the total display height of all
  247.     // of the rows.
  248.     CSize sizeTotal(sz.cx,
  249.         m_iFontHeight * (min(m_iViewHeight, INT_MAX / m_iFontHeight - 1)));
  250.  
  251.     m_iWndLines = max(1, (rectClient.bottom/m_iFontHeight));
  252.     // The vertical per-page scrolling distance is equal to the
  253.     // how many rows can be displayed in the current window, less
  254.     // one row for paging overlap.
  255.     CSize sizePage(sz.cx, m_iWndLines * m_iFontHeight);
  256.  
  257.     // The vertical per-line scrolling distance is equal to the
  258.         // height of the row.
  259.     CSize sizeLine(sz.cx, m_iFontHeight);
  260.  
  261.     SetScrollSizes(MM_TEXT, sizeTotal, sizePage, sizeLine);
  262.  
  263.     if (sizePage.cy >= sizeTotal.cy)
  264.     {
  265.         m_iFirstLine = 0;
  266.         SetScrollPos(SB_VERT, 0, TRUE);
  267.     }
  268.     else
  269.     {
  270.         int iPos = 0;
  271.         if ((m_iLastLine - m_iWndLines) * m_iFontHeight)  // No divide by 0
  272.             iPos = (m_iViewHeight * m_iFirstLine) / (m_iLastLine - m_iWndLines) * m_iFontHeight;
  273.         SetScrollPos(SB_VERT, iPos, TRUE);
  274.     }
  275. }
  276.  
  277. /////////////////////////////////////////////////////////////////////////////
  278. // CHexviewView printing
  279.  
  280. BOOL CHexviewView::OnPreparePrinting(CPrintInfo* pInfo)
  281. {
  282.     // default preparation
  283.     return DoPreparePrinting(pInfo);
  284. }
  285.  
  286. void CHexviewView::OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo)
  287. {
  288.     TEXTMETRIC tm;
  289.     pDC->GetTextMetrics(&tm);
  290.     int nPageHeight = pDC->GetDeviceCaps(VERTRES);
  291.     m_iFontHeight = tm.tmHeight + tm.tmExternalLeading;
  292.     m_iWndLines = nPageHeight / m_iFontHeight;
  293.  
  294.     CHexviewDoc* pDoc = GetDocument();
  295.     ASSERT_VALID(pDoc);
  296.     m_iFirstLine = 0;
  297.     int nTotalLines = (pDoc->TotalFileLength() + 15) / 16;
  298.     pInfo->SetMaxPage((nTotalLines + m_iWndLines - 1) / m_iWndLines);
  299. }
  300.  
  301. void CHexviewView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
  302. {
  303.     UpdateScrollSizes();
  304. }
  305.  
  306. /////////////////////////////////////////////////////////////////////////////
  307. // CHexviewView diagnostics
  308.  
  309. #ifdef _DEBUG
  310. void CHexviewView::AssertValid() const
  311. {
  312.     CScrollView::AssertValid();
  313. }
  314.  
  315. void CHexviewView::Dump(CDumpContext& dc) const
  316. {
  317.     CScrollView::Dump(dc);
  318. }
  319.  
  320. CHexviewDoc* CHexviewView::GetDocument() // non-debug version is inline
  321. {
  322.     ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CHexviewDoc)));
  323.     return (CHexviewDoc*)m_pDocument;
  324. }
  325. #endif //_DEBUG
  326.  
  327. /////////////////////////////////////////////////////////////////////////////
  328. // CHexviewView message handlers
  329.  
  330. void CHexviewView::OnDestroy() 
  331. {
  332.     delete m_cfFixedFont;
  333.     CScrollView::OnDestroy();
  334. }
  335.  
  336. void CHexviewView::OnPrepareDC(CDC* pDC, CPrintInfo* pInfo) 
  337. {
  338.     // TODO: Add your specialized code here and/or call the base class
  339.     
  340.     CScrollView::OnPrepareDC(pDC, pInfo);
  341.     CPoint pt = pDC->GetViewportOrg();
  342.     pt.y = 0;
  343.     pDC->SetViewportOrg(pt);
  344.  
  345. }
  346.  
  347. void CHexviewView::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) 
  348. {
  349.     switch (nSBCode) 
  350.     {
  351.     case SB_TOP:
  352.         m_iFirstLine = 0;
  353.         break;
  354.     
  355.     case SB_BOTTOM:
  356.         m_iFirstLine = m_iLastLine;
  357.         break;
  358.     
  359.     case SB_LINEUP:
  360.         m_iFirstLine--;
  361.         break;
  362.         
  363.     case SB_PAGEUP:    
  364.         m_iFirstLine -= m_iWndLines;
  365.         break;
  366.  
  367.     case SB_LINEDOWN:
  368.         m_iFirstLine++;
  369.         break;
  370.  
  371.     case SB_PAGEDOWN:
  372.         m_iFirstLine += m_iWndLines;
  373.         break;
  374.     
  375.     case SB_THUMBPOSITION:
  376.     case SB_THUMBTRACK:
  377.         m_iFirstLine = (nPos * m_iLastLine) / (m_iFontHeight * m_iViewHeight);
  378.         break;
  379.  
  380.     default:
  381.         return;
  382.     }
  383.  
  384.     if (m_iFirstLine >= m_iLastLine - m_iWndLines) 
  385.     {
  386.         m_iFirstLine = m_iLastLine - m_iWndLines;
  387.     }
  388.     if (m_iFirstLine < 0) m_iFirstLine = 0;
  389.     if (m_iWndLines >= m_iLastLine) 
  390.     {
  391.         m_iFirstLine = 0;
  392.     } 
  393.  
  394.     int iPos = 0;
  395.     if (m_iWndLines < m_iLastLine) 
  396.         iPos = (m_iViewHeight * m_iFirstLine) / (m_iLastLine - m_iWndLines) * m_iFontHeight;
  397.     TRACE("First Line: %d, Last Line: %d, Window lines: %d, Position: %d\n", 
  398.         m_iFirstLine, m_iLastLine, m_iWndLines, iPos);
  399.     SetScrollPos(SB_VERT, iPos, TRUE);
  400.     Invalidate(FALSE);
  401. }
  402.  
  403. void CHexviewView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) 
  404. {
  405.     // TODO: Add your message handler code here and/or call default
  406.  
  407.    switch (nChar) 
  408.    {
  409.     case VK_HOME:
  410.         OnVScroll(SB_TOP, 0, NULL);
  411.         break;
  412.  
  413.     case VK_END:
  414.         OnVScroll(SB_BOTTOM, 0, NULL);
  415.         break;
  416.  
  417.     case VK_UP:
  418.         OnVScroll(SB_LINEUP, 0, NULL);
  419.         break;
  420.  
  421.     case VK_DOWN:
  422.         OnVScroll(SB_LINEDOWN, 0, NULL);
  423.         break;
  424.  
  425.     case VK_PRIOR:
  426.         OnVScroll(SB_PAGEUP, 0, NULL);
  427.         break;
  428.  
  429.     case VK_NEXT:
  430.         OnVScroll(SB_PAGEDOWN, 0, NULL);
  431.         break;
  432.     
  433.     default:    
  434.         CScrollView::OnKeyDown(nChar, nRepCnt, nFlags);
  435.         break;
  436.     }
  437. }
  438.  
  439. void CHexviewView::OnPrint(CDC* pDC, CPrintInfo* pInfo) 
  440. {
  441.     TEXTMETRIC tm;
  442.     pDC->GetTextMetrics(&tm);
  443.     int nPageHeight = pDC->GetDeviceCaps(VERTRES);
  444.     int iFontHeight = tm.tmHeight + tm.tmExternalLeading;
  445.     int iFontWidth = tm.tmMaxCharWidth;
  446.     int iWndLines = nPageHeight / iFontHeight;
  447.     int iFirstLine = (pInfo->m_nCurPage -1) * iWndLines;
  448.     // Print the rows for the current page.
  449.  
  450.     int yTopOfPage = (pInfo->m_nCurPage -1) * iWndLines
  451.         * iFontHeight;
  452.  
  453.     CHexviewDoc* pDoc = GetDocument();
  454.     ASSERT_VALID(pDoc);
  455.  
  456.     DispData(pDC, iFirstLine, pDoc->TotalFileLength(), m_cfFixedFont,
  457.                             iWndLines, iFontHeight, 0, iFontWidth);
  458. }
  459.  
  460. void CHexviewView::OnSize(UINT nType, int cx, int cy) 
  461. {
  462.     UpdateScrollSizes();
  463.     CScrollView::OnSize(nType, cx, cy);
  464. }
  465.  
  466.  
  467. void CHexviewView::OnViewNextblock() 
  468. {
  469.     CHexviewDoc* pDoc = GetDocument();
  470.     ASSERT_VALID(pDoc);
  471.     if (pDoc->GetNextBlock(m_iCurrentOffset))
  472.     {
  473.         m_iFirstLine = 0;
  474.         m_iLastLine = (pDoc->BlockLength(m_iCurrentOffset) + 15) / 16;
  475.         SetScrollPos(SB_VERT, 0, TRUE);
  476.         UpdateScrollSizes();
  477.         Invalidate();
  478.     }
  479. }
  480.  
  481. void CHexviewView::OnViewPreviousblock() 
  482. {
  483.     CHexviewDoc* pDoc = GetDocument();
  484.     ASSERT_VALID(pDoc);
  485.     if (pDoc->GetPrevBlock(m_iCurrentOffset))
  486.     {
  487.         m_iFirstLine = 0;
  488.         m_iLastLine = (pDoc->BlockLength(m_iCurrentOffset) + 15) / 16;
  489.         SetScrollPos(SB_VERT, 0, TRUE);
  490.         UpdateScrollSizes();
  491.         Invalidate();
  492.     }
  493. }
  494.  
  495. void CHexviewView::OnUpdateViewNextblock(CCmdUI* pCmdUI) 
  496. {
  497.     CHexviewDoc* pDoc = GetDocument();
  498.     ASSERT_VALID(pDoc);
  499.     int iCurrentOffset = m_iCurrentOffset;
  500.     pCmdUI->Enable(pDoc->GetNextBlock(iCurrentOffset));
  501. }
  502.  
  503. void CHexviewView::OnUpdateViewPreviousblock(CCmdUI* pCmdUI) 
  504. {
  505.     CHexviewDoc* pDoc = GetDocument();
  506.     ASSERT_VALID(pDoc);
  507.     int iCurrentOffset = m_iCurrentOffset;
  508.     pCmdUI->Enable(pDoc->GetPrevBlock(iCurrentOffset));
  509. }
  510.  
  511.  
  512. void CHexviewView::OnViewGoto() 
  513. {
  514.     CGotoDlg dlgGoto;
  515.     CHexviewDoc* pDoc = GetDocument();
  516.     ASSERT_VALID(pDoc);
  517.  
  518.     if (pDoc->m_lStartOffset != -1)  // Show the initial offset
  519.         dlgGoto.m_lNewOffset = pDoc->m_lStartOffset;
  520.     else                             // Show the top of current block
  521.         dlgGoto.m_lNewOffset = m_iCurrentOffset;
  522.     if (dlgGoto.DoModal() == IDOK)
  523.     {
  524.         // Bogus offset
  525.         if (dlgGoto.m_lNewOffset > pDoc->TotalFileLength())
  526.         {
  527.             m_iFirstLine = 0;
  528.         }
  529.         else
  530.         {
  531.             // Find the right block
  532.             while (dlgGoto.m_lNewOffset > m_iCurrentOffset + pDoc->BlockLength(m_iCurrentOffset))
  533.             {
  534.                 pDoc->GetNextBlock(m_iCurrentOffset);
  535.             }
  536.             m_iFirstLine = (dlgGoto.m_lNewOffset - m_iCurrentOffset) / 16;
  537.             m_iLastLine = (pDoc->BlockLength(m_iCurrentOffset) + 15) / 16;
  538.             UpdateScrollSizes();
  539.         }
  540.         Invalidate();
  541.     }
  542. }
  543.