home *** CD-ROM | disk | FTP | other *** search
/ QBasic & Borland Pascal & C / Delphi5.iso / C / BC_502 / WORDPAD.PAK / MULTCONV.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1997-05-06  |  11.6 KB  |  511 lines

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