home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / sdktools / winnt / uconvert / uconvert.c < prev    next >
C/C++ Source or Header  |  1997-10-05  |  49KB  |  1,469 lines

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