UCONVERT.C
上传用户:shijixite
上传日期:2007-01-03
资源大小:108k
文件大小:48k
源码类别:

输入法编程

开发平台:

Visual C++

  1. /**************************************************************************
  2. * uconvert.c -- convert to/from unicode using
  3. *                MulitByteToWideChar & WideCharToMulitByte
  4. *
  5. *         Steve Firebaugh
  6. *         Microsoft Developer Support
  7. *         Copyright (c) 1992-1997 Microsoft Corporation
  8. *
  9. **************************************************************************/
  10. #define UNICODE
  11. #include <windows.h>
  12. #include <commdlg.h>
  13. #include "uconvert.h"
  14. #include "install.h"
  15. /**************************************************************************
  16. *  Global variables.
  17. **************************************************************************/
  18. HANDLE hInst;
  19. /* declare global HWNDs for the child windows.
  20. *   They are created at WM_CREATE  of the main window.
  21. *   Also used in the "View" dialogs.
  22. */
  23. HWND hwndLabel0, hwndLabel1;
  24. HWND hwndName0, hwndName1;
  25. HWND hwndSize0, hwndSize1;
  26. HWND hwndCodePage0, hwndCodePage1;
  27. HWND hwndByteOrder0, hwndByteOrder1;
  28. HWND hwndButton0, hwndButton1;
  29. /* Global variables storing the source and destination "type" information.
  30. *
  31. * used to communicate between main wnd proc, and *OptionsProc.
  32. *
  33. * gTypeSource - stores the type interpretation of the source data
  34. *       (and implicitly the destination data.)
  35. *   TYPEUNKNOWN: indeterminant... not set. Can not do conversion.
  36. *   TYPEUNICODE: source unicode & destination giDestinationCodePage.
  37. *   TYPECODEPAGE: source giSourceCodePage & destination unicode.
  38. *
  39. * giSourceCodePage stores valid source code page iff gTypeSource == TRUE
  40. * giDestinationCodePage stores valid destination code page iff gTypeSource == FALSE
  41. *
  42. */
  43. int gTypeSource;
  44. UINT giSourceCodePage;
  45. UINT giDestinationCodePage;
  46. /* Pointers to the source and destination data, and the
  47.  *  count of bytes in each of the buffers.
  48.  */
  49. #define NODATA 0
  50. PBYTE pSourceData =       NULL;
  51. PBYTE pDestinationData =  NULL;
  52. int   nBytesSource =      NODATA;
  53. int   nBytesDestination = NODATA;
  54. /* Conversion Options variables. */
  55. DWORD gMBFlags = MB_PRECOMPOSED;
  56. DWORD gWCFlags = 0;
  57. char  glpDefaultChar[4] = "?";
  58. BOOL  gUsedDefaultChar = FALSE;
  59. /* Handling the Byte Order Mark (BOM).
  60. *
  61. * If the input file begins with a BOM, then we know it is unicode,
  62. *  we skip over the BOM and decrement the size of data by SIZEOFBOM.
  63. *
  64. *
  65. * Before writing data that we know is unicode, write the szBOM string
  66. *  to the file.
  67. *
  68. * Notice that this means that the file sizes we show in the window
  69. *  do NOT include the BOM.
  70. */
  71. char szBOM[] = "377376";  // 0xFF, 0xFE  // leave off TEXT() macro.
  72. char szRBOM[] = "376377";  // 0xFF, 0xFE  // leave off TEXT() macro.
  73. #define SIZEOFBOM 2
  74. /* Title of main window */
  75. TCHAR TitleMBToWC[]= TEXT("UConvert -- MultiByteToWideChar()");
  76. TCHAR TitleWCToMB[]= TEXT("UConvert -- WideCharToMultiByte()");
  77. TCHAR TitleUnknown[]= TEXT("UConvert.");
  78. /* file name of the online help file */
  79. TCHAR szHelpPathName[] = TEXT("uconvert.HLP");
  80. /* Strings used to fill onscreen windows. */
  81. TCHAR szBlank[] = TEXT("");
  82. /* MessageBox() strings and flags. */
  83. TCHAR MBTitle[30]= TEXT("");
  84. UINT  MBFlags = MB_OK | MB_ICONEXCLAMATION;
  85. /* misc. defines affecting size and placement of child windows */
  86. #define BORDER    GetSystemMetrics (SM_CXFRAME)*4
  87. #define WHEIGHT   GetSystemMetrics (SM_CYMENU)
  88. /**************************************************************************
  89. *
  90. *  function:  WinMain()
  91. *
  92. *
  93. **************************************************************************/
  94. int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
  95.                      LPSTR lpCmdLine, int nCmdShow)
  96. {
  97.     MSG    msg;
  98.     WNDCLASS  wc;
  99.     HWND   hwndMain;
  100.     HACCEL haccel;
  101.     UNREFERENCED_PARAMETER( lpCmdLine );
  102.     UNREFERENCED_PARAMETER(  nCmdShow );
  103.     hInst = hInstance;
  104.     /* Check for previous instance.  If none, then register class. */
  105.     if (!hPrevInstance) {
  106.       wc.style = 0;
  107.       wc.lpfnWndProc = (WNDPROC)MainWndProc;
  108.       wc.cbClsExtra = 0;
  109.       wc.cbWndExtra = 0;
  110.       wc.hInstance = hInstance;
  111.       wc.hIcon = LoadIcon(hInstance, TEXT("uconvertIcon"));
  112.       wc.hCursor = LoadCursor(NULL, IDC_ARROW);
  113.       wc.hbrBackground = GetStockObject (LTGRAY_BRUSH);
  114.       wc.lpszMenuName =  TEXT("uconvertMenu");
  115.       wc.lpszClassName = TEXT("uconvert");
  116.       if (!RegisterClass(&wc)) return (FALSE);
  117.     }  /* class registered o.k. */
  118.     /* Create the main window.  Return false if CreateWindow() fails */
  119.     hwndMain = CreateWindow(
  120.         TEXT("uconvert"),
  121.         TitleUnknown,
  122.         (WS_OVERLAPPEDWINDOW & ~(WS_THICKFRAME | WS_MAXIMIZEBOX)) | WS_VISIBLE,
  123.         CW_USEDEFAULT,
  124.         CW_USEDEFAULT,
  125.         512,  // Big enough for most of the text.
  126.         16*WHEIGHT,
  127.         NULL, NULL, hInst, NULL);
  128.     if (!hwndMain) return (FALSE);
  129.     /* Load the accelerator table that provides clipboard support. */
  130.     haccel = LoadAccelerators (hInst, TEXT("uconvertAccel"));
  131.     LoadString(hInst,IDS_APP_WARNING,MBTitle,sizeof(MBTitle));
  132.     /* Loop getting messages and dispatching them. */
  133.     while (GetMessage(&msg, NULL, 0,0)) {
  134.       if (!TranslateAccelerator(hwndMain, haccel, &msg)) {
  135.         TranslateMessage(&msg);
  136.         DispatchMessage(&msg);
  137.       }
  138.     }
  139.     return (msg.wParam);
  140. }
  141. /**************************************************************************
  142. *
  143. *  function:  MainWndProc()
  144. *
  145. *
  146. * On WM_CREATE create all of the child windows.
  147. * On WM_DESTROY make sure that all dynamically allocated memory is freed.
  148. * On WM_PAINT, outline many of the child windows.
  149. * On WM_COMMAND, respond to the command messages properly.
  150. *
  151. **************************************************************************/
  152. LRESULT CALLBACK MainWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  153. {
  154. /* misc. variables used in multiple messages cases. */
  155. RECT clientrect;
  156. RECT rect;
  157. TCHAR buffer[50];
  158. static TCHAR szFilter[MAX_PATH];
  159.   switch (message) {
  160.     /**********************************************************************
  161.     *  WM_CREATE
  162.     *
  163.     * Create all of the child windows used on this main window.
  164.     *  Assign the HWNDs to the correct static variables.
  165.     *
  166.     **********************************************************************/
  167.     case WM_CREATE: {
  168.       GetClientRect (hwnd, &clientrect);
  169.       /* Create Source Windows. */
  170.       CopyRect (&rect, &clientrect);
  171.       rect.right = (clientrect.right - clientrect.left) /2;
  172.       InflateRect (&rect, -2*BORDER, -BORDER);
  173.       createwindows(&rect,
  174.                    hwnd,
  175.                    &hwndLabel0,
  176.                    &hwndName0,
  177.                    &hwndSize0,
  178.                    &hwndCodePage0,
  179.                    &hwndByteOrder0,
  180.                    &hwndButton0);
  181.       /* Create Destination Windows. */
  182.       CopyRect (&rect, &clientrect);
  183.       rect.left = (clientrect.right - clientrect.left) /2;
  184.       InflateRect (&rect, -2*BORDER, -BORDER);
  185.       createwindows(&rect,
  186.                    hwnd,
  187.                    &hwndLabel1,
  188.                    &hwndName1,
  189.                    &hwndSize1,
  190.                    &hwndCodePage1,
  191.                    &hwndByteOrder1,
  192.                    &hwndButton1);
  193.       /* fill in window information that is different for source/destination */
  194.       SetWindowText (hwndLabel0, LoadResourceString(IDS_SOURCE));
  195.       SetWindowText (hwndLabel1, LoadResourceString(IDS_DESTINATION));
  196.       SetWindowText (hwndButton0, LoadResourceString(IDS_VIEW_SOURCE_BTN));
  197.       SetWindowText (hwndButton1, LoadResourceString(IDS_VIEW_DESTINATION_BTN));
  198.       SetWindowLong (hwndButton0, GWL_ID, BID_VIEWSOURCE      );
  199.       SetWindowLong (hwndButton1, GWL_ID, BID_VIEWDESTINATION );
  200.       gTypeSource = TYPEUNKNOWN;
  201.       giSourceCodePage =      GetACP();  // Just some reasonable initializer.
  202.       giDestinationCodePage = GetACP();  // Just some reasonable initializer.
  203.       /* initialize source & destination data correctly */
  204.       SendMessage (hwnd, WM_COMMAND, MID_CLEARSOURCE,      0);
  205.       SendMessage (hwnd, WM_COMMAND, MID_CLEARDESTINATION, 0);
  206.       /* Build up the correct filter strings for OPENFILENAME structure
  207.        *  Do it here so that we only have to do it once.
  208.        */
  209.       {
  210.         TCHAR *p;
  211.         p = szFilter;
  212.         lstrcpy (buffer,LoadResourceString(IDS_FILE_FILTER_SPEC1));
  213.         lstrcpy (p,buffer);
  214.         p += lstrlen (buffer) +1;
  215.         lstrcpy (buffer,TEXT("*.*"));
  216.         lstrcpy (p,buffer);
  217.         p += lstrlen (buffer) +1;
  218.         lstrcpy (buffer,LoadResourceString(IDS_FILE_FILTER_SPEC2));
  219.         lstrcpy (p,buffer);
  220.         p += lstrlen (buffer) +1;
  221.         lstrcpy (buffer,TEXT("*.txt"));
  222.         lstrcpy (p,buffer);
  223.         p += lstrlen (buffer) +1;
  224.         lstrcpy (buffer,LoadResourceString(IDS_FILE_FILTER_SPEC3));
  225.         lstrcpy (p,buffer);
  226.         p += lstrlen (buffer) +1;
  227.         lstrcpy (buffer,TEXT("*.utf"));
  228.         lstrcpy (p,buffer);
  229.         p += lstrlen (buffer) +1;
  230.         lstrcpy (p,TEXT(""));
  231.       }
  232.     } break; /* end WM_CREATE */
  233.     /**********************************************************************
  234.     *  WM_DESTROY
  235.     *
  236.     * Release the Online help, and free allocated memory if any.
  237.     **********************************************************************/
  238.     case WM_DESTROY:
  239.       WinHelp( hwnd, szHelpPathName, (UINT) HELP_QUIT, (DWORD) NULL );
  240.       ManageMemory (MMFREE, MMSOURCE,      0, pSourceData);
  241.       ManageMemory (MMFREE, MMDESTINATION, 0, pDestinationData);
  242.       PostQuitMessage(0);
  243.     break;
  244.     /**********************************************************************
  245.     *  WM_CTLCOLOR*
  246.     *
  247.     * Set the background of the child controls to be gray here.
  248.     **********************************************************************/
  249.     case WM_CTLCOLORBTN:
  250.     case WM_CTLCOLORSTATIC: {
  251.       HDC hdc;
  252.       hdc = (HDC) wParam;
  253.       SetBkMode (hdc, TRANSPARENT);
  254.       return (LRESULT)GetStockObject (LTGRAY_BRUSH);
  255.     } break;
  256.     /**********************************************************************
  257.     *  WM_PAINT
  258.     *
  259.     * Simply draw the two vertical divider lines, and 3D frame the children.
  260.     *
  261.     **********************************************************************/
  262.     case WM_PAINT: {
  263.       HDC hdc;
  264.       PAINTSTRUCT ps;
  265.       hdc = BeginPaint(hwnd, &ps);
  266.       GetClientRect (hwnd, &clientrect);
  267.       /* draw vertical separator line in the center */
  268.       rect.left = (clientrect.right - clientrect.left ) /2 -1;
  269.       rect.top = clientrect.top;
  270.       rect.right = rect.left +1;;
  271.       rect.bottom = clientrect.bottom;
  272.       FrameRect (hdc, &rect, GetStockObject (GRAY_BRUSH));
  273.       SelectObject (hdc, GetStockObject (WHITE_PEN));
  274.       MoveToEx (hdc, rect.right, rect.top, NULL);
  275.       LineTo (hdc,rect.right, rect.bottom);
  276.       /* draw 3D outlines of child windows. */
  277.       framechildwindow (hdc, hwnd, hwndName0);
  278.       framechildwindow (hdc, hwnd, hwndSize0);
  279.       framechildwindow (hdc, hwnd, hwndCodePage0);
  280.       framechildwindow (hdc, hwnd, hwndByteOrder0);
  281.       framechildwindow (hdc, hwnd, hwndName1);
  282.       framechildwindow (hdc, hwnd, hwndSize1);
  283.       framechildwindow (hdc, hwnd, hwndCodePage1);
  284.       framechildwindow (hdc, hwnd, hwndByteOrder1);
  285.       /* underline the labels */
  286.       underlinechildwindow (hdc, hwnd, hwndLabel0);
  287.       underlinechildwindow (hdc, hwnd, hwndLabel1);
  288.       EndPaint (hwnd, &ps);
  289.     } break; /* end WM_PAINT */
  290.     /**********************************************************************
  291.     *  WMU_ADJUSTFORNEWSOURCE
  292.     *
  293.     * lParam - szName of source (file, clipboard, ...)
  294.     *
  295.     * global - nBytesSource
  296.     *
  297.     * "user message."  Set the text of the Source windows
  298.     **********************************************************************/
  299.     case WMU_ADJUSTFORNEWSOURCE: {
  300.       LPVOID szName;
  301.       szName = (LPVOID) lParam;
  302.       /* Set Window text appropriately */
  303.       SetWindowText (hwndName0, szName);
  304.       wsprintf (buffer, LoadResourceString(IDS_BYTES), nBytesSource);
  305.       SetWindowText (hwndSize0, buffer);
  306.       SetWindowText (hwndByteOrder0, szBlank);
  307.       /* Clear the destination data if any to avoid user confusion. */
  308.       SendMessage (hwnd, WM_COMMAND, MID_CLEARDESTINATION, 0);
  309.       /* Reset the "type strings" based on new gTypeSource. */
  310.       SendMessage (hwnd, WMU_SETTYPESTRINGS, 0,0);
  311.     } break;
  312.     /**********************************************************************
  313.     *  WMU_SETTYPESTRINGS
  314.     *
  315.     * "user message."  Set the text of the "type" windows to reflect
  316.     *  the state stored in gTypeSource and gi*CodePage.
  317.     *
  318.     **********************************************************************/
  319.     case WMU_SETTYPESTRINGS:
  320.       switch (gTypeSource) {
  321.         case TYPEUNICODE:
  322.           SetWindowText (hwndCodePage0, TEXT("Unicode"));
  323.           wsprintf (buffer, LoadResourceString(IDS_CODE_PAGE),
  324.                   giDestinationCodePage);
  325.           SetWindowText (hwndCodePage1, buffer);
  326.           SetWindowText (hwnd, TitleWCToMB);
  327.         break;
  328.         case TYPECODEPAGE:
  329.           wsprintf (buffer, LoadResourceString(IDS_CODE_PAGE),
  330.                   giSourceCodePage);
  331.           SetWindowText (hwndCodePage0, buffer);
  332.           SetWindowText (hwndCodePage1, TEXT("Unicode"));
  333.           SetWindowText (hwnd, TitleMBToWC);
  334.         break;
  335.         case TYPEUNKNOWN:
  336.           SetWindowText (hwndCodePage0, szBlank);
  337.           SetWindowText (hwndCodePage1, szBlank);
  338.           SetWindowText (hwnd, TitleUnknown);
  339.         break;
  340.       } /* end switch gTypeSource */
  341.     break;
  342.     /**********************************************************************
  343.     *  WM_INITMENU
  344.     *
  345.     * Manage the enabled state of all of the menus.
  346.     *  Notice that the button enabled state is taken care of in ManageMemory().
  347.     *
  348.     * In general, this is dependent upon pSourceData & pDestinationData.
  349.     *  They are either NULL or non-NULL, and menu items are dependent upon
  350.     *  this state.
  351.     *
  352.     * One exception is the "Paste from Clipboard menu" which is enabled
  353.     *  conditional upon there being text data in the clipboard.
  354.     *
  355.     **********************************************************************/
  356.     case WM_INITMENU:
  357.       /* Adjust the "Paste from Clipboard menu" */
  358.       OpenClipboard (hwnd);
  359.       if (IsClipboardFormatAvailable (CF_UNICODETEXT) ||
  360.           IsClipboardFormatAvailable (CF_OEMTEXT) ||
  361.           IsClipboardFormatAvailable (CF_TEXT))
  362.         EnableMenuItem (GetMenu (hwnd),MID_PASTESOURCE,      MF_ENABLED);
  363.       else
  364.         EnableMenuItem (GetMenu (hwnd),MID_PASTESOURCE,      MF_GRAYED);
  365.       CloseClipboard ();
  366.       /* Adjust the source data dependent menus. */
  367.       if (pSourceData != NULL) {
  368.         EnableMenuItem (GetMenu (hwnd),MID_SOURCEOPT,        MF_ENABLED);
  369.         EnableMenuItem (GetMenu (hwnd),MID_SWAPSOURCE,       MF_ENABLED);
  370.         EnableMenuItem (GetMenu (hwnd),MID_CLEARSOURCE,      MF_ENABLED);
  371.         EnableMenuItem (GetMenu (hwnd),MID_CONVERTNOW,       MF_ENABLED);
  372.         EnableMenuItem (GetMenu (hwnd),MID_CONVERSIONOPT,    MF_ENABLED);
  373.         EnableMenuItem (GetMenu (hwnd),MID_DESTINATIONOPT,   MF_ENABLED);
  374.       } else {
  375.         EnableMenuItem (GetMenu (hwnd),MID_SOURCEOPT,        MF_GRAYED);
  376.         EnableMenuItem (GetMenu (hwnd),MID_SWAPSOURCE,       MF_GRAYED);
  377.         EnableMenuItem (GetMenu (hwnd),MID_CLEARSOURCE,      MF_GRAYED);
  378.         EnableMenuItem (GetMenu (hwnd),MID_CONVERTNOW,       MF_GRAYED);
  379.         EnableMenuItem (GetMenu (hwnd),MID_CONVERSIONOPT,    MF_GRAYED);
  380.         EnableMenuItem (GetMenu (hwnd),MID_DESTINATIONOPT,   MF_GRAYED);
  381.       }
  382.       /* Adjust the destination data dependent menus. */
  383.       if (pDestinationData != NULL) {
  384.         EnableMenuItem (GetMenu (hwnd),MID_SAVEAS,           MF_ENABLED);
  385.         EnableMenuItem (GetMenu (hwnd),MID_SWAPDESTINATION,  MF_ENABLED);
  386.         EnableMenuItem (GetMenu (hwnd),MID_COPYDESTINATION,  MF_ENABLED);
  387.         EnableMenuItem (GetMenu (hwnd),MID_CLEARDESTINATION, MF_ENABLED);
  388.       } else {
  389.         EnableMenuItem (GetMenu (hwnd),MID_SAVEAS,           MF_GRAYED);
  390.         EnableMenuItem (GetMenu (hwnd),MID_SWAPDESTINATION,  MF_GRAYED);
  391.         EnableMenuItem (GetMenu (hwnd),MID_COPYDESTINATION,  MF_GRAYED);
  392.         EnableMenuItem (GetMenu (hwnd),MID_CLEARDESTINATION, MF_GRAYED);
  393.       }
  394.     break;
  395.     /**********************************************************************
  396.     *  WM_COMMAND
  397.     *
  398.     * Just switch() on the command ID.  Notice that menu and button
  399.     *  command messages are treated the same.
  400.     *
  401.     **********************************************************************/
  402.     case WM_COMMAND:
  403.       switch (LOWORD(wParam)) {
  404.         /******************************************************************
  405.         *  WM_COMMAND, MID_OPEN
  406.         *
  407.         * Put up common dialog, try to open & read file.
  408.         *  Fill windows with correct text & fill pSourceData.
  409.         ******************************************************************/
  410.         case MID_OPEN  : {
  411.           HANDLE hFile;
  412.           DWORD nBytesRead;
  413.           TCHAR szFile[MAX_PATH],szFileTitle[MAX_PATH];
  414.           /* First set up the structure for the GetOpenFileName
  415.            *  common dialog.
  416.            */
  417.           {
  418.             OPENFILENAME OpenFileName;
  419.             /* buffers for the file names. */
  420.             wsprintf (szFile, szBlank);
  421.             wsprintf (szFileTitle, szBlank);
  422.             OpenFileName.lStructSize       = sizeof(OPENFILENAME);
  423.             OpenFileName.hwndOwner         = hwnd;
  424.             OpenFileName.hInstance         = (HANDLE) hInst;
  425.             OpenFileName.lpstrFilter       = szFilter; // built in WM_CREATE
  426.             OpenFileName.lpstrCustomFilter = NULL;
  427.             OpenFileName.nMaxCustFilter    = 0L;
  428.             OpenFileName.nFilterIndex      = 1L;
  429.             OpenFileName.lpstrFile         = szFile;
  430.             OpenFileName.nMaxFile          = MAX_PATH;
  431.             OpenFileName.lpstrFileTitle    = szFileTitle;
  432.             OpenFileName.nMaxFileTitle     = MAX_PATH;
  433.             OpenFileName.lpstrInitialDir   = NULL;
  434.             OpenFileName.lpstrTitle        = LoadResourceString(IDS_OPEN_FILE_TITLE);
  435.             OpenFileName.nFileOffset       = 0;
  436.             OpenFileName.nFileExtension    = 0;
  437.             OpenFileName.lpstrDefExt       = NULL;
  438.             OpenFileName.lCustData         = 0;
  439.             OpenFileName.lpfnHook          = NULL;
  440.             OpenFileName.lpTemplateName    = NULL;
  441.             OpenFileName.Flags = OFN_HIDEREADONLY | OFN_FILEMUSTEXIST;
  442.             if (!GetOpenFileName(&OpenFileName)) return 0;
  443.           }
  444.           /* User has filled in the file information.
  445.            *  Try to open that file for reading.
  446.            */
  447.           hFile = CreateFile(szFile,
  448.                        GENERIC_READ,
  449.                        0,
  450.                        NULL,
  451.                        OPEN_EXISTING,
  452.                        FILE_ATTRIBUTE_NORMAL,
  453.                        NULL);
  454.           if (hFile == INVALID_HANDLE_VALUE) {
  455.             MessageBox (hwnd, LoadResourceString(IDS_OPEN_FILE_FAILED),
  456.                     MBTitle, MBFlags);
  457.             return 0;
  458.           }
  459.           /* make sure file is not too big... i.e. > 2^32
  460.            *  If it is OK, write the file size in hwndSize0
  461.            */
  462.           {
  463.             BY_HANDLE_FILE_INFORMATION bhfi;
  464.             GetFileInformationByHandle (hFile, &bhfi);
  465.             if (bhfi.nFileSizeHigh != 0) {
  466.               MessageBox (hwnd, LoadResourceString(IDS_FILE_TOO_BIG),
  467.                       MBTitle, MBFlags);
  468.               CloseHandle (hFile);
  469.               return 0;
  470.             }
  471.             nBytesSource= bhfi.nFileSizeLow;
  472.           }
  473.           /* Allocate space for string, including potential UNICODE_NULL */
  474.           pSourceData = ManageMemory (MMALLOC, MMSOURCE, nBytesSource +2, pSourceData);
  475.           if (pSourceData == NULL) {
  476.             CloseHandle (hFile);
  477.             return 0;
  478.           }
  479.           if (nBytesSource < SIZEOFBOM) {
  480.               gTypeSource = TYPEUNKNOWN;
  481.               goto no_bom;
  482.           }
  483.           /* first read two bytes and look for BOM */
  484.           if (!ReadFile (hFile, pSourceData,SIZEOFBOM, &nBytesRead, NULL)) {
  485.             MessageBox (hwnd, LoadResourceString(IDS_READFILE_FAILED),
  486.                     MBTitle, MBFlags);
  487.             CloseHandle (hFile);
  488.             pSourceData = ManageMemory (MMFREE, MMSOURCE, 0, pSourceData);
  489.             return 0;
  490.           }
  491.           /* If file begins with BOM, then we know the type,
  492.            *  we'll decrement the number of bytes by two,
  493.            *  and read the rest of the data.
  494.            */
  495.           if (IsBOM (pSourceData)) {
  496.             gTypeSource = TYPEUNICODE;
  497.             nBytesSource -=SIZEOFBOM;
  498.           /* If file begins with Reverse BOM, then we know the type,
  499.            *  we'll decrement the number of bytes by two,
  500.            *  and read the rest of the data, and post a message so
  501.            *  that we know to swap the order later.
  502.            */
  503.           } else if (IsRBOM (pSourceData)) {
  504.             gTypeSource = TYPEUNICODE;
  505.             nBytesSource -=SIZEOFBOM;
  506.             MessageBox (hwnd, LoadResourceString(IDS_SWAPPING_BYTE_ORDER),
  507.                     MBTitle, MBFlags);
  508.             PostMessage (hwnd, WM_COMMAND, MID_SWAPSOURCE, 0);
  509.           /* Oops, does not begin with BOM.
  510.            *  Reset file pointer, and read data.
  511.            */
  512.           } else {
  513.             gTypeSource = TYPEUNKNOWN;
  514.             SetFilePointer (hFile, -SIZEOFBOM, NULL, FILE_CURRENT);
  515.           }
  516.           no_bom:
  517.           /* try to read all of it into memory */
  518.           if (!ReadFile (hFile, pSourceData,nBytesSource, &nBytesRead, NULL)) {
  519.             MessageBox (hwnd, LoadResourceString(IDS_READFILE_FAILED),
  520.                     MBTitle, MBFlags);
  521.             CloseHandle (hFile);
  522.             pSourceData = ManageMemory (MMFREE, MMSOURCE, 0, pSourceData);
  523.             return 0;
  524.           }
  525.           CloseHandle (hFile);
  526.           /* If we don't know the file type at this point,
  527.            *  try to determine if it is unicode.
  528.            */
  529.           if (gTypeSource == TYPEUNKNOWN) {
  530.             if (IsUnicode (pSourceData)) {
  531.               gTypeSource = TYPEUNICODE;
  532.               pSourceData[nBytesSource]   = 0;  // UNICODE_NULL
  533.               pSourceData[nBytesSource+1] = 0;
  534.             } else {
  535.               gTypeSource = TYPECODEPAGE;
  536.               pSourceData[nBytesSource] = 0;
  537.             }
  538.           }
  539.           SendMessage (hwnd, WMU_ADJUSTFORNEWSOURCE, 0, (LPARAM)szFile);
  540.         } break;  /* end case MID_OPEN */
  541.         /******************************************************************
  542.         *  WM_COMMAND, MID_SAVEAS
  543.         *
  544.         * Put up common dialog, try to open file, and write data to it.
  545.         ******************************************************************/
  546.         case MID_SAVEAS: {
  547.           HANDLE hFile;
  548.           DWORD nBytesRead;
  549.           TCHAR szFile[MAX_PATH],szFileTitle[MAX_PATH];
  550.           if (nBytesDestination == NODATA ) {
  551.             MessageBox (hwnd, LoadResourceString(IDS_NOTEXT_TO_SAVE),
  552.                     MBTitle, MBFlags);
  553.             return 0;
  554.           }
  555.           /* Set up the structure for the GetSaveFileName
  556.            *  common dialog.
  557.            */
  558.           {
  559.             OPENFILENAME OpenFileName;
  560.             /* buffers for the file names. */
  561.             wsprintf (szFile, szBlank);
  562.             wsprintf (szFileTitle, szBlank);
  563.             OpenFileName.lStructSize       = sizeof(OPENFILENAME);
  564.             OpenFileName.hwndOwner         = hwnd;
  565.             OpenFileName.hInstance         = (HANDLE) hInst;
  566.             OpenFileName.lpstrFilter       = szFilter;
  567.             OpenFileName.lpstrCustomFilter = NULL;
  568.             OpenFileName.nMaxCustFilter    = 0L;
  569.             OpenFileName.nFilterIndex      = 1L;
  570.             OpenFileName.lpstrFile         = szFile;
  571.             OpenFileName.nMaxFile          = MAX_PATH;
  572.             OpenFileName.lpstrFileTitle    = szFileTitle;
  573.             OpenFileName.nMaxFileTitle     = MAX_PATH;
  574.             OpenFileName.lpstrInitialDir   = NULL;
  575.             OpenFileName.lpstrTitle        = LoadResourceString(IDS_SAVE_AS_TITLE);
  576.             OpenFileName.nFileOffset       = 0;
  577.             OpenFileName.nFileExtension    = 0;
  578.             OpenFileName.lpstrDefExt       = NULL;
  579.             OpenFileName.lCustData         = 0;
  580.             OpenFileName.lpfnHook          = NULL;
  581.             OpenFileName.lpTemplateName    = NULL;
  582.             OpenFileName.Flags = OFN_HIDEREADONLY;
  583.             if (!GetSaveFileName(&OpenFileName)) return 0;
  584.           }
  585.           /* User has filled in the file information.
  586.            *  Try to open that file for writing.
  587.            */
  588.           hFile = CreateFile(szFile,
  589.                       GENERIC_WRITE,
  590.                       0,
  591.                       NULL,
  592.                       CREATE_ALWAYS,
  593.                       FILE_ATTRIBUTE_NORMAL,
  594.                       NULL);
  595.           if (hFile == INVALID_HANDLE_VALUE) {
  596.             MessageBox (hwnd, LoadResourceString(IDS_CREATEFILE_FAILED),
  597.                     MBTitle, MBFlags);
  598.             return 0;
  599.           }
  600.           /* if destination is unicode, try to write BOM first.
  601.            *  unless the bytes have been swapped
  602.            *  (criterion: hwndByteOrder contains text)
  603.            *  in which case, write a Reverse Byte Order Mark.
  604.            */
  605.           if (gTypeSource == TYPECODEPAGE) {
  606.             if (GetWindowTextLength (hwndByteOrder1) == 0) {
  607.               if (!WriteFile (hFile, szBOM, SIZEOFBOM, &nBytesRead, NULL)) {
  608.                 MessageBox (hwnd, LoadResourceString(IDS_WRITEFILE_FAILED),
  609.                         MBTitle, MBFlags);
  610.                 CloseHandle (hFile);
  611.                 return 0;
  612.               }
  613.             }else {
  614.               if (!WriteFile (hFile, szRBOM, SIZEOFBOM, &nBytesRead, NULL)) {
  615.                 MessageBox (hwnd, LoadResourceString(IDS_WRITEFILE_FAILED),
  616.                         MBTitle, MBFlags);
  617.                 CloseHandle (hFile);
  618.                 return 0;
  619.               }
  620.             }
  621.           }
  622.           /* try to write all of it into memory */
  623.           if (!WriteFile (hFile, pDestinationData,nBytesDestination, &nBytesRead, NULL)) {
  624.             MessageBox (hwnd, LoadResourceString(IDS_WRITEFILE_FAILED),
  625.                     MBTitle, MBFlags);
  626.             CloseHandle (hFile);
  627.             return 0;
  628.           }
  629.           SetWindowText (hwndName1, szFile);
  630.           CloseHandle (hFile);
  631.         } break;
  632.         /**********************************************************************
  633.         *  WM_COMMAND, MID_PASTESOURCE
  634.         *
  635.         * Paste the clipboard's prefered data format into the source.
  636.         *  Fills pSourceData.
  637.         **********************************************************************/
  638.         case MID_PASTESOURCE: {
  639.           UINT  iFormat;
  640.           PVOID pData;
  641.           OpenClipboard (hwnd);
  642.           iFormat = 0;
  643.           while (iFormat = EnumClipboardFormats(iFormat))
  644.             if ((iFormat == CF_UNICODETEXT) || (iFormat == CF_OEMTEXT) || (iFormat == CF_TEXT)) {
  645.               HGLOBAL hMem;
  646.               hMem = GetClipboardData (iFormat);
  647.               pData = GlobalLock(hMem);
  648.               switch (iFormat) {
  649.                 case CF_UNICODETEXT:
  650.                   nBytesSource = lstrlenW (pData) *2;
  651.                   pSourceData= ManageMemory (MMALLOC, MMSOURCE, nBytesSource+2, pSourceData);
  652.                   lstrcpyW ((LPVOID)pSourceData, pData);
  653.                   gTypeSource = TYPEUNICODE;
  654.                 break;
  655.                 case CF_OEMTEXT:
  656.                   nBytesSource = lstrlenA (pData);
  657.                   pSourceData= ManageMemory (MMALLOC, MMSOURCE, nBytesSource+1, pSourceData);
  658.                   lstrcpyA (pSourceData, pData);
  659.                   gTypeSource = TYPECODEPAGE;
  660.                   giSourceCodePage = GetOEMCP();
  661.                 break;
  662.                 case CF_TEXT:
  663.                   nBytesSource = lstrlenA (pData);
  664.                   pSourceData= ManageMemory (MMALLOC, MMSOURCE, nBytesSource+1, pSourceData);
  665.                   lstrcpyA (pSourceData, pData);
  666.                   gTypeSource = TYPECODEPAGE;
  667.                   giSourceCodePage = GetACP();
  668.                 break;
  669.                 default: break;  // shouldn't get here
  670.               } /* end switch (iFormat) */
  671.               SendMessage (hwnd, WMU_ADJUSTFORNEWSOURCE, 0,
  672.                             (LPARAM)LoadResourceString(IDS_FROM_CLIPBOARD));
  673.               GlobalUnlock(hMem);
  674.             break;  /* break out of while loop. */
  675.             } /* end if iFormat */
  676.           CloseClipboard ();
  677.         } break;
  678.         /**********************************************************************
  679.         *  WM_COMMAND, MID_COPYDESTINATION
  680.         *
  681.         * Copy destination data to the clipboard.
  682.         **********************************************************************/
  683.         case MID_COPYDESTINATION:
  684.         {
  685.           HGLOBAL hMem;
  686.           if (pDestinationData == NULL) return FALSE;
  687.           if (gTypeSource != TYPEUNICODE) {
  688.               if (!(hMem = GlobalAlloc(
  689.                       GMEM_MOVEABLE | GMEM_DDESHARE,
  690.                       (lstrlenW((LPWSTR)pDestinationData)+1) * 2))) {
  691.                   return FALSE;
  692.               }
  693.               lstrcpyW(GlobalLock(hMem), (LPWSTR)pDestinationData);
  694.               GlobalUnlock(hMem);
  695.           } else {
  696.               if (!(hMem = GlobalAlloc(
  697.                       GMEM_MOVEABLE | GMEM_DDESHARE,
  698.                       lstrlenA(pDestinationData)+1))) {
  699.                   return FALSE;
  700.               }
  701.               lstrcpyA(GlobalLock(hMem), pDestinationData);
  702.               GlobalUnlock(hMem);
  703.           }
  704.           OpenClipboard (hwnd);
  705.           EmptyClipboard();
  706.           /* if source NOT unicode, then destination is, else look at dest CP */
  707.           if (gTypeSource != TYPEUNICODE)
  708.             SetClipboardData (CF_UNICODETEXT, hMem);
  709.           else if (giDestinationCodePage == GetOEMCP())
  710.             SetClipboardData (CF_OEMTEXT, hMem);
  711.           else
  712.             SetClipboardData (CF_TEXT, hMem);
  713.           CloseClipboard ();
  714.         break;
  715.         }
  716.         /******************************************************************
  717.         *  WM_COMMAND, MID_CONVERTNOW
  718.         *
  719.         * This is where the conversion actually takes place.
  720.         *  In either case, make the call twice.  Once to determine how
  721.         *  much memory is needed, allocate space, and then make the call again.
  722.         *
  723.         *  If conversion succeeds, it fills pDestinationData.
  724.         ******************************************************************/
  725.         case MID_CONVERTNOW: {
  726.           int nBytesNeeded, nWCharNeeded, nWCharSource;
  727.           if (nBytesSource == NODATA ) {
  728.             MessageBox (hwnd, LoadResourceString(IDS_LOAD_SOURCE_FILE),
  729.                     MBTitle, MBFlags);
  730.             return 0;
  731.           }
  732.           /* Converting UNICODE -> giDestinationCodePage*/
  733.           if (gTypeSource == TYPEUNICODE) {
  734.             nWCharSource = nBytesSource/2;
  735.             /* Query the number of bytes required to store the Dest string */
  736.             nBytesNeeded = WideCharToMultiByte(giDestinationCodePage, gWCFlags,
  737.                              (LPWSTR)pSourceData, nWCharSource,
  738.                              NULL, 0,
  739.                              glpDefaultChar, &gUsedDefaultChar);
  740.             /* Allocate the required amount of space */
  741.             if (nBytesNeeded == 0) {
  742.                 MessageBox (hwnd, LoadResourceString(IDS_FIRSTCALL_FAILED),
  743.                         MBTitle, MBFlags);
  744.                 break;
  745.             }
  746.             /* We need more 1 byte for '' */
  747.             pDestinationData= ManageMemory (MMALLOC, MMDESTINATION, nBytesNeeded + 2, pDestinationData);
  748.             /* Do the conversion */
  749.             nBytesDestination = WideCharToMultiByte(giDestinationCodePage, gWCFlags,
  750.                              (LPWSTR)pSourceData, nWCharSource,
  751.                              pDestinationData, nBytesNeeded, glpDefaultChar, &gUsedDefaultChar);
  752.             if (nBytesNeeded == 0) {
  753.                 MessageBox (hwnd, LoadResourceString(IDS_FIRSTCALL_FAILED),
  754.                         MBTitle, MBFlags);
  755.                 break;
  756.             }
  757.             *(LPSTR)((LPSTR)pDestinationData + nBytesNeeded) = '';
  758.           }
  759.           /* converting giSourceCodePage -> UNICODE */
  760.           else if (gTypeSource == TYPECODEPAGE) {
  761.             /* Query the number of WChar required to store the Dest string */
  762.             nWCharNeeded = MultiByteToWideChar(giSourceCodePage, gMBFlags,
  763.                              pSourceData, nBytesSource, NULL, 0 );
  764.             /* Allocate the required amount of space */
  765.             /* We need more 2 bytes for '' */
  766.             pDestinationData= ManageMemory (MMALLOC, MMDESTINATION, (nWCharNeeded+1)*2, pDestinationData);
  767.             /* Do the conversion */
  768.             nWCharNeeded = MultiByteToWideChar(giSourceCodePage, gMBFlags,
  769.                              pSourceData, nBytesSource,
  770.                              (LPWSTR)pDestinationData, nWCharNeeded);
  771.             *(LPWSTR)((LPWSTR)pDestinationData + nWCharNeeded) = L'';
  772.             /* MultiByteToWideChar returns # WCHAR, so multiply by 2 */
  773.             nBytesDestination = 2*nWCharNeeded ;
  774.           } else {
  775.             MessageBox (hwnd, LoadResourceString(IDS_SOURCE_TYPE_UNKNOWN),
  776.                     MBTitle, MBFlags);
  777.             return 0;
  778.           }
  779.           /* code common to all conversions... */
  780.           SetWindowText (hwndName1, LoadResourceString(IDS_DATA_NOT_SAVED));
  781.           wsprintf (buffer, LoadResourceString(IDS_BYTES), nBytesDestination);
  782.           SetWindowText (hwndSize1, buffer);
  783.           SetWindowText (hwndByteOrder1, szBlank);
  784.           /* Throw up "Save as" dialog to help the user along.
  785.            *  They can always <esc> if need be.
  786.            */
  787.           SendMessage (hwnd, WM_COMMAND, MID_SAVEAS, 0);
  788.         } break; /* end  case BID_CONVERT */
  789.         /******************************************************************
  790.         *  WM_COMMAND, BID_VIEWSOURCE
  791.         *
  792.         ******************************************************************/
  793.         case BID_VIEWSOURCE:
  794.           if (gTypeSource == TYPEUNICODE)
  795.             DialogBoxW (hInst, L"ShowTextDlg", hwnd, (DLGPROC)ViewSourceProc);
  796.           else
  797.             DialogBoxA (hInst, "ShowTextDlg", hwnd, (DLGPROC)ViewSourceProc);
  798.         break;
  799.         /******************************************************************
  800.         *  WM_COMMAND, BID_VIEWDESTINATION
  801.         *
  802.         ******************************************************************/
  803.         case BID_VIEWDESTINATION:
  804.           if (gTypeSource == TYPEUNICODE)
  805.             DialogBoxA (hInst, "ShowTextDlg", hwnd, (DLGPROC)ViewDestinationProc);
  806.           else
  807.             DialogBoxW (hInst, L"ShowTextDlg", hwnd, (DLGPROC)ViewDestinationProc);
  808.         break;
  809.         /******************************************************************
  810.         *  WM_COMMAND, MID_SOURCEOPT
  811.         *
  812.         * Allows user to change interpretation options for the source data.
  813.         *
  814.         *  Put up appropriate dialog box, and reset window text in response.
  815.         ******************************************************************/
  816.         case MID_SOURCEOPT:
  817.           if (DialogBox (hInst, TEXT("DataOptionsDlg"), hwnd, (DLGPROC)SourceOptionsProc)) {
  818.             SendMessage (hwnd, WMU_SETTYPESTRINGS, 0,0);
  819.             SendMessage (hwnd, WM_COMMAND, MID_CLEARDESTINATION, 0);
  820.           }
  821.         break;
  822.         /******************************************************************
  823.         *  WM_COMMAND, MID_DESTINATIONOPT
  824.         *
  825.         * Allows user to change options for destination data.
  826.         *
  827.         *  Put up appropriate dialog box, and reset window text in response.
  828.         ******************************************************************/
  829.         case MID_DESTINATIONOPT:
  830.           if (DialogBox (hInst, TEXT("DataOptionsDlg"), hwnd, (DLGPROC)DestinationOptionsProc)) {
  831.             SendMessage (hwnd, WMU_SETTYPESTRINGS, 0,0);
  832.             SendMessage (hwnd, WM_COMMAND, MID_CLEARDESTINATION, 0);
  833.           }
  834.         break;
  835.         /******************************************************************
  836.         *  WM_COMMAND, MID_CONVERSIONOPT
  837.         *
  838.         ******************************************************************/
  839.         case MID_CONVERSIONOPT:
  840.           if (DialogBox (hInst, TEXT("ConversionOptionsDlg"), hwnd, (DLGPROC)ConversionOptionsProc)) {
  841.             SendMessage (hwnd, WM_COMMAND, MID_CLEARDESTINATION, 0);
  842.           }
  843.         break;
  844.         /******************************************************************
  845.         *  WM_COMMAND, MID_SWAPSOURCE
  846.         *
  847.         * Allows user to reverse byte order of data.
  848.         *
  849.         ******************************************************************/
  850.         case MID_SWAPSOURCE: {
  851.           int i, end;
  852.           BYTE temp;
  853.           if (pSourceData == NULL) return FALSE;
  854.           end =  nBytesSource - 2;
  855.           for (i = 0; i<= end; i+=2) {
  856.             temp             = pSourceData[i];
  857.             pSourceData[i]   = pSourceData[i+1];
  858.             pSourceData[i+1] = temp;
  859.           }
  860.           if (GetWindowTextLength (hwndByteOrder0) == 0)
  861.             SetWindowText (hwndByteOrder0,
  862.                     LoadResourceString(IDS_BYTE_ORDER_REVERSED));
  863.           else
  864.             SetWindowText (hwndByteOrder0, szBlank);
  865.           /* Since source is different, invalidate Destination data. */
  866.           SendMessage (hwnd, WM_COMMAND, MID_CLEARDESTINATION, 0);
  867.         } break;
  868.         /******************************************************************
  869.         *  WM_COMMAND, MID_SWAPDESTINATION
  870.         *
  871.         * Allows user to reverse byte order of data.
  872.         *
  873.         ******************************************************************/
  874.         case MID_SWAPDESTINATION: {
  875.           int i, end;
  876.           BYTE temp;
  877.           if (pDestinationData == NULL) return FALSE;
  878.           end =  nBytesDestination - 2;
  879.           for (i = 0; i<= end; i+=2) {
  880.             temp             = pDestinationData[i];
  881.             pDestinationData[i]   = pDestinationData[i+1];
  882.             pDestinationData[i+1] = temp;
  883.           }
  884.           if (GetWindowTextLength (hwndByteOrder1) == 0)
  885.             SetWindowText (hwndByteOrder1,
  886.                     LoadResourceString(IDS_BYTE_ORDER_REVERSED));
  887.           else
  888.             SetWindowText (hwndByteOrder1, szBlank);
  889.         } break;
  890.         /**********************************************************************
  891.         *  WM_COMMAND, MID_CLEARDESTINATION
  892.         *
  893.         * Clear the destination information.  May cause data to be lost.
  894.         **********************************************************************/
  895.         case MID_CLEARDESTINATION:
  896.           SetWindowText (hwndSize1, szBlank);
  897.           SetWindowText (hwndName1, szBlank);
  898.           SetWindowText (hwndByteOrder1, szBlank);
  899.           pDestinationData= ManageMemory (MMFREE, MMDESTINATION, 0, pDestinationData);
  900.         break;
  901.         /**********************************************************************
  902.         *  WM_COMMAND, MID_CLEARSOURCE
  903.         *
  904.         * Clear the SOURCE information.  May cause data to be lost.
  905.         **********************************************************************/
  906.         case MID_CLEARSOURCE:
  907.           SetWindowText (hwndSize0, szBlank);
  908.           SetWindowText (hwndName0, szBlank);
  909.           SetWindowText (hwndByteOrder0, szBlank);
  910.           pSourceData= ManageMemory (MMFREE, MMSOURCE, 0, pSourceData);
  911.         break;
  912.         /******************************************************************
  913.         *  WM_COMMAND, MID_INSTALLTABLES
  914.         *
  915.         ******************************************************************/
  916.         case MID_INSTALLTABLES:
  917.           DialogBox (hInst, TEXT("InstallTableDlg"), hwnd, (DLGPROC)InstallTableProc);
  918.         break;
  919.         /* Simply call WinHelp to display the OnLine help file. */
  920.         case MID_HELP:
  921.           WinHelp( hwnd, szHelpPathName, HELP_INDEX, (DWORD) NULL );
  922.         break;
  923.         /* No-op Window procedure to simply display the dialog box. */
  924.         case MID_ABOUT:
  925.           ShellAbout (hwnd, TEXT("UConvert"), NULL, LoadIcon (hInst, TEXT("uconvertIcon")));
  926.         break;
  927.         /* Just close the window. */
  928.         case MID_EXIT:
  929.           PostMessage (hwnd, WM_CLOSE, 0,0);
  930.         break;
  931.       } /* end switch (LOWORD(wParam)) */
  932.     break;  /* end WM_COMMAND */
  933.     default: break;
  934.   } /* end switch */
  935.   return (DefWindowProc(hwnd, message, wParam, lParam));
  936. }
  937. /**************************************************************************
  938. *
  939. *  function:  IsUnicode()
  940. *
  941. * HACK... eventually use a proper function for IsUnicode
  942. *  Use function from unipad?
  943. *
  944. **************************************************************************/
  945. BOOL IsUnicode (PBYTE pb)
  946. {
  947.   return (IsBOM (pb));
  948. }
  949. /**************************************************************************
  950. *
  951. *  function:  IsBOM()
  952. *
  953. * true iff pb points to a Byte Order Mark.
  954. *
  955. **************************************************************************/
  956. BOOL IsBOM (PBYTE pb)
  957. {
  958.   if ((*pb == 0xFF) & (*(pb+1) == 0xFE))  // BOM
  959.     return TRUE;
  960.   else
  961.     return FALSE;
  962. }
  963. /**************************************************************************
  964. *
  965. *  function:  IsRBOM()
  966. *
  967. * true iff pb points to a reversed Byte Order Mark.
  968. *
  969. **************************************************************************/
  970. BOOL IsRBOM (PBYTE pb)
  971. {
  972.   if ((*pb == 0xFE) & (*(pb+1) == 0xFF))  // RBOM
  973.     return TRUE;
  974.   else
  975.     return FALSE;
  976. }
  977. /**************************************************************************
  978. *
  979. *  function:  framechildwindow()
  980. *
  981. * Simply draw a 3D frame around child window.
  982. *
  983. **************************************************************************/
  984. VOID framechildwindow (HDC hdc, HWND hwndParent, HWND hwndChild)
  985. {
  986. RECT rect;
  987.       GetWindowRect (hwndChild, &rect);
  988.       /* minor hack... assumes RECT is two points, right field starting first */
  989.       ScreenToClient (hwndParent, (LPPOINT)&rect);
  990.       ScreenToClient (hwndParent, (LPPOINT)&(rect.right));
  991.       InflateRect (&rect, 1, 1);
  992.       FrameRect (hdc, &rect, GetStockObject (GRAY_BRUSH));
  993.       InflateRect (&rect, -1, -1);
  994.       SelectObject (hdc, GetStockObject (WHITE_PEN));
  995.       MoveToEx (hdc, rect.right, rect.top, NULL);
  996.       LineTo (hdc,rect.right, rect.bottom);
  997.       LineTo (hdc,rect.left, rect.bottom);
  998.     return;
  999. }
  1000. /**************************************************************************
  1001. *
  1002. *  function:  underlinechildwindow()
  1003. *
  1004. * Underline child window.
  1005. *
  1006. **************************************************************************/
  1007. VOID underlinechildwindow (HDC hdc, HWND hwndParent, HWND hwndChild)
  1008. {
  1009. RECT rect;
  1010.       GetWindowRect (hwndChild, &rect);
  1011.       /* minor hack... assumes RECT is two points, right field starting first */
  1012.       ScreenToClient (hwndParent, (LPPOINT)&rect);
  1013.       ScreenToClient (hwndParent, (LPPOINT)&(rect.right));
  1014.       InflateRect (&rect, 1, 1);
  1015.       rect.top = rect.bottom-1;
  1016.       FrameRect (hdc, &rect, GetStockObject (GRAY_BRUSH));
  1017.       SelectObject (hdc, GetStockObject (WHITE_PEN));
  1018.       MoveToEx (hdc, rect.right, rect.bottom, NULL);
  1019.       LineTo (hdc,rect.left, rect.bottom);
  1020.     return;
  1021. }
  1022. /**************************************************************************
  1023. *
  1024. *  function:  createwindows()
  1025. *
  1026. * Create the child windows and pass the handles back in parameters.
  1027. *  Each Window is created relative to (inside of) prect.
  1028. *  top is a spacial pointer to the Y coordinate of the next window.
  1029. *
  1030. **************************************************************************/
  1031. VOID createwindows(PRECT prect,
  1032.                    HWND  hwndParent,
  1033.                    HWND* hwndLabel,
  1034.                    HWND* hwndName,
  1035.                    HWND* hwndSize,
  1036.                    HWND* hwndCodePage,
  1037.                    HWND* hwndByteOrder,
  1038.                    HWND* hwndButton)
  1039. {
  1040. int top;
  1041.   top = prect->top;
  1042.   *hwndLabel = CreateWindow(
  1043.           TEXT("STATIC"),
  1044.           szBlank,
  1045.           WS_CHILD | WS_VISIBLE | SS_CENTER,
  1046.           prect->left,
  1047.           top,
  1048.           prect->right - prect->left,
  1049.           WHEIGHT,
  1050.           hwndParent, NULL, hInst, 0);
  1051.   top += WHEIGHT*5/2;
  1052.   *hwndName = CreateWindow(
  1053.           TEXT("STATIC"),
  1054.           szBlank,
  1055.           WS_CHILD | WS_VISIBLE | SS_RIGHT,
  1056.           prect->left,
  1057.           top,
  1058.           prect->right - prect->left,
  1059.           WHEIGHT,
  1060.           hwndParent, NULL, hInst, 0);
  1061.   top += WHEIGHT*2;
  1062.   *hwndSize = CreateWindow(
  1063.           TEXT("STATIC"),
  1064.           szBlank,
  1065.           WS_CHILD | WS_VISIBLE | SS_LEFT,
  1066.           prect->left,
  1067.           top,
  1068.           (prect->right - prect->left) *3/4,
  1069.           WHEIGHT,
  1070.           hwndParent, NULL, hInst, 0);
  1071.   top += WHEIGHT*2;
  1072.   *hwndCodePage = CreateWindow(
  1073.           TEXT("STATIC"),
  1074.           szBlank,
  1075.           WS_CHILD | WS_VISIBLE | SS_LEFT,
  1076.           prect->left,
  1077.           top,
  1078.           (prect->right - prect->left) *3/4,
  1079.           WHEIGHT,
  1080.           hwndParent, NULL, hInst, 0);
  1081.   top += WHEIGHT*2;
  1082.   *hwndByteOrder = CreateWindow(
  1083.           TEXT("STATIC"),
  1084.           szBlank,
  1085.           WS_CHILD | WS_VISIBLE | SS_LEFT,
  1086.           prect->left,
  1087.           top,
  1088.           (prect->right - prect->left) *3/4,
  1089.           WHEIGHT,
  1090.           hwndParent, NULL, hInst, 0);
  1091.   top += WHEIGHT*2;
  1092.   *hwndButton = CreateWindow(
  1093.           TEXT("BUTTON"),
  1094.           TEXT("ViewText"),
  1095.           WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
  1096.           prect->left,
  1097.           top,
  1098.           prect->right - prect->left,
  1099.           WHEIGHT*9/7,
  1100.           hwndParent, NULL, hInst, 0);
  1101.   return;
  1102. }
  1103. /**************************************************************************
  1104. *
  1105. *  function:  ManageMemory()
  1106. *
  1107. * Do all memory management here for the source and destination pointers.
  1108. *  We also enable/disable the "View..." buttons to reflect existence of data.
  1109. *
  1110. *
  1111. * PARAMETERS
  1112. *
  1113. *  message : {MMALLOC, MMFREE}
  1114. *    Alloc when requested by MMALLOC, and free the existing, passed in, pointer.
  1115. *    Free when requested by MMFREE.
  1116. *  sourcedestination : {MMSOURCE, MMDESTINATION}
  1117. *  nBytes - number to alloc on MMALLOC messages.
  1118. *  p - old pointer to be freed.
  1119. *
  1120. *
  1121. * GLOBALS
  1122. *
  1123. *  hwndButton0, hwndButton1
  1124. *
  1125. **************************************************************************/
  1126. LPVOID ManageMemory (UINT message, UINT sourcedestination, DWORD nBytes, LPVOID p)
  1127. {
  1128.   switch (message) {
  1129.     case MMFREE :
  1130.       if (sourcedestination == MMSOURCE)
  1131.         EnableWindow (hwndButton0, FALSE);
  1132.       else if (sourcedestination == MMDESTINATION)
  1133.         EnableWindow (hwndButton1, FALSE);
  1134.       if (p != NULL) GlobalFree (GlobalHandle (p));
  1135.       return NULL;
  1136.     break;
  1137.     case MMALLOC :
  1138.       if (sourcedestination == MMSOURCE)
  1139.         EnableWindow (hwndButton0, TRUE);
  1140.       else if (sourcedestination == MMDESTINATION)
  1141.         EnableWindow (hwndButton1, TRUE);
  1142.       if (p != NULL) GlobalFree (GlobalHandle (p));
  1143.       p = (LPVOID) GlobalAlloc (GPTR, nBytes);
  1144.       return p;
  1145.     break;
  1146.   } /* end switch (message) */
  1147.   return NULL;
  1148. }
  1149. /**************************************************************************
  1150. *
  1151. *  function:  LoadResourceString()
  1152. *
  1153. *  Loads a resource string from string table and returns a pointer
  1154. *  to the string.
  1155. *
  1156. *  PARAMETERS: wID - resource string id
  1157. *
  1158. **************************************************************************/
  1159. LPTSTR LoadResourceString(UINT wID)
  1160. {
  1161.     static TCHAR szBuf[512];
  1162.     LoadString((HANDLE)GetModuleHandle(NULL),wID,szBuf,sizeof(szBuf));
  1163.     return szBuf;
  1164. }