home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / mfc / ole / wordpad / multconv.cpp < prev    next >
C/C++ Source or Header  |  1998-03-26  |  12KB  |  511 lines

  1. // convert.cpp : implementation file
  2. //
  3. // This is a part of the Microsoft Foundation Classes C++ library.
  4. // Copyright (C) 1992-1998 Microsoft Corporation
  5. // All rights reserved.
  6. //
  7. // This source code is only intended as a supplement to the
  8. // Microsoft Foundation Classes Reference and related
  9. // electronic documentation provided with the library.
  10. // See these sources for detailed information regarding the
  11. // Microsoft Foundation Classes product.
  12.  
  13. #include "stdafx.h"
  14. #include "wordpad.h"
  15. #include "multconv.h"
  16. #include "mswd6_32.h"
  17.  
  18. #ifdef _DEBUG
  19. #undef THIS_FILE
  20. static char BASED_CODE THIS_FILE[] = __FILE__;
  21. #endif
  22.  
  23. #ifdef CONVERTERS
  24. CConverter* CConverter::m_pThis = NULL;
  25. #endif
  26.  
  27. #define BUFFSIZE 4096
  28.  
  29. CTrackFile::CTrackFile(CFrameWnd* pWnd) : CFile()
  30. {
  31.     m_nLastPercent = -1;
  32.     m_dwLength = 0;
  33.     m_pFrameWnd = pWnd;
  34.     VERIFY(m_strComplete.LoadString(IDS_COMPLETE));
  35.     VERIFY(m_strWait.LoadString(IDS_PLEASE_WAIT));
  36.     VERIFY(m_strSaving.LoadString(IDS_SAVING));
  37. //  OutputPercent(0);
  38. }
  39.  
  40. CTrackFile::~CTrackFile()
  41. {
  42.     OutputPercent(100);
  43.     if (m_pFrameWnd != NULL)
  44.         m_pFrameWnd->SetMessageText(AFX_IDS_IDLEMESSAGE);
  45. }
  46.  
  47. UINT CTrackFile::Read(void FAR* lpBuf, UINT nCount)
  48. {
  49.     UINT n = CFile::Read(lpBuf, nCount);
  50.     if (m_dwLength != 0)
  51.         OutputPercent((int)((GetPosition()*100)/m_dwLength));
  52.     return n;
  53. }
  54.  
  55. void CTrackFile::Write(const void FAR* lpBuf, UINT nCount)
  56. {
  57.     CFile::Write(lpBuf, nCount);
  58.     OutputString(m_strSaving);
  59. //  if (m_dwLength != 0)
  60. //      OutputPercent((int)((GetPosition()*100)/m_dwLength));
  61. }
  62.  
  63. void CTrackFile::OutputString(LPCTSTR lpsz)
  64. {
  65.     if (m_pFrameWnd != NULL)
  66.     {
  67.         m_pFrameWnd->SetMessageText(lpsz);
  68.         CWnd* pBarWnd = m_pFrameWnd->GetMessageBar();
  69.         if (pBarWnd != NULL)
  70.             pBarWnd->UpdateWindow();
  71.     }
  72. }
  73.  
  74. void CTrackFile::OutputPercent(int nPercentComplete)
  75. {
  76.     if (m_pFrameWnd != NULL && m_nLastPercent != nPercentComplete)
  77.     {
  78.         m_nLastPercent = nPercentComplete;
  79.         TCHAR buf[64];
  80.         int n = nPercentComplete;
  81.         wsprintf(buf, (n==100) ? m_strWait : m_strComplete, n);
  82.         OutputString(buf);
  83.     }
  84. }
  85.  
  86. COEMFile::COEMFile(CFrameWnd* pWnd) : CTrackFile(pWnd)
  87. {
  88. }
  89.  
  90. UINT COEMFile::Read(void FAR* lpBuf, UINT nCount)
  91. {
  92.     UINT n = CTrackFile::Read(lpBuf, nCount);
  93.     OemToCharBuffA((const char*)lpBuf, (char*)lpBuf, n);
  94.     return n;
  95. }
  96.  
  97. void COEMFile::Write(const void FAR* lpBuf, UINT nCount)
  98. {
  99.     CharToOemBuffA((const char*)lpBuf, (char*)lpBuf, nCount);
  100.     CTrackFile::Write(lpBuf, nCount);
  101. }
  102.  
  103. #ifdef CONVERTERS
  104.  
  105. HGLOBAL CConverter::StringToHGLOBAL(LPCSTR pstr)
  106. {
  107.     HGLOBAL hMem = NULL;
  108.     if (pstr != NULL)
  109.     {
  110.         hMem = GlobalAlloc(GHND, (lstrlenA(pstr)*2)+1);
  111.         char* p = (char*) GlobalLock(hMem);
  112.         ASSERT(p != NULL);
  113.         if (p != NULL)
  114.             lstrcpyA(p, pstr);
  115.         GlobalUnlock(hMem);
  116.     }
  117.     return hMem;
  118. }
  119.  
  120. CConverter::CConverter(LPCSTR pszLibName, CFrameWnd* pWnd) : CTrackFile(pWnd)
  121. {
  122.     USES_CONVERSION;
  123.     m_hBuff = NULL;
  124.     m_pBuf = NULL;
  125.     m_nBytesAvail = 0;
  126.     m_nBytesWritten = 0;
  127.     m_nPercent = 0;
  128.     m_hEventFile = NULL;
  129.     m_hEventConv = NULL;
  130.     m_bDone = TRUE;
  131.     m_bConvErr = FALSE;
  132.     m_hFileName = NULL;
  133.     OFSTRUCT ofs;
  134.     if (OpenFile(pszLibName, &ofs, OF_EXIST) == HFILE_ERROR)
  135.     {
  136.         m_hLibCnv = NULL;
  137.         return;
  138.     }
  139.     m_hLibCnv = LoadLibraryA(pszLibName);
  140.     if (m_hLibCnv < (HINSTANCE)HINSTANCE_ERROR)
  141.         m_hLibCnv = NULL;
  142.     else
  143.     {
  144.         LoadFunctions();
  145.         ASSERT(m_pInitConverter != NULL);
  146.         if (m_pInitConverter != NULL)
  147.         {
  148.             CString str = AfxGetAppName();
  149.             str.MakeUpper();
  150.             VERIFY(m_pInitConverter(AfxGetMainWnd()->GetSafeHwnd(), T2CA(str)));
  151.         }
  152.     }
  153. }
  154.  
  155. CConverter::CConverter(CFrameWnd* pWnd) : CTrackFile(pWnd)
  156. {
  157.     m_pInitConverter = NULL;
  158.     m_pIsFormatCorrect = NULL;
  159.     m_pForeignToRtf = NULL;
  160.     m_pRtfToForeign = NULL;
  161.     m_bConvErr = FALSE;
  162.     m_hFileName = NULL;
  163. }
  164.  
  165. CConverter::~CConverter()
  166. {
  167.     if (!m_bDone) // converter thread hasn't exited
  168.     {
  169.         WaitForConverter();
  170.         m_nBytesAvail = 0;
  171.         VERIFY(ResetEvent(m_hEventFile));
  172.         m_nBytesAvail = 0;
  173.         SetEvent(m_hEventConv);
  174.         WaitForConverter();// wait for DoConversion exit
  175.         VERIFY(ResetEvent(m_hEventFile));
  176.     }
  177.  
  178.     if (m_hEventFile != NULL)
  179.         VERIFY(CloseHandle(m_hEventFile));
  180.     if (m_hEventConv != NULL)
  181.         VERIFY(CloseHandle(m_hEventConv));
  182.     if (m_hLibCnv != NULL)
  183.         FreeLibrary(m_hLibCnv);
  184.     if (m_hFileName != NULL)
  185.         GlobalFree(m_hFileName);
  186. }
  187.  
  188. void CConverter::WaitForConverter()
  189. {
  190.     // while event not signalled -- process messages
  191.     while (MsgWaitForMultipleObjects(1, &m_hEventFile, FALSE, INFINITE,
  192.         QS_SENDMESSAGE) != WAIT_OBJECT_0)
  193.     {
  194.         MSG msg;
  195.         PeekMessage(&msg, 0, 0, 0, PM_NOREMOVE);
  196.     }
  197. }
  198.  
  199. void CConverter::WaitForBuffer()
  200. {
  201.     // while event not signalled -- process messages
  202.     while (MsgWaitForMultipleObjects(1, &m_hEventConv, FALSE, INFINITE,
  203.         QS_SENDMESSAGE) != WAIT_OBJECT_0)
  204.     {
  205.         MSG msg;
  206.         PeekMessage(&msg, 0, 0, 0, PM_NOREMOVE);
  207.     }
  208. }
  209.  
  210. UINT CConverter::ConverterThread(LPVOID)
  211. {
  212.     ASSERT(m_pThis != NULL);
  213.  
  214.     HRESULT hRes = OleInitialize(NULL);
  215.     ASSERT(hRes == S_OK || hRes == S_FALSE);
  216.     m_pThis->DoConversion();
  217.     OleUninitialize();
  218.  
  219.     return 0;
  220. }
  221.  
  222. BOOL CConverter::IsFormatCorrect(LPCTSTR pszFileName)
  223. {
  224.     USES_CONVERSION;
  225.     int nRet;
  226.     if (m_hLibCnv == NULL || m_pIsFormatCorrect == NULL)
  227.         return FALSE;
  228.  
  229.     char buf[_MAX_PATH];
  230.     strcpy(buf, T2CA(pszFileName));
  231.  
  232.     CharToOemA(buf, buf);
  233.  
  234.     HGLOBAL hFileName = StringToHGLOBAL(buf);
  235.     HGLOBAL hDesc = GlobalAlloc(GHND, 256);
  236.     ASSERT(hDesc != NULL);
  237.     nRet = m_pIsFormatCorrect(hFileName, hDesc);
  238.     GlobalFree(hDesc);
  239.     GlobalFree(hFileName);
  240.     return (nRet == 1) ? TRUE : FALSE;
  241. }
  242.  
  243. // static callback function
  244. int CALLBACK CConverter::WriteOutStatic(int cch, int nPercentComplete)
  245. {
  246.     ASSERT(m_pThis != NULL);
  247.     return m_pThis->WriteOut(cch, nPercentComplete);
  248. }
  249.  
  250. int CALLBACK CConverter::WriteOut(int cch, int nPercentComplete)
  251. {
  252.     ASSERT(m_hBuff != NULL);
  253.     m_nPercent = nPercentComplete;
  254.     if (m_hBuff == NULL)
  255.         return -9;
  256.     if (cch != 0)
  257.     {
  258.         WaitForBuffer();
  259.         VERIFY(ResetEvent(m_hEventConv));
  260.         m_nBytesAvail = cch;
  261.         SetEvent(m_hEventFile);
  262.         WaitForBuffer();
  263.     }
  264.     return 0; //everything OK
  265. }
  266.  
  267. int CALLBACK CConverter::ReadInStatic(int /*flags*/, int nPercentComplete)
  268. {
  269.     ASSERT(m_pThis != NULL);
  270.     return m_pThis->ReadIn(nPercentComplete);
  271. }
  272.  
  273. int CALLBACK CConverter::ReadIn(int /*nPercentComplete*/)
  274. {
  275.     ASSERT(m_hBuff != NULL);
  276.     if (m_hBuff == NULL)
  277.         return -8;
  278.  
  279.     SetEvent(m_hEventFile);
  280.     WaitForBuffer();
  281.     VERIFY(ResetEvent(m_hEventConv));
  282.  
  283.     return m_nBytesAvail;
  284. }
  285.  
  286. BOOL CConverter::DoConversion()
  287. {
  288.     USES_CONVERSION;
  289.     m_nLastPercent = -1;
  290. //  m_dwLength = 0; // prevent Read/Write from displaying
  291.     m_nPercent = 0;
  292.  
  293.     ASSERT(m_hBuff != NULL);
  294.     ASSERT(m_pThis != NULL);
  295.     HGLOBAL hDesc = StringToHGLOBAL("");
  296.     HGLOBAL hSubset = StringToHGLOBAL("");
  297.  
  298.     int nRet;
  299.     if (m_bForeignToRtf)
  300.     {
  301.         ASSERT(m_pForeignToRtf != NULL);
  302.         ASSERT(m_hFileName != NULL);
  303.         nRet = m_pForeignToRtf(m_hFileName, NULL, m_hBuff, hDesc, hSubset,
  304.             (LPFNOUT)WriteOutStatic);
  305.         // wait for next CConverter::Read to come through
  306.         WaitForBuffer();
  307.         VERIFY(ResetEvent(m_hEventConv));
  308.     }
  309.     else if (!m_bForeignToRtf)
  310.     {
  311.         ASSERT(m_pRtfToForeign != NULL);
  312.         ASSERT(m_hFileName != NULL);
  313.         nRet = m_pRtfToForeign(m_hFileName, NULL, m_hBuff, hDesc,
  314.             (LPFNIN)ReadInStatic);
  315.         // don't need to wait for m_hEventConv
  316.     }
  317.  
  318.     GlobalFree(hDesc);
  319.     GlobalFree(hSubset);
  320.     if (m_pBuf != NULL)
  321.         GlobalUnlock(m_hBuff);
  322.     GlobalFree(m_hBuff);
  323.  
  324.     if (nRet != 0)
  325.         m_bConvErr = TRUE;
  326.  
  327.     m_bDone = TRUE;
  328.     m_nPercent = 100;
  329.     m_nLastPercent = -1;
  330.  
  331.     SetEvent(m_hEventFile);
  332.  
  333.     return (nRet == 0);
  334. }
  335.  
  336. void CConverter::LoadFunctions()
  337. {
  338.     m_pInitConverter = (PINITCONVERTER)GetProcAddress(m_hLibCnv, "InitConverter32");
  339.     m_pIsFormatCorrect = (PISFORMATCORRECT)GetProcAddress(m_hLibCnv, "IsFormatCorrect32");
  340.     m_pForeignToRtf = (PFOREIGNTORTF)GetProcAddress(m_hLibCnv, "ForeignToRtf32");
  341.     m_pRtfToForeign = (PRTFTOFOREIGN)GetProcAddress(m_hLibCnv, "RtfToForeign32");
  342. }
  343. #endif
  344.  
  345. ///////////////////////////////////////////////////////////////////////////////
  346.  
  347. BOOL CConverter::Open(LPCTSTR pszFileName, UINT nOpenFlags,
  348.     CFileException* pException)
  349. {
  350.     USES_CONVERSION;
  351.     // we convert to oem and back because of the following case
  352.     // test(c).txt becomes testc.txt in OEM and stays testc.txt to Ansi
  353.     char buf[_MAX_PATH];
  354.     strcpy(buf, T2CA(pszFileName));
  355.     CharToOemA(buf, buf);
  356.     OemToCharA(buf, buf);
  357.  
  358.     LPTSTR lpszFileNameT = A2T(buf);
  359.  
  360.     // let's make sure we could do what is wanted directly even though we aren't
  361.     m_bCloseOnDelete = FALSE;
  362.     m_hFile = (UINT)hFileNull;
  363.  
  364.     BOOL bOpen = CFile::Open(lpszFileNameT, nOpenFlags, pException);
  365.     CFile::Close();
  366.     if (!bOpen)
  367.         return FALSE;
  368.  
  369.     m_bForeignToRtf = !(nOpenFlags & (CFile::modeReadWrite | CFile::modeWrite));
  370.  
  371.     // check for reading empty file
  372.     if (m_bForeignToRtf)
  373.     {
  374.         CFileStatus stat;
  375.         if (CFile::GetStatus(lpszFileNameT, stat) && stat.m_size == 0)
  376.             return TRUE;
  377.     }
  378.  
  379.     //set security attributes to inherit handle
  380.     SECURITY_ATTRIBUTES sa = {sizeof(SECURITY_ATTRIBUTES), NULL, TRUE};
  381.     //create the events
  382.     m_hEventFile = CreateEvent(&sa, TRUE, FALSE, NULL);
  383.     m_hEventConv = CreateEvent(&sa, TRUE, FALSE, NULL);
  384.     //create the converter thread and create the events
  385.  
  386.     CharToOemA(buf, buf);
  387.     ASSERT(m_hFileName == NULL);
  388.     m_hFileName = StringToHGLOBAL(buf);
  389.  
  390.     m_pThis = this;
  391.     m_bDone = FALSE;
  392.     m_hBuff = GlobalAlloc(GHND, BUFFSIZE);
  393.     ASSERT(m_hBuff != NULL);
  394.  
  395.     AfxBeginThread(ConverterThread, this, THREAD_PRIORITY_NORMAL, 0, 0, &sa);
  396.  
  397.     return TRUE;
  398. }
  399.  
  400. // m_hEventConv -- the main thread signals this event when ready for more data
  401. // m_hEventFile -- the converter signals this event when data is ready
  402.  
  403. UINT CConverter::Read(void FAR* lpBuf, UINT nCount)
  404. {
  405.     ASSERT(m_bForeignToRtf);
  406.     if (m_bDone)
  407.         return 0;
  408.     // if converter is done
  409.     int cch = nCount;
  410.     BYTE* pBuf = (BYTE*)lpBuf;
  411.     while (cch != 0)
  412.     {
  413.         if (m_nBytesAvail == 0)
  414.         {
  415.             if (m_pBuf != NULL)
  416.                 GlobalUnlock(m_hBuff);
  417.             m_pBuf = NULL;
  418.             SetEvent(m_hEventConv);
  419.             WaitForConverter();
  420.             VERIFY(ResetEvent(m_hEventFile));
  421.             if (m_bConvErr)
  422.                 AfxThrowFileException(CFileException::generic);
  423.             if (m_bDone)
  424.                 return nCount - cch;
  425.             m_pBuf = (BYTE*)GlobalLock(m_hBuff);
  426.             ASSERT(m_pBuf != NULL);
  427.         }
  428.         int nBytes = min(cch, m_nBytesAvail);
  429.         memcpy(pBuf, m_pBuf, nBytes);
  430.         pBuf += nBytes;
  431.         m_pBuf += nBytes;
  432.         m_nBytesAvail -= nBytes;
  433.         cch -= nBytes;
  434.         OutputPercent(m_nPercent);
  435.     }
  436.     return nCount - cch;
  437. }
  438.  
  439. void CConverter::Write(const void FAR* lpBuf, UINT nCount)
  440. {
  441.     ASSERT(!m_bForeignToRtf);
  442.  
  443.     m_nBytesWritten += nCount;
  444.     while (nCount != 0)
  445.     {
  446.         WaitForConverter();
  447.         VERIFY(ResetEvent(m_hEventFile));
  448.         if (m_bConvErr)
  449.             AfxThrowFileException(CFileException::generic);
  450.         m_nBytesAvail = min(nCount, BUFFSIZE);
  451.         nCount -= m_nBytesAvail;
  452.         BYTE* pBuf = (BYTE*)GlobalLock(m_hBuff);
  453.         ASSERT(pBuf != NULL);
  454.         memcpy(pBuf, lpBuf, m_nBytesAvail);
  455.         GlobalUnlock(m_hBuff);
  456.         SetEvent(m_hEventConv);
  457.     }
  458.     OutputString(m_strSaving);
  459. }
  460.  
  461. LONG CConverter::Seek(LONG lOff, UINT nFrom)
  462. {
  463.     if (lOff != 0 && nFrom != current)
  464.         AfxThrowNotSupportedException();
  465.     return 0;
  466. }
  467.  
  468. DWORD CConverter::GetPosition() const
  469. {
  470.     return 0;
  471. }
  472.  
  473. void CConverter::Flush()
  474. {
  475. }
  476.  
  477. void CConverter::Close()
  478. {
  479. }
  480.  
  481. void CConverter::Abort()
  482. {
  483. }
  484.  
  485. DWORD CConverter::GetLength() const
  486. {
  487.     ASSERT_VALID(this);
  488.     return 1;
  489. }
  490.  
  491. CFile* CConverter::Duplicate() const
  492. {
  493.     AfxThrowNotSupportedException();
  494.     return NULL;
  495. }
  496.  
  497. void CConverter::LockRange(DWORD, DWORD)
  498. {
  499.     AfxThrowNotSupportedException();
  500. }
  501.  
  502. void CConverter::UnlockRange(DWORD, DWORD)
  503. {
  504.     AfxThrowNotSupportedException();
  505. }
  506.  
  507. void CConverter::SetLength(DWORD)
  508. {
  509.     AfxThrowNotSupportedException();
  510. }
  511.