MULTCONV.CPP
上传用户:aakk678
上传日期:2022-07-09
资源大小:406k
文件大小:12k
源码类别:

界面编程

开发平台:

Visual C++

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