home *** CD-ROM | disk | FTP | other *** search
/ ftp.funduc.com / 2014.08.ftp.funduc.com.tar / ftp.funduc.com / fshedcode-072212.zip / fshedView.cpp < prev    next >
C/C++ Source or Header  |  2012-07-03  |  168KB  |  4,619 lines

  1. /////////////////////////////////////////////////////////////////////////////
  2. //    License (GPLv2+):
  3. //    This program is free software; you can redistribute it and/or modify
  4. //    it under the terms of the GNU General Public License as published by
  5. //    the Free Software Foundation; either version 2 of the License, or
  6. //    (at your option) any later version.
  7. //
  8. //    This program is distributed in the hope that it will be useful, but
  9. //    WITHOUT ANY WARRANTY; without even the implied warranty of
  10. //    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  11. //    General Public License for more details.
  12. //
  13. //    You should have received a copy of the GNU General Public License
  14. //    along with this program; if not, write to the Free Software
  15. //    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. /////////////////////////////////////////////////////////////////////////////
  17.  
  18. // fshedView.cpp : implementation of the CFshedView class
  19. //
  20.  
  21. #include "stdafx.h"
  22. #include "atlbase.h"
  23. #include "fshed.h"
  24. #include <fcntl.h>
  25. #include <sys/types.h>
  26. #include <sys/stat.h>
  27. #include <io.h>
  28. #include <mbstring.h>
  29.  
  30. //#include "fshedDoc.h"
  31. #include "fshedView.h"
  32. #include "AddBookmarkDlg.h"
  33. #include "RemoveBookmarkDlg.h"
  34. #include "HexDumpDlg.h"
  35. #include "AppendDialog.h"
  36. #include "ManipulateBitsDlg.h"
  37. #include "SelectBlockDlg.h"
  38. #include "PasteSpecialDlg.h"
  39. #include "GotoDlg.h"
  40.  
  41. #ifdef _DEBUG
  42. #define new DEBUG_NEW
  43. #undef THIS_FILE
  44. static char THIS_FILE[] = __FILE__;
  45. #endif
  46.  
  47. #define SUB_RELEASE_NO "156"
  48. #define NO_FILE (Doc->filename[0] == '\0')
  49. #define LASTBYTE (Doc->DataArray.GetUpperBound ())
  50.  
  51. //--------------------------------------------------------------------------------------------
  52. // FIND_BYTES
  53. // Arguments:
  54. // ps   = Start position.
  55. // ls   = Length of src array.
  56. // pb   = Start of searchstring.
  57. // lb   = Length searchstring.
  58. // mode = -1 : backwards search.
  59. //         1 : forward search.
  60. // cmp  = pointer to function that is applied to data before comparing.
  61. //
  62. // Return:
  63. // Position of found string or -1 if not there.
  64.  
  65. int find_bytes (char* ps, int ls, char* pb, int lb, int mode, char (*cmp) (char))
  66. {
  67.     int start, inc, end, i;
  68.     if (mode == 1)
  69.     {
  70.         start = 0;
  71.         inc = 1;
  72.         end = ls - lb + 1;
  73.     }
  74.     else
  75.     {
  76.         start = ls - lb;
  77.         inc = -1;
  78.         end = 1;
  79.     }
  80.  
  81.     for (; mode * start < end; start += inc)
  82.     {
  83.         for (i = start; i < start + lb; i++)
  84.         {
  85.             if (cmp (ps[i]) != cmp (pb[i - start]))
  86.                 break;
  87.         }
  88.         if (i == start + lb)
  89.             return start;
  90.     }
  91.  
  92.     return -1;
  93. }
  94.  
  95. #ifndef _UNICODE
  96. extern AFX_DATA const BOOL _afxDBCS;
  97. #endif
  98. typedef int (_cdecl * AFX_COMPARE_PROC)(LPCSTR str1, LPCSTR str2);
  99.  
  100. int find_bytes (char* ps, int ls, long lStartSel, long lEndSel,
  101.                 const char* lpszFind, int lb, BOOL bNext, BOOL bCase, BOOL bWholeWord)
  102. {
  103.     UINT nLen = ls;
  104.     int nStartChar = lStartSel, nEndChar = lEndSel;
  105.    if (bWholeWord)
  106.       ++nStartChar;
  107.     UINT nStart = nStartChar;
  108.     int iDir = bNext ? +1 : -1;
  109.  
  110.     // can't find a match before the first character
  111.     if (nStart == 0 && iDir < 0)
  112.         return FALSE;
  113.  
  114.     CWaitCursor wait;
  115.     LPCSTR lpszText = ps;
  116.  
  117.     if (iDir < 0)
  118.     {
  119.         // always go back one for search backwards
  120.         nStart -= (UINT)((lpszText+nStart) - (LPCSTR)
  121.             _mbsdec((const unsigned char *)lpszText, (const unsigned char *)lpszText+nStart));
  122.     }
  123.     else if (nStartChar != nEndChar) // && SameAsSelected(lpszFind, bCase))
  124.     {
  125.         // easy to go backward/forward with SBCS
  126.         if (_istlead(lpszText[nStart]))
  127.             nStart++;
  128.         nStart += iDir;
  129.     }
  130.  
  131.     // handle search with nStart past end of buffer
  132.     size_t nLenFind = strlen(lpszFind);
  133.     if (nStart+nLenFind-1 >= nLen)
  134.     {
  135.         if (iDir < 0 && nLen >= nLenFind)
  136.         {
  137. #ifndef _UNICODE
  138.             if (_afxDBCS)
  139.             {
  140.                 // walk back to previous character n times
  141.                 nStart = nLen;
  142.                 int n = nLenFind;
  143.                 while (n--)
  144.                 {
  145.                     nStart -= (lpszText+nStart) - (LPSTR)
  146.                         _mbsdec((const unsigned char *)lpszText, (const unsigned char *)lpszText+nStart);
  147.                 }
  148.             }
  149.             else
  150. #endif
  151.             {
  152.                 // single-byte character set is easy and fast
  153.                 nStart = nLen - (UINT)nLenFind;
  154.             }
  155.             ASSERT(nStart+nLenFind-1 <= nLen);
  156.         }
  157.         else
  158.         {
  159.             return -1;
  160.         }
  161.     }
  162.  
  163.     // start the search at nStart
  164.     LPCSTR lpsz = lpszText + nStart;
  165.     AFX_COMPARE_PROC pfnCompare = bCase ? strcmp : _strcmpi;
  166.  
  167. #ifndef _UNICODE
  168.     if (_afxDBCS)
  169.     {
  170.         // double-byte string search
  171.         LPCSTR lpszStop;
  172.         if (iDir > 0)
  173.         {
  174.             // start at current and find _first_ occurrance
  175.             lpszStop = lpszText + nLen - nLenFind + 1;
  176.         }
  177.         else
  178.         {
  179.             // start at top and find _last_ occurrance
  180.             lpszStop = lpsz;
  181.             lpsz = lpszText;
  182.         }
  183.  
  184.         LPCSTR lpszFound = NULL;
  185.         while (lpsz <= lpszStop)
  186.         {
  187.             if (!bCase || (*lpsz == *lpszFind &&
  188.                 (!_istlead(*lpsz) || lpsz[1] == lpszFind[1])))
  189.             {
  190.                 LPTSTR lpch = (LPTSTR)(lpsz + nLenFind);
  191.                 TCHAR chSave = *lpch;
  192.                 *lpch = '\0';
  193.                 int nResult = (*pfnCompare)(lpsz, lpszFind);
  194.                 *lpch = chSave;
  195.                 if (nResult == 0)
  196.                 {
  197.                     lpszFound = lpsz;
  198.                     if (iDir > 0)
  199.                         break;
  200.                 }
  201.             }
  202.             lpsz = (LPCSTR)_mbsinc((const unsigned char *)lpsz);
  203.         }
  204.  
  205.         if (lpszFound != NULL)
  206.         {
  207.             int n = (int)(lpszFound - lpszText);
  208.             return n;
  209.         }
  210.     }
  211.     else
  212. #endif
  213.     {
  214.         // single-byte string search
  215.         UINT nCompare;
  216.         if (iDir < 0)
  217.             nCompare = (UINT)(lpsz - lpszText) + 1;
  218.         else
  219.             nCompare = nLen - (UINT)(lpsz - lpszText) - (UINT)nLenFind + 1;
  220.  
  221.         while (nCompare > 0)
  222.         {
  223.             ASSERT(lpsz >= lpszText);
  224.             ASSERT(lpsz+nLenFind-1 <= lpszText+nLen-1);
  225.  
  226.             LPSTR lpch = (LPSTR)(lpsz + nLenFind);
  227.             char chSave = *lpch;
  228.             *lpch = '\0';
  229.             int nResult = (*pfnCompare)(lpsz, lpszFind);
  230.             *lpch = chSave;
  231.             if (nResult == 0)
  232.             {
  233.                 int n = (int)(lpsz - lpszText);
  234.                 return n;
  235.             }
  236.  
  237.             // restore character at end of search
  238.             *lpch = chSave;
  239.  
  240.             // move on to next substring
  241.             nCompare--;
  242.             lpsz += iDir;
  243.         }
  244.     }
  245.  
  246.     return -1;
  247. }
  248.  
  249. inline char equal (char c)
  250. {
  251.     return c;
  252. }
  253.  
  254. inline char lower_case (char c)
  255. {
  256.     if (c >= 'A' && c <= 'Z')
  257.         return 'a' + c - 'A';
  258.     else
  259.         return c;
  260. }
  261.  
  262. //Pabs changed - line insert
  263. //used to swap tmpstart and tmpend if start>end
  264. template<class T>void swap(T& x, T& y){
  265.     T temp = x;
  266.     x = y;
  267.     y = temp;
  268. }
  269.  
  270. /////////////////////////////////////////////////////////////////////////////
  271. // CFshedView
  272. static const UINT _myMsgForFindReplace = ::RegisterWindowMessage(FINDMSGSTRING);
  273.  
  274. IMPLEMENT_DYNCREATE(CFshedView, CView)
  275.  
  276. BEGIN_MESSAGE_MAP(CFshedView, CView)
  277.     //{{AFX_MSG_MAP(CFshedView)
  278.     ON_WM_CREATE()
  279.     ON_WM_LBUTTONDOWN()
  280.     ON_WM_MOUSEMOVE()
  281.     ON_WM_LBUTTONUP()
  282.     ON_WM_SIZE()
  283.     ON_WM_KEYDOWN()
  284.     ON_WM_CHAR()
  285.     ON_WM_TIMER()
  286.     ON_WM_VSCROLL()
  287.     ON_WM_HSCROLL()
  288.     ON_WM_KILLFOCUS()
  289.     ON_WM_SETFOCUS()
  290.     ON_WM_MOUSEWHEEL()
  291.     ON_COMMAND(ID_EDIT_FIND, OnEditFind)
  292.     ON_COMMAND(ID_EDIT_CUT, OnEditCut)
  293.     ON_COMMAND(ID_EDIT_COPY, OnEditCopy)
  294.     ON_COMMAND(ID_EDIT_PASTE, OnEditPaste)
  295.     ON_COMMAND(ID_EDIT_REPEAT, OnEditRepeat)
  296.     ON_COMMAND(ID_EDIT_REPLACE, OnEditReplace)
  297.     ON_COMMAND_RANGE(IDM_BOOKMARK1, IDM_BOOKMARK9, OnBookmark)
  298.     ON_COMMAND(IDM_REMOVE_BKM, OnRemoveBkm)
  299.     ON_COMMAND(IDM_CLEARALL_BMK, OnClearallBmk)
  300.     ON_COMMAND(IDM_ADDBOOKMARK, OnAddbookmark)
  301.     ON_COMMAND(IDM_COPY_HEXDUMP, OnCopyHexdump)
  302.     ON_COMMAND(IDM_INSERTFILE, OnInsertfile)
  303.     ON_COMMAND(IDM_SAVESELAS, OnSaveselas)
  304.     ON_COMMAND(ID_EDIT_CLEAR, OnEditClear)
  305.     ON_COMMAND(ID_EDIT_SELECT_ALL, OnEditSelectAll)
  306.     ON_COMMAND(IDA_INSERTMODETOGGLE, OnInsertmodetoggle)
  307.     ON_COMMAND(IDM_CHANGE_MODE, OnChangeMode)
  308.     ON_COMMAND(IDM_EDIT_READONLYMODE, OnEditReadonlymode)
  309.     ON_COMMAND(IDM_EDIT_APPEND, OnEditAppend)
  310.     ON_COMMAND(IDM_EDIT_MANIPULATEBITS, OnEditManipulatebits)
  311.     ON_COMMAND(IDM_SELECT_BLOCK, OnSelectBlock)
  312.     ON_COMMAND(IDM_READFLOAT, OnReadfloat)
  313.     ON_COMMAND(IDM_READ_UNICODE, OnReadUnicode)
  314.     ON_COMMAND(IDM_READ_UTF8, OnReadUtf8)
  315.     ON_COMMAND(IDM_PROPERTIES, OnProperties)
  316.     ON_COMMAND(IDM_REVERT, OnRevert)
  317.     ON_COMMAND(IDM_GO_TO, OnGoto)
  318.     ON_COMMAND(ID_BOOKMARKS_GOTOBOOKMARK, OnBookmarksGotobookmark)
  319.     ON_UPDATE_COMMAND_UI(ID_BOOKMARKS_GOTOBOOKMARK, OnUpdateBookmarksGotobookmark)
  320.     ON_UPDATE_COMMAND_UI(IDM_EDIT_READONLYMODE, OnUpdateEditReadonlymode)
  321.     ON_COMMAND(ID_EDIT_PASTE_SPECIAL, OnEditPasteSpecial)
  322.     ON_WM_CONTEXTMENU()
  323.     //}}AFX_MSG_MAP
  324.     // Standard printing commands
  325.     ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint)
  326.     ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint)
  327.     ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview)
  328.     ON_REGISTERED_MESSAGE(_myMsgForFindReplace, OnFindReplaceCmd)
  329. END_MESSAGE_MAP()
  330.  
  331. /////////////////////////////////////////////////////////////////////////////
  332. // CFshedView construction/destruction
  333.  
  334. CFshedView::CFshedView()
  335. {
  336.    hFont = NULL;
  337.    iCutMode = BST_CHECKED;
  338.  
  339.     bDontMarkCurrentPos = FALSE;
  340.  
  341.     bInsertingHex = FALSE;
  342.  
  343.     iWindowX = CW_USEDEFAULT;
  344.     iWindowY = CW_USEDEFAULT;
  345.     iWindowWidth = CW_USEDEFAULT;
  346.     iWindowHeight = CW_USEDEFAULT;
  347.     iWindowShowCmd = SW_SHOW;
  348.  
  349.     iHexWidth = 3;
  350.  
  351.     // iClipboardEncode = TRUE;
  352.  
  353.     pcGotoDlgBuffer = NULL;
  354.     iGotoDlgBufLen = 0;
  355.     iBmkCount=0;
  356.     szFileName[0] = '\0';
  357.     iInsertMode = FALSE;
  358.     bSelected = FALSE;
  359.     bLButtonIsDown = FALSE;
  360.     iStartOfSelection = 0;
  361.     iEndOfSelection = 0;
  362.     m_stScreenSettings.iByteSpace = 2;
  363.     m_stScreenSettings.iCharSpace = 1;
  364.     m_stScreenSettings.iCharsPerLine = App->m_iOffsetLen + m_stScreenSettings.iByteSpace + 
  365.                                        App->m_iBytesPerLine * 3 + m_stScreenSettings.iCharSpace + 
  366.                                        App->m_iBytesPerLine;
  367.     m_iEnteringMode = BYTES;
  368. //    m_iFileChanged = FALSE;
  369.  
  370.     // Read in the last saved preferences.
  371. //    count_instances();
  372. //    read_ini_data ();
  373.  
  374.     bSelected = FALSE;
  375.     bLButtonIsDown = FALSE;
  376. //    m_iFileChanged = FALSE;
  377.  
  378.    m_bFirstSearch = TRUE;
  379.     m_pFindReplaceDlg = NULL; // find or replace dialog
  380.     m_bFindOnly = TRUE; // Is pFindReplace the find or replace?
  381.     m_bCase = FALSE; // TRUE==case sensitive, FALSE==not
  382.     m_bNext = TRUE;  // TRUE==search down, FALSE== search up
  383.     m_bWord = FALSE; // TRUE==match whole word, FALSE==not
  384.    m_lInitialSearchPos = 0;
  385. }
  386.  
  387. CFshedView::~CFshedView()
  388. {
  389.     if (hFont != NULL)
  390.         DeleteObject (hFont);
  391.     if( pcGotoDlgBuffer != NULL )
  392.         delete [] pcGotoDlgBuffer;
  393.    if (m_pFindReplaceDlg)
  394.       delete m_pFindReplaceDlg;
  395. }
  396.  
  397. BOOL CFshedView::PreCreateWindow(CREATESTRUCT& cs)
  398. {
  399.     // TODO: Modify the Window class or styles here by modifying
  400.     //  the CREATESTRUCT cs
  401.  
  402.     return CView::PreCreateWindow(cs);
  403. }
  404.  
  405. /////////////////////////////////////////////////////////////////////////////
  406. // CFshedView drawing
  407.  
  408. void CFshedView::OnDraw(CDC* pDC)
  409. {
  410.     CFshedDoc* pDoc = GetDocument();
  411.     ASSERT_VALID(pDoc);
  412.  
  413.  
  414.     // TODO: add draw code for native data here
  415. //    PAINTSTRUCT ps;
  416. //   HDC hdc = ::BeginPaint (m_hWnd, &ps);
  417.    HDC hdc = pDC->m_hDC;
  418.     //-------------------------------------------------------
  419.     HideCaret ();
  420.     // Delete remains of last position.
  421.     int a, b;
  422.     b = min (m_stScreenSettings.iCurLine + m_stScreenSettings.cyBuffer, m_stScreenSettings.iNumlines-1);
  423.     iBkColor = PALETTERGB (GetRValue(App->m_clrBk),GetGValue(App->m_clrBk),GetBValue(App->m_clrBk));
  424.     iTextColor = PALETTERGB (GetRValue(App->m_clrText),GetGValue(App->m_clrText),GetBValue(App->m_clrText));
  425.     SetTextColor (hdc, iTextColor);
  426.     SetBkColor (hdc, iBkColor);
  427.     HPEN pen1 = CreatePen (PS_SOLID, 1, iBkColor);
  428.     HPEN oldpen = (HPEN) SelectObject (hdc, pen1);
  429.     HBRUSH brush1 = CreateSolidBrush (iBkColor);
  430.     HBRUSH oldbrush = (HBRUSH) SelectObject (hdc, brush1);
  431.     // Delete lower border if there are empty lines on screen.
  432.     if ((b-m_stScreenSettings.iCurLine+1)*m_stScreenSettings.cyChar+CLIENT_BORDER_WIDTH < m_stScreenSettings.cyClient-CLIENT_BORDER_WIDTH)
  433.         Rectangle (hdc, CLIENT_BORDER_WIDTH, (b-m_stScreenSettings.iCurLine+1)*m_stScreenSettings.cyChar+CLIENT_BORDER_WIDTH + m_stScreenSettings.iToolbarHeight, m_stScreenSettings.cxClient-CLIENT_BORDER_WIDTH,
  434.             m_stScreenSettings.cyClient-CLIENT_BORDER_WIDTH + m_stScreenSettings.iToolbarHeight);
  435.     // Delete right border.
  436.     Rectangle (hdc, ((m_stScreenSettings.iHscrollMax+1)-m_stScreenSettings.iHscrollPos)*m_stScreenSettings.cxChar+CLIENT_BORDER_WIDTH, CLIENT_BORDER_WIDTH + m_stScreenSettings.iToolbarHeight,
  437.         m_stScreenSettings.cxClient-CLIENT_BORDER_WIDTH, m_stScreenSettings.cyClient-CLIENT_BORDER_WIDTH + m_stScreenSettings.iToolbarHeight);
  438.     SelectObject (hdc, oldpen);
  439.     SelectObject (hdc, oldbrush);
  440.     DeleteObject (pen1);
  441.     DeleteObject (brush1);
  442.     
  443.     // Get font.
  444.     HFONT oldfont = (HFONT) SelectObject (hdc, hFont);
  445.     HPEN sep_pen = CreatePen (PS_SOLID, 1, App->m_clrSep);
  446.     oldpen = (HPEN) SelectObject (hdc, sep_pen);
  447.  
  448.     if( Linebuffer.GetSize() < m_stScreenSettings.iCharsPerLine )
  449.     {
  450.         // Linebuffer too small.
  451.         if( Linebuffer.SetSize( m_stScreenSettings.iCharsPerLine ) )
  452.         {
  453.             Linebuffer.ExpandToSize();
  454.             // Linebuffer successfully resized.
  455.             HBRUSH hbr = CreateSolidBrush( App->m_clrBmk );
  456.             if (iUpdateLine == -1)
  457.             {
  458.                 for (a = m_stScreenSettings.iCurLine; a <= b; a++)
  459.                     print_line( hdc, a, Linebuffer, hbr );
  460.             }
  461.             else
  462.             {
  463.                 print_line( hdc, iUpdateLine, Linebuffer, hbr );
  464.             }
  465.             DeleteObject( hbr );
  466.             SelectObject (hdc, oldpen);
  467.             DeleteObject (sep_pen);
  468.             SelectObject (hdc, oldfont);
  469.             // Mark character.
  470.             mark_char (hdc);
  471.             // Draw client-border.
  472.             draw_client_border (hdc);
  473.             ShowCaret ();
  474. //         ::EndPaint (m_hWnd, &ps);
  475.             set_caret_pos ();
  476.             set_wnd_title ();
  477.             iUpdateLine = -1;
  478.         }
  479.         else
  480.         {
  481.             // Could not allocate line buffer.
  482.             Rectangle( hdc, 0, m_stScreenSettings.iToolbarHeight, m_stScreenSettings.cxClient, m_stScreenSettings.cyClient + m_stScreenSettings.iToolbarHeight);
  483.             TCHAR buf[] = _T("Error: could not allocate line buffer.\nPlease save your changes and restart frhed.");
  484.             RECT r;
  485.             r.top = CLIENT_BORDER_WIDTH + m_stScreenSettings.iToolbarHeight;
  486.             r.left = CLIENT_BORDER_WIDTH;
  487.             r.right = m_stScreenSettings.cxClient;
  488.             r.bottom = m_stScreenSettings.cyClient + m_stScreenSettings.iToolbarHeight;
  489.             DrawText( hdc, buf, -1, &r, DT_LEFT );
  490.         }
  491.         
  492.     }
  493.     else
  494.     {
  495.         // Linebuffer large enough.
  496.             HBRUSH hbr = CreateSolidBrush( App->m_clrBmk );
  497.             if (iUpdateLine == -1)
  498.             {
  499.                 for (a = m_stScreenSettings.iCurLine; a <= b; a++)
  500.                     print_line( hdc, a, Linebuffer, hbr );
  501.             }
  502.             else
  503.             {
  504.                 print_line( hdc, iUpdateLine, Linebuffer, hbr );
  505.             }
  506.             DeleteObject( hbr );
  507.             SelectObject (hdc, oldpen);
  508.             DeleteObject (sep_pen);
  509.             SelectObject (hdc, oldfont);
  510.             // Mark character.
  511.             mark_char (hdc);
  512.             // Draw client-border.
  513.             draw_client_border (hdc);
  514.             ShowCaret ();
  515. //         ::EndPaint (m_hWnd, &ps);
  516.             set_caret_pos ();
  517.             set_wnd_title ();
  518.             iUpdateLine = -1;
  519.     }
  520. }
  521.  
  522. /////////////////////////////////////////////////////////////////////////////
  523. // CFshedView printing
  524.  
  525. BOOL CFshedView::OnPreparePrinting(CPrintInfo* pInfo)
  526. {
  527.     // default preparation
  528.     return DoPreparePrinting(pInfo);
  529. }
  530.  
  531. void CFshedView::OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo)
  532. {
  533.    m_saveSettings.CopySettings(m_stScreenSettings);
  534.  
  535.    int nHeight = -::MulDiv(App->m_iFontSize, pDC->GetDeviceCaps(LOGPIXELSY), 72);
  536.    make_font(pDC->GetSafeHdc(), nHeight);
  537.    HFONT of = (HFONT) SelectObject (pDC->GetSafeHdc(), hFont);
  538.    TEXTMETRIC tm;
  539.    pDC->GetTextMetrics(&tm);
  540.     m_stScreenSettings.cxClient = pDC->GetDeviceCaps(HORZRES);
  541.     m_stScreenSettings.cyClient = pDC->GetDeviceCaps(VERTRES);
  542.     m_stScreenSettings.cxChar = tm.tmAveCharWidth;
  543.     m_stScreenSettings.cxCaps = (tm.tmPitchAndFamily & 1 ? 3 : 2) * m_stScreenSettings.cxChar / 2;
  544.     m_stScreenSettings.cyChar = tm.tmHeight + tm.tmExternalLeading;
  545.    
  546.     m_stScreenSettings.cxBuffer = max (1, m_stScreenSettings.cxClient / m_stScreenSettings.cxChar);
  547.     m_stScreenSettings.cyBuffer = max (1, m_stScreenSettings.cyClient / m_stScreenSettings.cyChar);
  548.    SelectObject (pDC->GetSafeHdc(), of);
  549.  
  550.     // Adjust bytes per line to width of window.
  551.     // m_stScreenSettings.cxBuffer = maximal width of client-area in chars.
  552.     if( App->m_bAutomaticBPL )
  553.     {
  554.         int bytemax = m_stScreenSettings.cxBuffer - App->m_iOffsetLen - m_stScreenSettings.iByteSpace - m_stScreenSettings.iCharSpace;
  555.         App->m_iBytesPerLine = bytemax / 4;
  556.         if (App->m_iBytesPerLine < 1)
  557.             App->m_iBytesPerLine = 1;
  558.     }
  559.     // Caret or end of selection will be vertically centered if line not visible.
  560.     if( bSelected )
  561.     {
  562.         if( iEndOfSelection / App->m_iBytesPerLine < m_stScreenSettings.iCurLine || iEndOfSelection / App->m_iBytesPerLine > m_stScreenSettings.iCurLine + m_stScreenSettings.cyBuffer )
  563.             m_stScreenSettings.iCurLine = max( 0, iEndOfSelection / App->m_iBytesPerLine - m_stScreenSettings.cyBuffer / 2 );
  564.     }
  565.     else
  566.     {
  567.         if( m_stScreenSettings.iCurByte/App->m_iBytesPerLine < m_stScreenSettings.iCurLine || m_stScreenSettings.iCurByte/App->m_iBytesPerLine > m_stScreenSettings.iCurLine + m_stScreenSettings.cyBuffer )
  568.             m_stScreenSettings.iCurLine = max( 0, m_stScreenSettings.iCurByte/App->m_iBytesPerLine-m_stScreenSettings.cyBuffer/2 );
  569.     }
  570.  
  571.     m_stScreenSettings.iCharsPerLine = App->m_iOffsetLen + m_stScreenSettings.iByteSpace + App->m_iBytesPerLine*3 + m_stScreenSettings.iCharSpace + App->m_iBytesPerLine;
  572.  
  573.     // Get number of lines to display.
  574.     if ((Doc->DataArray.GetLength()+1) % App->m_iBytesPerLine == 0)
  575.         m_stScreenSettings.iNumlines = (Doc->DataArray.GetLength()+1) / App->m_iBytesPerLine;
  576.     else
  577.         m_stScreenSettings.iNumlines = (Doc->DataArray.GetLength()+1) / App->m_iBytesPerLine + 1;
  578.     
  579.     if (m_stScreenSettings.iNumlines <= 0xffff)
  580.         m_stScreenSettings.iVscrollMax = m_stScreenSettings.iNumlines-1;
  581.     else
  582.         m_stScreenSettings.iVscrollMax = 0xffff;
  583.    //keydown(VK_HOME);
  584.     pInfo->SetMaxPage((m_stScreenSettings.iNumlines + m_stScreenSettings.cyBuffer - 1) / m_stScreenSettings.cyBuffer);
  585. }
  586.  
  587. void CFshedView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
  588. {
  589.     // TODO: add cleanup after printing
  590.    m_stScreenSettings.CopySettings(m_saveSettings);
  591.    update_for_new_datasize();
  592. }
  593.  
  594. /////////////////////////////////////////////////////////////////////////////
  595. // CFshedView diagnostics
  596.  
  597. #ifdef _DEBUG
  598. void CFshedView::AssertValid() const
  599. {
  600.     CView::AssertValid();
  601. }
  602.  
  603. void CFshedView::Dump(CDumpContext& dc) const
  604. {
  605.     CView::Dump(dc);
  606. }
  607.  
  608. CFshedDoc* CFshedView::GetDocument() // non-debug version is inline
  609. {
  610.     ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CFshedDoc)));
  611.     return (CFshedDoc*)m_pDocument;
  612. }
  613. #endif //_DEBUG
  614.  
  615. //-------------------------------------------------------------------
  616. int CFshedView::read_ini_data ()
  617. {
  618.     return 0;
  619. }
  620.  
  621. //-------------------------------------------------------------------
  622. int CFshedView::save_ini_data ()
  623. {
  624.     return 0;
  625. }
  626.  
  627.  
  628. //-------------------------------------------------------------------
  629. // Find char c from pointer to array src on, return it's position.
  630. int CFshedView::find_byte_pos (const char* src, char c)
  631. {
  632.     int i=0;
  633.     while (src[i] != c)
  634.     {
  635.         i++;
  636.     }
  637.     return i;
  638. }
  639.  
  640. //-------------------------------------------------------------------
  641. // dest must be set to right length before calling.
  642. int CFshedView::create_bc_translation (char* dest, const char* src, int srclen, int charmode, int binmode)
  643. {
  644.     int i, di=0, bclen;
  645.     for (i=0; i<srclen; i++)
  646.     {
  647.         if ((bclen = is_bytecode (&(src[i]), srclen-i)) > 0) // Get length of byte-code.
  648.         {
  649.             // Bytecode found.
  650.             translate_bytecode (&(dest[di]), &(src[i]), srclen-i, binmode);
  651.             di += bclen;
  652.             i += find_byte_pos (&(src[i]), '>');
  653.         }
  654.         else // Normal character.
  655.         {
  656.             if (src[i] == '\\') // Special char "\<" or "\\"?
  657.             {
  658.                 if (i+1 < srclen)
  659.                 {
  660.                     if (src[i+1] == '<')
  661.                     {
  662.                         dest[di++] = '<'; // Special char recognized.
  663.                         i++;
  664.                     }
  665.                     else if( src[i+1] == '\\' )
  666.                     {
  667.                         dest[di++] = '\\'; // Special char recognized.
  668.                         i++;
  669.                     }
  670.                     else
  671.                         dest[di++] = src[i]; // Unknown special char.
  672.                 }
  673.                 else
  674.                     dest[di++] = src[i]; // Not enough space for special char.
  675.             }
  676.             else
  677.             {
  678.                 // No special char.
  679.                 switch (charmode)
  680.                 {
  681.                 case ANSI_SET:
  682.                     dest[di++] = src[i];
  683.                     break;
  684.  
  685.                 case OEM_SET:
  686.                     dest[di++] = TranslateAnsiToOem (src[i]);
  687.                     break;
  688.                 }
  689.             }
  690.         }
  691.     }
  692.     return di;
  693. }
  694.  
  695. //-------------------------------------------------------------------
  696. // Get value of one code.
  697. // Return: value of code.
  698. // bytecode must be checked before.
  699. int CFshedView::translate_bytecode (char* dest, const char* src, int srclen, int binmode)
  700. {
  701.     int i, k=0;
  702.     char buf[50];
  703.     for (i=4; i<srclen; i++)
  704.     {
  705.         if (src[i]=='>')
  706.             break;
  707.         else
  708.         {
  709.             buf[k++] = src[i];
  710.         }
  711.     }
  712.     buf[k] = 0;
  713.     int value;
  714.     float fvalue;
  715.     double dvalue;
  716.     switch (src[2]) // Get value from text.
  717.     {
  718.     case 'd':
  719.         sscanf (buf, "%d", &value);
  720.         break;
  721.  
  722.     case 'h':
  723.         sscanf (buf, "%x", &value);
  724.         break;
  725.  
  726.     case 'l':
  727.         sscanf (buf, "%f", &fvalue);
  728.         break;
  729.  
  730.     case 'o':
  731.         sscanf (buf, "%lf", &dvalue);
  732.         break;
  733.     }
  734.  
  735.     if (binmode == LITTLEENDIAN_MODE)
  736.     {
  737.         switch (src[1])
  738.         {
  739.         case 'b':
  740.             dest[0] = (char) value;
  741.             break;
  742.  
  743.         case 'w':
  744.             dest[0] = (value & 0xff);
  745.             dest[1] = (value & 0xff00)>>8;
  746.             break;
  747.         
  748.         case 'l':
  749.             dest[0] = (value & 0xff);
  750.             dest[1] = (value & 0xff00)>>8;
  751.             dest[2] = (value & 0xff0000)>>16;
  752.             dest[3] = (value & 0xff000000)>>24;
  753.             break;
  754.  
  755.         case 'f':
  756.             *((float*)dest) = fvalue;
  757.             break;
  758.  
  759.         case 'd':
  760.             *((double*)dest) = dvalue;
  761.             break;
  762.         }
  763.     }
  764.     else // BIGENDIAN_MODE
  765.     {
  766.         switch (src[1])
  767.         {
  768.         case 'b':
  769.             dest[0] = (char) value;
  770.             break;
  771.  
  772.         case 'w':
  773.             dest[0] = HIBYTE (LOWORD (value));
  774.             dest[1] = LOBYTE (LOWORD (value));
  775.             break;
  776.         
  777.         case 'l':
  778.             dest[0] = HIBYTE (HIWORD (value));
  779.             dest[1] = LOBYTE (HIWORD (value));
  780.             dest[2] = HIBYTE (LOWORD (value));
  781.             dest[3] = LOBYTE (LOWORD (value));
  782.             break;
  783.  
  784.         case 'f':
  785.             {
  786.                 char* p = (char*) &fvalue;
  787.                 int i;
  788.                 for (i=0; i<4; i++)
  789.                 {
  790.                     dest[i] = p[3-i];
  791.                 }
  792.             }
  793.             break;
  794.  
  795.         case 'd':
  796.             {
  797.                 char* p = (char*) &dvalue;
  798.                 int i;
  799.                 for (i=0; i<8; i++)
  800.                 {
  801.                     dest[i] = p[7-i];
  802.                 }
  803.             }
  804.             break;
  805.         }
  806.     }
  807.     return value;
  808. }
  809.  
  810. //-------------------------------------------------------------------
  811. // Get length of code.
  812. int CFshedView::calc_bctrans_destlen (const char* src, int srclen)
  813. {
  814.     int i, destlen = 0, l, k;
  815.     for (i=0; i<srclen; i++)
  816.     {
  817.         if ((l = is_bytecode (&(src[i]), srclen-i)) == 0)
  818.         {
  819.             if (src[i] == '\\')
  820.             {
  821.                 if (i+1 < srclen)
  822.                 {
  823.                     if (src[i+1] == '<')
  824.                     {
  825.                         // Code for "<" alone without decoding.
  826.                         destlen++;
  827.                         i++;
  828.                     }
  829.                     else if( src[i+1] == '\\' )
  830.                     {
  831.                         // Code for "\\".
  832.                         destlen++;
  833.                         i++;
  834.                     }
  835.                     else
  836.                     {
  837.                         destlen++;
  838.                     }
  839.                 }
  840.                 else
  841.                 {
  842.                     destlen++;
  843.                 }
  844.             }
  845.             else
  846.             {
  847.                 destlen++;
  848.             }
  849.         }
  850.         else
  851.         {
  852.             destlen += l;
  853.             for (k=i; i<srclen; k++)
  854.             {
  855.                 if (src[k]=='>')
  856.                     break;
  857.             }
  858.             i = k;
  859.         }
  860.     }
  861.     return destlen;
  862. }
  863.  
  864. //-------------------------------------------------------------------
  865. // Bytecode?
  866. // Return = 0 if no bytecode
  867. //          = Length 1/2/4 if bytecode
  868. int CFshedView::is_bytecode (const char* src, int len)
  869. {
  870.     int i=0;
  871.  
  872.     if (src[i] == '<')
  873.     {
  874.         if (i+1 < len)
  875.         {
  876.             switch (src[i+1])
  877.             {
  878.             case 'b': case 'w': case 'l': case 'f': case 'd':
  879.                 if (i+2 < len)
  880.                 {
  881.                     switch (src[i+2])
  882.                     {
  883.                         case 'd': case 'h': case 'l': case 'o':
  884.                             if (i+3 < len)
  885.                             {
  886.                                 if (src[i+3] == ':')
  887.                                 {
  888.                                     int j,k;
  889.                                     for (j=4; j < len; j++)
  890.                                     {
  891.                                         if (src[i+j] == '>')
  892.                                             break;
  893.                                     }
  894.                                     if (j==4 || j==len)
  895.                                         return FALSE;
  896.                                     for (k=4; k<j; k++)
  897.                                     {
  898.                                         switch (src[i+2])
  899.                                         {
  900.                                         case 'd':
  901.                                             if ((src[i+k]>='0' && src[i+k]<='9') || src[i+k]=='-')
  902.                                                 continue;
  903.                                             else
  904.                                                 return FALSE; // Non-digit found.
  905.                                             break;
  906.  
  907.                                         case 'h':
  908.                                             if ((src[i+k]>='0' && src[i+k]<='9') ||
  909.                                              (src[i+k]>='a' && src[i+k]<='f'))
  910.                                                 continue;
  911.                                             else
  912.                                                 return FALSE; // Non-hex-digit.
  913.                                             break;
  914.  
  915.                                         case 'o': case 'l': // float or double.
  916.                                             if ((src[i+k]>='0' && src[i+k]<='9') || src[i+k]=='-' || src[i+k]=='.' || src[i+k]=='e' || src[i+k]=='E')
  917.                                                 continue;
  918.                                             else
  919.                                                 return FALSE;
  920.                                             break;
  921.                                         }
  922.                                     }
  923.                                     switch (src[i+1])
  924.                                     {
  925.                                     default:
  926.                                     case 'b': return 1;
  927.                                     case 'w': return 2;
  928.                                     case 'l': return 4;
  929.                                     case 'f': return 4;
  930.                                     case 'd': return 8;
  931.                                     }
  932.                                 }
  933.                                 else
  934.                                     return FALSE; // No ':'.
  935.                             }
  936.                             else
  937.                                 return FALSE; // No space for ':'.
  938.                             break;
  939.                         
  940.                         default:
  941.                             return FALSE; // Wrong second option.
  942.                     }
  943.                 }
  944.                 else
  945.                     return FALSE; // No space for option 2.
  946.                 break;
  947.             
  948.             default:
  949.                 return FALSE; // Wrong first option.
  950.                 break;
  951.             }
  952.         }
  953.         else
  954.             return FALSE; // No space for option 1;
  955.     }
  956.     else
  957.         return FALSE; // No '<'.
  958. }
  959.  
  960. #ifdef _UNICODE
  961. int CFshedView::create_bc_translation (char** ppd, LPCTSTR src, int srclen, int charmode, int binmode)
  962. {
  963.     int destLen = WideCharToMultiByte(CP_ACP, 0, (LPWSTR)src, (int)_tcslen(src), NULL, NULL, NULL, NULL);
  964.     char *charstring = new char[destLen + 1];
  965.     WideCharToMultiByte(CP_ACP, 0, (LPWSTR)src, (int)_tcslen(src), 
  966.         charstring, destLen, NULL, NULL);  
  967.     charstring[destLen] = 0;
  968.     int nRtn = create_bc_translation(ppd, charstring, srclen, charmode, binmode);
  969.     delete charstring;
  970.     return nRtn;
  971. }
  972. #endif
  973.  
  974. //-------------------------------------------------------------------
  975. // Create translation of bytecode-string.
  976. // Return: Length of resulting string.
  977. // ppd = pointer to pointer to result, must be delete[]-ed later.
  978. // If the input string was empty, no translated array is created and zero is returned.
  979. int CFshedView::create_bc_translation (char** ppd, const char* src, int srclen, int charmode, int binmode)
  980. {
  981.     int destlen = calc_bctrans_destlen (src, srclen);
  982.     if (destlen > 0)
  983.     {
  984.         *ppd = new char[destlen];
  985.         create_bc_translation (*ppd, src, srclen, charmode, binmode);
  986.         return destlen;
  987.     }
  988.     else
  989.     {
  990.         // Empty input string => don't allocate anything and return 0.
  991.         *ppd = NULL;
  992.         return 0;
  993.     }
  994. }
  995.  
  996. //-------------------------------------------------------------------
  997. // Translate an array of bytes to a text string using special syntax.
  998. // Return: Length of string including zero-byte.
  999. int CFshedView::translate_bytes_to_BC (CString &strTranslated, unsigned char* src, int srclen)
  1000. {
  1001.     int i, k = 0;
  1002.     char buf[16];
  1003.    strTranslated.Empty();
  1004.     for (i=0; i<srclen; i++)
  1005.     {
  1006.         if (src[i] == '<')
  1007.         {
  1008.             strTranslated += '\\';
  1009.             strTranslated += '<';
  1010.         }
  1011.         else if( src[i] == '\\' )
  1012.         {
  1013.             strTranslated += '\\';
  1014.             strTranslated += '\\';
  1015.         }
  1016.         else if (src[i] >= 32 && src[i] < 127)
  1017.         {
  1018.             strTranslated += src[i];
  1019.         }
  1020.         else if( src[i]==10 || src[i]==13 )
  1021.         {
  1022.             strTranslated += src[i];
  1023.         }
  1024.         else
  1025.         {
  1026.             strTranslated += '<';
  1027.             strTranslated += 'b';
  1028.             strTranslated += 'h';
  1029.             strTranslated += ':';
  1030.             sprintf (buf, "%2.2x", src[i]);
  1031.             strTranslated += buf[0];
  1032.             strTranslated += buf[1];
  1033.             strTranslated += '>';
  1034.         }
  1035.     }
  1036.     return strTranslated.GetLength();
  1037. }
  1038.  
  1039. //-------------------------------------------------------------------
  1040. // Used with translate_bytes_to_BC.
  1041. // Return: Length of bytecode-string including zero-byte.
  1042. int CFshedView::byte_to_BC_destlen (char* src, int srclen)
  1043. {
  1044.     int i, destlen = 1;
  1045.     for (i=0; i<srclen; i++)
  1046.     {
  1047.         if (src[i] == '<')
  1048.             destlen+=2; // Escapecode needed.
  1049.         else if( src[i] == '\\' )
  1050.             destlen+=2; // Escapecode needed.
  1051.         else if (src[i] >= 32 && src[i] < 127)
  1052.             destlen++; // Normal char.
  1053.         else if( src[i]==10 || src[i]==13 )
  1054.             destlen++; // LF/CR.
  1055.         else
  1056.             destlen+=7; // Escapecode needed.
  1057.     }
  1058.     return destlen;
  1059. }
  1060.  
  1061. //-------------------------------------------------------------------
  1062. // If filesize changes, scrollbars etc. must be adjusted.
  1063. void CFshedView::update_for_new_datasize ()
  1064. {
  1065.     RECT r;
  1066.     GetClientRect (&r);
  1067.     resize_window (r.right, r.bottom);
  1068. }
  1069.  
  1070. //-------------------------------------------------------------------
  1071. char CFshedView::TranslateAnsiToOem (char c)
  1072. {
  1073.     TCHAR sbuf[2];
  1074.     char dbuf[2];
  1075.     sbuf[0]=c;
  1076.     sbuf[1]=0;
  1077.     CharToOemBuff (sbuf, dbuf, 1);
  1078.     return dbuf[0];
  1079. }
  1080.  
  1081. //--------------------------------------------------------------------------------------------
  1082. // Window was resized to new width of cx and new height of cy.
  1083. int CFshedView::resize_window (int cx, int cy)
  1084. {
  1085.     // Get font data.
  1086.    HDC hdc = ::GetDC (m_hWnd);
  1087.     if (make_font (hdc))
  1088.    {
  1089.        HFONT of = (HFONT) SelectObject( hdc, hFont );
  1090.        TEXTMETRIC tm;
  1091.        GetTextMetrics (hdc, &tm);
  1092.        m_stScreenSettings.cxChar = tm.tmAveCharWidth;
  1093.        m_stScreenSettings.cxCaps = (tm.tmPitchAndFamily & 1 ? 3 : 2) * m_stScreenSettings.cxChar / 2;
  1094.        m_stScreenSettings.cyChar = tm.tmHeight + tm.tmExternalLeading;
  1095.        SelectObject (hdc, of);
  1096.    }
  1097.    ::ReleaseDC (m_hWnd, hdc);
  1098.    
  1099.     //--------------------------------------------
  1100.     // Resize statusbar.
  1101.     int x, y, x2, y2;
  1102.     RECT rWindow;
  1103.    ::GetWindowRect (hwndStatusBar, &rWindow);
  1104.     y2 = rWindow.bottom - rWindow.top;
  1105.     x = 0;
  1106.     y = cy - y2;
  1107.     x2 = cx;
  1108.    ::MoveWindow (hwndStatusBar, x, y, x2, y2, TRUE);
  1109.  
  1110.     int y3 = 0;
  1111. //   ::GetWindowRect (hwndToolBar, &rWindow);
  1112. //    m_stScreenSettings.iToolbarHeight = y3 = rWindow.bottom - rWindow.top;
  1113. //    x = 0;
  1114. //    y = 0;
  1115. //    x2 = cx;
  1116. //   ::MoveWindow (hwndToolBar, x, y, x2, y3, TRUE);
  1117.  
  1118.     // Get client size.
  1119.     m_stScreenSettings.cxClient = cx;
  1120.     m_stScreenSettings.cyClient = cy - y2 - y3;
  1121.  
  1122.     // Resize scrollbars.
  1123.     int cyh = GetSystemMetrics (SM_CYHSCROLL),
  1124.         cxv = GetSystemMetrics (SM_CXVSCROLL);
  1125.    ::MoveWindow (hwndHBar, 0, m_stScreenSettings.cyClient - cyh + y3, m_stScreenSettings.cxClient - cxv, cyh, FALSE);
  1126.    ::MoveWindow (hwndVBar, m_stScreenSettings.cxClient - cxv, y3, cxv, m_stScreenSettings.cyClient, FALSE);
  1127.    ::RedrawWindow (hwndHBar, NULL, NULL, RDW_INVALIDATE | RDW_ERASENOW | RDW_ALLCHILDREN);
  1128.    ::RedrawWindow (hwndVBar, NULL, NULL, RDW_INVALIDATE | RDW_ERASENOW | RDW_ALLCHILDREN);
  1129.  
  1130.     // Resize client area.
  1131.     m_stScreenSettings.cxClient -= cxv;
  1132.     m_stScreenSettings.cyClient -= cyh;
  1133.  
  1134.     //--------------------------------------------
  1135.     // Set statusbar divisions.
  1136.     int statbarw;
  1137.    if (IsZoomed())
  1138.         statbarw = cx;
  1139.     else
  1140.         statbarw = m_stScreenSettings.cxClient;
  1141.     // Allocate an array for holding the right edge coordinates.
  1142.     HLOCAL hloc = LocalAlloc (LHND, sizeof(int) * 3);
  1143.     int* lpParts = (int*) LocalLock(hloc); 
  1144.  
  1145.     // Calculate the right edge coordinate for each part, and
  1146.     // copy the coordinates to the array.
  1147.     lpParts[0] = statbarw*4/6;
  1148.     lpParts[1] = statbarw*5/6;
  1149.     lpParts[2] = statbarw;
  1150.  
  1151.     // Tell the status window to create the window parts. 
  1152.    ::SendMessage (hwndStatusBar, SB_SETPARTS, (WPARAM) 3,
  1153.         (LPARAM) lpParts);
  1154.  
  1155.     // Free the array, and return. 
  1156.     LocalUnlock(hloc); 
  1157.     LocalFree(hloc);
  1158.     //--------------------------------------------
  1159.  
  1160.     m_stScreenSettings.cxBuffer = max (1, m_stScreenSettings.cxClient / m_stScreenSettings.cxChar);
  1161.     m_stScreenSettings.cyBuffer = max (1, m_stScreenSettings.cyClient / m_stScreenSettings.cyChar);
  1162.     // Adjust bytes per line to width of window.
  1163.     // m_stScreenSettings.cxBuffer = maximal width of client-area in chars.
  1164.     if( App->m_bAutomaticBPL )
  1165.     {
  1166.         int bytemax = m_stScreenSettings.cxBuffer-App->m_iOffsetLen-m_stScreenSettings.iByteSpace-m_stScreenSettings.iCharSpace;
  1167.         App->m_iBytesPerLine = bytemax / 4;
  1168.         if (App->m_iBytesPerLine < 1)
  1169.             App->m_iBytesPerLine = 1;
  1170.     }
  1171.     // Caret or end of selection will be vertically centered if line not visible.
  1172.     if( bSelected )
  1173.     {
  1174.         if( iEndOfSelection / App->m_iBytesPerLine < m_stScreenSettings.iCurLine || iEndOfSelection / App->m_iBytesPerLine > m_stScreenSettings.iCurLine + m_stScreenSettings.cyBuffer )
  1175.             m_stScreenSettings.iCurLine = max( 0, iEndOfSelection / App->m_iBytesPerLine - m_stScreenSettings.cyBuffer / 2 );
  1176.     }
  1177.     else
  1178.     {
  1179.         if( m_stScreenSettings.iCurByte/App->m_iBytesPerLine < m_stScreenSettings.iCurLine || m_stScreenSettings.iCurByte/App->m_iBytesPerLine > m_stScreenSettings.iCurLine + m_stScreenSettings.cyBuffer )
  1180.             m_stScreenSettings.iCurLine = max( 0, m_stScreenSettings.iCurByte/App->m_iBytesPerLine-m_stScreenSettings.cyBuffer/2 );
  1181.     }
  1182.    ASSERT(m_stScreenSettings.iCurLine >= 0);
  1183.     adjust_vscrollbar();
  1184.  
  1185.     m_stScreenSettings.iCharsPerLine = App->m_iOffsetLen + m_stScreenSettings.iByteSpace + App->m_iBytesPerLine*3 + m_stScreenSettings.iCharSpace + App->m_iBytesPerLine;
  1186.  
  1187.     // Get number of lines to display.
  1188.     if ((Doc->DataArray.GetLength()+1) % App->m_iBytesPerLine == 0)
  1189.         m_stScreenSettings.iNumlines = (Doc->DataArray.GetLength()+1) / App->m_iBytesPerLine;
  1190.     else
  1191.         m_stScreenSettings.iNumlines = (Doc->DataArray.GetLength()+1) / App->m_iBytesPerLine + 1;
  1192.     TRACE("Num Bytes %d, per line %d\n", Doc->DataArray.GetLength(), App->m_iBytesPerLine);
  1193. //    if (m_stScreenSettings.iNumlines <= 0xffff)
  1194.         m_stScreenSettings.iVscrollMax = m_stScreenSettings.iNumlines-1;
  1195. //    else
  1196. //        m_stScreenSettings.iVscrollMax = 0xffff;
  1197.  
  1198.    SCROLLINFO si;
  1199.    memset(&si, 0, sizeof(si));
  1200.    si.cbSize = sizeof(si);
  1201.    si.fMask = SIF_POS | SIF_RANGE;
  1202.    si.nMax = m_stScreenSettings.iVscrollMax;
  1203.    si.nPos = m_stScreenSettings.iVscrollPos;
  1204.    TRACE("Range max %d, pos %d\n", si.nMax, si.nPos);
  1205.    ::SetScrollInfo(hwndVBar, SB_CTL, &si, TRUE);
  1206. //   ::SetScrollRange (hwndVBar, SB_CTL, 0, m_stScreenSettings.iVscrollMax, FALSE);
  1207. //   ::SetScrollPos (hwndVBar, SB_CTL, m_stScreenSettings.iVscrollPos, TRUE);
  1208.  
  1209.     m_stScreenSettings.iHscrollMax = m_stScreenSettings.iCharsPerLine - 1;
  1210.     m_stScreenSettings.iHscrollPos = 0;
  1211.    memset(&si, 0, sizeof(si));
  1212.    si.cbSize = sizeof(si);
  1213.    si.fMask = SIF_POS | SIF_RANGE;
  1214.    si.nMax = m_stScreenSettings.iHscrollMax;
  1215.    si.nPos = m_stScreenSettings.iHscrollPos;
  1216.    ::SetScrollInfo(hwndHBar, SB_CTL, &si, TRUE);
  1217. //   ::SetScrollRange (hwndHBar, SB_CTL, 0, m_stScreenSettings.iHscrollMax, FALSE);
  1218. //   ::SetScrollPos (hwndHBar, SB_CTL, m_stScreenSettings.iHscrollPos, TRUE);
  1219.  
  1220.     set_wnd_title ();
  1221.     if (this == GetFocus ())
  1222.         set_caret_pos ();
  1223.     repaint ();
  1224.     return TRUE;
  1225. }
  1226.  
  1227. //--------------------------------------------------------------------------------------------
  1228. // Set the window title and the statusbar text.
  1229. void CFshedView::set_wnd_title()
  1230. {
  1231.     TCHAR buf[512];
  1232.     if (_tcslen (Doc->filename) != 0)
  1233.     {
  1234.         // Change window title.
  1235.         if (Doc->bFilestatusChanged)
  1236.         {
  1237.             _stprintf (buf, _T("[%s"), Doc->filename);
  1238.             if (GetDocument()->IsModified())
  1239.                 _tcscat (buf, _T(" *"));
  1240.             _tcscat (buf, _T("]"));
  1241.             if (Doc->bPartialOpen==TRUE)
  1242.                 _tcscat (buf, _T(" - P"));
  1243.             _tcscat (buf, _T(" - frhed"));
  1244.             SetWindowText (buf);
  1245.             Doc->bFilestatusChanged = FALSE;
  1246.         }
  1247.         // Selection going on.
  1248.         if (bSelected == TRUE)
  1249.         {
  1250.             if (iEndOfSelection >= iStartOfSelection)
  1251.             {
  1252.                 _stprintf (buf, _T("Selected: Offset %d=0x%x to %d=0x%x (%d byte(s))"), iStartOfSelection, iStartOfSelection,
  1253.                     iEndOfSelection, iEndOfSelection, iEndOfSelection-iStartOfSelection+1);
  1254.             }
  1255.             else
  1256.             {
  1257.                 _stprintf (buf, _T("Selected: Offset %d=0x%x to %d=0x%x (%d byte(s))"), iEndOfSelection, iEndOfSelection,
  1258.                     iStartOfSelection, iStartOfSelection, iStartOfSelection-iEndOfSelection+1);
  1259.             }
  1260.             ::SendMessage (hwndStatusBar, SB_SETTEXT, 0, (LPARAM) buf);
  1261.         }
  1262.         else // Normal display.
  1263.         {
  1264. //Pabs changed - \t removed from end of string literal ("Offset %d=0x%x\t" -> "Offset %d=0x%x")
  1265.             _stprintf (buf, _T("Offset %d=0x%x"), m_stScreenSettings.iCurByte, m_stScreenSettings.iCurByte);
  1266. //end
  1267.             int wordval, longval;
  1268.             TCHAR buf2[80];
  1269. //Pabs changed - line insert
  1270.             if (Doc->DataArray.GetLength()-m_stScreenSettings.iCurByte > 0){//if we are not looking at the End byte
  1271.                 // R. Kibria: changed the output slightly (used to be "Bits = 0b").
  1272.                 _tcscat (buf, _T("   Bits="));//append stuff to status text
  1273.                 TCHAR zzz = Doc->DataArray[m_stScreenSettings.iCurByte];//quicker to have a tmp var than to call operator[] 8 times
  1274.                 for(int i=0;i<8;i++)buf2[i]=((zzz>>i)&0x1?'1':'0');//Extract bits
  1275.                 for(int i=0;i<4;i++)swap(buf2[i],buf2[7-i]);//flip order-for some reason it doesn't display correctly going i-- or i++ in for loop
  1276.                 buf2[8]='\0';//terminate string
  1277.                 _tcscat (buf, buf2);//append to status text
  1278.             }
  1279.             _tcscat (buf, _T("\t"));//add that \t back on to the status text
  1280. //end
  1281.             if (App->m_bUnsignedView) // Values signed/unsigned?
  1282.             {
  1283.                 // UNSIGNED
  1284.                 if (App->m_iBinaryMode == LITTLEENDIAN_MODE)
  1285.                 {
  1286.                     // UNSIGNED LITTLEENDIAN_MODE
  1287.                     // Decimal value of byte.
  1288.                     if (Doc->DataArray.GetLength ()-m_stScreenSettings.iCurByte >= 1)
  1289.                     {
  1290.                         _stprintf (buf2, _T("\tUnsigned: B:%u"), (unsigned int) Doc->DataArray[m_stScreenSettings.iCurByte]);
  1291.                         _tcscat (buf, buf2);
  1292.                     }
  1293.                     else
  1294.                     {
  1295.                         _tcscpy(buf2, _T("\tEND"));
  1296.                         _tcscat(buf, buf2);
  1297.                     }
  1298.                     // Space enough for a word?
  1299.                     if (Doc->DataArray.GetLength ()-m_stScreenSettings.iCurByte >= 2)
  1300.                     {
  1301.                         // Space enough for a word.
  1302.                         wordval = (Doc->DataArray[m_stScreenSettings.iCurByte+1] << 8) | Doc->DataArray[m_stScreenSettings.iCurByte];
  1303.                         _stprintf (buf2, _T(",W:%u"), (unsigned int) wordval);
  1304.                         _tcscat (buf, buf2);
  1305.                     }
  1306.                     if (Doc->DataArray.GetLength ()-m_stScreenSettings.iCurByte >= 4)
  1307.                     {
  1308.                         // Space enough for a longword.
  1309.                         longval = wordval | (((Doc->DataArray[m_stScreenSettings.iCurByte + 3] << 8) | Doc->DataArray[m_stScreenSettings.iCurByte + 2]) << 16);
  1310.                         _stprintf (buf2, _T(",L:%u"), (unsigned int) longval);
  1311.                         _tcscat (buf, buf2);
  1312.                     }
  1313.                 }
  1314.                 else
  1315.                 {
  1316.                     // UNSIGNED BIGENDIAN_MODE
  1317.                     // Decimal value of byte.
  1318.                     if (Doc->DataArray.GetLength ()-m_stScreenSettings.iCurByte >= 1)
  1319.                     {
  1320.                         _stprintf (buf2, _T("\tUnsigned: B:%u"), (unsigned int) Doc->DataArray[m_stScreenSettings.iCurByte]);
  1321.                         _tcscat(buf, buf2);
  1322.                     }
  1323.                     else
  1324.                     {
  1325.                         _tcscpy(buf2, _T("\tEND"));
  1326.                         _tcscat(buf, buf2);
  1327.                     }
  1328.                     // Space enough for a word?
  1329.                     if (Doc->DataArray.GetLength ()-m_stScreenSettings.iCurByte >= 2)
  1330.                     {
  1331.                         // Space enough for a word.
  1332.                         wordval = (Doc->DataArray[m_stScreenSettings.iCurByte] << 8) | Doc->DataArray[m_stScreenSettings.iCurByte+1];
  1333.                         _stprintf(buf2, _T(",W:%u"), (unsigned int) wordval);
  1334.                         _tcscat (buf, buf2);
  1335.                     }
  1336.                     if (Doc->DataArray.GetLength ()-m_stScreenSettings.iCurByte >= 4)
  1337.                     {
  1338.                         // Space enough for a longword.
  1339.                         longval = (wordval<<16) | (Doc->DataArray[m_stScreenSettings.iCurByte+2]<<8) | (Doc->DataArray[m_stScreenSettings.iCurByte+3]);
  1340.                         _stprintf (buf2, _T(",L:%u"), (unsigned int) longval);
  1341.                         _tcscat (buf, buf2);
  1342.                     }
  1343.                 }
  1344.             }
  1345.             else // SIGNED
  1346.             {
  1347.                 if (App->m_iBinaryMode == LITTLEENDIAN_MODE)
  1348.                 {
  1349.                     // SIGNED LITTLEENDIAN_MODE
  1350.                     // Decimal value of byte.
  1351.                     if (Doc->DataArray.GetLength ()-m_stScreenSettings.iCurByte >= 1)
  1352.                     {
  1353.                         _stprintf(buf2, _T("\tSigned: B:%d"), (int) (signed char) Doc->DataArray[m_stScreenSettings.iCurByte]);
  1354.                         _tcscat(buf, buf2);
  1355.                     }
  1356.                     else
  1357.                     {
  1358.                         _stprintf (buf2, _T("\tEND"));
  1359.                         _tcscat (buf, buf2);
  1360.                     }
  1361.                     // Space enough for a word?
  1362.                     if (Doc->DataArray.GetLength ()-m_stScreenSettings.iCurByte >= 2)
  1363.                     {
  1364.                         // Space enough for a word.
  1365.                         wordval = (Doc->DataArray[m_stScreenSettings.iCurByte + 1] << 8) | Doc->DataArray[m_stScreenSettings.iCurByte];
  1366.                         _stprintf (buf2, _T(",W:%d"), (int) (signed short) wordval);
  1367.                         _tcscat (buf, buf2);
  1368.                     }
  1369.                     if (Doc->DataArray.GetLength ()-m_stScreenSettings.iCurByte >= 4)
  1370.                     {
  1371.                         // Space enough for a longword.
  1372.                         longval = wordval | (((Doc->DataArray[m_stScreenSettings.iCurByte + 3] << 8) | Doc->DataArray[m_stScreenSettings.iCurByte + 2]) << 16);
  1373.                         _stprintf (buf2, _T(",L:%d"), (signed int) longval);
  1374.                         _tcscat (buf, buf2);
  1375.                     }
  1376.                 }
  1377.                 else
  1378.                 {
  1379.                     // SIGNED BIGENDIAN_MODE
  1380.                     // Decimal value of byte.
  1381.                     if (Doc->DataArray.GetLength ()-m_stScreenSettings.iCurByte >= 1)
  1382.                     {
  1383.                         _stprintf (buf2, _T("\tSigned: B:%d"), (signed char) Doc->DataArray[m_stScreenSettings.iCurByte]);
  1384.                         _tcscat (buf, buf2);
  1385.                     }
  1386.                     else
  1387.                     {
  1388.                         _stprintf (buf2, _T("\tEND"));
  1389.                         _tcscat (buf, buf2);
  1390.                     }
  1391.                     // Space enough for a word.
  1392.                     if (Doc->DataArray.GetLength ()-m_stScreenSettings.iCurByte >= 2)
  1393.                     {
  1394.                         // Space enough for a longword.
  1395.                         wordval = (Doc->DataArray[m_stScreenSettings.iCurByte] << 8) | Doc->DataArray[m_stScreenSettings.iCurByte+1];
  1396.                         _stprintf (buf2, _T(",W:%d"), (int) (signed short) wordval);
  1397.                         _tcscat (buf, buf2);
  1398.                     }
  1399.                     if (Doc->DataArray.GetLength ()-m_stScreenSettings.iCurByte >= 4)
  1400.                     {
  1401.                         // Space enough for a longword.
  1402.                         longval = (wordval<<16) | (Doc->DataArray[m_stScreenSettings.iCurByte+2]<<8) | (Doc->DataArray[m_stScreenSettings.iCurByte+3]);
  1403.                         _stprintf (buf2, _T(",L:%d"), (signed int) longval);
  1404.                         _tcscat (buf, buf2);
  1405.                     }
  1406.                 }
  1407.             }
  1408.          ::SendMessage (hwndStatusBar, SB_SETTEXT, 0, (LPARAM) buf);
  1409.  
  1410.             // Character set, input mode or read-only, binary mode.
  1411.             switch (App->m_iCharacterSet)
  1412.             {
  1413.             case ANSI_FIXED_FONT:
  1414.                 _tcscpy(buf, _T("\tANSI"));
  1415.                 break;
  1416.  
  1417.             case OEM_FIXED_FONT:
  1418.                 _tcscpy(buf, _T("\tOEM"));
  1419.                 break;
  1420.             }
  1421.  
  1422.             if (Doc->bReadOnly)
  1423.             {
  1424.                 _tcscpy(buf2, _T(" / READ"));
  1425.                 _tcscat (buf, buf2);
  1426.             }
  1427.             else if (iInsertMode)
  1428.             {
  1429.                 _tcscpy(buf2, _T(" / INS"));
  1430.                 _tcscat (buf, buf2);
  1431.             }
  1432.             else
  1433.             {
  1434.                 _tcscpy(buf2, _T(" / OVR"));
  1435.                 _tcscat (buf, buf2);
  1436.             }
  1437.             if (App->m_iBinaryMode == LITTLEENDIAN_MODE)
  1438.             {
  1439.                 _tcscpy(buf2, _T(" / L")); // Intel
  1440.                 _tcscat (buf, buf2);
  1441.             }
  1442.             else if (App->m_iBinaryMode == BIGENDIAN_MODE)
  1443.             {
  1444.                 _tcscpy(buf2, _T(" / B")); // Motorola
  1445.                 _tcscat (buf, buf2);
  1446.             }
  1447.          ::SendMessage (hwndStatusBar, SB_SETTEXT, 1, (LPARAM) buf);
  1448.             
  1449.             // File size.
  1450.             _stprintf (buf, _T("\tSize: %u"), Doc->DataArray.GetLength ());
  1451.          ::SendMessage (hwndStatusBar, SB_SETTEXT, 2, (LPARAM) buf);
  1452.         }
  1453.     }
  1454.     else
  1455.     {
  1456.         SetWindowText (_T("fshed"));
  1457.       ::SendMessage (hwndStatusBar, WM_SETTEXT, 0, (LPARAM) _T("No file loaded"));
  1458.     }
  1459. }
  1460.  
  1461. //--------------------------------------------------------------------------------------------
  1462. // Set Caret position.
  1463. void CFshedView::set_caret_pos ()
  1464. {
  1465.     if (bSelected)
  1466.     {
  1467.       ::SetCaretPos (-m_stScreenSettings.cxChar, -m_stScreenSettings.cyChar + m_stScreenSettings.iToolbarHeight);
  1468.         return;
  1469.     }
  1470.  
  1471.     int iCaretLine = m_stScreenSettings.iCurByte / App->m_iBytesPerLine,
  1472.         iBottomLine = m_stScreenSettings.iCurLine + m_stScreenSettings.cyBuffer - 1;
  1473.  
  1474.     switch (m_iEnteringMode)    
  1475.     {
  1476.     case CHARS:
  1477.         if (iCaretLine >= m_stScreenSettings.iCurLine && iCaretLine <= iBottomLine && Doc->filename[0] != '\0')
  1478.         {
  1479.             int y = iCaretLine - m_stScreenSettings.iCurLine,
  1480.                 x = App->m_iOffsetLen+m_stScreenSettings.iByteSpace+App->m_iBytesPerLine*3+m_stScreenSettings.iCharSpace
  1481.                 - m_stScreenSettings.iHscrollPos + (m_stScreenSettings.iCurByte%App->m_iBytesPerLine);
  1482.          ::SetCaretPos (CLIENT_BORDER_WIDTH + x*m_stScreenSettings.cxChar, CLIENT_BORDER_WIDTH + y*m_stScreenSettings.cyChar + m_stScreenSettings.iToolbarHeight);
  1483.         }
  1484.         else
  1485.          ::SetCaretPos (-m_stScreenSettings.cxChar, -m_stScreenSettings.cyChar + m_stScreenSettings.iToolbarHeight);
  1486.         break;
  1487.     case BYTES:
  1488.         // If caret in vertical visible area...
  1489.         if (iCaretLine >= m_stScreenSettings.iCurLine && iCaretLine <= iBottomLine && Doc->filename[0] != '\0')
  1490.         {
  1491.             int y = iCaretLine - m_stScreenSettings.iCurLine,
  1492.                 x = App->m_iOffsetLen+m_stScreenSettings.iByteSpace + (m_stScreenSettings.iCurByte%App->m_iBytesPerLine)*3 - m_stScreenSettings.iHscrollPos + m_stScreenSettings.iCurNibble;
  1493.          ::SetCaretPos (CLIENT_BORDER_WIDTH + x*m_stScreenSettings.cxChar, CLIENT_BORDER_WIDTH + y*m_stScreenSettings.cyChar + m_stScreenSettings.iToolbarHeight);
  1494.         }
  1495.         else
  1496.          ::SetCaretPos (-m_stScreenSettings.cxChar, -m_stScreenSettings.cyChar + m_stScreenSettings.iToolbarHeight);
  1497.     }
  1498. }
  1499.  
  1500. //--------------------------------------------------------------------------------------------
  1501. // Repaints the whole window.
  1502. int CFshedView::repaint( int line )
  1503. {
  1504.     HideCaret();
  1505.     iUpdateLine = line;
  1506.     InvalidateRect(NULL, FALSE );
  1507.     UpdateWindow();
  1508.     ShowCaret();
  1509.     return 0;
  1510. }
  1511.  
  1512. //--------------------------------------------------------------------------------------------
  1513. // Clear everything up.
  1514. void CFshedView::clear_all ()
  1515. {
  1516.     App->m_iOffsetLen = 8;
  1517.     m_stScreenSettings.iByteSpace = 2;
  1518.     App->m_iBytesPerLine = 16;
  1519.     m_stScreenSettings.iCharSpace = 1;
  1520.     m_stScreenSettings.iCharsPerLine = App->m_iOffsetLen + m_stScreenSettings.iByteSpace + App->m_iBytesPerLine*3 + m_stScreenSettings.iCharSpace + App->m_iBytesPerLine;
  1521.     Doc->DataArray.ClearAll ();
  1522.     Doc->filename[0] = '\0';
  1523.     m_stScreenSettings.iVscrollMax = 0;
  1524.     m_stScreenSettings.iVscrollPos = 0;
  1525.     m_stScreenSettings.iVscrollInc = 0;
  1526.     m_stScreenSettings.iHscrollMax = 0;
  1527.     m_stScreenSettings.iHscrollPos = 0;
  1528.     m_stScreenSettings.iHscrollInc = 0;
  1529.     m_stScreenSettings.iCurLine = 0;
  1530.     m_stScreenSettings.iCurByte = 0;
  1531.     m_stScreenSettings.iCurNibble = 0;
  1532. }
  1533.  
  1534. //--------------------------------------------------------------------------------------------
  1535. // Set the vertical scrollbar position.
  1536. void CFshedView::adjust_vscrollbar ()
  1537. {
  1538.     m_stScreenSettings.iVscrollPos = (int) ((float)m_stScreenSettings.iCurLine * ((float)m_stScreenSettings.iVscrollMax)/(float)(m_stScreenSettings.iNumlines-1));
  1539.    SCROLLINFO si;
  1540.    memset(&si, 0, sizeof(si));
  1541.    si.cbSize = sizeof(si);
  1542.    si.fMask = SIF_POS;
  1543.    si.nPos = m_stScreenSettings.iVscrollPos;
  1544.    ::SetScrollInfo(hwndVBar, SB_CTL, &si, TRUE);
  1545. //   ::SetScrollPos (hwndVBar, SB_CTL, m_stScreenSettings.iVscrollPos, TRUE);
  1546. }
  1547.  
  1548. //--------------------------------------------------------------------------------------------
  1549. // Set the horizontal scrollbar position.
  1550. void CFshedView::adjust_hscrollbar ()
  1551. {
  1552.    SCROLLINFO si;
  1553.    memset(&si, 0, sizeof(si));
  1554.    si.cbSize = sizeof(si);
  1555.    si.fMask = SIF_POS;
  1556.    si.nPos = m_stScreenSettings.iHscrollPos;
  1557.    ::SetScrollInfo(hwndHBar, SB_CTL, &si, TRUE);
  1558. //   ::SetScrollPos (hwndHBar, SB_CTL, m_stScreenSettings.iHscrollPos, TRUE);
  1559. }
  1560.  
  1561. //-------------------------------------------------------------------
  1562. int CFshedView::make_font(HDC hdc, int nHeight)
  1563. {
  1564.    //if (m_bPrinting)
  1565.    //   return 0;
  1566.  
  1567.     if (hFont != NULL)
  1568.         DeleteObject (hFont);
  1569.     //HDC hdc = ::GetDC (m_hWnd);
  1570.     if (nHeight == 0)
  1571.         nHeight = -MulDiv(App->m_iFontSize, GetDeviceCaps(hdc, LOGPIXELSY), 72);
  1572.     //::ReleaseDC (m_hWnd, hdc);
  1573.     int cset;
  1574.     if (App->m_iCharacterSet==ANSI_FIXED_FONT)
  1575.         cset = ANSI_CHARSET;
  1576.     else
  1577.         cset = OEM_CHARSET;
  1578.     hFont = CreateFont (nHeight,0,0,0,0,0,0,0,cset,OUT_DEFAULT_PRECIS,
  1579.         CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,FIXED_PITCH | FF_DONTCARE,0);
  1580.     return 1;
  1581. }
  1582.  
  1583. //--------------------------------------------------------------------------------------------
  1584. // Repaint one line in the window.
  1585. void CFshedView::print_line (HDC hdc, int line, char* linbuf, HBRUSH hbr )
  1586. {
  1587.     // line = absolute line number.
  1588.     // if line not visible:
  1589.     if (line < m_stScreenSettings.iCurLine || line > m_stScreenSettings.iCurLine + m_stScreenSettings.cyBuffer)
  1590.         return;
  1591.    if (line < 0)
  1592.    {
  1593.       TRACE("Invalid line %d not drawn\n", line);
  1594.       return;
  1595.    }
  1596.  
  1597.     int startpos = line * App->m_iBytesPerLine, endpos, i = 0, m;
  1598.     char buf[80], c;
  1599.  
  1600.     // Return if this line does not even contain the end-of-file double
  1601.     // underscore (at index upperbound+1).
  1602.     if( startpos > Doc->DataArray.GetUpperBound() + 1 )
  1603.     {
  1604.         return;
  1605.     }
  1606.  
  1607.     // Write offset.
  1608.     sprintf (buf, "%%%d.%dx", App->m_iOffsetLen, App->m_iOffsetLen);
  1609.     for (m=0; m<m_stScreenSettings.iByteSpace; m++)
  1610.         buf[5+m] = ' ';
  1611.     buf[5+m] = '\0';
  1612.     sprintf (linbuf, buf, startpos);
  1613.     
  1614.     // Last line reached? Then only write rest of bytes.
  1615.     // startpos+App->m_iBytesPerLine-1 = Last byte in current line.
  1616.     if (startpos+App->m_iBytesPerLine > Doc->DataArray.GetLength ())
  1617.     {
  1618.         // If the first byte of the next line would not be valid, then
  1619.         // only print the bytes up to and including the last byte of the file.
  1620.         endpos = Doc->DataArray.GetUpperBound()+1;
  1621.     }
  1622.     else
  1623.     {
  1624.         // Print the bytes up to the end of this line, they are all valid.
  1625.         endpos = startpos+App->m_iBytesPerLine-1;
  1626.     }
  1627.     // Could happen on arrow down, so that last line is on bottom of window:
  1628.     if( endpos < startpos )
  1629.     {
  1630.         endpos = startpos;
  1631.     }
  1632.     // Write bytes.
  1633.     m = App->m_iOffsetLen+m_stScreenSettings.iByteSpace; // Index of first byte in line.
  1634.     for (i=startpos; i<=endpos; i++)
  1635.     {
  1636.         if (i == Doc->DataArray.GetLength())
  1637.         {
  1638.             linbuf[m++] = '_';
  1639.             linbuf[m++] = '_';
  1640.             linbuf[m++] = ' ';
  1641.         }
  1642.         else
  1643.         {
  1644.             c = (Doc->DataArray[i] >> 4);
  1645.             if( c < 10 )
  1646.                 c += '0';
  1647.             else
  1648.                 c = c - 10 + 'a';
  1649.             linbuf[m++] = c;
  1650.             c = (Doc->DataArray[i] & 0x0f);
  1651.             if( c < 10 )
  1652.                 c += '0';
  1653.             else
  1654.                 c = c - 10 + 'a';
  1655.             linbuf[m++] = c;
  1656.             linbuf[m++] = ' ';
  1657.         }
  1658.     }
  1659.     // Write spaces for non-existant bytes.
  1660.     if (endpos-startpos < App->m_iBytesPerLine-1)
  1661.     {
  1662.         for (i=0; i<App->m_iBytesPerLine-1-(endpos-startpos); i++)
  1663.         {
  1664.             linbuf[m++] = ' ';
  1665.             linbuf[m++] = ' ';
  1666.             linbuf[m++] = ' ';
  1667.         }
  1668.     }
  1669.  
  1670.     // Write offset to chars.
  1671.     for (i=0; i<m_stScreenSettings.iCharSpace; i++)
  1672.         linbuf[m++] = ' ';
  1673.     
  1674.     // Write ASCIIs.
  1675.     for (i=startpos; i<=endpos; i++)
  1676.     {
  1677.         if (i == Doc->DataArray.GetLength())
  1678.         {
  1679.             linbuf[m++] = ' ';
  1680.         }
  1681.         else if (App->m_iCharacterSet == OEM_FIXED_FONT && Doc->DataArray[i]!=0)
  1682.         {
  1683.             linbuf[m++] = Doc->DataArray[i];
  1684.         }
  1685.         else if ((Doc->DataArray[i]>=32 && Doc->DataArray[i]<=126) || (Doc->DataArray[i]>=160 && Doc->DataArray[i]<=255) || (Doc->DataArray[i]>=145 && Doc->DataArray[i]<=146))
  1686.         {
  1687.             linbuf[m++] = Doc->DataArray[i];
  1688.         }
  1689.         else
  1690.         {
  1691.             linbuf[m++] = '.';
  1692.         }
  1693.     }
  1694.  
  1695.     // Write spaces for nonexisting chars.
  1696.     if (endpos-startpos < App->m_iBytesPerLine-1)
  1697.         for (i=0; i<App->m_iBytesPerLine-1-(endpos-startpos); i++)
  1698.             linbuf[m++] = ' ';
  1699.     
  1700. //   TRACE("Offset %d to %d\n", startpos, endpos);
  1701. //    TRACE("Line Buffer: %s\n", linbuf);
  1702.     //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1703.     int line_len = m; // Length of the line in chars.
  1704.  
  1705.     // Set normal text colors.
  1706.     iBkColor = PALETTERGB (GetRValue(App->m_clrBk),GetGValue(App->m_clrBk),GetBValue(App->m_clrBk));
  1707.     iTextColor = PALETTERGB (GetRValue(App->m_clrText),GetGValue(App->m_clrText),GetBValue(App->m_clrText));
  1708.     SetTextColor (hdc, iTextColor);
  1709.     SetBkColor (hdc, iBkColor);
  1710.  
  1711.     // How much of offset and byte-space is visible? Print it in normal text colors.
  1712.     if( m_stScreenSettings.iHscrollPos < App->m_iOffsetLen + m_stScreenSettings.iByteSpace )
  1713.     {
  1714.         // A part of offset+byte-space is visible.
  1715.         // Write offset to screen.
  1716.         TextOutA( hdc, CLIENT_BORDER_WIDTH, CLIENT_BORDER_WIDTH + ( line - m_stScreenSettings.iCurLine ) * m_stScreenSettings.cyChar + m_stScreenSettings.iToolbarHeight, linbuf + m_stScreenSettings.iHscrollPos, App->m_iOffsetLen + m_stScreenSettings.iByteSpace - m_stScreenSettings.iHscrollPos );
  1717.     }
  1718.  
  1719.     int iHexStart = App->m_iOffsetLen + m_stScreenSettings.iByteSpace;
  1720.     int iHexXStart = iHexStart * m_stScreenSettings.cxChar;
  1721.  
  1722.     // Write char-space, if it is visible.
  1723.     if( m_stScreenSettings.iHscrollPos < App->m_iOffsetLen + m_stScreenSettings.iByteSpace + App->m_iBytesPerLine * iHexWidth )
  1724.     {
  1725.         // Char-space is visible.
  1726.         TextOutA( hdc,
  1727.             CLIENT_BORDER_WIDTH + ( iHexStart + App->m_iBytesPerLine * iHexWidth - m_stScreenSettings.iHscrollPos ) * m_stScreenSettings.cxChar,
  1728.             CLIENT_BORDER_WIDTH + ( line - m_stScreenSettings.iCurLine ) * m_stScreenSettings.cyChar + m_stScreenSettings.iToolbarHeight,
  1729.             linbuf + iHexStart + App->m_iBytesPerLine * iHexWidth,
  1730.             m_stScreenSettings.iCharSpace );
  1731.     }
  1732.  
  1733.     iSelBkColor = PALETTERGB (GetRValue(App->m_clrSelBk),GetGValue(App->m_clrSelBk),GetBValue(App->m_clrSelBk));
  1734.     iSelTextColor = PALETTERGB (GetRValue(App->m_clrSelText),GetGValue(App->m_clrSelText),GetBValue(App->m_clrSelText));
  1735.     BOOL last_normtext = TRUE;
  1736.  
  1737.     int p, el = startpos + App->m_iBytesPerLine - 1 - 1, s, e;
  1738.     for( p = startpos; p <= el; p++ )
  1739.     {
  1740.         // Write hex, if it is visible.
  1741.         // s = Position in string of last character of current hex.
  1742.         s = App->m_iOffsetLen + m_stScreenSettings.iByteSpace + ( p - startpos + 1 ) * iHexWidth;
  1743.         e = s - iHexWidth;
  1744.         // Print only if at least a part of the hex is visible.
  1745.         if( m_stScreenSettings.iHscrollPos < s && m_stScreenSettings.iHscrollPos + m_stScreenSettings.cxBuffer >= e )
  1746.         {
  1747.             // Selected bytes must be printed in selection colors.
  1748.             if( bSelected && IN_BOUNDS( p, iStartOfSelection, iEndOfSelection ) )
  1749.             {
  1750.                 if( last_normtext )
  1751.                 {
  1752.                     // Set selection colors.
  1753.                     SetTextColor (hdc, iSelTextColor);
  1754.                     SetBkColor (hdc, iSelBkColor);
  1755.                     last_normtext = FALSE;
  1756.                 }
  1757.             }
  1758.             else
  1759.             {
  1760.                 if( !last_normtext )
  1761.                 {
  1762.                     // Set normal text colors.
  1763.                     SetTextColor (hdc, iTextColor);
  1764.                     SetBkColor (hdc, iBkColor);
  1765.                     last_normtext = TRUE;
  1766.                 }
  1767.             }
  1768.             // Hex is visible.
  1769.             TextOutA( hdc,
  1770.                 CLIENT_BORDER_WIDTH + ( iHexStart + ( p - startpos ) * iHexWidth - m_stScreenSettings.iHscrollPos ) * m_stScreenSettings.cxChar,
  1771.                 CLIENT_BORDER_WIDTH + ( line - m_stScreenSettings.iCurLine ) * m_stScreenSettings.cyChar + m_stScreenSettings.iToolbarHeight,
  1772.                 linbuf + iHexStart + ( p - startpos ) * iHexWidth,
  1773.                 iHexWidth );
  1774.         }
  1775.  
  1776.         s = App->m_iOffsetLen + m_stScreenSettings.iByteSpace + App->m_iBytesPerLine * iHexWidth + m_stScreenSettings.iCharSpace + ( p - startpos + 1);
  1777.         // Write char, if it is visible.
  1778.         if( m_stScreenSettings.iHscrollPos < s && m_stScreenSettings.iHscrollPos + m_stScreenSettings.cxBuffer >= s - 1 )
  1779.         {
  1780.             // Selected bytes must be printed in selection colors.
  1781.             if( bSelected && IN_BOUNDS( p, iStartOfSelection, iEndOfSelection ) )
  1782.             {
  1783.                 if( last_normtext )
  1784.                 {
  1785.                     // Set selection colors.
  1786.                     SetTextColor (hdc, iSelTextColor);
  1787.                     SetBkColor (hdc, iSelBkColor);
  1788.                     last_normtext = FALSE;
  1789.                 }
  1790.             }
  1791.             else
  1792.             {
  1793.                 if( !last_normtext )
  1794.                 {
  1795.                     // Set normal text colors.
  1796.                     SetTextColor (hdc, iTextColor);
  1797.                     SetBkColor (hdc, iBkColor);
  1798.                     last_normtext = TRUE;
  1799.                 }
  1800.             }
  1801.             // Char is visible.
  1802.             TextOutA( hdc,
  1803.                 CLIENT_BORDER_WIDTH + ( iHexStart + App->m_iBytesPerLine * iHexWidth + m_stScreenSettings.iCharSpace + ( p - startpos ) - m_stScreenSettings.iHscrollPos ) * m_stScreenSettings.cxChar,
  1804.                 CLIENT_BORDER_WIDTH + ( line - m_stScreenSettings.iCurLine ) * m_stScreenSettings.cyChar + m_stScreenSettings.iToolbarHeight,
  1805.                 linbuf + iHexStart + App->m_iBytesPerLine * iHexWidth + m_stScreenSettings.iCharSpace + ( p - startpos ),
  1806.                 1 );
  1807.         }
  1808.     }
  1809.     
  1810.     // The last hex in the line is not completely in selection colors. It's
  1811.     // succeding space must be printed in normal text colors (visually more
  1812.     // appealing).
  1813.     // Write hex, if it is visible.
  1814.     // s = Position in string of last character of current hex.
  1815.     s = App->m_iOffsetLen + m_stScreenSettings.iByteSpace + ( p - startpos + 1 ) * iHexWidth;
  1816.     e = s - iHexWidth;
  1817.     // Print only if at least a part of the hex is visible.
  1818.     if( m_stScreenSettings.iHscrollPos < s && m_stScreenSettings.iHscrollPos + m_stScreenSettings.cxBuffer >= e )
  1819.     {
  1820.         // Selected bytes must be printed in selection colors.
  1821.         if( bSelected && IN_BOUNDS( p, iStartOfSelection, iEndOfSelection ) )
  1822.         {
  1823.             if( last_normtext )
  1824.             {
  1825.                 // Output the last space first.
  1826.                 TextOutA( hdc,
  1827.                     CLIENT_BORDER_WIDTH + ( iHexStart + ( p - startpos ) * iHexWidth - m_stScreenSettings.iHscrollPos ) * m_stScreenSettings.cxChar + 2 * m_stScreenSettings.cxChar,
  1828.                     CLIENT_BORDER_WIDTH + ( line - m_stScreenSettings.iCurLine ) * m_stScreenSettings.cyChar + m_stScreenSettings.iToolbarHeight,
  1829.                     " ",
  1830.                     1 );
  1831.                 // Set selection colors.
  1832.                 SetTextColor (hdc, iSelTextColor);
  1833.                 SetBkColor (hdc, iSelBkColor);
  1834.                 last_normtext = FALSE;
  1835.                 last_normtext = TRUE;
  1836.                 // Write hex.
  1837.                 TextOutA( hdc,
  1838.                     CLIENT_BORDER_WIDTH + ( iHexStart + ( p - startpos ) * iHexWidth - m_stScreenSettings.iHscrollPos ) * m_stScreenSettings.cxChar,
  1839.                     CLIENT_BORDER_WIDTH + ( line - m_stScreenSettings.iCurLine ) * m_stScreenSettings.cyChar + m_stScreenSettings.iToolbarHeight,
  1840.                     linbuf + iHexStart + ( p - startpos ) * iHexWidth,
  1841.                     iHexWidth - 1 );
  1842.             }
  1843.             else
  1844.             {
  1845.                 // Write hex.
  1846.                 TextOutA( hdc,
  1847.                     CLIENT_BORDER_WIDTH + ( iHexStart + ( p - startpos ) * iHexWidth - m_stScreenSettings.iHscrollPos ) * m_stScreenSettings.cxChar,
  1848.                     CLIENT_BORDER_WIDTH + ( line - m_stScreenSettings.iCurLine ) * m_stScreenSettings.cyChar + m_stScreenSettings.iToolbarHeight,
  1849.                     linbuf + iHexStart + ( p - startpos ) * iHexWidth,
  1850.                     iHexWidth - 1 );
  1851.                 // Set normal text colors.
  1852.                 SetTextColor (hdc, iTextColor);
  1853.                 SetBkColor (hdc, iBkColor);
  1854.                 last_normtext = TRUE;
  1855.                 // Output the last space.
  1856.                 TextOutA( hdc,
  1857.                     CLIENT_BORDER_WIDTH + ( iHexStart + ( p - startpos ) * iHexWidth - m_stScreenSettings.iHscrollPos ) * m_stScreenSettings.cxChar + 2 * m_stScreenSettings.cxChar,
  1858.                     CLIENT_BORDER_WIDTH + ( line - m_stScreenSettings.iCurLine ) * m_stScreenSettings.cyChar + m_stScreenSettings.iToolbarHeight,
  1859.                     " ",
  1860.                     1 );
  1861.             }
  1862.         }
  1863.         else
  1864.         {
  1865.             // Non-selected hex.
  1866.             if( !last_normtext )
  1867.             {
  1868.                 // Set normal text colors.
  1869.                 SetTextColor (hdc, iTextColor);
  1870.                 SetBkColor (hdc, iBkColor);
  1871.                 last_normtext = TRUE;
  1872.             }
  1873.             // Hex is visible.
  1874.             TextOutA( hdc,
  1875.                 CLIENT_BORDER_WIDTH + ( iHexStart + ( p - startpos ) * iHexWidth - m_stScreenSettings.iHscrollPos ) * m_stScreenSettings.cxChar,
  1876.                 CLIENT_BORDER_WIDTH + ( line - m_stScreenSettings.iCurLine ) * m_stScreenSettings.cyChar + m_stScreenSettings.iToolbarHeight,
  1877.                 linbuf + iHexStart + ( p - startpos ) * iHexWidth,
  1878.                 iHexWidth );
  1879.         }
  1880.     }
  1881.  
  1882.     s = App->m_iOffsetLen + m_stScreenSettings.iByteSpace + App->m_iBytesPerLine * iHexWidth + m_stScreenSettings.iCharSpace + ( p - startpos + 1);
  1883.     // Write char, if it is visible.
  1884.     if( m_stScreenSettings.iHscrollPos < s && m_stScreenSettings.iHscrollPos + m_stScreenSettings.cxBuffer >= s - 1 )
  1885.     {
  1886.         // Selected bytes must be printed in selection colors.
  1887.         if( bSelected && IN_BOUNDS( p, iStartOfSelection, iEndOfSelection ) )
  1888.         {
  1889.             if( last_normtext )
  1890.             {
  1891.                 // Set selection colors.
  1892.                 SetTextColor (hdc, iSelTextColor);
  1893.                 SetBkColor (hdc, iSelBkColor);
  1894.             }
  1895.         }
  1896.         else
  1897.         {
  1898.             if( !last_normtext )
  1899.             {
  1900.                 // Set normal text colors.
  1901.                 SetTextColor (hdc, iTextColor);
  1902.                 SetBkColor (hdc, iBkColor);
  1903.             }
  1904.         }
  1905.         // Char is visible.
  1906.         TextOutA( hdc,
  1907.             CLIENT_BORDER_WIDTH + ( iHexStart + App->m_iBytesPerLine * iHexWidth + m_stScreenSettings.iCharSpace + ( p - startpos ) - m_stScreenSettings.iHscrollPos ) * m_stScreenSettings.cxChar,
  1908.             CLIENT_BORDER_WIDTH + ( line - m_stScreenSettings.iCurLine ) * m_stScreenSettings.cyChar + m_stScreenSettings.iToolbarHeight,
  1909.             linbuf + iHexStart + App->m_iBytesPerLine * iHexWidth + m_stScreenSettings.iCharSpace + ( p - startpos ),
  1910.             1 );
  1911.     }
  1912.  
  1913.     //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  1914.     // Separators.
  1915.     for (i = 0; i < (App->m_iBytesPerLine / 4) + 1; i++)
  1916.     {
  1917.         m = (App->m_iOffsetLen+m_stScreenSettings.iByteSpace)*m_stScreenSettings.cxChar - m_stScreenSettings.cxChar/2 + 3*m_stScreenSettings.cxChar*4*i - m_stScreenSettings.cxChar*m_stScreenSettings.iHscrollPos;
  1918.         MoveToEx (hdc, CLIENT_BORDER_WIDTH+m, CLIENT_BORDER_WIDTH+(line-m_stScreenSettings.iCurLine)*m_stScreenSettings.cyChar + m_stScreenSettings.iToolbarHeight, NULL);
  1919.         LineTo (hdc, CLIENT_BORDER_WIDTH+m, CLIENT_BORDER_WIDTH+(line-m_stScreenSettings.iCurLine+1)*m_stScreenSettings.cyChar + m_stScreenSettings.iToolbarHeight);
  1920.     }
  1921.     // Separator for chars.
  1922.     m = CHARSTART*m_stScreenSettings.cxChar - m_stScreenSettings.cxChar*m_stScreenSettings.iHscrollPos - 2;
  1923.     MoveToEx (hdc, CLIENT_BORDER_WIDTH+m, CLIENT_BORDER_WIDTH+(line-m_stScreenSettings.iCurLine)*m_stScreenSettings.cyChar + m_stScreenSettings.iToolbarHeight, NULL);
  1924.     LineTo (hdc, CLIENT_BORDER_WIDTH+m, CLIENT_BORDER_WIDTH+(line-m_stScreenSettings.iCurLine+1)*m_stScreenSettings.cyChar + m_stScreenSettings.iToolbarHeight);
  1925.     // Second separator.
  1926.     MoveToEx (hdc, CLIENT_BORDER_WIDTH+m+2, CLIENT_BORDER_WIDTH+(line-m_stScreenSettings.iCurLine)*m_stScreenSettings.cyChar + m_stScreenSettings.iToolbarHeight, NULL);
  1927.     LineTo (hdc, CLIENT_BORDER_WIDTH+m+2, CLIENT_BORDER_WIDTH+(line-m_stScreenSettings.iCurLine+1)*m_stScreenSettings.cyChar + m_stScreenSettings.iToolbarHeight);
  1928.  
  1929.     // Print bookmark indicators.
  1930.     // Are there bookmarks in this line?
  1931.     el = startpos + App->m_iBytesPerLine - 1;
  1932.     int chpos;
  1933.     RECT r;
  1934.     // Brush for bookmark borders.
  1935.     for( i = 0; i < iBmkCount; i++ )
  1936.     {
  1937.         // Print the bookmark if it is within the file.
  1938.         if( IN_BOUNDS( pbmkList[i].offset, startpos, el ) && pbmkList[i].offset <= Doc->DataArray.GetUpperBound() )
  1939.         {
  1940.             // Found a bookmark in this line.
  1941.             // Mark hex.
  1942.             chpos = App->m_iOffsetLen + m_stScreenSettings.iByteSpace + ( pbmkList[i].offset % App->m_iBytesPerLine )*3 - m_stScreenSettings.iHscrollPos;
  1943.             r.left = CLIENT_BORDER_WIDTH + chpos * m_stScreenSettings.cxChar;
  1944.             r.top = CLIENT_BORDER_WIDTH + ( pbmkList[i].offset / App->m_iBytesPerLine - m_stScreenSettings.iCurLine ) * m_stScreenSettings.cyChar + m_stScreenSettings.iToolbarHeight;
  1945.             r.right = CLIENT_BORDER_WIDTH + r.left + 2*m_stScreenSettings.cxChar;
  1946.             r.bottom = CLIENT_BORDER_WIDTH + ( pbmkList[i].offset / App->m_iBytesPerLine - m_stScreenSettings.iCurLine + 1 ) * m_stScreenSettings.cyChar + m_stScreenSettings.iToolbarHeight;
  1947.             FrameRect( hdc, &r, hbr );
  1948.  
  1949.             // Mark char.
  1950.             chpos = App->m_iOffsetLen + m_stScreenSettings.iByteSpace + App->m_iBytesPerLine*3 + m_stScreenSettings.iCharSpace
  1951.                 + ( pbmkList[i].offset % App->m_iBytesPerLine ) - m_stScreenSettings.iHscrollPos;
  1952.             r.left = CLIENT_BORDER_WIDTH + chpos * m_stScreenSettings.cxChar;
  1953.             r.top = CLIENT_BORDER_WIDTH + ( pbmkList[i].offset / App->m_iBytesPerLine - m_stScreenSettings.iCurLine) * m_stScreenSettings.cyChar + m_stScreenSettings.iToolbarHeight;
  1954.             r.right = CLIENT_BORDER_WIDTH + ( chpos + 1 ) * m_stScreenSettings.cxChar;
  1955.             r.bottom = CLIENT_BORDER_WIDTH + ( pbmkList[i].offset / App->m_iBytesPerLine - m_stScreenSettings.iCurLine + 1 ) * m_stScreenSettings.cyChar + m_stScreenSettings.iToolbarHeight;
  1956.             FrameRect( hdc, &r, hbr );
  1957.         }
  1958.     }
  1959.     return;
  1960. }
  1961.  
  1962. //--------------------------------------------------------------------------------------------
  1963. // Highlight (invert) the character/byte at the current offset.
  1964. void CFshedView::mark_char (HDC hdc)
  1965. {
  1966.     if( bDontMarkCurrentPos )
  1967.         return;
  1968.  
  1969.     if (bSelected)
  1970.     {
  1971.       ::SetCaretPos (-m_stScreenSettings.cxChar, -m_stScreenSettings.cyChar);
  1972.         return;
  1973.     }
  1974.  
  1975.     int DC_was_allocated = FALSE;
  1976.     if (hdc == 0)
  1977.     {
  1978.       hdc = ::GetDC (m_hWnd);
  1979.         DC_was_allocated = TRUE;        
  1980.     }
  1981.  
  1982.     int chpos;
  1983.     RECT r;
  1984.     switch (m_iEnteringMode)
  1985.     {
  1986.     case CHARS:
  1987.         chpos = App->m_iOffsetLen + m_stScreenSettings.iByteSpace + (m_stScreenSettings.iCurByte%App->m_iBytesPerLine)*3 - m_stScreenSettings.iHscrollPos;
  1988.         r.left = CLIENT_BORDER_WIDTH + chpos * m_stScreenSettings.cxChar;
  1989.         r.top = CLIENT_BORDER_WIDTH + (m_stScreenSettings.iCurByte/App->m_iBytesPerLine-m_stScreenSettings.iCurLine)*m_stScreenSettings.cyChar + m_stScreenSettings.iToolbarHeight;
  1990.         r.right = CLIENT_BORDER_WIDTH + r.left + 2*m_stScreenSettings.cxChar;
  1991.         r.bottom = CLIENT_BORDER_WIDTH + (m_stScreenSettings.iCurByte/App->m_iBytesPerLine-m_stScreenSettings.iCurLine+1)*m_stScreenSettings.cyChar + m_stScreenSettings.iToolbarHeight;
  1992.         InvertRect (hdc, &r);
  1993.         break;
  1994.     case BYTES:
  1995.         chpos = App->m_iOffsetLen + m_stScreenSettings.iByteSpace + App->m_iBytesPerLine*3 + m_stScreenSettings.iCharSpace
  1996.             + (m_stScreenSettings.iCurByte % App->m_iBytesPerLine) - m_stScreenSettings.iHscrollPos;
  1997.         r.left = CLIENT_BORDER_WIDTH + chpos * m_stScreenSettings.cxChar;
  1998.         r.top = CLIENT_BORDER_WIDTH + (m_stScreenSettings.iCurByte/App->m_iBytesPerLine-m_stScreenSettings.iCurLine)*m_stScreenSettings.cyChar + m_stScreenSettings.iToolbarHeight;
  1999.         r.right = CLIENT_BORDER_WIDTH + (chpos+1)*m_stScreenSettings.cxChar;
  2000.         r.bottom = CLIENT_BORDER_WIDTH + (m_stScreenSettings.iCurByte/App->m_iBytesPerLine-m_stScreenSettings.iCurLine+1)*m_stScreenSettings.cyChar + m_stScreenSettings.iToolbarHeight;
  2001.         InvertRect (hdc, &r);
  2002.     }
  2003.  
  2004.     if (DC_was_allocated)
  2005.       ::ReleaseDC (m_hWnd, hdc);
  2006. }
  2007.  
  2008. //-------------------------------------------------------------------
  2009. void CFshedView::draw_client_border (HDC hdc)
  2010. {
  2011.     // Border for client-area.
  2012.     int DC_was_allocated = FALSE;
  2013.     if (hdc == 0)
  2014.     {
  2015.       hdc = ::GetDC (m_hWnd);
  2016.         DC_was_allocated = TRUE;
  2017.     }
  2018.     RECT r;
  2019.     r.left = 0;
  2020.     r.top =  m_stScreenSettings.iToolbarHeight;
  2021.     r.right = m_stScreenSettings.cxClient;
  2022.     r.bottom = m_stScreenSettings.cyClient + m_stScreenSettings.iToolbarHeight;
  2023.     DrawEdge (hdc, &r, EDGE_SUNKEN, BF_RECT);
  2024.     if (DC_was_allocated)
  2025.     {
  2026.       ::ReleaseDC (m_hWnd, hdc);
  2027.     }
  2028. }
  2029.  
  2030. //--------------------------------------------------------------------------------------------
  2031. // Handler for character keys.
  2032. int CFshedView::character (char ch)
  2033. {
  2034.     // If there is selection return now.
  2035.     if (bSelected)
  2036.         return 0;
  2037.  
  2038.     // If we are in read-only mode, give a warning and return,
  2039.     // except if TAB was pressed.
  2040.     if( Doc->bReadOnly && ch != '\t' )
  2041.     {
  2042.       ::MessageBox( m_hWnd, _T("Can't change file because read-only mode is engaged!"), _T("Keyboard editing"), MB_OK | MB_ICONERROR );
  2043.         return 0;
  2044.     }
  2045.  
  2046.     char x, c = tolower (ch);
  2047.     if (ch == '\t') // TAB => change EnteringMode.
  2048.     {
  2049.         if (m_iEnteringMode == BYTES)
  2050.             m_iEnteringMode = CHARS;
  2051.         else
  2052.             m_iEnteringMode = BYTES;
  2053.         
  2054.         int log_column;
  2055.         if (m_iEnteringMode == BYTES)
  2056.             log_column = BYTES_LOGICAL_COLUMN;
  2057.         else
  2058.             log_column = CHARS_LOGICAL_COLUMN;
  2059.  
  2060.         if (log_column >= m_stScreenSettings.iHscrollPos+m_stScreenSettings.cxBuffer) // Cursor too far right...
  2061.             m_stScreenSettings.iHscrollPos = log_column-(m_stScreenSettings.cxBuffer-1); // Cursor to right border.
  2062.         else if (log_column < m_stScreenSettings.iHscrollPos) // Cursor too far left.
  2063.             m_stScreenSettings.iHscrollPos = log_column; // Cursor to left border.
  2064.         adjust_hscrollbar ();
  2065.         repaint ();
  2066.         return 0;
  2067.     }
  2068.  
  2069.     // If read-only mode, return.
  2070.     if( Doc->bReadOnly )
  2071.         return 1;
  2072.     
  2073.     // If in bytes and char is not a hex digit, return.
  2074.     if (m_iEnteringMode==BYTES && !((c>='a'&&c<='f')||(c>='0'&&c<='9')))
  2075.         return 1;
  2076.  
  2077.     // If caret at EOF.
  2078.     if (m_stScreenSettings.iCurByte == Doc->DataArray.GetLength())
  2079.     {
  2080.         if (Doc->DataArray.InsertAtGrow(m_stScreenSettings.iCurByte, 0, 1) == TRUE)
  2081.         {
  2082.             m_stScreenSettings.iCurNibble = 0;
  2083.             iInsertMode = FALSE;
  2084.             character (ch);
  2085.             update_for_new_datasize ();
  2086.             return 1;
  2087.         }
  2088.         else
  2089.         {
  2090.          ::MessageBox (NULL, _T("Not enough memory for inserting character."), _T("Insert mode error"), MB_OK | MB_ICONERROR);
  2091.         }
  2092.         return 0;
  2093.     }
  2094.  
  2095.     if( iInsertMode )
  2096.     {
  2097.         // INSERT
  2098.         if( m_iEnteringMode == BYTES )
  2099.         {
  2100.             if( ( c >= 'a' && c <= 'f' ) || ( c >= '0' && c <= '9' ) )
  2101.             {
  2102.                 if( bInsertingHex )
  2103.                 {
  2104.                     // Expecting the lower nibble of the recently inserted byte now.
  2105.                     // The bInsertingHex mode must be turned off if anything other is done
  2106.                     // except entering a valid hex digit. This is checked for in the
  2107.                     // HexEditorWindow::OnWndMsg() method.
  2108.                     bInsertingHex = FALSE;
  2109.                     if (c >= 'a' && c <= 'f')
  2110.                         x = c - 0x61 + 0x0a;
  2111.                     else
  2112.                         x = c - 0x30;
  2113.                     Doc->DataArray[m_stScreenSettings.iCurByte] = (Doc->DataArray[m_stScreenSettings.iCurByte] & 0xf0) | x;
  2114.                Doc->SetModifiedFlag();
  2115.                     Doc->bFilestatusChanged = TRUE;
  2116.                     m_stScreenSettings.iCurByte++;
  2117.                     m_stScreenSettings.iCurNibble = 0;
  2118.                     update_for_new_datasize();
  2119.                 }
  2120.                 else
  2121.                 {
  2122.                     // Insert a new byte with the high nibble set to value just typed.
  2123.                     if( Doc->DataArray.InsertAtGrow( m_stScreenSettings.iCurByte, 0, 1 ) == TRUE )
  2124.                     {
  2125.                         bInsertingHex = TRUE;
  2126.                         if (c >= 'a' && c <= 'f')
  2127.                             x = c - 0x61 + 0x0a;
  2128.                         else
  2129.                             x = c - 0x30;
  2130.                         Doc->DataArray[m_stScreenSettings.iCurByte] = (Doc->DataArray[m_stScreenSettings.iCurByte] & 0x0f) | (x << 4);
  2131.                   Doc->SetModifiedFlag();
  2132.                         Doc->bFilestatusChanged = TRUE;
  2133.                         m_stScreenSettings.iCurNibble = 1;
  2134.                         update_for_new_datasize();
  2135.                     }
  2136.                     else
  2137.                     {
  2138.                   ::MessageBox (NULL, _T("Not enough memory for inserting."), _T("Insert mode error"), MB_OK | MB_ICONERROR);
  2139.                         return 0;
  2140.                     }
  2141.                 }
  2142.             }
  2143.             return 1;
  2144.         }
  2145.         else if (m_iEnteringMode == CHARS)
  2146.         {
  2147.             if (Doc->DataArray.InsertAtGrow(m_stScreenSettings.iCurByte, 0, 1) == TRUE)
  2148.             {
  2149.                 m_stScreenSettings.iCurNibble = 0;
  2150.                 iInsertMode = FALSE;
  2151.                 character (ch);
  2152.                 iInsertMode = TRUE;
  2153.                 m_stScreenSettings.iCurNibble = 0;
  2154.                 update_for_new_datasize ();
  2155.             }
  2156.             else
  2157.             {
  2158.             ::MessageBox (NULL, _T("Not enough memory for inserting."), _T("Insert mode error"), MB_OK | MB_ICONERROR);
  2159.                 return 0;
  2160.             }
  2161.         }
  2162.         return 1;
  2163.     }
  2164.     else
  2165.     {
  2166.         // OVERWRITE
  2167.         // TAB => change mode.
  2168.         // Byte-mode: only a-f, 0-9 allowed.
  2169.         if ((m_iEnteringMode == BYTES) && ((c >= 'a' && c <= 'f') || (c >= '0' && c <= '9')))
  2170.         {
  2171.             if (c >= 'a' && c <= 'f')
  2172.                 x = c - 0x61 + 0x0a;
  2173.             else
  2174.                 x = c - 0x30;
  2175.             if (m_stScreenSettings.iCurNibble == 0)
  2176.                 Doc->DataArray[m_stScreenSettings.iCurByte] = (Doc->DataArray[m_stScreenSettings.iCurByte] & 0x0f) | (x << 4);
  2177.             else
  2178.                 Doc->DataArray[m_stScreenSettings.iCurByte] = (Doc->DataArray[m_stScreenSettings.iCurByte] & 0xf0) | x;
  2179.          Doc->SetModifiedFlag();
  2180.             Doc->bFilestatusChanged = TRUE;
  2181.             keydown (VK_RIGHT);
  2182.         }
  2183.         // Char-mode.
  2184.         else if (m_iEnteringMode == CHARS)
  2185.         {
  2186.             switch (App->m_iCharacterSet)
  2187.             {
  2188.             case ANSI_FIXED_FONT:
  2189.                 Doc->DataArray[m_stScreenSettings.iCurByte] = ch;
  2190.                 break;
  2191.  
  2192.             case OEM_FIXED_FONT:
  2193.                 {
  2194.                     TCHAR src[2];
  2195.                     char dst[2];
  2196.                     src[0] = ch;
  2197.                     src[1] = 0;
  2198.                     CharToOem (src, dst);
  2199.                     Doc->DataArray[m_stScreenSettings.iCurByte] = dst[0];
  2200.                 }
  2201.                 break;
  2202.             }
  2203.          Doc->SetModifiedFlag();
  2204.             Doc->bFilestatusChanged = TRUE;
  2205.             keydown (VK_RIGHT);
  2206.         }
  2207.     }
  2208.     return 0;
  2209. }
  2210.  
  2211. //--------------------------------------------------------------------------------------------
  2212. // Handler for non-character keys (arrow keys, page up/down etc.)
  2213. int CFshedView::keydown (int key)
  2214. {
  2215.     if (Doc->filename[0] == '\0' || m_stScreenSettings.iCurByte<0)
  2216.         return 0;
  2217.  
  2218.     int log_column, scrollflag;
  2219.  
  2220.     if (bSelected)
  2221.         switch (key)
  2222.         {
  2223.         case VK_END:
  2224.         case VK_HOME:
  2225.         case VK_LEFT:
  2226.         case VK_RIGHT:
  2227.         case VK_UP:
  2228.         case VK_DOWN:
  2229.         case VK_PRIOR:
  2230.         case VK_NEXT:
  2231.             m_stScreenSettings.iCurByte = iEndOfSelection;
  2232.             bSelected = FALSE;
  2233.             adjust_vscrollbar ();
  2234.             repaint ();
  2235.         default:
  2236.             break;
  2237.         }
  2238.  
  2239.     switch (key)
  2240.     {
  2241.     case VK_HOME:
  2242.     {
  2243.         m_stScreenSettings.iCurByte = BYTELINE * App->m_iBytesPerLine;
  2244.         m_stScreenSettings.iCurNibble = 0;
  2245.         if (m_iEnteringMode == BYTES)
  2246.             log_column = BYTES_LOGICAL_COLUMN;
  2247.         else
  2248.             log_column = CHARS_LOGICAL_COLUMN;
  2249.         if (log_column < m_stScreenSettings.iHscrollPos) // Cursor too far to the left?
  2250.         {
  2251.             m_stScreenSettings.iHscrollPos = log_column;
  2252.             adjust_hscrollbar ();
  2253.             repaint ();
  2254.         }
  2255.         else
  2256.         {
  2257.             repaint (BYTELINE);
  2258.         }
  2259.         if (CURSOR_TOO_HIGH || CURSOR_TOO_LOW)
  2260.         {
  2261.             m_stScreenSettings.iCurLine = max (0, m_stScreenSettings.iCurByte/App->m_iBytesPerLine-m_stScreenSettings.cyBuffer/2);
  2262.             adjust_vscrollbar ();
  2263.             repaint ();
  2264.         }
  2265.         break;
  2266.     }
  2267.     
  2268.     case VK_END:
  2269.     {
  2270.         // Set position:
  2271.         m_stScreenSettings.iCurByte = (BYTELINE + 1) * App->m_iBytesPerLine - 1;
  2272.         if (m_stScreenSettings.iCurByte > LASTBYTE+1)
  2273.             m_stScreenSettings.iCurByte = LASTBYTE+1;
  2274.         m_stScreenSettings.iCurNibble = 1;
  2275.  
  2276.         if (m_iEnteringMode == BYTES)
  2277.             log_column = BYTES_LOGICAL_COLUMN;
  2278.         else
  2279.             log_column = CHARS_LOGICAL_COLUMN;
  2280.         
  2281.         // If logical column too far to right:
  2282.         if (log_column > LAST_LOG_COLUMN)
  2283.         {
  2284.             m_stScreenSettings.iHscrollPos = log_column - m_stScreenSettings.cxBuffer + 1;
  2285.             adjust_hscrollbar ();
  2286.             repaint ();
  2287.         }
  2288.         else
  2289.         {
  2290.             repaint (BYTELINE);
  2291.         }
  2292.         
  2293.         if (CURSOR_TOO_HIGH || CURSOR_TOO_LOW)
  2294.         {
  2295.             m_stScreenSettings.iCurLine = max (0, m_stScreenSettings.iCurByte/App->m_iBytesPerLine-m_stScreenSettings.cyBuffer/2);
  2296.             adjust_vscrollbar ();
  2297.             repaint ();
  2298.         }
  2299.         break;
  2300.     }
  2301.  
  2302.     case VK_UP:
  2303.         // If possible, cursor one line up.
  2304.         if (m_stScreenSettings.iCurByte >= App->m_iBytesPerLine)
  2305.             m_stScreenSettings.iCurByte -= App->m_iBytesPerLine;
  2306.         // If cursor pos. before or behind visible area...
  2307.         scrollflag = FALSE;
  2308.         if (CURSOR_TOO_HIGH || CURSOR_TOO_LOW)
  2309.         {
  2310.             adjust_vscrollbar ();
  2311.             scrollflag = TRUE;
  2312.         }
  2313.  
  2314.         if (m_iEnteringMode == BYTES)
  2315.             log_column = BYTES_LOGICAL_COLUMN;
  2316.         else
  2317.             log_column = CHARS_LOGICAL_COLUMN;
  2318.  
  2319.         // If cursor too far horiz.
  2320.         if (log_column < m_stScreenSettings.iHscrollPos || log_column > LAST_LOG_COLUMN)
  2321.         {
  2322.             m_stScreenSettings.iHscrollPos = log_column;
  2323.             adjust_hscrollbar ();
  2324.             repaint ();
  2325.             break;
  2326.         }
  2327.         else if (!scrollflag)
  2328.         {
  2329.             repaint (BYTELINE+1);
  2330.             repaint (BYTELINE);
  2331.         }
  2332.         else // scrollflag
  2333.         {
  2334.             if (m_stScreenSettings.iCurLine-BYTELINE==1) // One line up.
  2335.             {
  2336.                 m_stScreenSettings.iCurLine = BYTELINE;
  2337.                 RECT r;
  2338.                 r.left = CLIENT_BORDER_WIDTH;
  2339.                 r.top = CLIENT_BORDER_WIDTH + m_stScreenSettings.iToolbarHeight;
  2340.                 r.right = m_stScreenSettings.cxClient - CLIENT_BORDER_WIDTH;
  2341.                 r.bottom = m_stScreenSettings.cyClient - CLIENT_BORDER_WIDTH;
  2342. //                ScrollWindow (0, m_stScreenSettings.cyChar, &r, &r);
  2343. //                repaint (BYTELINE+1);
  2344. //                repaint (BYTELINE);
  2345.                 repaint ();
  2346.             }
  2347.             else
  2348.             {
  2349.                 m_stScreenSettings.iCurLine = BYTELINE;
  2350.                 repaint ();
  2351.             }
  2352.          ASSERT(m_stScreenSettings.iCurLine >= 0);
  2353.         }
  2354.         break;
  2355.  
  2356.     case VK_DOWN:
  2357.         // If possible cursor one line down.
  2358.         if (m_stScreenSettings.iCurByte+App->m_iBytesPerLine <= Doc->DataArray.GetLength())
  2359.             m_stScreenSettings.iCurByte += App->m_iBytesPerLine;
  2360.         
  2361.         scrollflag = FALSE;
  2362.         if (CURSOR_TOO_HIGH || CURSOR_TOO_LOW)
  2363.         {
  2364.             adjust_vscrollbar ();
  2365.             scrollflag = TRUE;
  2366.         }
  2367.  
  2368.         if (m_iEnteringMode == BYTES)
  2369.             log_column = BYTES_LOGICAL_COLUMN;
  2370.         else
  2371.             log_column = CHARS_LOGICAL_COLUMN;
  2372.  
  2373.         if (log_column < m_stScreenSettings.iHscrollPos || log_column > LAST_LOG_COLUMN)
  2374.         {
  2375.             m_stScreenSettings.iHscrollPos = log_column;
  2376.             adjust_hscrollbar ();
  2377.             repaint ();
  2378.             break;
  2379.         }
  2380.         else if (!scrollflag)
  2381.         {
  2382.             repaint (BYTELINE-1);
  2383.             repaint (BYTELINE);
  2384.         }
  2385.         else // scrollflag
  2386.         {
  2387.             int nLine = BYTELINE;
  2388.             if (BYTELINE==m_stScreenSettings.iCurLine+m_stScreenSettings.cyBuffer) // Cursor one line down.
  2389.             {
  2390.                 m_stScreenSettings.iCurLine = max (0, BYTELINE-(m_stScreenSettings.cyBuffer-1)); // Cursor at bottom of screen.
  2391.                 RECT r;
  2392.                 r.left = CLIENT_BORDER_WIDTH;
  2393.                 r.top = CLIENT_BORDER_WIDTH + m_stScreenSettings.iToolbarHeight;
  2394.                 r.right = m_stScreenSettings.cxClient - CLIENT_BORDER_WIDTH;
  2395.                 r.bottom = m_stScreenSettings.cyClient - CLIENT_BORDER_WIDTH;
  2396. //                ScrollWindow (0, -m_stScreenSettings.cyChar, &r, &r);
  2397. //                repaint (BYTELINE-1);
  2398. //                repaint (BYTELINE);
  2399. //                repaint (BYTELINE+1);
  2400.                 repaint ();
  2401.                 mark_char( 0 );
  2402.             }
  2403.             else
  2404.             {
  2405.                 m_stScreenSettings.iCurLine = max (0, BYTELINE-(m_stScreenSettings.cyBuffer-1));
  2406.                 repaint ();
  2407.             }
  2408.          ASSERT(m_stScreenSettings.iCurLine >= 0);
  2409.         }
  2410.         break;
  2411.     
  2412.     case VK_LEFT:
  2413.     {
  2414.         if (m_iEnteringMode == BYTES) // BYTE-Mode.
  2415.         {
  2416.             if (m_stScreenSettings.iCurNibble == 1) // 1 nibble to the left...
  2417.                 m_stScreenSettings.iCurNibble = 0;
  2418.             else if (m_stScreenSettings.iCurByte != 0) // Or 1 byte to the left.
  2419.             {
  2420.                 m_stScreenSettings.iCurByte--;
  2421.                 m_stScreenSettings.iCurNibble = 1;
  2422.             }
  2423.         }
  2424.         else // CHAR-Mode.
  2425.         {
  2426.             if (m_stScreenSettings.iCurByte != 0)
  2427.                 m_stScreenSettings.iCurByte--; // 1 Byte to the left.
  2428.         }
  2429.  
  2430.         // If new line not visible, then scroll.
  2431.         scrollflag = FALSE;
  2432.         if (CURSOR_TOO_HIGH || CURSOR_TOO_LOW)
  2433.         {
  2434.             m_stScreenSettings.iCurLine = BYTELINE;
  2435.          ASSERT(m_stScreenSettings.iCurLine >= 0);
  2436.             adjust_vscrollbar ();
  2437.             scrollflag = TRUE;
  2438.         }
  2439.         
  2440.         if (m_iEnteringMode == BYTES)
  2441.             log_column = BYTES_LOGICAL_COLUMN;
  2442.         else
  2443.             log_column = CHARS_LOGICAL_COLUMN;
  2444.  
  2445.         if (log_column < m_stScreenSettings.iHscrollPos)
  2446.         {
  2447.             m_stScreenSettings.iHscrollPos = log_column;
  2448.             adjust_hscrollbar ();
  2449.             repaint ();
  2450.             break;
  2451.         }
  2452.         else if (log_column > LAST_LOG_COLUMN)
  2453.         {
  2454.             m_stScreenSettings.iHscrollPos = log_column-(m_stScreenSettings.cxBuffer-1);
  2455.             adjust_hscrollbar ();
  2456.             repaint ();
  2457.             break;
  2458.         }
  2459.         else if (!scrollflag)
  2460.         {
  2461.             if (m_stScreenSettings.iCurByte%App->m_iBytesPerLine==App->m_iBytesPerLine-1) // Just got to previous line.
  2462.                 repaint (BYTELINE+1);
  2463.             repaint (BYTELINE);
  2464.         }
  2465.         else
  2466.             repaint ();
  2467.         break;
  2468.     }
  2469.  
  2470.     case VK_RIGHT:
  2471.     {
  2472.         if (m_iEnteringMode == BYTES)
  2473.         {
  2474.             if (m_stScreenSettings.iCurNibble == 0)
  2475.                 m_stScreenSettings.iCurNibble = 1;
  2476.             else if (m_stScreenSettings.iCurByte <= LASTBYTE)
  2477.             {
  2478.                 m_stScreenSettings.iCurNibble = 0;
  2479.                 m_stScreenSettings.iCurByte++;
  2480.             }
  2481.         }
  2482.         else
  2483.         {
  2484.             if (m_stScreenSettings.iCurByte <= LASTBYTE)
  2485.                 m_stScreenSettings.iCurByte++;
  2486.         }
  2487.         
  2488.         scrollflag = FALSE;
  2489.         if (CURSOR_TOO_HIGH || CURSOR_TOO_LOW)
  2490.         {
  2491.             m_stScreenSettings.iCurLine = max (BYTELINE-m_stScreenSettings.cyBuffer+1, 0);
  2492.             adjust_vscrollbar ();
  2493.             scrollflag = TRUE;
  2494.         }
  2495.  
  2496.         if (m_iEnteringMode == BYTES)
  2497.             log_column = BYTES_LOGICAL_COLUMN;
  2498.         else
  2499.             log_column = CHARS_LOGICAL_COLUMN;
  2500.  
  2501.         if (log_column >= m_stScreenSettings.iHscrollPos+m_stScreenSettings.cxBuffer)
  2502.         {
  2503.             m_stScreenSettings.iHscrollPos = log_column-(m_stScreenSettings.cxBuffer-1);
  2504.             adjust_hscrollbar ();
  2505.             repaint ();
  2506.             break;
  2507.         }
  2508.         else if (log_column < m_stScreenSettings.iHscrollPos)
  2509.         {
  2510.             m_stScreenSettings.iHscrollPos = log_column;
  2511.             adjust_hscrollbar ();
  2512.             repaint ();
  2513.             break;
  2514.         }
  2515.         else if (scrollflag != TRUE) // If one line down but cursor not too far horiz.
  2516.         {
  2517.             if (m_stScreenSettings.iCurByte%App->m_iBytesPerLine==0)
  2518.                 repaint (BYTELINE-1);
  2519.             repaint (BYTELINE);
  2520.         }
  2521.         else
  2522.             repaint ();
  2523.         break;
  2524.     }
  2525.  
  2526.     case VK_PRIOR:
  2527.         if (BYTELINE >= m_stScreenSettings.cyBuffer)
  2528.         {
  2529.             m_stScreenSettings.iCurByte -= m_stScreenSettings.cyBuffer * App->m_iBytesPerLine; // 1 page up.
  2530.             m_stScreenSettings.iCurLine -= m_stScreenSettings.cyBuffer;
  2531.             if (m_stScreenSettings.iCurLine < 0)
  2532.                 m_stScreenSettings.iCurLine = BYTELINE;
  2533.         }
  2534.         else
  2535.         {
  2536.             m_stScreenSettings.iCurLine = 0; // To top.
  2537.             m_stScreenSettings.iCurByte = BYTEPOS;
  2538.         }
  2539.         if (CURSOR_TOO_HIGH || CURSOR_TOO_LOW)
  2540.             m_stScreenSettings.iCurLine = m_stScreenSettings.iCurByte/App->m_iBytesPerLine;
  2541.       ASSERT(m_stScreenSettings.iCurLine >= 0);
  2542.         adjust_vscrollbar ();
  2543.         repaint ();
  2544.         break;
  2545.  
  2546.     case VK_NEXT:
  2547.         m_stScreenSettings.iCurByte += m_stScreenSettings.cyBuffer*App->m_iBytesPerLine;
  2548.         if (m_stScreenSettings.iCurByte > LASTBYTE+1)
  2549.         {
  2550.             m_stScreenSettings.iCurByte = (LASTBYTE+1)/App->m_iBytesPerLine*App->m_iBytesPerLine + BYTEPOS;
  2551.             if (m_stScreenSettings.iCurByte > LASTBYTE+1)
  2552.                 m_stScreenSettings.iCurByte = LASTBYTE+1;
  2553.             m_stScreenSettings.iCurLine = BYTELINE;
  2554.             adjust_view_for_caret ();
  2555.         }
  2556.         else
  2557.         {
  2558.             m_stScreenSettings.iCurLine += m_stScreenSettings.cyBuffer;
  2559.             if (m_stScreenSettings.iCurLine > LASTLINE)
  2560.                 m_stScreenSettings.iCurLine = BYTELINE;
  2561.         }
  2562.       ASSERT(m_stScreenSettings.iCurLine >= 0);
  2563.         if (CURSOR_TOO_HIGH || CURSOR_TOO_LOW)
  2564.             m_stScreenSettings.iCurLine = max (BYTELINE-m_stScreenSettings.cyBuffer+1, 0);
  2565.         adjust_vscrollbar ();
  2566.         repaint ();
  2567.         break;
  2568.     }
  2569.     return 0;
  2570. }
  2571.  
  2572. //--------------------------------------------------------------------------------------------
  2573. // Set horizontal scroll position so that caret is visible.
  2574. void CFshedView::adjust_view_for_caret ()
  2575. {
  2576.     int log_column;
  2577.     if (m_iEnteringMode == BYTES)
  2578.         log_column = BYTES_LOGICAL_COLUMN;
  2579.     else
  2580.         log_column = CHARS_LOGICAL_COLUMN;
  2581.  
  2582.     if (log_column >= m_stScreenSettings.iHscrollPos+m_stScreenSettings.cxBuffer)
  2583.         m_stScreenSettings.iHscrollPos = log_column-(m_stScreenSettings.cxBuffer-1);
  2584.     else if (log_column < m_stScreenSettings.iHscrollPos)
  2585.         m_stScreenSettings.iHscrollPos = log_column;
  2586.     adjust_hscrollbar ();
  2587. }
  2588.  
  2589. //-------------------------------------------------------------------
  2590. int CFshedView::timer ()
  2591. {
  2592.     if (!bSelected || !bTimerSet)
  2593.         return 0;
  2594.  
  2595.     if (iMouseY > m_stScreenSettings.cyBuffer*m_stScreenSettings.cyChar)
  2596.     {
  2597.         // Lower border reached.
  2598.         if (m_stScreenSettings.iCurLine < LASTLINE)
  2599.             m_stScreenSettings.iCurLine++;
  2600.         adjust_vscrollbar ();
  2601.         repaint ();
  2602.     }
  2603.     else if (iMouseY < 0)
  2604.     {
  2605.         // Upper border reached.
  2606.         if (m_stScreenSettings.iCurLine > 0)
  2607.             m_stScreenSettings.iCurLine--;
  2608.         adjust_vscrollbar ();
  2609.         repaint ();
  2610.     }
  2611.     return 1;
  2612. }
  2613.  
  2614. //-------------------------------------------------------------------
  2615. void CFshedView::adjust_view_for_selection ()
  2616. {
  2617.     if( bSelected )
  2618.     {
  2619.         // EOS above current upper line?
  2620.         if( iEndOfSelection / App->m_iBytesPerLine < m_stScreenSettings.iCurLine )
  2621.             // => then set current line to EOS.
  2622.             m_stScreenSettings.iCurLine = iEndOfSelection / App->m_iBytesPerLine;
  2623.  
  2624.         // EOS under current last line?
  2625.         else if( iEndOfSelection/App->m_iBytesPerLine > m_stScreenSettings.iCurLine+m_stScreenSettings.cyBuffer - 1 )
  2626.         {
  2627.             // => then EOS is in new last line.
  2628.             m_stScreenSettings.iCurLine = iEndOfSelection / App->m_iBytesPerLine - m_stScreenSettings.cyBuffer + 1;
  2629.             if( m_stScreenSettings.iCurLine < 0 )
  2630.                 m_stScreenSettings.iCurLine = 0;
  2631.         }
  2632.       ASSERT(m_stScreenSettings.iCurLine >= 0);
  2633.         adjust_vscrollbar();
  2634.     }
  2635. }
  2636.  
  2637. /////////////////////////////////////////////////////////////////////////////
  2638. // CFshedView message handlers
  2639.  
  2640. int CFshedView::OnCreate(LPCREATESTRUCT lpCreateStruct) 
  2641. {
  2642.     if (CView::OnCreate(lpCreateStruct) == -1)
  2643.         return -1;
  2644.  
  2645.     // Create Statusbar.
  2646.     InitCommonControls ();
  2647.     hwndStatusBar = CreateStatusWindow (
  2648.          CCS_BOTTOM | WS_CHILD | WS_VISIBLE | SBARS_SIZEGRIP,
  2649.         _T("Ready"), m_hWnd, 2);
  2650.  
  2651. //   hwndToolBar = CreateTBar(hInstance, m_hWnd, IDB_TOOLBAR);
  2652.  
  2653.     // Create Scrollbars.
  2654.     hwndHBar = CreateWindow (_T("scrollbar"), NULL, WS_CHILD | WS_VISIBLE | SBS_HORZ,
  2655.         0,0,0,0, m_hWnd, (HMENU) 1, AfxGetInstanceHandle(), NULL);
  2656.     hwndVBar = CreateWindow (_T("scrollbar"), NULL, WS_CHILD | WS_VISIBLE | SBS_VERT,
  2657.         0,0,0,0, m_hWnd, (HMENU) 2, AfxGetInstanceHandle(), NULL);
  2658.  
  2659.     m_stScreenSettings.iVscrollMax = 0;
  2660.     m_stScreenSettings.iVscrollPos = 0;
  2661.     m_stScreenSettings.iVscrollInc = 0;
  2662.     m_stScreenSettings.iHscrollMax = 0;
  2663.     m_stScreenSettings.iHscrollPos = 0;
  2664.     m_stScreenSettings.iHscrollInc = 0;
  2665.  
  2666.     m_stScreenSettings.iCurLine = 0;
  2667.     m_stScreenSettings.iCurByte = 0;
  2668.     m_stScreenSettings.iCurNibble = 0;
  2669.     
  2670.     DragAcceptFiles(TRUE ); // Accept files dragged into window.
  2671.     
  2672.     return 0;
  2673. }
  2674.  
  2675. void CFshedView::OnPaint() 
  2676. {
  2677. //    CPaintDC dc(this); // device context for painting
  2678.     
  2679. }
  2680.  
  2681.  
  2682. void CFshedView::OnLButtonDown(UINT nFlags, CPoint point) 
  2683. {
  2684.     if (NO_FILE)
  2685.         return;
  2686.  
  2687.    int yPos = point.y;
  2688.    int xPos = point.x;
  2689.    yPos -= m_stScreenSettings.iToolbarHeight;
  2690.     int scr_column = xPos / m_stScreenSettings.cxChar,
  2691.         scr_row = yPos / m_stScreenSettings.cyChar,
  2692.         log_column = scr_column + m_stScreenSettings.iHscrollPos,
  2693.         line = m_stScreenSettings.iCurLine + scr_row;
  2694.     iLBDownX = xPos;
  2695.     iLBDownY = yPos;
  2696.  
  2697.     // Is the Shift-key held? If yes, then set the position clicked on
  2698.     // as end of selection.
  2699.     if( nFlags & MK_SHIFT )
  2700.     {
  2701.         // Set start of selection.
  2702.         // Click on bytes.
  2703.         if (log_column >= App->m_iOffsetLen + m_stScreenSettings.iByteSpace && log_column <= m_stScreenSettings.iCharsPerLine - 1 - App->m_iBytesPerLine - m_stScreenSettings.iCharSpace - 1)
  2704.         {
  2705.             // Not clicked on empty place:
  2706.             if ((log_column-App->m_iOffsetLen-(m_stScreenSettings.iByteSpace-1))%3 != 0)
  2707.             {
  2708.                 int bytenum = (log_column-App->m_iOffsetLen-(m_stScreenSettings.iByteSpace-1))/3,
  2709.                     nibblenum = ((log_column-App->m_iOffsetLen-(m_stScreenSettings.iByteSpace-1))%3)-1;
  2710.                 int newpos = line * App->m_iBytesPerLine + bytenum;
  2711.                 if( newpos <= LASTBYTE )
  2712.                 {
  2713.                     // If no selection yet, select from current caret position.
  2714.                     if( !bSelected )
  2715.                     {
  2716.                         bSelected = TRUE;
  2717.                         iStartOfSelection = m_stScreenSettings.iCurByte;
  2718.                     }
  2719.                     iEndOfSelection = newpos;
  2720.                 }
  2721.             }
  2722.         }
  2723.         // Click on chars.
  2724.         else if (log_column > m_stScreenSettings.iCharsPerLine - 1 - App->m_iBytesPerLine    && log_column < m_stScreenSettings.iCharsPerLine)
  2725.         {
  2726.             int newpos = line * App->m_iBytesPerLine + (log_column - (m_stScreenSettings.iCharsPerLine - App->m_iBytesPerLine));
  2727.             if( newpos <= LASTBYTE )
  2728.             {
  2729.                 // If no selection yet, select from current caret position.
  2730.                 if( !bSelected )
  2731.                 {
  2732.                     bSelected = TRUE;
  2733.                     iStartOfSelection = m_stScreenSettings.iCurByte;
  2734.                 }
  2735.                 iEndOfSelection = newpos;
  2736.             }
  2737.         }
  2738.         return;
  2739.     }
  2740.  
  2741.     // Set start of selection.
  2742.     // Click on bytes.
  2743.     if (log_column >= App->m_iOffsetLen + m_stScreenSettings.iByteSpace && log_column <= m_stScreenSettings.iCharsPerLine - 1 - App->m_iBytesPerLine - m_stScreenSettings.iCharSpace - 1)
  2744.     {
  2745.         // Not clicked on empty place:
  2746.         if ((log_column-App->m_iOffsetLen-(m_stScreenSettings.iByteSpace-1))%3 != 0)
  2747.         {
  2748.             bLButtonIsDown = TRUE;
  2749.             bSelected = FALSE;
  2750.             int bytenum = (log_column-App->m_iOffsetLen-(m_stScreenSettings.iByteSpace-1))/3,
  2751.                 nibblenum = ((log_column-App->m_iOffsetLen-(m_stScreenSettings.iByteSpace-1))%3)-1;
  2752.             int newpos = line * App->m_iBytesPerLine + bytenum;
  2753.             if( newpos <= LASTBYTE )
  2754.             {
  2755.                 iStartOfSelection = newpos;
  2756.                 iEndOfSelection = newpos;
  2757.             }
  2758.             else if( newpos == LASTBYTE + 1 )
  2759.             {
  2760.                 bLButtonIsDown = FALSE; // Don't select, this can only set caret to END.
  2761.             }
  2762.         }
  2763.     }
  2764.     // Click on chars.
  2765.     else if (log_column > m_stScreenSettings.iCharsPerLine - 1 - App->m_iBytesPerLine    && log_column < m_stScreenSettings.iCharsPerLine)
  2766.     {
  2767.         bLButtonIsDown = TRUE;
  2768.         bSelected = FALSE;
  2769.         int newpos = line * App->m_iBytesPerLine + (log_column - (m_stScreenSettings.iCharsPerLine - App->m_iBytesPerLine));
  2770.         if( newpos <= LASTBYTE )
  2771.         {
  2772.             iStartOfSelection = newpos;
  2773.             iEndOfSelection = newpos;
  2774.         }
  2775.         else if( newpos == LASTBYTE + 1 )
  2776.         {
  2777.             bLButtonIsDown = FALSE; // Don't select, this can only set caret to END.
  2778.         }
  2779.     }
  2780.     
  2781.     CView::OnLButtonDown(nFlags, point);
  2782. }
  2783.  
  2784. void CFshedView::OnMouseMove(UINT nFlags, CPoint point) 
  2785. {
  2786.    int yPos = point.y;
  2787.    int xPos = point.x;
  2788.    yPos -= m_stScreenSettings.iToolbarHeight;
  2789.     iMouseX = xPos;
  2790.     iMouseY = yPos;
  2791.     // If not selecting at the moment.
  2792.     if (bLButtonIsDown == FALSE)
  2793.         return;
  2794.  
  2795.     bSelected = TRUE;
  2796.     // Capture mouse.
  2797.     if (GetCapture() == NULL)
  2798.     {
  2799.         SetCapture ();
  2800.         SetCursor( LoadCursor( NULL, IDC_IBEAM ) );
  2801.     }
  2802.  
  2803.     int scr_column = xPos / m_stScreenSettings.cxChar,
  2804.         scr_row = yPos / m_stScreenSettings.cyChar,
  2805.         log_column = scr_column + m_stScreenSettings.iHscrollPos,
  2806.         line = m_stScreenSettings.iCurLine + scr_row;
  2807.  
  2808.     // Set end of selection according to cursor pos.
  2809.     // Scroll if cursor above or under window.
  2810.     if (yPos>m_stScreenSettings.cyBuffer*m_stScreenSettings.cyChar || yPos<0)
  2811.     {
  2812.         if (bTimerSet==FALSE)
  2813.         {
  2814.             // Set timer for scrolling.
  2815.             SetTimer (TIMERID, TIMERDURATION, NULL);
  2816.             bTimerSet = TRUE;
  2817.         }
  2818.     }
  2819.     // If cursor on bytes.
  2820.     else if (log_column >= App->m_iOffsetLen + m_stScreenSettings.iByteSpace && log_column <= m_stScreenSettings.iCharsPerLine - 1 - App->m_iBytesPerLine - m_stScreenSettings.iCharSpace - 1)
  2821.     {
  2822.         KillTimer (TIMERID);
  2823.         bTimerSet = FALSE;
  2824.         // If not clicked on empty place.
  2825.         if ((log_column-App->m_iOffsetLen-(m_stScreenSettings.iByteSpace-1))%3 != 0)
  2826.         {
  2827.             int bytenum = (log_column-App->m_iOffsetLen-(m_stScreenSettings.iByteSpace-1))/3,
  2828.                 nibblenum = ((log_column-App->m_iOffsetLen-(m_stScreenSettings.iByteSpace-1))%3)-1;
  2829.             int newpos = line * App->m_iBytesPerLine + bytenum;
  2830.             if (newpos <= LASTBYTE)
  2831.             {
  2832.                 iEndOfSelection = newpos;
  2833.                 repaint ();
  2834.             }
  2835.         }
  2836.     }
  2837.     // If cursor on chars.
  2838.     else if (log_column > m_stScreenSettings.iCharsPerLine - 1 - App->m_iBytesPerLine    && log_column < m_stScreenSettings.iCharsPerLine)
  2839.     {
  2840.         KillTimer (TIMERID);
  2841.         bTimerSet = FALSE;
  2842.         int newpos = line * App->m_iBytesPerLine + (log_column - (m_stScreenSettings.iCharsPerLine - App->m_iBytesPerLine));
  2843.         if (newpos <= LASTBYTE)
  2844.         {
  2845.             iEndOfSelection = newpos;
  2846.             repaint ();
  2847.         }
  2848.     }
  2849.     
  2850.     CView::OnMouseMove(nFlags, point);
  2851. }
  2852.  
  2853. void CFshedView::OnLButtonUp(UINT nFlags, CPoint point) 
  2854. {
  2855.    int yPos = point.y;
  2856.    int xPos = point.x;
  2857.     // Kill timer.
  2858.     KillTimer (TIMERID);
  2859.     bTimerSet = FALSE;
  2860.     // Reset cursor from I-beam to arrow.
  2861.     SetCursor( LoadCursor( NULL, IDC_ARROW ) );
  2862.     // Release mouse.
  2863.     ReleaseCapture ();
  2864.     bLButtonIsDown = FALSE;
  2865.    yPos -= m_stScreenSettings.iToolbarHeight;
  2866.  
  2867.     // If button released where it was pressed (set caret).
  2868.     if (iLBDownX == xPos && iLBDownY == yPos)
  2869.     {
  2870.         int scr_column = xPos / m_stScreenSettings.cxChar, // Column on the screen.
  2871.             scr_row = yPos / m_stScreenSettings.cyChar,    // Line on the screen.
  2872.             log_column = scr_column + m_stScreenSettings.iHscrollPos,    // Logical column.
  2873.             line = m_stScreenSettings.iCurLine + scr_row; // Absolute line number.
  2874.  
  2875.         // If click on bytes: set caret there.
  2876.         if (log_column >= App->m_iOffsetLen + m_stScreenSettings.iByteSpace && log_column <= m_stScreenSettings.iCharsPerLine - 1 - App->m_iBytesPerLine - m_stScreenSettings.iCharSpace - 1)
  2877.         {
  2878.             // If not clicked on empty place:
  2879.             if ((log_column-App->m_iOffsetLen-(m_stScreenSettings.iByteSpace-1))%3 != 0)
  2880.             {
  2881.                 int bytenum = (log_column-App->m_iOffsetLen-(m_stScreenSettings.iByteSpace-1))/3,
  2882.                     nibblenum = ((log_column-App->m_iOffsetLen-(m_stScreenSettings.iByteSpace-1))%3)-1;
  2883.                 int newpos = line * App->m_iBytesPerLine + bytenum;
  2884.                 if( newpos <= LASTBYTE + 1 )
  2885.                 {
  2886.                     m_stScreenSettings.iCurByte = newpos;
  2887.                     m_stScreenSettings.iCurNibble = nibblenum;
  2888.                     m_iEnteringMode = BYTES;
  2889.                     repaint ();
  2890.                 }
  2891.             }
  2892.         }
  2893.         // If click on chars: set caret there.
  2894.         else if (log_column > m_stScreenSettings.iCharsPerLine - 1 - App->m_iBytesPerLine    && log_column < m_stScreenSettings.iCharsPerLine)
  2895.         {
  2896.             int newpos = line * App->m_iBytesPerLine + (log_column - (m_stScreenSettings.iCharsPerLine - App->m_iBytesPerLine));
  2897.             if( newpos <= LASTBYTE + 1 )
  2898.             {
  2899.                 m_stScreenSettings.iCurByte = newpos;
  2900.                 m_iEnteringMode = CHARS;
  2901.                 repaint ();
  2902.             }
  2903.         }
  2904.     }
  2905.     
  2906.     CView::OnLButtonUp(nFlags, point);
  2907. }
  2908.  
  2909. void CFshedView::OnSize(UINT nType, int cx, int cy) 
  2910. {
  2911.     CView::OnSize(nType, cx, cy);
  2912.     
  2913.    resize_window(cx, cy);
  2914. }
  2915.  
  2916. void CFshedView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) 
  2917. {
  2918.    keydown( nChar );    
  2919.     CView::OnKeyDown(nChar, nRepCnt, nFlags);
  2920. }
  2921.  
  2922. void CFshedView::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags) 
  2923. {
  2924.    character( nChar );
  2925.     
  2926.     CView::OnChar(nChar, nRepCnt, nFlags);
  2927. }
  2928.  
  2929. void CFshedView::OnTimer(UINT_PTR nIDEvent) 
  2930. {
  2931.    timer();
  2932.     
  2933.     CView::OnTimer(nIDEvent);
  2934. }
  2935.  
  2936. void CFshedView::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) 
  2937. {
  2938.     if (NO_FILE || Doc->DataArray.GetLength()==0)
  2939.         return;
  2940.  
  2941.     m_stScreenSettings.iVscrollInc = 0;
  2942.    SCROLLINFO si;
  2943.    memset(&si, 0, sizeof(si));
  2944.    si.cbSize = sizeof(si);
  2945.     switch (nSBCode)
  2946.     {
  2947.     case SB_TOP:
  2948.         m_stScreenSettings.iCurLine = 0;
  2949.         break;
  2950.     case SB_BOTTOM:
  2951.         m_stScreenSettings.iCurLine = m_stScreenSettings.iNumlines-1;
  2952.         break;
  2953.     case SB_LINEUP:
  2954.         if (m_stScreenSettings.iCurLine > 0)
  2955.             m_stScreenSettings.iCurLine -= 1;
  2956.         break;
  2957.     case SB_LINEDOWN:
  2958.         if (m_stScreenSettings.iCurLine < m_stScreenSettings.iNumlines-1)
  2959.             m_stScreenSettings.iCurLine += 1;
  2960.         break;
  2961.     case SB_PAGEUP:
  2962.         if (m_stScreenSettings.iCurLine >= m_stScreenSettings.cyBuffer)
  2963.             m_stScreenSettings.iCurLine -= m_stScreenSettings.cyBuffer;
  2964.         else
  2965.             m_stScreenSettings.iCurLine = 0;
  2966.         break;
  2967.     case SB_PAGEDOWN:
  2968.         if (m_stScreenSettings.iCurLine <= m_stScreenSettings.iNumlines-1-m_stScreenSettings.cyBuffer)
  2969.             m_stScreenSettings.iCurLine += m_stScreenSettings.cyBuffer;
  2970.         else
  2971.             m_stScreenSettings.iCurLine = m_stScreenSettings.iNumlines-1;
  2972.         break;
  2973.     case SB_THUMBTRACK:
  2974. //    case SB_THUMBPOSITION:
  2975. //   case SB_ENDSCROLL:
  2976.       si.fMask = SIF_TRACKPOS;
  2977.       ::GetScrollInfo(hwndVBar, SB_CTL, &si);
  2978.       si.fMask = SIF_POS;
  2979.       TRACE("Track by %u, track pos %u\n", nPos, si.nTrackPos);
  2980.       nPos = si.nTrackPos;
  2981.  
  2982.         m_stScreenSettings.iCurLine = (int) (nPos * ((float)(m_stScreenSettings.iNumlines-1)/(float)m_stScreenSettings.iVscrollMax));
  2983.       si.nPos = si.nTrackPos;
  2984.  
  2985.       ::SetScrollInfo(hwndVBar, SB_CTL, &si, TRUE);
  2986. //      ::SetScrollPos (hwndVBar, SB_CTL, nPos, TRUE);
  2987.         if (m_stScreenSettings.iCurLine > m_stScreenSettings.iNumlines-1)
  2988.             m_stScreenSettings.iCurLine = m_stScreenSettings.iNumlines-1;
  2989.         // Make sure the number of empty lines is as small as possible.
  2990.         if( m_stScreenSettings.iNumlines - m_stScreenSettings.iCurLine < m_stScreenSettings.cyBuffer )
  2991.         {
  2992.             m_stScreenSettings.iCurLine = ( ( Doc->DataArray.GetUpperBound() + 1 ) / App->m_iBytesPerLine ) - ( m_stScreenSettings.cyBuffer - 1 );
  2993.             if( m_stScreenSettings.iCurLine < 0 )
  2994.                 m_stScreenSettings.iCurLine = 0;
  2995.         }
  2996.       else
  2997.          ASSERT(m_stScreenSettings.iCurLine >= 0);
  2998.         repaint();
  2999.         return;
  3000.     default:
  3001.         break;
  3002.     }
  3003.     m_stScreenSettings.iVscrollPos = (int) ((float)m_stScreenSettings.iCurLine * ((float)m_stScreenSettings.iVscrollMax)/(float)(m_stScreenSettings.iNumlines-1));
  3004.    si.fMask = SIF_POS;
  3005.    si.nPos = m_stScreenSettings.iVscrollPos;
  3006.    TRACE("Vert scroll to offset %d\n", si.nPos);
  3007.    ::SetScrollInfo(hwndVBar, SB_CTL, &si, TRUE);
  3008. //   ::SetScrollPos (hwndVBar, SB_CTL, m_stScreenSettings.iVscrollPos, TRUE);
  3009.     if (m_stScreenSettings.iCurLine > m_stScreenSettings.iNumlines-1)
  3010.         m_stScreenSettings.iCurLine = m_stScreenSettings.iNumlines-1;
  3011.     repaint ();
  3012. //    CView::OnVScroll(nSBCode, nPos, pScrollBar);
  3013. }
  3014.  
  3015. void CFshedView::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) 
  3016. {
  3017.     if (NO_FILE || Doc->DataArray.GetLength()==0)
  3018.         return;
  3019.  
  3020.     m_stScreenSettings.iHscrollInc = 0;
  3021.     switch (nSBCode)
  3022.     {
  3023.     case SB_TOP:
  3024.         m_stScreenSettings.iHscrollInc = -m_stScreenSettings.iHscrollPos;
  3025.         break;
  3026.     case SB_BOTTOM:
  3027.         m_stScreenSettings.iHscrollInc = m_stScreenSettings.iHscrollMax - m_stScreenSettings.iHscrollPos;
  3028.         break;
  3029.     case SB_LINEUP:
  3030.         if (m_stScreenSettings.iHscrollPos > 0)
  3031.             m_stScreenSettings.iHscrollInc = -1;
  3032.         break;
  3033.     case SB_LINEDOWN:
  3034.         if (m_stScreenSettings.iHscrollPos < m_stScreenSettings.iHscrollMax)
  3035.             m_stScreenSettings.iHscrollInc = 1;
  3036.         break;
  3037.     case SB_PAGEUP:
  3038.         if (m_stScreenSettings.iHscrollPos >= m_stScreenSettings.cxBuffer)
  3039.             m_stScreenSettings.iHscrollInc = -m_stScreenSettings.cxBuffer;
  3040.         else
  3041.             m_stScreenSettings.iHscrollInc = -m_stScreenSettings.iHscrollPos;
  3042.         break;
  3043.     case SB_PAGEDOWN:
  3044.         if (m_stScreenSettings.iHscrollPos <= m_stScreenSettings.iHscrollMax-m_stScreenSettings.cxBuffer)
  3045.             m_stScreenSettings.iHscrollInc = m_stScreenSettings.cxBuffer;
  3046.         else
  3047.             m_stScreenSettings.iHscrollInc = m_stScreenSettings.iHscrollMax - m_stScreenSettings.iHscrollPos;
  3048.         break;
  3049.     case SB_THUMBTRACK:
  3050.         m_stScreenSettings.iHscrollInc = nPos - m_stScreenSettings.iHscrollPos;
  3051.         break;
  3052.     default:
  3053.         break;
  3054.     }
  3055.     m_stScreenSettings.iHscrollPos += m_stScreenSettings.iHscrollInc;
  3056.    SCROLLINFO si;
  3057.    memset(&si, 0, sizeof(si));
  3058.    si.cbSize = sizeof(si);
  3059.    si.fMask = SIF_POS;
  3060.    si.nPos = m_stScreenSettings.iHscrollPos;
  3061.    ::SetScrollInfo(hwndHBar, SB_CTL, &si, TRUE);
  3062. //   ::SetScrollPos (hwndHBar, SB_CTL, m_stScreenSettings.iHscrollPos, TRUE);
  3063.     InvalidateRect (NULL, FALSE);
  3064.     UpdateWindow ();
  3065. //    CView::OnHScroll(nSBCode, nPos, pScrollBar);
  3066. }
  3067.  
  3068. void CFshedView::OnKillFocus(CWnd* pNewWnd) 
  3069. {
  3070. //    CView::OnKillFocus(pNewWnd);
  3071.     HideCaret ();
  3072.     DestroyCaret ();
  3073. }
  3074.  
  3075. void CFshedView::OnSetFocus(CWnd* pOldWnd) 
  3076. {
  3077. //    CView::OnSetFocus(pOldWnd);
  3078.     if (m_stScreenSettings.cxChar == 0 || m_stScreenSettings.cyChar == 0)
  3079.     {
  3080.          HDC hdc = ::GetDC (m_hWnd);
  3081.         if (make_font (hdc))
  3082.       {
  3083.            HFONT of = (HFONT) SelectObject (hdc, hFont);
  3084.            TEXTMETRIC tm;
  3085.            GetTextMetrics (hdc, &tm);
  3086.            m_stScreenSettings.cxChar = tm.tmAveCharWidth;
  3087.            m_stScreenSettings.cxCaps = (tm.tmPitchAndFamily & 1 ? 3 : 2) * m_stScreenSettings.cxChar / 2;
  3088.            m_stScreenSettings.cyChar = tm.tmHeight + tm.tmExternalLeading;
  3089.            SelectObject (hdc, of);
  3090.       }
  3091.       ::ReleaseDC (m_hWnd, hdc);
  3092.     }
  3093.     update_for_new_datasize ();
  3094.    ::CreateCaret (m_hWnd, NULL, m_stScreenSettings.cxChar, m_stScreenSettings.cyChar);
  3095.     set_caret_pos ();
  3096.     ShowCaret ();
  3097. }
  3098.  
  3099. void CFshedView::OnEditCut() 
  3100. {
  3101.    int iCutOffset, iCutNumberOfBytes;
  3102.     if (bSelected) // If selecting...
  3103.     {
  3104.         if (iEndOfSelection >= iStartOfSelection)
  3105.         {
  3106.             iCutOffset = iStartOfSelection;
  3107.             iCutNumberOfBytes = iEndOfSelection-iStartOfSelection+1;
  3108.         }
  3109.         else
  3110.         {
  3111.             iCutOffset = iEndOfSelection;
  3112.             iCutNumberOfBytes = iStartOfSelection-iEndOfSelection+1;
  3113.         }
  3114.     }
  3115.     else // No selection: cut current byte.
  3116.     {
  3117.         iCutOffset = m_stScreenSettings.iCurByte;
  3118.         iCutNumberOfBytes = 1;
  3119.     }
  3120.    iCutMode = BST_CHECKED;
  3121. //    if (DialogBox (hInstance, MAKEINTRESOURCE (IDD_CUTDIALOG), hwnd, (DLGPROC) CutDlgProc))
  3122.     {
  3123.         // Can requested number be cut?
  3124.         // DataArray.GetLength ()-iCutOffset = number of bytes from current pos. to end.
  3125.         if( Doc->DataArray.GetLength() - iCutOffset >= iCutNumberOfBytes )
  3126.         {
  3127.             // OK
  3128.             int newlen = Doc->DataArray.GetLength () - iCutNumberOfBytes;
  3129.             // Cut to clipboard?
  3130.             switch (iCutMode)
  3131.             {
  3132.             case BST_CHECKED:
  3133.                 {
  3134.                     // Transfer to clipboard.
  3135.                     int destlen = byte_to_BC_destlen ((char*) &(Doc->DataArray[iCutOffset]), iCutNumberOfBytes);
  3136.                     HGLOBAL hGlobal = GlobalAlloc (GHND, destlen * sizeof(TCHAR));
  3137.                     if (hGlobal != NULL)
  3138.                     {
  3139.                         CWaitCursor zzz;
  3140.                         char* pd = (char*) GlobalLock (hGlobal);
  3141.                         CString strData;
  3142.                         translate_bytes_to_BC (strData, &(Doc->DataArray[iCutOffset]), iCutNumberOfBytes);
  3143.                         memcpy(pd, strData, destlen * sizeof(TCHAR));
  3144.                         GlobalUnlock (hGlobal);
  3145.                         OpenClipboard ();
  3146.                         EmptyClipboard ();
  3147.                         SetClipboardData (CF_UNICODETEXT, hGlobal);
  3148.                         CloseClipboard ();
  3149.                     }
  3150.                     else
  3151.                     {
  3152.                         // Not enough memory for clipboard.
  3153.                         AfxMessageBox (IDS_ERR_ACC_CLIP);
  3154.                         return;
  3155.                     }
  3156.                     break;
  3157.                 }
  3158.                 
  3159.             default:
  3160.                 break;
  3161.             }
  3162.             // Cut data.
  3163.             if (Doc->DataArray.RemoveAt (iCutOffset, iCutNumberOfBytes) == FALSE)
  3164.             {
  3165.                 AfxMessageBox(IDS_ERR_CUT);
  3166.                 return;
  3167.             }
  3168.             m_stScreenSettings.iCurByte = iCutOffset;
  3169.             if (m_stScreenSettings.iCurByte > LASTBYTE)
  3170.                 m_stScreenSettings.iCurByte = LASTBYTE;
  3171.             if (m_stScreenSettings.iCurByte<0)
  3172.                 m_stScreenSettings.iCurByte=0;
  3173.             Doc->SetModifiedFlag();
  3174.             Doc->bFilestatusChanged = TRUE;
  3175.             bSelected = FALSE;
  3176.             update_for_new_datasize ();
  3177.             repaint ();
  3178.         }
  3179.         else
  3180.         {
  3181.             // Too many bytes to cut.
  3182.             AfxMessageBox(IDS_ERR_CUT_BYTES);
  3183.         }
  3184.     }
  3185. }
  3186.  
  3187. void CFshedView::OnEditCopy() 
  3188. {
  3189.    int iCopyStartOffset, iCopyEndOffset;
  3190.     if (!bSelected)
  3191.     {
  3192.         // No selection: copy current byte.
  3193.         iCopyStartOffset = m_stScreenSettings.iCurByte;
  3194.         iCopyEndOffset = m_stScreenSettings.iCurByte;
  3195.     }
  3196.     else
  3197.     {
  3198.         // Copy selection.
  3199.         if (iEndOfSelection >= iStartOfSelection)
  3200.         {
  3201.             iCopyStartOffset = iStartOfSelection;
  3202.             iCopyEndOffset = iEndOfSelection;
  3203.         }
  3204.         else
  3205.         {
  3206.             iCopyStartOffset = iEndOfSelection;
  3207.             iCopyEndOffset = iStartOfSelection;
  3208.         }
  3209.     }
  3210.  
  3211. //    if (DialogBox (hInstance, MAKEINTRESOURCE (IDD_COPYDIALOG), hwnd, (DLGPROC) CopyDlgProc) != FALSE)
  3212.     {
  3213.         // Get dialogue values.
  3214.         iStartOfSelection = iCopyStartOffset;
  3215.         iEndOfSelection = iCopyEndOffset;
  3216.         if (iEndOfSelection >= iStartOfSelection)
  3217.         {
  3218.             int destlen = byte_to_BC_destlen ((char*) &(Doc->DataArray[iStartOfSelection]), iEndOfSelection-iStartOfSelection+1);
  3219.             HGLOBAL hGlobal = GlobalAlloc (GHND, destlen * sizeof(TCHAR));
  3220.             if (hGlobal != NULL)
  3221.             {
  3222.                 CWaitCursor zzz;
  3223.                 TCHAR* pd = (TCHAR*) GlobalLock (hGlobal);
  3224.                 CString strData;
  3225.                 translate_bytes_to_BC (strData, &(Doc->DataArray[iStartOfSelection]), iEndOfSelection-iStartOfSelection+1);
  3226.                 memcpy(pd, strData, destlen * sizeof(TCHAR));
  3227.                 GlobalUnlock (hGlobal);
  3228.                 OpenClipboard ();
  3229.                 EmptyClipboard ();
  3230.                 SetClipboardData (CF_UNICODETEXT, hGlobal);
  3231.                 CloseClipboard ();
  3232.             }
  3233.             else
  3234.                 AfxMessageBox (IDS_ERR_COPY_MEM);
  3235.         }
  3236.         else
  3237.         {
  3238.             AfxMessageBox(IDS_ERR_END_OFFSET);
  3239.         }
  3240.     }
  3241.     adjust_view_for_selection ();
  3242. }
  3243.  
  3244. void CFshedView::OnEditPaste() 
  3245. {
  3246. //Pabs changed - line comment out
  3247. //    iPasteTimes = 1;
  3248. //    iPasteAsText = FALSE;
  3249. //end
  3250.    UINT iRtn = AfxMessageBox(IDS_INSERT_OVR, MB_YESNOCANCEL);
  3251.    if (iRtn == IDCANCEL)
  3252.       return;
  3253.  
  3254.    char *pcPasteText = NULL;
  3255.     if (OpenClipboard ())
  3256.     {
  3257.         HGLOBAL hClipMemory = GetClipboardData (CF_TEXT);
  3258.         if (hClipMemory != NULL)
  3259.         {
  3260.             int gsize = (int)GlobalSize (hClipMemory);
  3261.             if (gsize > 0)
  3262.             {
  3263.                 char* pClipMemory = (char*) GlobalLock (hClipMemory);
  3264.                 pcPasteText = new char[gsize];
  3265.                 memcpy (pcPasteText, pClipMemory, gsize);
  3266.             }
  3267.             GlobalUnlock (hClipMemory);
  3268.         }
  3269.       else
  3270.          return;
  3271.         CloseClipboard ();
  3272.     }
  3273.    else
  3274.       return;
  3275.  
  3276.    int iPasteMode, iPasteAsText = TRUE, iPasteSkip = 0, iPasteTimes = 1;
  3277.     if( iRtn == IDYES )
  3278.         iPasteMode = 2;
  3279.     else
  3280.         iPasteMode = 1;
  3281. //    if (DialogBox (hInstance, MAKEINTRESOURCE (IDD_PASTEDIALOG), hwnd, (DLGPROC) PasteDlgProc))
  3282.     {
  3283.         switch( iPasteMode )
  3284.         {
  3285.         case 1: // Overwrite.
  3286.             {
  3287.                 char* pcPastestring;
  3288.                 // Create findstring.
  3289.                 int destlen;
  3290.                 if (iPasteAsText == TRUE )
  3291.                 {
  3292.                     destlen = (int)strlen( pcPasteText );
  3293.                     pcPastestring = new char[ destlen ];
  3294.                     memcpy( pcPastestring, pcPasteText, destlen );
  3295.                 }
  3296.                 else
  3297.                 {
  3298.                     destlen = create_bc_translation (&pcPastestring, pcPasteText, (int)strlen (pcPasteText), App->m_iCharacterSet, App->m_iBinaryMode);
  3299.                 }
  3300.                 if (destlen > 0)
  3301.                 {
  3302.                     // Enough space for writing?
  3303.                     // DataArray.GetLength()-m_stScreenSettings.iCurByte = number of bytes from including curbyte to end.
  3304. //Pabs changed - "(iPasteSkip+destlen)" used to be "destlen"
  3305.                     if (Doc->DataArray.GetLength()-m_stScreenSettings.iCurByte >= (iPasteSkip+destlen)*iPasteTimes)
  3306. //end
  3307.                     {
  3308.                         // Overwrite data.
  3309.                         CWaitCursor zzz;
  3310.                         int i,k;
  3311.                         for (k=0; k<iPasteTimes; k++)
  3312.                         {
  3313.                             for (i=0; i<destlen; i++)
  3314.                             {
  3315.                                 Doc->DataArray[(m_stScreenSettings.iCurByte+k*(iPasteSkip+destlen))+i] = pcPastestring[i];
  3316.                             }
  3317.                         }
  3318.                         Doc->SetModifiedFlag();
  3319.                         Doc->bFilestatusChanged = TRUE;
  3320.                     }
  3321.                     else
  3322.                         AfxMessageBox (IDS_ERR_OVR_SPACE);
  3323.                     delete [] pcPastestring;
  3324.                 }
  3325.                 delete [] pcPasteText;
  3326.                 repaint ();
  3327.                 break;
  3328.             }
  3329.  
  3330.         case 2: // Insert.
  3331.             {
  3332.                 char* pcPastestring;
  3333.                 int destlen;
  3334.                 if( iPasteAsText == TRUE )
  3335.                 {
  3336.                     destlen = (int)strlen( pcPasteText );
  3337.                     pcPastestring = new char[ destlen ];
  3338.                     memcpy( pcPastestring, pcPasteText, destlen );
  3339.                 }
  3340.                 else
  3341.                 {
  3342.                     destlen = create_bc_translation( &pcPastestring, pcPasteText, (int)strlen( pcPasteText ), App->m_iCharacterSet, App->m_iBinaryMode );
  3343.                 }
  3344.                 if( destlen > 0 )
  3345.                 {
  3346.                     // Insert at m_stScreenSettings.iCurByte. Bytes there will be pushed up.
  3347.                     CWaitCursor zzz;
  3348.                     int i, k;
  3349.                     for( k = 0,i=m_stScreenSettings.iCurByte; k < iPasteTimes; k++ ){
  3350.                         if (!Doc->DataArray.InsertAtGrow(m_stScreenSettings.iCurByte,(unsigned char*)pcPastestring,0,destlen)){
  3351.                             delete [] pcPastestring;
  3352.                             delete [] pcPasteText;
  3353.                             AfxMessageBox(IDS_ERR_MEM_INSERT);
  3354.                             update_for_new_datasize ();
  3355.                             return;
  3356.                         }
  3357.                         Doc->SetModifiedFlag();
  3358.                         Doc->bFilestatusChanged = TRUE;
  3359.                         m_stScreenSettings.iCurByte+=destlen+iPasteSkip;
  3360.                     }
  3361.                     m_stScreenSettings.iCurByte=i;
  3362.                     Doc->SetModifiedFlag();
  3363.                     Doc->bFilestatusChanged = TRUE;
  3364.                     update_for_new_datasize ();
  3365.                     delete [] pcPastestring;
  3366.                 }
  3367.                 else
  3368.                 {
  3369.                     delete [] pcPasteText;
  3370.                     AfxMessageBox(IDS_ERR_INS_ZERO);
  3371.                     update_for_new_datasize ();
  3372.                     return;
  3373.                 }
  3374.                 delete [] pcPasteText;
  3375.                 repaint ();
  3376.                 break;
  3377.             }
  3378.  
  3379.         default:
  3380.             break;
  3381.         }
  3382.     }
  3383. }
  3384.  
  3385. void CFshedView::OnPrint(CDC* pDC, CPrintInfo* pInfo) 
  3386. {
  3387.    m_stScreenSettings.iCurLine = (pInfo->m_nCurPage - 1) * m_stScreenSettings.cyBuffer;
  3388.    TRACE("Page %d, Lines %d to %d\n", pInfo->m_nCurPage, m_stScreenSettings.iCurLine, m_stScreenSettings.iCurLine + m_stScreenSettings.cyBuffer - 1);
  3389.    int nHeight = -::MulDiv(App->m_iFontSize, pDC->GetDeviceCaps(LOGPIXELSY), 72);
  3390.    if (make_font(pDC->GetSafeHdc(), nHeight))
  3391.    {
  3392.        HFONT of = (HFONT) SelectObject(pDC->GetSafeHdc(), hFont);
  3393.        TEXTMETRIC tm;
  3394.        pDC->GetTextMetrics(&tm);
  3395.        m_stScreenSettings.cxChar = tm.tmAveCharWidth;
  3396.        m_stScreenSettings.cxCaps = (tm.tmPitchAndFamily & 1 ? 3 : 2) * m_stScreenSettings.cxChar / 2;
  3397.        m_stScreenSettings.cyChar = tm.tmHeight + tm.tmExternalLeading;
  3398.        SelectObject(pDC->GetSafeHdc(), of);
  3399.    }
  3400.    OnDraw(pDC);
  3401. }
  3402.  
  3403. //-------------------------------------------------------------------
  3404. int CFshedView::GotoBookmark( int cmd )
  3405. {
  3406.     if( pbmkList[ cmd - IDM_BOOKMARK1 ].offset >= 0 && pbmkList[ cmd - IDM_BOOKMARK1 ].offset <= Doc->DataArray.GetLength() )
  3407.     {
  3408.         m_stScreenSettings.iCurByte = pbmkList[ cmd - IDM_BOOKMARK1 ].offset;
  3409.         update_for_new_datasize();
  3410.         adjust_vscrollbar();
  3411.         repaint();
  3412.     }
  3413.     else
  3414.     {
  3415.         AfxMessageBox (IDS_ERR_BAD_BOOKMARK);
  3416.     }
  3417.     return 0;
  3418. }
  3419.  
  3420. void CFshedView::OnBookmark(UINT nId) 
  3421. {
  3422.    GotoBookmark(nId);
  3423. }
  3424.  
  3425. void CFshedView::OnRemoveBkm() 
  3426. {
  3427.     if (iBmkCount==0)
  3428.     {
  3429.         AfxMessageBox (IDS_ERR_NOBK2REMOVE);
  3430.         return;
  3431.     }
  3432.    CRemoveBookmarkDlg dlgRemBk(this);
  3433.    dlgRemBk.m_pbmkRemove = pbmkList;
  3434.     dlgRemBk.m_nNumBookmarks = iBmkCount;
  3435.     if (dlgRemBk.DoModal() == IDOK)
  3436.     {
  3437.         if (pbmkList[dlgRemBk.m_nSelBookmark].name != NULL)
  3438.             delete [] (pbmkList[dlgRemBk.m_nSelBookmark].name);
  3439.         int i;
  3440.         for (i = dlgRemBk.m_nSelBookmark; i < iBmkCount-1; i++)
  3441.             pbmkList[i] = pbmkList[i+1];
  3442.         iBmkCount--;
  3443.         repaint();
  3444.     }
  3445. }
  3446.  
  3447. void CFshedView::OnClearallBmk() 
  3448. {
  3449.     if (AfxMessageBox(IDS_PRMPT_CLEARALLBK, MB_YESNO | MB_ICONQUESTION ) == IDYES )
  3450.     {
  3451.         int i;
  3452.         for (i=0; i<iBmkCount; i++)
  3453.             if (pbmkList[i].name != NULL)
  3454.                 delete [] (pbmkList[i].name);
  3455.         iBmkCount = 0;
  3456.         repaint();
  3457.     }
  3458. }
  3459.  
  3460. void CFshedView::OnAddbookmark() 
  3461. {
  3462.     if (Doc->DataArray.GetLength()<=0)
  3463.     {
  3464.         AfxMessageBox (IDS_ERR_NOBK_EMPTY);
  3465.         return;
  3466.     }
  3467.     if (iBmkCount < BMKMAX)
  3468.     {
  3469.       CAddBookmarkDlg dlgBk(this);
  3470.         dlgBk.m_nOffset = m_stScreenSettings.iCurByte;
  3471.         if (dlgBk.DoModal() == IDOK)
  3472.         {
  3473.             if (dlgBk.m_nOffset >=0 && dlgBk.m_nOffset <= Doc->DataArray.GetLength())
  3474.             {
  3475.                 // Is there already a bookmark on this offset?
  3476.                 int i;
  3477.                 for (i = 0; i < iBmkCount; i++)
  3478.                 {
  3479.                     if (pbmkList[ i ].offset == dlgBk.m_nOffset)
  3480.                     {
  3481.                         AfxMessageBox(IDS_ERR_ALREADY_BK);
  3482.                         return;
  3483.                     }
  3484.                 }
  3485.                 // No bookmark on that position yet.
  3486.                 pbmkList[iBmkCount].offset = dlgBk.m_nOffset;
  3487.                 if (dlgBk.m_strName.GetLength() > 0)
  3488.                 {
  3489.                     pbmkList[iBmkCount].name = new TCHAR[dlgBk.m_strName.GetLength() + 1];
  3490.                     _tcscpy (pbmkList[iBmkCount].name, dlgBk.m_strName);
  3491.                 }
  3492.                 else
  3493.                     pbmkList[iBmkCount].name = NULL;
  3494.                 iBmkCount++;
  3495.  
  3496.                 repaint();
  3497.             }
  3498.             else
  3499.             {
  3500.                 AfxMessageBox (IDS_ERR_NOBK_POS);
  3501.                 return;
  3502.             }
  3503.         }
  3504.     }
  3505.     else
  3506.     {
  3507.         AfxMessageBox(IDS_ERR_NOMORE_BK);
  3508.     }
  3509. }
  3510.  
  3511. void CFshedView::OnCopyHexdump() 
  3512. {
  3513.     if (Doc->DataArray.GetLength() <= 0)
  3514.     {
  3515.         AfxMessageBox (IDS_ERR_DUMP_EMPTY);
  3516.         return;
  3517.     }
  3518.    CHexDumpDlg dlgDump(this);
  3519.     if( !bSelected )
  3520.     {
  3521.         // Assume whole file is to be hexdumped.
  3522.         dlgDump.m_nEndOffset = ((Doc->DataArray.GetUpperBound())/App->m_iBytesPerLine)*App->m_iBytesPerLine;
  3523.     }
  3524.     else
  3525.     {
  3526.         // Assume selected area is to be hexdumped.
  3527.         // Make sure end of selection is greater than start of selection.
  3528.         if( iEndOfSelection < iStartOfSelection )
  3529.         {
  3530.             int i = iEndOfSelection;
  3531.             iEndOfSelection = iStartOfSelection;
  3532.             iStartOfSelection = i;
  3533.         }
  3534.         dlgDump.m_nStartOffset = ( iStartOfSelection / App->m_iBytesPerLine ) * App->m_iBytesPerLine;
  3535.         dlgDump.m_nEndOffset = ( iEndOfSelection / App->m_iBytesPerLine ) * App->m_iBytesPerLine;
  3536.     }
  3537.  
  3538.     if (dlgDump.DoModal() == IDOK)
  3539.     {
  3540.         // Show wait cursor.
  3541.         if (dlgDump.m_nStartOffset % App->m_iBytesPerLine != 0 || dlgDump.m_nEndOffset % App->m_iBytesPerLine != 0)
  3542.         {
  3543.             AfxMessageBox(IDS_ERR_DUMPOFFSETS);
  3544.             return;
  3545.         }
  3546.         SetCursor (LoadCursor (NULL, IDC_WAIT));
  3547.         // Number of lines to copy:
  3548.         int linecount = (dlgDump.m_nEndOffset - dlgDump.m_nStartOffset) / App->m_iBytesPerLine + 1;
  3549.         // Req'd mem for lines:
  3550.         // (Every line ended with CR+LF ('\r'+'\n'))
  3551.         int buflen = linecount * (m_stScreenSettings.iCharsPerLine+2) + 1;
  3552.         // Create hexdump.
  3553.         int a,b,k,m,n,j,l;
  3554.         char buf1[128], buf2[128];
  3555.         char* pMem = new char[buflen];
  3556.         for (n=0; n < buflen; n++)
  3557.             pMem[n] = ' ';
  3558.         // Write hexdump.
  3559.         // a = first byte of first line of hexdump.
  3560.         // b = first byte of last line of hexdump.
  3561.         b = dlgDump.m_nEndOffset;
  3562.         // a = Offset of current line.
  3563.         // k = Offset in text array.
  3564.         for (k = 0, a = dlgDump.m_nStartOffset; a <= b; a += App->m_iBytesPerLine, k += m_stScreenSettings.iCharsPerLine + 2)
  3565.         {
  3566.             // Write offset.
  3567.             sprintf (buf1, "%%%d.%dx", App->m_iOffsetLen, App->m_iOffsetLen);
  3568.             for (m = 0; m < m_stScreenSettings.iByteSpace; m++)
  3569.                 strcat (buf1, " ");
  3570.             sprintf (buf2, buf1, a); // buf2 = Offset+Spaces.
  3571.             l = 0; // l = Offset in line, relative to k.
  3572.             n = 0;
  3573.             while (buf2[n] != '\0')
  3574.                 pMem[k + (l++)] = buf2[n++]; // Copy Offset. l = next empty place after spaces.
  3575.             // Write bytes and chars.
  3576.             for (j = 0; j < App->m_iBytesPerLine; j++)
  3577.             {
  3578.                 if (a+j > Doc->DataArray.GetUpperBound ())
  3579.                 {
  3580.                     // Nonexistant byte.
  3581.                     pMem[k + l + j*3    ] = ' ';
  3582.                     pMem[k + l + j*3 + 1] = ' ';
  3583.                     pMem[k + l + j*3 + 2] = ' ';
  3584.                     // Nonexistant char.
  3585.                     pMem[k + l + App->m_iBytesPerLine*3 + m_stScreenSettings.iCharSpace + j] = ' ';
  3586.                 }
  3587.                 else
  3588.                 {
  3589.                     // Write byte.
  3590.                     sprintf (buf1, "%2.2x ", Doc->DataArray[a + j]);
  3591.                     pMem[k + l + j*3    ] = buf1[0];
  3592.                     pMem[k + l + j*3 + 1] = buf1[1];
  3593.                     pMem[k + l + j*3 + 2] = buf1[2];
  3594.                     // Write char.
  3595.                     if( App->m_iCharacterSet == OEM_FIXED_FONT && Doc->DataArray[a + j] != 0 )
  3596.                         pMem[k + l + App->m_iBytesPerLine*3 + m_stScreenSettings.iCharSpace + j] = Doc->DataArray[a + j];
  3597.                     else if( (Doc->DataArray[a + j] >= 32 && Doc->DataArray[a + j] <= 126) || 
  3598.                   (Doc->DataArray[a + j]>=160 && Doc->DataArray[a + j] <= 255) || 
  3599.                   (Doc->DataArray[a + j] >= 145 && Doc->DataArray[a + j] <= 146) )
  3600.                         pMem[k + l + App->m_iBytesPerLine*3 + m_stScreenSettings.iCharSpace + j] = Doc->DataArray[a + j];
  3601.                     else
  3602.                         pMem[k + l + App->m_iBytesPerLine*3 + m_stScreenSettings.iCharSpace + j] = '.';
  3603.                 }
  3604.             }
  3605.             pMem[k + m_stScreenSettings.iCharsPerLine    ] = '\r';
  3606.             pMem[k + m_stScreenSettings.iCharsPerLine + 1] = '\n';
  3607.         }
  3608.         pMem[buflen-1] = '\0';
  3609.         // Remove wait cursor.
  3610.         SetCursor (LoadCursor (NULL, IDC_ARROW));
  3611.         if (dlgDump.m_nExportTo == 1)
  3612.         {
  3613.             // To clipboard.
  3614.             HGLOBAL hGlobal = GlobalAlloc (GHND, buflen);
  3615.             if (hGlobal != NULL)
  3616.             {
  3617.                 char* pDest = (char*) GlobalLock (hGlobal);
  3618.                 memcpy (pDest, pMem, buflen);
  3619.                 GlobalUnlock (hGlobal);
  3620.                 OpenClipboard ();
  3621.                 EmptyClipboard ();
  3622.                 SetClipboardData (CF_TEXT, hGlobal);
  3623.                 CloseClipboard ();
  3624.             }
  3625.             else
  3626.                 AfxMessageBox(IDS_ERR_HEX_NOMEM);
  3627.         }
  3628.         else
  3629.         {
  3630.             // to file.
  3631.             TCHAR szFileName[_MAX_PATH];
  3632.             TCHAR szTitleName[_MAX_FNAME + _MAX_EXT];
  3633.             _tcscpy (szFileName, _T("hexdump.txt"));
  3634.             OPENFILENAME ofn;
  3635.             ofn.lStructSize = sizeof (OPENFILENAME);
  3636.             ofn.hwndOwner = m_hWnd;
  3637.             ofn.hInstance = NULL;
  3638.             ofn.lpstrFilter = _T("All Files (*.*)\0*.*\0\0");
  3639.             ofn.lpstrCustomFilter = NULL;
  3640.             ofn.nMaxCustFilter = 0;
  3641.             ofn.nFilterIndex = 0;
  3642.             ofn.lpstrFile = szFileName;
  3643.             ofn.nMaxFile = _MAX_PATH;
  3644.             ofn.lpstrFileTitle = szTitleName;
  3645.             ofn.nMaxFileTitle = _MAX_FNAME + _MAX_EXT;
  3646.             ofn.lpstrInitialDir = NULL;
  3647.             ofn.lpstrTitle = NULL;
  3648.             ofn.Flags = OFN_HIDEREADONLY | OFN_CREATEPROMPT;
  3649.             ofn.nFileOffset = 0;
  3650.             ofn.nFileExtension = 0;
  3651.             ofn.lpstrDefExt = NULL;
  3652.             ofn.lCustData = 0L;
  3653.             ofn.lpfnHook = NULL;
  3654.             ofn.lpTemplateName = NULL;
  3655.             if (GetSaveFileName (&ofn))
  3656.             {
  3657.                 int filehandle;
  3658.                 if ((filehandle = _topen(szFileName, _O_RDWR|_O_CREAT|_O_TRUNC|_O_BINARY,_S_IREAD|_S_IWRITE)) != -1)
  3659.                 {
  3660.                     // Write file.
  3661.                     if ((_write (filehandle, pMem, buflen-1)) != -1)
  3662.                     {
  3663.                         AfxMessageBox(IDS_OK_SAVING);
  3664.                     }
  3665.                     else
  3666.                         AfxMessageBox(IDS_ERR_HEX_SAVE);
  3667.                     _close (filehandle);
  3668.                 }
  3669.                 else
  3670.                     AfxMessageBox(IDS_ERR_HEX_SAVE);
  3671.             }
  3672.             repaint ();
  3673.         }
  3674.         delete [] pMem;
  3675.     }
  3676. }
  3677.  
  3678. void CFshedView::OnInsertfile() 
  3679. {
  3680.     TCHAR szFileName[_MAX_PATH];
  3681.     TCHAR szTitleName[_MAX_FNAME + _MAX_EXT];
  3682.     szFileName[0] = '\0';
  3683.     OPENFILENAME ofn;
  3684.     ofn.lStructSize = sizeof (OPENFILENAME);
  3685.     ofn.hwndOwner = m_hWnd;
  3686.     ofn.hInstance = NULL;
  3687.     ofn.lpstrFilter = _T("All Files (*.*)\0*.*\0\0");
  3688.     ofn.lpstrCustomFilter = NULL;
  3689.     ofn.nMaxCustFilter = 0;
  3690.     ofn.nFilterIndex = 0;
  3691.     ofn.lpstrFile = szFileName;
  3692.     ofn.nMaxFile = _MAX_PATH;
  3693.     ofn.lpstrFileTitle = szTitleName;
  3694.     ofn.nMaxFileTitle = _MAX_FNAME + _MAX_EXT;
  3695.     ofn.lpstrInitialDir = NULL;
  3696.     ofn.lpstrTitle = NULL;
  3697.     ofn.Flags = OFN_HIDEREADONLY | OFN_CREATEPROMPT;
  3698.     ofn.nFileOffset = 0;
  3699.     ofn.nFileExtension = 0;
  3700.     ofn.lpstrDefExt = NULL;
  3701.     ofn.lCustData = 0L;
  3702.     ofn.lpfnHook = NULL;
  3703.     ofn.lpTemplateName = NULL;
  3704.     if (GetOpenFileName (&ofn))
  3705.     {
  3706.         // RK: don't allow inserting same file we're editing right now.
  3707.         if( _tcscmp( szFileName, Doc->filename ) == 0 )
  3708.         {
  3709.             AfxMessageBox(IDS_ERR_NOSELFINS);
  3710.             return;
  3711.         }
  3712.  
  3713.         int fhandle;
  3714.         if ((fhandle=_topen(szFileName,_O_RDONLY|_O_BINARY))!=-1)
  3715.       {
  3716.             int inslen;
  3717.             if ((inslen = _filelength (fhandle)) != -1)
  3718.          {
  3719.                 if (inslen)
  3720.             {
  3721.                     unsigned char* insbuf = new unsigned char[inslen];
  3722.                     if (insbuf!=NULL){
  3723.                         if (_read (fhandle, insbuf, inslen) != -1)
  3724.                   {
  3725.                             if (!Doc->DataArray.InsertAtGrow(m_stScreenSettings.iCurByte,insbuf,0,inslen))
  3726.                         AfxMessageBox(IDS_ERR_INS_DATA);
  3727.                             // RK: changed "true" to TRUE.
  3728.                             else
  3729.                      {
  3730.                                 // RK: Added a call to update_for_new_datasize().
  3731. //                                m_iFileChanged = TRUE;
  3732.                                 Doc->bFilestatusChanged = TRUE;
  3733.                         Doc->SetModifiedFlag();
  3734.                                 update_for_new_datasize();
  3735.                                 repaint();
  3736.                             }
  3737.                         }
  3738.                         else 
  3739.                      AfxMessageBox(IDS_ERR_READING_FILE);
  3740.                         delete []insbuf;
  3741.                     }
  3742.                     else 
  3743.                   AfxMessageBox(IDS_ERR_MEM_READFILE);
  3744.                 }
  3745.             }
  3746.             // RK: Spelling of "size"!
  3747.             else 
  3748.             AfxMessageBox(IDS_ERR_CHK_FILESIZE);
  3749.             _close (fhandle);
  3750.         }
  3751.         else 
  3752.          AfxMessageBox(IDS_ERR_FILEOPEN);
  3753.     }
  3754. }
  3755.  
  3756. void CFshedView::OnSaveselas() 
  3757. {
  3758.     TCHAR szFileName[_MAX_PATH];
  3759.     TCHAR szTitleName[_MAX_FNAME + _MAX_EXT];
  3760.     OPENFILENAME ofn;
  3761.     szTitleName[0] = szFileName[0] = '\0';
  3762.     ofn.lStructSize = sizeof (OPENFILENAME);
  3763.     ofn.hwndOwner = m_hWnd;
  3764.     ofn.hInstance = NULL;
  3765.     ofn.lpstrFilter = _T("All Files (*.*)\0*.*\0\0");
  3766.     ofn.lpstrCustomFilter = NULL;
  3767.     ofn.nMaxCustFilter = 0;
  3768.     ofn.nFilterIndex = 0;
  3769.     ofn.lpstrFile = szFileName;
  3770.     ofn.nMaxFile = _MAX_PATH;
  3771.     ofn.lpstrFileTitle = szTitleName;
  3772.     ofn.nMaxFileTitle = _MAX_FNAME + _MAX_EXT;
  3773.     ofn.lpstrInitialDir = NULL;
  3774.     ofn.lpstrTitle = NULL;
  3775.     ofn.Flags = OFN_HIDEREADONLY | OFN_CREATEPROMPT;
  3776.     ofn.nFileOffset = 0;
  3777.     ofn.nFileExtension = 0;
  3778.     ofn.lpstrDefExt = NULL;
  3779.     ofn.lCustData = 0L;
  3780.     ofn.lpfnHook = NULL;
  3781.     ofn.lpTemplateName = NULL;
  3782.     if (GetSaveFileName (&ofn))
  3783.     {
  3784.         int filehandle;
  3785.         if ((filehandle = _topen (szFileName, _O_RDWR|_O_CREAT|_O_TRUNC|_O_BINARY,_S_IREAD|_S_IWRITE)) != -1)
  3786.         {
  3787.             CWaitCursor zzz;
  3788.             if (iStartOfSelection > iEndOfSelection)
  3789.             swap(iStartOfSelection, iEndOfSelection);
  3790.             if (!((_write (filehandle, &Doc->DataArray[iStartOfSelection], iEndOfSelection - iStartOfSelection+1)) != -1))
  3791.                 AfxMessageBox (IDS_ERR_FILESAVE);
  3792.             _close (filehandle);
  3793.         }
  3794.         else
  3795.             AfxMessageBox(IDS_ERR_FILESAVE);
  3796.     }
  3797.     repaint ();
  3798. }
  3799.  
  3800. void CFshedView::OnEditClear() 
  3801. {
  3802.     iCutMode = BST_UNCHECKED;
  3803.    OnEditCut();    
  3804. }
  3805.  
  3806. void CFshedView::OnEditSelectAll() 
  3807. {
  3808.     if (Doc->DataArray.GetLength() > 0)
  3809.    {
  3810.        bSelected = TRUE;
  3811.        iStartOfSelection = 0;
  3812.        iEndOfSelection = Doc->DataArray.GetUpperBound ();
  3813.        adjust_view_for_selection ();
  3814.        repaint ();
  3815.    }
  3816. }
  3817.  
  3818. void CFshedView::OnInsertmodetoggle() 
  3819. {
  3820.     iInsertMode = (iInsertMode) ? FALSE : TRUE;
  3821.     set_wnd_title();
  3822. }
  3823.  
  3824. void CFshedView::OnChangeMode() 
  3825. {
  3826.    character ('\t');
  3827. }
  3828.  
  3829. void CFshedView::OnEditReadonlymode() 
  3830. {
  3831.     if (Doc->bReadOnly == FALSE )
  3832.         Doc->bReadOnly = TRUE;
  3833.     else
  3834.         Doc->bReadOnly = FALSE;
  3835.     set_wnd_title();
  3836.     update_for_new_datasize();
  3837. }
  3838.  
  3839. void CFshedView::OnEditAppend() 
  3840. {
  3841. //    iManipPos = m_stScreenSettings.iCurByte;
  3842.    CAppendDialog dlgAppend(this);
  3843.     if (dlgAppend.DoModal() == IDOK)
  3844.     {
  3845.         int i, oldupbound = Doc->DataArray.GetLength();
  3846.         CWaitCursor zzz;
  3847.         if (Doc->DataArray.SetSize (Doc->DataArray.GetSize() + dlgAppend.m_nNumBytes) == FALSE)
  3848.         {
  3849.             AfxMessageBox(IDS_ERR_APPEND_MEM);
  3850.             return;
  3851.         }
  3852.         Doc->DataArray.SetUpperBound(Doc->DataArray.GetUpperBound() + dlgAppend.m_nNumBytes);
  3853.         for (i=0; i < dlgAppend.m_nNumBytes; i++)
  3854.             Doc->DataArray[oldupbound+i] = 0;
  3855.         Doc->bFilestatusChanged = TRUE;
  3856.         Doc->SetModifiedFlag();
  3857.         update_for_new_datasize ();
  3858.         repaint ();
  3859.     }
  3860. }
  3861.  
  3862. void CFshedView::OnEditManipulatebits() 
  3863. {
  3864.     if (Doc->DataArray.GetLength() == 0)
  3865.     {
  3866.         AfxMessageBox(IDS_ERR_EMPTY_FILE);
  3867.         return;
  3868.     }
  3869.     if (m_stScreenSettings.iCurByte < 0 || m_stScreenSettings.iCurByte > LASTBYTE)
  3870.     {
  3871.         AfxMessageBox (IDS_ERR_SELBYTE);
  3872.         return;
  3873.     }
  3874.     CManipulateBitsDlg    dlgManip(this);
  3875.     dlgManip.m_chValue = Doc->DataArray[m_stScreenSettings.iCurByte];
  3876.     dlgManip.m_nBitPos = m_stScreenSettings.iCurByte;
  3877.     if (dlgManip.DoModal() == IDOK)
  3878.     {
  3879.         Doc->DataArray[m_stScreenSettings.iCurByte] = dlgManip.m_chValue;
  3880.         Doc->bFilestatusChanged = TRUE;
  3881.         Doc->SetModifiedFlag();
  3882.         repaint ();
  3883.     }
  3884. }
  3885.  
  3886. void CFshedView::OnSelectBlock() 
  3887. {
  3888.    CSelectBlockDlg dlgSelBlock(this);
  3889.     dlgSelBlock.m_nStartOffset = dlgSelBlock.m_nEndOffset = m_stScreenSettings.iCurByte;
  3890.     if (dlgSelBlock.DoModal() == IDOK)
  3891.     {
  3892.         iStartOfSelection = dlgSelBlock.m_nStartOffset ;
  3893.         iEndOfSelection = dlgSelBlock.m_nEndOffset;
  3894.         bSelected = TRUE;
  3895.         adjust_view_for_selection ();
  3896.         repaint ();
  3897.     }
  3898. }
  3899.  
  3900. void MessageCopyBox(HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType, HWND hwnd)
  3901. {
  3902.     int len=(int)_tcslen(lpText);//get the # bytes needed to store the string (not counting '\0')
  3903.     //& get where we have to put a '\0' character later
  3904.     // RK: Added "?" to end of string.
  3905.    CString strText;
  3906.     strText.LoadString(IDS_MSG_COPY_TO_CLIP);
  3907.    strText = lpText + strText;
  3908.     if (IDYES == MessageBox (hWnd, strText, lpCaption, MB_YESNO | uType))
  3909.     {
  3910.         //user wants to copy output
  3911.         len++;//1 extra for '\0'
  3912.         HGLOBAL hGlobal = GlobalAlloc (GHND, len * sizeof(TCHAR)); //alloc clip mem
  3913.         if (hGlobal != NULL)//succesful in above
  3914.         {
  3915.             TCHAR* pd = (TCHAR*) GlobalLock (hGlobal);// get pointer to clip data
  3916.             if(pd)
  3917.             {
  3918.                 //succesfuly got pointer
  3919.                 _tcscpy(pd,lpText);//copy lpText into global mem
  3920.                 GlobalUnlock (hGlobal);//unlock global mem
  3921.                 if(OpenClipboard(hwnd))
  3922.                 {
  3923.                     CWaitCursor zzz;
  3924.                     // open clip
  3925.                     EmptyClipboard(); //empty clip
  3926.                     SetClipboardData (CF_UNICODETEXT, hGlobal);//copy to clip
  3927.                     CloseClipboard (); //close clip
  3928.                 }
  3929.                 else //failed to open clip
  3930.                     AfxMessageBox(IDS_ERR_ACC_CLIP);
  3931.             }
  3932.             else
  3933.             {//failed to get pointer to global mem
  3934.                 GlobalFree(hGlobal);
  3935.                    AfxMessageBox (IDS_ERR_HEX_NOMEM);
  3936.             }
  3937.         }
  3938.         else// failed to allocate global mem
  3939.             AfxMessageBox (IDS_ERR_HEX_NOMEM);
  3940.     }
  3941. //user doesn't want to copy output
  3942. }
  3943.  
  3944. void CFshedView::OnReadfloat() 
  3945. {
  3946.     CString strBuf;
  3947.     float floatval;
  3948.     int len = (iEndOfSelection - iStartOfSelection + 1);
  3949.     if (len >= 4)
  3950.     {
  3951.         // enough space for float.
  3952.         if (App->m_iBinaryMode == LITTLEENDIAN_MODE)
  3953.             floatval = *((float*)&(Doc->DataArray[iStartOfSelection]));
  3954.         else // BIGENDIAN_MODE
  3955.         {
  3956.             char* pf = (char*) &floatval;
  3957.             int i;
  3958.             for (i = 0; i < 4; i++)
  3959.                 pf[i] = Doc->DataArray[iStartOfSelection + 3 - i];
  3960.         }
  3961.         strBuf.Format(IDS_FMT_FLOAT_SIZE, floatval);
  3962.     }
  3963.     else
  3964.        strBuf.LoadString(IDS_FMT_FLOAT_NOSPACE);
  3965.     double dval;
  3966.     CString strBuf2;
  3967.     if (len >= 8)
  3968.     {
  3969.         // enough space for double.
  3970.         if (App->m_iBinaryMode == LITTLEENDIAN_MODE)
  3971.             dval = *((double*)&(Doc->DataArray[iStartOfSelection]));
  3972.         else // BIGENDIAN_MODE
  3973.         {
  3974.             char* pd = (char*) &dval;
  3975.             int i;
  3976.             for (i=0; i<8; i++)
  3977.                 pd[i] = Doc->DataArray[iStartOfSelection+7-i];
  3978.         }
  3979.         strBuf2.Format(IDS_FMT_DOUBLE_VAL, dval);
  3980.     }
  3981.     else
  3982.         strBuf2.LoadString(IDS_FMT_DOUBLE_NOSPACE);
  3983.     strBuf += strBuf2;
  3984.     strBuf2.LoadString(IDS_LAB_FLOATVALS);
  3985.     MessageCopyBox (NULL, strBuf, strBuf2, MB_ICONINFORMATION, m_hWnd);
  3986. }
  3987.  
  3988. void CFshedView::OnProperties() 
  3989. {
  3990.     CString strBuf;
  3991.     strBuf.LoadString(IDS_LAB_FN_PATH);
  3992.     LPTSTR pc;
  3993.     CString strBuf2;
  3994.     GetFullPathName (Doc->filename, MAX_PATH, strBuf2.GetBuffer(MAX_PATH), &pc);
  3995.     strBuf2.ReleaseBuffer();
  3996.     strBuf += strBuf2;
  3997.     if (Doc->bPartialOpen)
  3998.     {
  3999.         strBuf2.Format(IDS_LAB_PART_OPEN, Doc->iPartialOffset, Doc->iPartialOffset, 
  4000.         Doc->DataArray.GetLength(), Doc->DataArray.GetLength() / 1024);
  4001.     }
  4002.     else
  4003.     {
  4004.         strBuf2.Format(IDS_LAB_FILE_SIZE, Doc->DataArray.GetLength(), 
  4005.         Doc->DataArray.GetLength() / 1024);
  4006.     }
  4007.     strBuf += strBuf2;
  4008.     strBuf2.Format(IDS_LAB_NUM_LINES, m_stScreenSettings.iNumlines);
  4009.     strBuf += strBuf2;
  4010.     strBuf2.LoadString(IDS_TTL_FILE_PROP);
  4011.     MessageCopyBox (NULL, strBuf, strBuf2, MB_ICONINFORMATION, m_hWnd);
  4012. }
  4013.  
  4014.  
  4015. void CFshedView::OnRevert() 
  4016. {
  4017.     if (Doc->load_file (Doc->filename))
  4018.     {
  4019.         m_stScreenSettings.iVscrollMax = m_stScreenSettings.iVscrollPos = m_stScreenSettings.iVscrollInc = m_stScreenSettings.iHscrollMax = m_stScreenSettings.iHscrollPos = 
  4020.         m_stScreenSettings.iHscrollInc = m_stScreenSettings.iCurLine = m_stScreenSettings.iCurByte = m_stScreenSettings.iCurNibble = 0;
  4021.         Doc->SetModifiedFlag(FALSE);
  4022.         Doc->bFilestatusChanged = TRUE;
  4023.         Doc->bFileNeverSaved = FALSE;
  4024.         bSelected=FALSE;
  4025.         RECT rc;
  4026.         GetClientRect (&rc);
  4027.         SendMessage (WM_SIZE, 0, (rc.bottom << 16) | rc.right);
  4028.         InvalidateRect (NULL, FALSE);
  4029.         UpdateWindow ();
  4030.     }                    
  4031. }
  4032.  
  4033. void CFshedView::OnBookmarksGotobookmark() 
  4034. {
  4035.     CRemoveBookmarkDlg dlgRemBk(this);
  4036.     dlgRemBk.m_pbmkRemove = pbmkList;
  4037.     dlgRemBk.m_nNumBookmarks = iBmkCount;
  4038.     dlgRemBk.m_uWindowTitle = IDS_TTL_GOTO_BK;
  4039.     if (dlgRemBk.DoModal() == IDOK)
  4040.     {
  4041.         m_stScreenSettings.iCurByte = pbmkList[dlgRemBk.m_nSelBookmark].offset;
  4042.         update_for_new_datasize();
  4043.         adjust_vscrollbar();
  4044.         repaint();
  4045.     }
  4046. }
  4047.  
  4048. void CFshedView::OnUpdateBookmarksGotobookmark(CCmdUI* pCmdUI) 
  4049. {
  4050.    pCmdUI->Enable(iBmkCount);
  4051. }
  4052.  
  4053. void CFshedView::OnUpdateEditReadonlymode(CCmdUI* pCmdUI) 
  4054. {
  4055.    pCmdUI->SetCheck(Doc->bReadOnly);
  4056. }
  4057.  
  4058. void CFshedView::OnEditPasteSpecial() 
  4059. {
  4060.    CPasteSpecialDlg dlgPaste;
  4061.    if (dlgPaste.DoModal() == IDOK)
  4062.    {
  4063.         char* pcPastestring;
  4064.         // Create findstring.
  4065.         int destlen;
  4066.         if (dlgPaste.m_bPasteAsText == TRUE)
  4067.         {
  4068.             destlen = WideCharToMultiByte(CP_ACP, 0, (LPWSTR)(LPCTSTR)dlgPaste.m_strClipText, 
  4069.                 dlgPaste.m_strClipText.GetLength(), NULL, NULL, NULL, NULL);
  4070.             pcPastestring = new char[destlen + 1];
  4071.             WideCharToMultiByte(CP_ACP, 0, (LPWSTR)(LPCTSTR)dlgPaste.m_strClipText, dlgPaste.m_strClipText.GetLength(), 
  4072.                 pcPastestring, destlen, NULL, NULL);    // use it to call OLE here
  4073.             pcPastestring[destlen] = 0;
  4074.         }
  4075.         else
  4076.             destlen = create_bc_translation (&pcPastestring, dlgPaste.m_strClipText, (int)_tcslen(dlgPaste.m_strClipText), App->m_iCharacterSet, App->m_iBinaryMode);
  4077.         if (destlen > 0)
  4078.         {
  4079.             if (!dlgPaste.m_nInsertMode) // Overwrite.
  4080.             {
  4081.                 // Enough space for writing?
  4082.                 // DataArray.GetLength()-m_stScreenSettings.iCurByte = number of bytes from including curbyte to end.
  4083.                 if ((Doc->DataArray.GetLength() - m_stScreenSettings.iCurByte) >= 
  4084.                     (dlgPaste.m_nSkipBytes + destlen) * dlgPaste.m_nNumTimes)
  4085.                 {
  4086.                     // Overwrite data.
  4087.                     CWaitCursor zzz;
  4088.                     int i,k;
  4089.                     for (k = 0; k < dlgPaste.m_nNumTimes; k++)
  4090.                     {
  4091.                         for (i=0; i<destlen; i++)
  4092.                         {
  4093.                             Doc->DataArray[(m_stScreenSettings.iCurByte + k * (dlgPaste.m_nSkipBytes + destlen)) + i] = pcPastestring[i];
  4094.                         }
  4095.                     }
  4096.                     Doc->SetModifiedFlag();
  4097.                     Doc->bFilestatusChanged = TRUE;
  4098.                 }
  4099.                 else
  4100.                 {
  4101.                     AfxMessageBox(_T("Not enough space for overwriting."), MB_OK | MB_ICONERROR);
  4102.                 }
  4103.                 delete [] pcPastestring;
  4104.             }
  4105.             else // Insert.
  4106.             {
  4107.                 CWaitCursor zzz;
  4108.                 // Insert at m_stScreenSettings.iCurByte. Byte there will be pushed up.
  4109.                 int i, k;
  4110.                 for (k = 0,i = m_stScreenSettings.iCurByte; k < dlgPaste.m_nNumTimes; k++)
  4111.                 {
  4112.                     if (!Doc->DataArray.InsertAtGrow(m_stScreenSettings.iCurByte,(unsigned char*)pcPastestring,0,destlen))
  4113.                     {
  4114.                         delete [] pcPastestring;
  4115.                         AfxMessageBox (_T("Not enough memory for inserting."), MB_OK | MB_ICONERROR);
  4116.                         update_for_new_datasize ();
  4117.                         return;
  4118.                     }
  4119.                     Doc->SetModifiedFlag();
  4120.                     Doc->bFilestatusChanged = TRUE;
  4121.                     m_stScreenSettings.iCurByte += destlen + dlgPaste.m_nSkipBytes;
  4122.                 }
  4123.                 m_stScreenSettings.iCurByte=i;
  4124.                 Doc->SetModifiedFlag();
  4125.                 Doc->bFilestatusChanged = TRUE;
  4126.                 update_for_new_datasize ();
  4127.                 delete [] pcPastestring;
  4128.             }
  4129.             repaint ();
  4130.         }
  4131.    }
  4132. }
  4133.  
  4134. void CFshedView::OnEditFindReplace(BOOL bFindOnly)
  4135. {
  4136.     ASSERT_VALID(this);
  4137.     m_bFirstSearch = TRUE;
  4138.     if (m_pFindReplaceDlg != NULL)
  4139.     {
  4140.         if (m_bFindOnly == bFindOnly)
  4141.         {
  4142.             m_pFindReplaceDlg->SetActiveWindow();
  4143.             m_pFindReplaceDlg->ShowWindow(SW_SHOW);
  4144.             return;
  4145.         }
  4146.         else
  4147.         {
  4148.             ASSERT(m_bFindOnly != bFindOnly);
  4149.             m_pFindReplaceDlg->SendMessage(WM_CLOSE);
  4150.             ASSERT(m_pFindReplaceDlg == NULL);
  4151.             ASSERT_VALID(this);
  4152.         }
  4153.     }
  4154.     CString strFind = GetSelText();
  4155.     // if selection is empty or spans multiple lines use old find text
  4156.     if (strFind.IsEmpty() || (strFind.FindOneOf(_T("\n\r")) != -1))
  4157.         strFind = m_strFind;
  4158.     CString strReplace = m_strReplace;
  4159.     m_pFindReplaceDlg = new CFindReplaceDialog;
  4160.     ASSERT(m_pFindReplaceDlg != NULL);
  4161.     DWORD dwFlags = NULL;
  4162.     if (m_bNext)
  4163.         dwFlags |= FR_DOWN;
  4164.     if (m_bCase)
  4165.         dwFlags |= FR_MATCHCASE;
  4166.     if (m_bWord)
  4167.         dwFlags |= FR_WHOLEWORD;
  4168.     // hide stuff that RichEdit doesn't support
  4169. //    dwFlags |= FR_HIDEUPDOWN;
  4170.     if (!m_pFindReplaceDlg->Create(bFindOnly, strFind, strReplace, dwFlags, this))
  4171.     {
  4172.         m_pFindReplaceDlg = NULL;
  4173.         ASSERT_VALID(this);
  4174.         return;
  4175.     }
  4176.     ASSERT(m_pFindReplaceDlg != NULL);
  4177.     m_bFindOnly = bFindOnly;
  4178.     m_pFindReplaceDlg->SetActiveWindow();
  4179.     m_pFindReplaceDlg->ShowWindow(SW_SHOW);
  4180.     ASSERT_VALID(this);
  4181. }
  4182.  
  4183. BOOL CFshedView::FindTextSimple(LPCTSTR lpszFind, BOOL bCase, BOOL bWord, BOOL m_bNext)
  4184. {
  4185.     USES_CONVERSION;
  4186.     ASSERT(lpszFind != NULL);
  4187.     FINDTEXTEX ft;
  4188.  
  4189.     GetSel(ft.chrg);
  4190.     if (m_bFirstSearch)
  4191.     {
  4192.         m_lInitialSearchPos = ft.chrg.cpMin;
  4193.         m_bFirstSearch = FALSE;
  4194.     }
  4195.  
  4196.     ft.lpstrText = lpszFind;
  4197.     if (ft.chrg.cpMin != ft.chrg.cpMax) // i.e. there is a selection
  4198.     {
  4199. #ifndef _UNICODE
  4200.         // If byte at beginning of selection is a DBCS lead byte,
  4201.         // increment by one extra byte.
  4202.         TEXTRANGE textRange;
  4203.         TCHAR ch[2];
  4204.         textRange.chrg.cpMin = ft.chrg.cpMin;
  4205.         textRange.chrg.cpMax = ft.chrg.cpMin + 1;
  4206.         textRange.lpstrText = ch;
  4207.         SendMessage(EM_GETTEXTRANGE, 0, (LPARAM)&textRange);
  4208.         if (_istlead(ch[0]))
  4209.         {
  4210.             ASSERT(ft.chrg.cpMax - ft.chrg.cpMin >= 2);
  4211.             ft.chrg.cpMin++;
  4212.         }
  4213. #endif
  4214.  
  4215.         ft.chrg.cpMin++;
  4216.     }
  4217.  
  4218.     if (m_lInitialSearchPos >= 0)
  4219.         ft.chrg.cpMax = GetTextLength();
  4220.     else
  4221.         ft.chrg.cpMax = GetTextLength()+m_lInitialSearchPos;
  4222.  
  4223.     DWORD dwFlags = bCase ? FR_MATCHCASE : 0;
  4224.     dwFlags |= bWord ? FR_WHOLEWORD : 0;
  4225.  
  4226.     // if we find the text return TRUE
  4227.     if (FindAndSelect(dwFlags, ft, m_bNext) != -1)
  4228.         return TRUE;
  4229.     // if the original starting point was not the beginning of the buffer
  4230.     // and we haven't already been here
  4231.     else if (m_lInitialSearchPos > 0)
  4232.     {
  4233.         ft.chrg.cpMin = 0;
  4234.         ft.chrg.cpMax = m_lInitialSearchPos;
  4235.         m_lInitialSearchPos = m_lInitialSearchPos - GetTextLength();
  4236.         return FindAndSelect(dwFlags, ft, m_bNext) != -1;
  4237.     }
  4238.     // not found
  4239.     else
  4240.         return FALSE;
  4241. }
  4242.  
  4243. long CFshedView::FindAndSelect(DWORD dwFlags, FINDTEXTEX& ft, BOOL bNext)
  4244. {
  4245.    long index = FindText(dwFlags, bNext, &ft);
  4246.     if (index != -1) // i.e. we found something
  4247.         SetSel(ft.chrgText);
  4248.     return index;
  4249. }
  4250.  
  4251. void CFshedView::TextNotFound(LPCTSTR lpszFind)
  4252. {
  4253.     ASSERT_VALID(this);
  4254.     m_bFirstSearch = TRUE;
  4255.     OnTextNotFound(lpszFind);
  4256. }
  4257.  
  4258. void CFshedView::OnTextNotFound(LPCTSTR)
  4259. {
  4260.     MessageBeep(MB_ICONHAND);
  4261. }
  4262.  
  4263. BOOL CFshedView::FindText(LPCTSTR lpszFind, BOOL bCase, BOOL bWord, BOOL bNext)
  4264. {
  4265.     ASSERT_VALID(this);
  4266.     CWaitCursor wait;
  4267.     return FindTextSimple(lpszFind, bCase, bWord, bNext);
  4268. }
  4269.  
  4270. void CFshedView::OnReplaceSel(LPCTSTR lpszFind, BOOL bNext, BOOL bCase,
  4271.     BOOL bWord, LPCTSTR lpszReplace)
  4272. {
  4273.     ASSERT_VALID(this);
  4274.     m_strFind = lpszFind;
  4275.     m_strReplace = lpszReplace;
  4276.     m_bCase = bCase;
  4277.     m_bWord = bWord;
  4278.     m_bNext = bNext;
  4279.  
  4280.     if (!SameAsSelected(m_strFind, m_bCase, m_bWord))
  4281.     {
  4282.         if (!FindText(m_strFind, m_bCase, m_bWord))
  4283.             TextNotFound(m_strFind);
  4284.         else
  4285.             AdjustDialogPosition(m_pFindReplaceDlg);
  4286.         return;
  4287.     }
  4288.  
  4289.     ReplaceSel(m_strReplace);
  4290.     if (!FindText(m_strFind, m_bCase, m_bWord))
  4291.         TextNotFound(m_strFind);
  4292.     else
  4293.         AdjustDialogPosition(m_pFindReplaceDlg);
  4294.     ASSERT_VALID(this);
  4295. }
  4296.  
  4297. void CFshedView::OnFindNext(LPCTSTR lpszFind, BOOL bNext, BOOL bCase, BOOL bWord)
  4298. {
  4299.     ASSERT_VALID(this);
  4300.  
  4301.     m_strFind = lpszFind;
  4302.     m_bCase = bCase;
  4303.     m_bWord = bWord;
  4304.     m_bNext = bNext;
  4305.  
  4306.     if (!FindText(m_strFind, m_bCase, m_bWord, m_bNext))
  4307.         TextNotFound(m_strFind);
  4308.     else
  4309.         AdjustDialogPosition(m_pFindReplaceDlg);
  4310.     ASSERT_VALID(this);
  4311. }
  4312.  
  4313. void CFshedView::OnReplaceAll(LPCTSTR lpszFind, LPCTSTR lpszReplace, BOOL bCase, BOOL bWord)
  4314. {
  4315.     ASSERT_VALID(this);
  4316.     m_strFind = lpszFind;
  4317.     m_strReplace = lpszReplace;
  4318.     m_bCase = bCase;
  4319.     m_bWord = bWord;
  4320.     m_bNext = TRUE;
  4321.  
  4322.     CWaitCursor wait;
  4323.     // no selection or different than what looking for
  4324.     if (!SameAsSelected(m_strFind, m_bCase, m_bWord))
  4325.     {
  4326.         if (!FindText(m_strFind, m_bCase, m_bWord))
  4327.         {
  4328.             TextNotFound(m_strFind);
  4329.             return;
  4330.         }
  4331.     }
  4332.  
  4333.     HideSelection(TRUE, FALSE);
  4334.     do
  4335.     {
  4336.         ReplaceSel(m_strReplace);
  4337.     } while (FindTextSimple(m_strFind, m_bCase, m_bWord));
  4338.     TextNotFound(m_strFind);
  4339.     HideSelection(FALSE, FALSE);
  4340.  
  4341.     ASSERT_VALID(this);
  4342. }
  4343.  
  4344. LRESULT CFshedView::OnFindReplaceCmd(WPARAM, LPARAM lParam)
  4345. {
  4346.     ASSERT_VALID(this);
  4347.     CFindReplaceDialog* pDialog = CFindReplaceDialog::GetNotifier(lParam);
  4348.     ASSERT(pDialog != NULL);
  4349.     ASSERT(pDialog == m_pFindReplaceDlg);
  4350.     if (pDialog->IsTerminating())
  4351.         m_pFindReplaceDlg = NULL;
  4352.     else if (pDialog->FindNext())
  4353.     {
  4354.         OnFindNext(pDialog->GetFindString(), pDialog->SearchDown(),
  4355.             pDialog->MatchCase(), pDialog->MatchWholeWord());
  4356.     }
  4357.     else if (pDialog->ReplaceCurrent())
  4358.     {
  4359.         ASSERT(!m_bFindOnly);
  4360.         OnReplaceSel(pDialog->GetFindString(),
  4361.             pDialog->SearchDown(), pDialog->MatchCase(), pDialog->MatchWholeWord(),
  4362.             pDialog->GetReplaceString());
  4363.     }
  4364.     else if (pDialog->ReplaceAll())
  4365.     {
  4366.         ASSERT(!m_bFindOnly);
  4367.         OnReplaceAll(pDialog->GetFindString(), pDialog->GetReplaceString(),
  4368.             pDialog->MatchCase(), pDialog->MatchWholeWord());
  4369.     }
  4370.     ASSERT_VALID(this);
  4371.     return 0;
  4372. }
  4373.  
  4374. BOOL CFshedView::SameAsSelected(LPCTSTR lpszCompare, BOOL bCase, BOOL /*bWord*/)
  4375. {
  4376.     // check length first
  4377.     size_t nLen = lstrlen(lpszCompare);
  4378.     long lStartChar, lEndChar;
  4379.     GetSel(lStartChar, lEndChar);
  4380.     if (nLen != (size_t)(lEndChar - lStartChar))
  4381.         return FALSE;
  4382.  
  4383.     // length is the same, check contents
  4384.     CString strSelect = GetSelText();
  4385.     return (bCase && lstrcmp(lpszCompare, strSelect) == 0) ||
  4386.         (!bCase && lstrcmpi(lpszCompare, strSelect) == 0);
  4387. }
  4388.  
  4389. void CFshedView::OnEditFind()
  4390. {
  4391.     ASSERT_VALID(this);
  4392.     OnEditFindReplace(TRUE);
  4393. }
  4394.  
  4395. void CFshedView::OnEditReplace()
  4396. {
  4397.     ASSERT_VALID(this);
  4398.     OnEditFindReplace(FALSE);
  4399. }
  4400.  
  4401. void CFshedView::OnEditRepeat()
  4402. {
  4403.     ASSERT_VALID(this);
  4404.     if (!FindText(m_strFind, m_bCase, m_bWord))
  4405.         TextNotFound(m_strFind);
  4406. }
  4407.  
  4408. void CFshedView::AdjustDialogPosition(CDialog* pDlg)
  4409. {
  4410.     ASSERT(pDlg != NULL);
  4411.     long lStart, lEnd;
  4412.     GetSel(lStart, lEnd);
  4413.     CPoint point = GetCharPos(lStart);
  4414.     ClientToScreen(&point);
  4415.     CRect rectDlg;
  4416.     pDlg->GetWindowRect(&rectDlg);
  4417.     if (rectDlg.PtInRect(point))
  4418.     {
  4419.         if (point.y > rectDlg.Height())
  4420.             rectDlg.OffsetRect(0, point.y - rectDlg.bottom - 20);
  4421.         else
  4422.         {
  4423.             int nVertExt = GetSystemMetrics(SM_CYSCREEN);
  4424.             if (point.y + rectDlg.Height() < nVertExt)
  4425.                 rectDlg.OffsetRect(0, 40 + point.y - rectDlg.top);
  4426.         }
  4427.         pDlg->MoveWindow(&rectDlg);
  4428.     }
  4429. }
  4430. // Rich edit compatible functions
  4431. long CFshedView::GetTextLength( ) 
  4432. {
  4433.     return Doc->DataArray.GetLength();
  4434. }
  4435.  
  4436.  
  4437. long CFshedView::FindText( DWORD dwFlags, BOOL bNext, FINDTEXTEX* pFindText )
  4438. {
  4439.     CWaitCursor zzz;
  4440.  
  4441.     long lStart, lEnd;
  4442.     GetSel(lStart, lEnd);
  4443.     int destLen = WideCharToMultiByte(CP_ACP, 0, (LPWSTR)pFindText->lpstrText, (int)_tcslen(pFindText->lpstrText), NULL, NULL, NULL, NULL);
  4444.     char *charstring = new char[destLen + 1];
  4445.     WideCharToMultiByte(CP_ACP, 0, (LPWSTR)pFindText->lpstrText, (int)_tcslen(pFindText->lpstrText), 
  4446.         charstring, destLen, NULL, NULL); 
  4447.     charstring[destLen] = 0;
  4448.     long i = find_bytes((char*) &Doc->DataArray.GetRefAt(0), Doc->DataArray.GetLength(), 
  4449.       lStart, lEnd,
  4450.       charstring, (int)strlen(charstring), bNext, 
  4451.       (dwFlags & FR_MATCHCASE) ? TRUE : FALSE, (dwFlags & FR_WHOLEWORD) ? TRUE : FALSE);
  4452.    delete charstring;
  4453.    if (i != -1)
  4454.    {
  4455.         m_stScreenSettings.iCurByte = i;
  4456.       pFindText->chrgText.cpMin = m_stScreenSettings.iCurByte;
  4457.       pFindText->chrgText.cpMax = m_stScreenSettings.iCurByte + (long)_tcslen(pFindText->lpstrText) - 1;
  4458.    }
  4459.  
  4460.    
  4461.    return i;
  4462. }
  4463.  
  4464. CPoint CFshedView::GetCharPos( long lChar ) const
  4465. {
  4466.    CPoint pt(0, 0);
  4467.    return pt;
  4468. }
  4469.  
  4470. void CFshedView::HideSelection( BOOL bHide, BOOL bPerm )
  4471. {
  4472. }
  4473.  
  4474. CString CFshedView::GetSelText( ) 
  4475.    CString strText; 
  4476.    if (bSelected)
  4477.    {
  4478.       strText = CString((char*)&Doc->DataArray.GetRefAt(iStartOfSelection), iEndOfSelection - iStartOfSelection + 1);
  4479.    }
  4480.    return strText; 
  4481. }
  4482.  
  4483. void CFshedView::GetSel( CHARRANGE& cr ) const 
  4484. {
  4485.     cr.cpMin = iStartOfSelection;
  4486.     cr.cpMax = iEndOfSelection + 1;
  4487. }
  4488.  
  4489. void CFshedView::GetSel( long& nStartChar, long& nEndChar ) const 
  4490. {
  4491.    nStartChar = iStartOfSelection;
  4492.    nEndChar = iEndOfSelection + 1;
  4493. }
  4494.  
  4495. void CFshedView::SetSel( CHARRANGE& cr ) 
  4496. {
  4497.     iStartOfSelection = cr.cpMin;
  4498.     iEndOfSelection = cr.cpMax;
  4499.    bSelected = TRUE;
  4500.     adjust_view_for_selection();
  4501.     repaint();
  4502. }
  4503.  
  4504. void CFshedView::SetSel( long nStartChar, long nEndChar ) 
  4505. {
  4506.     iStartOfSelection = nStartChar;
  4507.     iEndOfSelection = nEndChar;
  4508.    bSelected = TRUE;
  4509.     adjust_view_for_selection();
  4510.     repaint();
  4511. }
  4512.  
  4513. void CFshedView::ReplaceSel( LPCTSTR lpszNewText, BOOL bCanUndo) 
  4514. {
  4515.    int nSelLen = iEndOfSelection - iStartOfSelection + 1;
  4516.    int nRepLen = WideCharToMultiByte(CP_ACP, 0, lpszNewText, (int)_tcslen(lpszNewText), NULL, NULL, NULL, NULL);
  4517.    if (nSelLen < nRepLen)
  4518.       Doc->DataArray.InsertAtGrow(iStartOfSelection, ' ', nRepLen - nSelLen);
  4519.    else if (nSelLen > nRepLen)
  4520.       Doc->DataArray.RemoveAt(iStartOfSelection, nSelLen - nRepLen);
  4521.     WideCharToMultiByte(CP_ACP, 0, (LPWSTR)lpszNewText, (int)_tcslen(lpszNewText), 
  4522.         (LPSTR)Doc->DataArray.GetBuffer(iStartOfSelection, nRepLen), nRepLen, NULL, NULL); 
  4523.     //Doc->DataArray.CopyFrom(iStartOfSelection, (unsigned char *)lpszNewText, nRepLen);
  4524.     Doc->SetModifiedFlag();
  4525.     Doc->bFilestatusChanged = TRUE;
  4526.     repaint ();
  4527. }
  4528.  
  4529. void CFshedView::OnUpdate(CView* pSender, LPARAM lHint, CObject* pHint) 
  4530. {
  4531.     update_for_new_datasize ();
  4532. }
  4533.  
  4534. BOOL CFshedView::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)
  4535. {
  4536.     if (zDelta < 0)
  4537.         SendMessage(WM_VSCROLL,SB_LINEDOWN);
  4538.     else
  4539.         SendMessage(WM_VSCROLL,SB_LINEUP);
  4540.     return CView::OnMouseWheel(nFlags,zDelta,pt);
  4541. }
  4542.  
  4543. void CFshedView::OnGoto()
  4544. {
  4545.     CGotoDlg dlgGoto(this);
  4546.     dlgGoto.m_nOffset = m_stScreenSettings.iCurByte;
  4547.     if (dlgGoto.DoModal() == IDOK)
  4548.     {
  4549.         if (dlgGoto.m_bRelative)
  4550.             iEndOfSelection = iStartOfSelection += dlgGoto.m_nOffset;
  4551.         else
  4552.             iEndOfSelection = iStartOfSelection = dlgGoto.m_nOffset;
  4553.         bSelected = TRUE;
  4554.         adjust_view_for_selection ();
  4555.         repaint ();
  4556.     }
  4557. }
  4558.  
  4559. void CFshedView::OnContextMenu(CWnd* pWnd, CPoint point)
  4560. {
  4561.     // TODO: Add your message handler code here
  4562.     // Load the desired menu
  4563.     CMenu mnuPopup;
  4564.     mnuPopup.LoadMenu(IDM_HEX_CONTEXT);
  4565.  
  4566.     // Find the rectangle
  4567.     CRect rect;
  4568.     GetWindowRect(&rect);
  4569.  
  4570.     // Get a pointer to the first item of the menu
  4571.     CMenu *mnuPopupMenu = mnuPopup.GetSubMenu(0);
  4572.     ASSERT(mnuPopupMenu);
  4573.     
  4574.     // Find out if the user right-clicked the button
  4575.     // because we are interested only in the button
  4576.     if( rect.PtInRect(point) ) // Since the user right-clicked the button, display the context menu
  4577.         mnuPopupMenu->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, point.x, point.y, this);
  4578. }
  4579.  
  4580. void CFshedView::OnReadUnicode() 
  4581. {
  4582.     int len = max(2, (iEndOfSelection - iStartOfSelection + 1) / 2 * 2);
  4583.     unsigned char* pf = new unsigned char[len + sizeof(TCHAR)];
  4584.     if (App->m_iBinaryMode == LITTLEENDIAN_MODE)
  4585.     {
  4586.         memcpy(pf, Doc->DataArray + iStartOfSelection, len);
  4587.     }
  4588.     else // BIGENDIAN_MODE
  4589.     {
  4590.         for (int i = 0; i < len; i += 2)
  4591.         {
  4592.             pf[i] = Doc->DataArray[iStartOfSelection + i + 1];
  4593.             pf[i + 1] = Doc->DataArray[iStartOfSelection + i];
  4594.         }
  4595.     }
  4596.     pf[len - 1] = pf[len - 2] = 0;
  4597.     CString strCaption;
  4598.     strCaption.LoadString(IDS_UNICODE_STRING);
  4599.     MessageCopyBox (NULL, (LPCTSTR)pf, strCaption, MB_ICONINFORMATION, m_hWnd);
  4600.     delete pf;
  4601.  
  4602. }
  4603.  
  4604. void CFshedView::OnReadUtf8() 
  4605. {
  4606.     int len = (iEndOfSelection - iStartOfSelection + 1);
  4607.     // we want to convert an MBCS string in lpszA
  4608.     int nWideLen = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)&Doc->DataArray.GetRefAt(iStartOfSelection), len, NULL, NULL);
  4609.     wchar_t *szUnicode = new wchar_t[nWideLen + 1];
  4610.     MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)&Doc->DataArray.GetRefAt(iStartOfSelection), len, szUnicode, nWideLen);
  4611.     szUnicode[nWideLen] = 0;
  4612.  
  4613.     CString strCaption;
  4614.     strCaption.LoadString(IDS_UNICODE_STRING);
  4615.     MessageCopyBox (NULL, szUnicode, strCaption, MB_ICONINFORMATION, m_hWnd);
  4616.     delete szUnicode;
  4617. }
  4618.