home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / magazine / pcmagazi / 1992 / 18 / hexview.c < prev    next >
Text File  |  1992-07-11  |  29KB  |  753 lines

  1. // HexView - Windows 3.x and NT/WIN32 Hex File Viewer
  2. // Copyright (C) 1992 Ray Duncan
  3. // PC Magazine * Ziff Davis Publications
  4.  
  5. #define dim(x) (sizeof(x) / sizeof(x[0]))   // returns no. of elements
  6. #define EXENAMESIZE 256                     // max length of path+filename
  7. #define BUFSIZE 65520                       // size of file I/O buffer
  8. #define BPL 16                              // bytes per line
  9.  
  10. #include "stdlib.h"
  11. #include "windows.h"
  12. #include "string.h"
  13. #include "commdlg.h"
  14. #include "hexview.h"
  15.  
  16. HANDLE hInst;                               // module instance handle
  17. HWND hFrame;                                // handle for frame window
  18. HWND hChild;                                // handle for child window
  19. HFONT hFont;                                // handle for nonprop. font
  20. INT CharX, CharY;                           // character dimensions
  21. INT LPP;                                    // lines per page
  22. INT BPP;                                    // bytes per page
  23. INT ThumbInc;                               // bytes per thumb unit
  24. INT hFile = -1;                             // handle for current file
  25. char szFileName[EXENAMESIZE+1];             // name of current file
  26. HANDLE hBuff;                               // handle for file I/O buffer
  27. LPSTR lpBuff;                               // far pointer to file buffer
  28. LONG ViewPtr;                               // addr, first line current page
  29. LONG FilePtr;                               // addr, start of i/o buffer
  30. LONG FileSize;                              // length of current file
  31. LONG FileIndex;                             // index from thumb tracking
  32. LONG TopAddr;                               // address, top of last page
  33. LONG TopLine;                               // line num, top of last page
  34. INT WinWidth;                               // width of frame client area
  35.  
  36. char szFrameClass[] = "HexView";            // classname for frame window
  37. char szChildClass[] = "HexViewChild";       // classname for child window
  38. char szAppName[] = "Hex File Viewer";       // long application name
  39. char szMenuName[] = "HexViewMenu";          // name of menu resource
  40. char szIconName[] = "HexViewIcon";          // name of icon resource
  41. char szIni[] = "Hexview.Ini" ;              // initialization filename
  42.  
  43. char *szFilter[] = {                        // filters for Open dialog
  44.     "All Files (*.*)", "*.*",               
  45.     "Executable files (*.EXE)", "*.EXE",
  46.     "Object Modules (*.OBJ)", "*.OBJ",
  47.     "" };
  48.  
  49. //
  50. // Table of window messages supported by FrameWndProc()
  51. // and the functions which correspond to each message.
  52. //
  53. struct decodeWord frameMsgs[] = {
  54.     WM_PAINT, DoPaint,
  55.     WM_SIZE, DoSize,
  56.     WM_COMMAND, DoCommand,
  57.     WM_CLOSE, DoClose,
  58.     WM_DESTROY, DoDestroy,
  59.     WM_VSCROLL, DoVScroll, } ;
  60.  
  61. //
  62. // Table of window messages supported by ChildWndProc()
  63. // and the functions which correspond to each message.
  64. //
  65. struct decodeWord childMsgs[] = {
  66.     WM_PAINT, DoChildPaint, } ;
  67.  
  68. //
  69. // Table of menubar item IDs and their corresponding functions.
  70. //
  71. struct decodeWord menuitems[] = {
  72.     IDM_OPEN, DoMenuOpen,
  73.     IDM_EXIT, DoMenuExit,
  74.     IDM_ABOUT, DoMenuAbout, } ;
  75.  
  76. //
  77. // WinMain -- entry point for this application from Windows.
  78. //
  79. INT APIENTRY WinMain(HANDLE hInstance,
  80.     HANDLE hPrevInstance, LPSTR lpCmdLine, INT nCmdShow)
  81. {
  82.     MSG msg;                                // receives message packet
  83.  
  84.     hInst = hInstance;                      // save instance handle
  85.  
  86.     if(!hPrevInstance)                      // if first instance,
  87.         if(!InitApp(hInstance))             // register window class
  88.         {
  89.             MessageBox(hFrame, "Can't initialize HexView!", szAppName,
  90.                 MB_ICONSTOP | MB_OK);
  91.             return(FALSE);
  92.         }
  93.  
  94.     if(!InitInstance(hInstance, nCmdShow))  // create instance window
  95.     {
  96.         MessageBox(hFrame, "Can't initialize HexView!", szAppName,
  97.             MB_ICONSTOP | MB_OK);
  98.         return(FALSE);
  99.     }
  100.  
  101.     while(GetMessage(&msg, NULL, 0, 0))     // while message != WM_QUIT
  102.     {
  103.         TranslateMessage(&msg);             // translate virtual key codes
  104.         DispatchMessage(&msg);              // dispatch message to window
  105.     }
  106.  
  107.     TermInstance(hInstance);                // clean up for this instance
  108.     return(msg.wParam);                     // return code = WM_QUIT value
  109. }
  110.  
  111. //
  112. // InitApp --- global initialization code for this application.
  113. // Registers window classes for frame and child windows.
  114. //
  115. BOOL InitApp(HANDLE hInstance)
  116. {
  117.     WNDCLASS  wc;                           // window class data
  118.     BOOL bParent, bChild;                   // status from RegisterClass
  119.  
  120.     // set parameters for frame window class
  121.     wc.style = CS_HREDRAW|CS_VREDRAW;       // class style
  122.     wc.lpfnWndProc = FrameWndProc;          // class callback function
  123.     wc.cbClsExtra = 0;                      // extra per-class data
  124.     wc.cbWndExtra = 0;                      // extra per-window data
  125.     wc.hInstance = hInstance;               // handle of class owner
  126.     wc.hIcon = LoadIcon(hInst, "HexViewIcon");      // application icon
  127.     wc.hCursor = LoadCursor(NULL, IDC_ARROW);       // default cursor
  128.     wc.hbrBackground = GetStockObject(WHITE_BRUSH); // background color 
  129.     wc.lpszMenuName =  szMenuName;          // name of menu resource
  130.     wc.lpszClassName = szFrameClass;        // name of window class
  131.  
  132.     bParent = RegisterClass(&wc);           // register parent window class
  133.  
  134.     // modify some of the parameters for the child window class
  135.     wc.style = 0;                           // class style
  136.     wc.lpfnWndProc = ChildWndProc;          // class callback function
  137.     wc.lpszMenuName =  NULL;                // name of menu resource
  138.     wc.lpszClassName = szChildClass;        // name of window class
  139.  
  140.     bChild = RegisterClass(&wc);            // register child window class
  141.  
  142.     return(bChild && bParent);              // return combined status
  143. }
  144.  
  145. //
  146. // InitInstance --- instance initialization code for this application.
  147. // Gets information about system nonproportional font.  Allocates memory 
  148. // to use as file I/O buffer.  Creates frame window, gets initialization 
  149. // information (if any) from INI file (Windows 3.x) or registration 
  150. // database (WIN32/NT). Positions and sizes window, opens and positions
  151. // file if initialization info found.
  152. //
  153. BOOL InitInstance(HANDLE hInstance, INT nCmdShow)
  154. {
  155.     HDC hdc;                                // handle for device context
  156.     TEXTMETRIC tm;                          // font information
  157.     RECT rect;                              // window position & size
  158.     char buff[80];                          // scratch buffer
  159.  
  160.     hFrame = CreateWindow(                  // create frame window
  161.         szFrameClass,                       // window class name
  162.         szAppName,                          // text for title bar
  163.         WS_OVERLAPPEDWINDOW | WS_VSCROLL,   // window style
  164.         CW_USEDEFAULT, CW_USEDEFAULT,       // default position
  165.         CW_USEDEFAULT, CW_USEDEFAULT,       // default size
  166.         NULL,                               // no parent window
  167.         NULL,                               // use class default menu
  168.         hInstance,                          // window owner
  169.         NULL);                              // unused pointer
  170.  
  171.     if(!hFrame) return(FALSE);              // error, can't create window
  172.  
  173.     hdc = GetDC(hFrame);                    // get device context
  174.     hFont = GetStockObject(SYSTEM_FIXED_FONT);  
  175.     SelectObject(hdc, hFont);               // realize nonproportional
  176.     GetTextMetrics(hdc, &tm);               // font, get character size,
  177.     CharX = tm.tmAveCharWidth;              // and calculate window width
  178.     CharY = tm.tmHeight + tm.tmExternalLeading;
  179.     WinWidth = (CharX * 75) + GetSystemMetrics(SM_CXVSCROLL);
  180.     ReleaseDC(hFrame, hdc);                 // release device context
  181.  
  182.     if(!(hBuff = GlobalAlloc(GMEM_MOVEABLE, BUFSIZE)))  // allocate memory
  183.         return(FALSE);                      // error, out of memory
  184.  
  185.     lpBuff = GlobalLock(hBuff);             // get far pointer to memory
  186.  
  187.     GetWindowRect(hFrame, &rect);           // get window position, size
  188.  
  189.     // read saved position/size profile for our frame window, if any
  190.     rect.left = GetPrivateProfileInt("Frame", "xul", rect.left, szIni);
  191.     rect.top = GetPrivateProfileInt("Frame", "yul", rect.top, szIni);
  192.     rect.right = GetPrivateProfileInt("Frame", "xlr", rect.right, szIni);
  193.     rect.bottom = GetPrivateProfileInt("Frame", "ylr", rect.bottom, szIni);
  194.  
  195.     MoveWindow(hFrame, rect.left, rect.top, // force window position, size  
  196.         WinWidth, rect.bottom-rect.top, TRUE);
  197.  
  198.     // get saved filename and file offset for display, if any
  199.     GetPrivateProfileString("File", "filename", "", szFileName, 
  200.         EXENAMESIZE, szIni);
  201.     GetPrivateProfileString("File", "fileptr", "", buff, sizeof(buff), szIni);
  202.  
  203.     if(szFileName[0])                       // if filename and file offset
  204.     {                                       // was saved from previous
  205.         OpenDataFile();                     // execution, open the file
  206.         ReadDataFile();                     // and set file position
  207.         SetFilePosition(atol(buff));
  208.     }
  209.     
  210.     ShowWindow(hFrame, nCmdShow);           // make frame window visible
  211.     UpdateWindow(hFrame);                   // force WM_PAINT message
  212.     return(TRUE);                           // return success flag
  213. }
  214.  
  215. //
  216. // TermInstance -- instance termination code for this application.
  217. // This is a general-purpose opportunity to clean up after ourselves.
  218. //
  219. BOOL TermInstance(HANDLE hinstance)
  220. {
  221.     if(hFile != -1)                         // close file if any
  222.         _lclose(hFile);
  223.  
  224.     GlobalUnlock(hBuff);                    // unlock the memory buffer
  225.     GlobalFree(hBuff);                      // release the buffer
  226.     return(TRUE);                           // return success flag
  227. }
  228.  
  229. //
  230. // FrameWndProc --- callback function for application frame window.
  231. // Decodes window message using table frameMsgs[] and runs corresponding
  232. // function.  If no match found, passes message to Windows DefWindowProc().
  233. //
  234. LONG FAR APIENTRY FrameWndProc(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam)
  235. {
  236.     INT i;                                  
  237.  
  238.     for(i = 0; i < dim(frameMsgs); i++)     
  239.     {                                       
  240.         if(wMsg == frameMsgs[i].Code)
  241.             return((*frameMsgs[i].Fxn)(hWnd, wMsg, wParam, lParam));
  242.     }
  243.  
  244.     return(DefWindowProc(hWnd, wMsg, wParam, lParam));
  245. }
  246.  
  247. //
  248. // ChildWndProc --- callback function for application child window.
  249. // Works like FrameWndProc, except uses table childMsgs[].
  250. //
  251. LONG FAR APIENTRY ChildWndProc(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam)
  252. {
  253.     INT i;                                  
  254.  
  255.     for(i = 0; i < dim(childMsgs); i++)     
  256.     {                                       
  257.         if(wMsg == childMsgs[i].Code)
  258.             return((*childMsgs[i].Fxn)(hWnd, wMsg, wParam, lParam));
  259.     }
  260.  
  261.     return(DefWindowProc(hWnd, wMsg, wParam, lParam));
  262. }
  263.  
  264. //
  265. // DoCommand -- processes WM_COMMAND messages for frame window. 
  266. // Decodes the menubar item with the menuitems[] array, then
  267. // runs the corresponding function to process the command.
  268. // If no match found, passes message to Windows DefWindowProc().
  269. // 
  270. LONG DoCommand(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam)
  271. {
  272.     INT i;                       
  273.  
  274.     for(i = 0; i < dim(menuitems); i++)     
  275.     {                                       
  276.         if(wParam == menuitems[i].Code)
  277.             return((*menuitems[i].Fxn)(hWnd, wMsg, wParam, lParam));
  278.     }
  279.  
  280.     return(DefWindowProc(hWnd, wMsg, wParam, lParam));
  281. }
  282.  
  283. //
  284. // DoDestroy -- processes the WM_DESTROY message for frame window by
  285. // posting a WM_QUIT message to the same window, forcing WinMain
  286. // to fall out of the event loop.
  287. // 
  288. LONG DoDestroy(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam)
  289. {
  290.     PostQuitMessage(0);          
  291.     return(FALSE);                   
  292. }
  293.  
  294. //
  295. // DoClose -- processes a WM_CLOSE message for frame window by
  296. // saving the current window position, size, filename, and file 
  297. // offset, then forcing a WM_DESTROY message.
  298. // 
  299. LONG DoClose(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam)
  300. {
  301.     UpdateFrameProfile();                   // save window information
  302.     DestroyWindow(hWnd);                    // then close down the app
  303.     return(FALSE);                              
  304. }
  305.  
  306. //
  307. // DoVScroll -- process various WM_VSCROLL messages for frame window.
  308. // The user can generate these messages by dragging thumb, clicking
  309. // in scrollbar, or clicking arrows at both ends of scrollbar.
  310. // 
  311. LONG DoVScroll(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam)
  312. {
  313.     RECT rect;
  314.  
  315.     switch(LOWORD(wParam))                  // LOWORD is vital for Win32
  316.     {                                       
  317.         case SB_TOP:                        // go to top of file if
  318.             if(ViewPtr)                     // we aren't there already
  319.             {
  320.                 SetFilePosition(0);
  321.                 Repaint();
  322.             }
  323.             break;
  324.  
  325.         case SB_BOTTOM:                     // go to bottom of file if
  326.             SetFilePosition(FileSize);      // we aren't there already
  327.             Repaint();
  328.             break;
  329.  
  330.         case SB_LINEUP:                     // scroll up by one line if
  331.             if(ViewPtr)                     // we aren't already at top
  332.             {   
  333.                 SetFilePosition(ViewPtr - BPL);
  334.                 ScrollWindow(hWnd, 0, CharY, NULL, NULL);
  335.                 UpdateWindow(hWnd);
  336.             }
  337.             break;
  338.  
  339.         case SB_LINEDOWN:                   // scroll down by one line if
  340.             if(ViewPtr < TopAddr)           // we aren't already at bottom
  341.             {
  342.                 SetFilePosition(ViewPtr + BPL);
  343.                 ScrollWindow(hWnd, 0, -CharY, NULL, NULL);
  344.                 GetClientRect(hWnd, &rect);
  345.                 rect.top = max(0, (LPP-1) * CharY);
  346.                 InvalidateRect(hWnd, &rect, TRUE);
  347.                 UpdateWindow(hWnd);
  348.             }
  349.             break;
  350.  
  351.         case SB_PAGEUP:                     // scroll up by one page
  352.             SetFilePosition(ViewPtr - BPP);
  353.             Repaint();  
  354.             break;
  355.  
  356.         case SB_PAGEDOWN:                   // scroll down by one page
  357.             SetFilePosition(ViewPtr + BPP);
  358.             Repaint();
  359.             break;
  360.  
  361.         case SB_THUMBPOSITION:              // reposition file by thumb
  362.             SetFilePosition(ThumbInc * (LONG) THUMBPOS);
  363.             Repaint();
  364.             break;
  365.  
  366.         case SB_THUMBTRACK:                 // track drag of thumb
  367.             ThumbTrack(THUMBPOS);
  368.             break;
  369.     }
  370.  
  371.     return(FALSE);                              
  372. }
  373.  
  374. //
  375. // DoPaint -- process WM_PAINT message for frame window by
  376. // painting hex and ASCII data dump for file offsets that fall
  377. // within the window.  We make no attempt to optimize this for
  378. // painting regions that are smaller than the window.
  379. // 
  380. LONG DoPaint(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam)
  381. {
  382.     HDC hdc;                                // scratch device context
  383.     PAINTSTRUCT ps;                         // scratch paint structure
  384.     INT i;
  385.  
  386.     hdc = BeginPaint(hWnd, &ps);            // get device context
  387.     SelectObject(hdc, hFont);               // realize nonprop. font
  388.  
  389.     if(hFile != -1)                         // paint all lines that
  390.     {                                       // fall within the window
  391.         for(i = 0; i < LPP; i++)
  392.             DisplayLine(hdc, i);
  393.     }
  394.  
  395.     EndPaint(hWnd, &ps);                    // release device context
  396.     return(FALSE);
  397. }
  398.  
  399. //
  400. // DoChildPaint -- process WM_PAINT message for child window.
  401. // These occur during thumb drag; we put up a tiny window that
  402. // displays the file offset corresponding to the thumb position.
  403. // 
  404. LONG DoChildPaint(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam)
  405. {
  406.     HDC hdc;
  407.     PAINTSTRUCT ps;
  408.     RECT rect;
  409.     char buff[256];
  410.  
  411.     hdc = BeginPaint(hWnd, &ps);            // get device context
  412.     GetClientRect(hWnd, &rect);             // get client area dimensions
  413.     SelectObject(hdc, hFont);               // select nonproportional font
  414.     wsprintf(buff, "%08lX", FileIndex);     // format file index from thumb
  415.     DrawText(hdc, buff, -1,                 // paint index into window
  416.         &rect, DT_CENTER | DT_VCENTER | DT_SINGLELINE); 
  417.     EndPaint(hWnd, &ps);                    // release device context
  418.     return(FALSE);
  419. }
  420.  
  421. //
  422. // DoSize -- process WM_SIZE message for frame window by calculating
  423. // the number of lines per page and bytes per page for new window size.
  424. // Also reposition the display if we were already at end of file and
  425. // the window grew.
  426. //
  427. LONG DoSize(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam)
  428. {
  429.     LPP = HIWORD(lParam) / CharY;           // calc lines per page
  430.     BPP = LPP * BPL;                        // calc bytes per page
  431.     ConfigDisplay();                        // calc display parameters
  432.     if(ViewPtr > TopAddr)                   // make sure window refilled
  433.         SetFilePosition(TopAddr);
  434.     return(FALSE);
  435. }
  436.  
  437. //
  438. // DoMenuOpen -- process File-Open command from menu bar. All
  439. // the hard work is done by the OpenFile common dialog.
  440. //
  441. LONG DoMenuOpen(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam)
  442. {
  443.     OPENFILENAME ofn;                       // used by common dialogs
  444.  
  445.     szFileName[0]  = '\0';                  // init filename buffer
  446.  
  447.     ofn.lStructSize = sizeof(OPENFILENAME); // length of structure
  448.     ofn.hwndOwner = hWnd;                   // handle for owner window
  449.     ofn.lpstrFilter = szFilter[0];          // address of filter list
  450.     ofn.lpstrCustomFilter = NULL;           // custom filter buffer address
  451.     ofn.nFilterIndex = 1;                   // pick default filter
  452.     ofn.lpstrFile = szFileName;             // buffer for path+filename
  453.     ofn.nMaxFile = EXENAMESIZE;             // length of buffer
  454.     ofn.lpstrFileTitle = NULL;              // buffer for filename only
  455.     ofn.lpstrInitialDir = NULL;             // initial directory for dialog
  456.     ofn.lpstrTitle = NULL;                  // title for dialog box
  457.     ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
  458.     ofn.lpstrDefExt = NULL;                 // default extension 
  459.  
  460.     if(GetOpenFileName(&ofn))               // display open dialog
  461.     {
  462.         OpenDataFile();                     // open file for viewing
  463.         ReadDataFile();                     // initialize data buffer
  464.         Repaint();                          // force display of data
  465.     }
  466.  
  467.     return(FALSE);
  468. }
  469.  
  470. //
  471. // DoMenuExit -- process File-Exit command from menu bar.  This
  472. // is simply handled by sending a WM_CLOSE message as though Close
  473. // had been picked on the System menu to shut down the app.
  474. // 
  475. LONG DoMenuExit(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam)
  476. {
  477.     SendMessage (hWnd, WM_CLOSE, 0, 0L);    
  478.     return(FALSE);                          
  479. }
  480.  
  481. //
  482. // DoMenuAbout -- process File-About command from menu bar. We
  483. // allocate a thunk for the dialog callback routine, display the
  484. // dialog, then release the thunk after the dialog is dismissed.
  485. // 
  486. LONG DoMenuAbout(HWND hWnd, UINT wMsg, UINT wParam, LONG lParam)
  487. {
  488.     WNDPROC lpProcAbout;                    
  489.  
  490.     lpProcAbout = MakeProcInstance((WNDPROC)AboutDlgProc, hInst);
  491.     DialogBox(hInst, "AboutBox", hWnd, lpProcAbout);         
  492.     FreeProcInstance(lpProcAbout);
  493.     return(FALSE);                              
  494. }
  495.  
  496. //
  497. // AboutDlgProc -- This is the callback routine for the About... dialog.
  498. //
  499. BOOL FAR APIENTRY AboutDlgProc (HWND hwnd, UINT msg, UINT wParam, LONG lParam)
  500. {
  501.     if((msg==WM_COMMAND) && (wParam==IDOK)) // dismiss dialog if OK 
  502.         EndDialog(hwnd, 0);                 // button was clicked, 
  503.     return(FALSE);                          // otherwise do nothing
  504. }
  505.  
  506. //
  507. // SetWindowCaption -- concatenate the filename with the application
  508. // name, then update the frame window's title bar.
  509. //
  510. VOID SetWindowCaption(char * szFilename)
  511. {
  512.     char szTemp[EXENAMESIZE+1];             
  513.  
  514.     strcpy(szTemp, szAppName);              // get application name
  515.     strcat(szTemp, " - ");                  // add separator
  516.     strcat(szTemp, szFileName);             // add filename
  517.     SetWindowText(hFrame, szTemp);          // put result into title bar
  518. }
  519.  
  520. //
  521. // Repaint -- force refresh of formatted output in main window. This
  522. // gets called at various points when the file position is changed.
  523. //
  524. VOID Repaint(VOID)
  525. {
  526.     InvalidateRect(hFrame, NULL, TRUE);     // repaint entire window 
  527. }
  528.  
  529. //
  530. // SetFilePosition - called during processing of various vertical scrollbar 
  531. // messages to set ViewPtr to a valid value.
  532. //
  533. VOID SetFilePosition(LONG NewViewPtr)
  534. {
  535.     if(hChild)                              // destroy the child window
  536.     {                                       // if it happens to be active
  537.         DestroyWindow(hChild);
  538.         hChild = (HWND) 0;
  539.     }
  540.  
  541.     if(hFile == -1)                         // bail out if no file open
  542.         return;
  543.  
  544.     ViewPtr = NewViewPtr & 0x0FFFFFFF0;     // offset is multiple of 16
  545.                                             
  546.     if(ViewPtr > TopAddr)                   // enforce legal file offset
  547.         ViewPtr = TopAddr;
  548.     if(ViewPtr < 0)
  549.         ViewPtr = 0;
  550.  
  551.     SetScrollPos(hFrame, SB_VERT,           // set thumb on scrollbar
  552.         ViewPtr/ThumbInc, TRUE);
  553. }
  554.  
  555. //
  556. // ConfigDisplay -- Configure various display parameters and scrollbar
  557. // range according to current window size and file size.
  558. //
  559. VOID ConfigDisplay(VOID)
  560. {
  561.     // calc address and line number of first line, last page
  562.     TopAddr = max(((FileSize + 15) & 0x0FFFFFFF0) - BPP, 0);
  563.     TopLine = TopAddr / BPL;
  564.  
  565.     // calculate bytes per scrollbar increment
  566.     ThumbInc = BPL * ((TopLine/32767) + 1);
  567.  
  568.     // configure vertical scrollbar or make it disappear if not needed
  569.     if(BPP >= FileSize)                     // file fits within window
  570.     {
  571.         SetScrollRange(hFrame, SB_VERT, 0, 0, FALSE);
  572.         SetScrollPos(hFrame, SB_VERT, 0, TRUE);
  573.         if(ViewPtr) SetFilePosition(0);
  574.     }
  575.     else                                    // file is too big for window
  576.     {
  577.         SetScrollRange(hFrame, SB_VERT, 0, ((TopLine*BPL)/ThumbInc), FALSE);
  578.         SetScrollPos(hFrame, SB_VERT, ViewPtr/ThumbInc, TRUE);
  579.     }
  580. }
  581.  
  582. //
  583. // ThumbTrack() - called during processing of WM_VSCROLL message to track
  584. // thumb position, also forcing update of file offset in child window.
  585. //
  586. VOID ThumbTrack(INT pos)
  587. {
  588.     RECT rect;
  589.     INT SizeX = CharX * 10;                 // calc size of child window
  590.     INT SizeY = CharY * 2;
  591.  
  592.     if(!hChild)                             // create child window 
  593.     {
  594.         GetClientRect(hFrame, &rect);       // get client area of frame
  595.  
  596.         hChild = CreateWindow(              // create child window
  597.             szChildClass,                   // window class name
  598.             NULL,                           // text for title bar
  599.             WS_CHILD | WS_BORDER | WS_VISIBLE,  // window style
  600.             (rect.right-SizeX) / 2,         // x position
  601.             (rect.bottom-SizeY) / 2,        // y position
  602.             SizeX,                          // window width
  603.             SizeY,                          // window height
  604.             hFrame,                         // frame is parent window
  605.             (HMENU) 1,                      // child window ID
  606.             hInst,                          // window owner module
  607.             NULL);                          // unused pointer
  608.     }
  609.  
  610.     // calculate file location to display, force repaint of child window
  611.     FileIndex = min((LONG) pos * (LONG) ThumbInc, TopAddr);   
  612.     InvalidateRect(hChild, NULL, TRUE);     
  613. }
  614.  
  615. //
  616. // DisplayLine -- format and display a single line of hex/ASCII dump
  617. // using the device context and relative window line number supplied
  618. // by the caller.  The file data offset is calculated from the
  619. // relative window line and the offset corresponding to the line 
  620. // currently at the top of the window.
  621. //
  622. VOID DisplayLine(HDC hdc, INT line)
  623. {
  624.     INT i;
  625.     char buff[256], c, *p;
  626.     LONG x;
  627.  
  628.     if((ViewPtr + (LONG) line*BPL) < FileSize)
  629.     {
  630.         // format file offset as 8-digit hex number
  631.         p = buff + wsprintf(buff, "%08lX ", ViewPtr + (LONG) line*BPL);
  632.  
  633.         // format this 16-bytes as hex data
  634.         for(i = 0; i < BPL; i++)  
  635.         {
  636.             x = ViewPtr + (LONG)(line * BPL) + i;
  637.  
  638.             if(x < FileSize)
  639.                 p += wsprintf(p, "%02X ", GetByte(x) & 0x0ff);
  640.             else
  641.                 p += wsprintf(p, "   ");
  642.         }
  643.  
  644.         // format same 16-bytes as ASCII, using "." for control characters
  645.         for(i = 0; i < BPL; i++)           
  646.         {
  647.             x = ViewPtr + (LONG)(line * BPL) + i;
  648.  
  649.             if(x < FileSize)
  650.             {
  651.                 c = GetByte(x);
  652.                 if(c < 0x20) 
  653.                     c = '.';
  654.             }
  655.             else c = ' ';
  656.             *p++ = c;
  657.         }
  658.  
  659.         // append a null byte, then paint the formatted data
  660.         *p = '\0';                          
  661.         TextOut(hdc, 0, line*CharY, buff, strlen(buff));
  662.     }
  663. }
  664.  
  665. //
  666. // GetByte -- retrieve data byte from file I/O buffer, performing
  667. // disk I/O as necessary.  This is a simple-minded virtual memory
  668. // scheme when file is larger than buffer.
  669. //
  670. char GetByte(LONG addr)
  671. {
  672.     if(!((addr >= FilePtr) && (addr < (FilePtr + BUFSIZE))))
  673.     {
  674.         FilePtr = (addr - (BUFSIZE/2)) & 0x0FFFFFFF0;
  675.         if(FilePtr < 0) FilePtr = 0;
  676.         ReadDataFile();
  677.     }
  678.  
  679.     return(lpBuff[addr - FilePtr]);
  680. }
  681.  
  682. //
  683. // OpenDataFile -- open specified file for viewing, save handle. The
  684. // filename was previously placed in szFileName by OpenFile common dialog.
  685. //
  686. VOID OpenDataFile(VOID)
  687. {
  688.     if(hFile != -1)                         // close previous file if any
  689.         _lclose(hFile);
  690.  
  691.     hFile = _lopen(szFileName, OF_READ);    // try and open the new file
  692.  
  693.     if(hFile == -1)                         // bail out if no such file
  694.     {
  695.         MessageBox(hFrame, "Can't open file!", szAppName, MB_ICONSTOP|MB_OK);
  696.         return;
  697.     }
  698.  
  699.     FileSize = _llseek(hFile, 0, 2);        // get size of file
  700.     ViewPtr = 0;                            // reset window address pointer
  701.     FilePtr = 0;                            // reset file i/o pointer
  702.     ConfigDisplay();                        // calc display parameters
  703.     SetWindowCaption(szFileName);           // update title bar
  704. }
  705.  
  706.  
  707. //
  708. // ReadDataFile -- read data from specified file to I/O buffer, using
  709. // current file position set by caller.
  710. //
  711. VOID ReadDataFile(VOID)
  712. {
  713.     if(hFile == -1)                         // bail out if no file open
  714.         return;
  715.     _llseek(hFile, FilePtr, 0);             // position file pointer
  716.     _lread(hFile, lpBuff, BUFSIZE);         // read the file
  717. }
  718.  
  719. //
  720. // UpdateFrameProfile() --  Update frame window profile in INI file
  721. // (if Win 3.x) or registration database (if NT/WIN32) by saving the
  722. // current window position, size, name of file being displayed, file offset.
  723. //
  724. VOID UpdateFrameProfile(VOID)
  725. {
  726.     RECT rect;
  727.     char temp[20];
  728.  
  729.     if(IsIconic(hFrame) || IsZoomed(hFrame)) return;
  730.  
  731.     GetWindowRect(hFrame, &rect);           // get position of frame window
  732.  
  733.     wsprintf(temp,"%d", rect.left);
  734.     WritePrivateProfileString("Frame", "xul", temp, "HexView.ini");
  735.  
  736.     wsprintf(temp,"%d", rect.top);
  737.     WritePrivateProfileString("Frame", "yul", temp, "HexView.ini");
  738.  
  739.     wsprintf(temp,"%d", rect.right);
  740.     WritePrivateProfileString("Frame", "xlr", temp, "HexView.ini");
  741.  
  742.     wsprintf(temp,"%d", rect.bottom);
  743.     WritePrivateProfileString("Frame", "ylr", temp, "HexView.ini");
  744.  
  745.     WritePrivateProfileString("File", "filename", szFileName, "HexView.ini");
  746.  
  747.     wsprintf(temp,"%ld", ViewPtr);
  748.     WritePrivateProfileString("File", "fileptr", temp, "HexView.ini");
  749. }
  750.  
  751.  
  752.  
  753.