home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS - Coast to Coast / simteldosarchivecoasttocoast.iso / pcmag / vol11n19.zip / HEXVIEW.C < prev    next >
Text File  |  1992-10-12  |  29KB  |  774 lines

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