Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1234 lines
38 KiB

  1. // wordpad.cpp : Defines the class behaviors for the application.
  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. #include "stdafx.h"
  13. #include "wordpad.h"
  14. #include "mainfrm.h"
  15. #include "ipframe.h"
  16. #include "wordpdoc.h"
  17. #include "wordpvw.h"
  18. #include "strings.h"
  19. #include "key.h"
  20. #include "filenewd.h"
  21. #include <locale.h>
  22. #include <winnls.h>
  23. #include <winreg.h>
  24. #include "fixhelp.h"
  25. #include "filedlg.h"
  26. #if _WIN32_IE < 0x400
  27. #undef _WIN32_IE
  28. #define _WIN32_IE 0x0400
  29. #endif
  30. #include <shlobj.h>
  31. #define szRichName L"RICHED20"
  32. #define szNewRichName L"MSFTEDIT.DLL"
  33. extern BOOL AFXAPI AfxFullPath(LPTSTR lpszPathOut, LPCTSTR lpszFileIn);
  34. static BOOL RegisterHelper(LPCTSTR* rglpszRegister, LPCTSTR* rglpszSymbols,
  35. BOOL bReplace);
  36. #ifdef _DEBUG
  37. #undef THIS_FILE
  38. static char BASED_CODE THIS_FILE[] = __FILE__;
  39. #endif
  40. CLIPFORMAT cfEmbeddedObject;
  41. CLIPFORMAT cfRTF;
  42. CLIPFORMAT cfRTO;
  43. int CWordPadApp::m_nOpenMsg = RegisterWindowMessage(_T("WordPadOpenMessage"));
  44. int CWordPadApp::m_nPrinterChangedMsg = RegisterWindowMessage(_T("WordPadPrinterChanged"));
  45. int CWordPadApp::m_nOLEHelpMsg = RegisterWindowMessage(SZOLEUI_MSG_HELP);
  46. CUnit CWordPadApp::m_units[] =
  47. {
  48. // TPU, SmallDiv,MedDiv,LargeDiv,MinMove,szAbbrev, bSpace
  49. CUnit(1440, 180, 720, 1440, 90, IDS_INCH1_ABBREV, FALSE),//"
  50. CUnit(568, 142, 284, 568, 142, IDS_CM_ABBREV, TRUE),//cm's
  51. CUnit(20, 120, 720, 720, 100, IDS_POINT_ABBREV, TRUE),//points
  52. CUnit(240, 240, 1440, 1440, 120, IDS_PICA_ABBREV, TRUE),//picas
  53. CUnit(1440, 180, 720, 1440, 90, IDS_INCH2_ABBREV, FALSE),//in
  54. CUnit(1440, 180, 720, 1440, 90, IDS_INCH3_ABBREV, FALSE),//inch
  55. CUnit(1440, 180, 720, 1440, 90, IDS_INCH4_ABBREV, FALSE),//inches
  56. // Non-localized units
  57. CUnit(1440, 180, 720, 1440, 90, IDS_INCH1_NOLOC, FALSE),//"
  58. CUnit(1440, 180, 720, 1440, 90, IDS_INCH2_NOLOC, FALSE),//in
  59. CUnit(1440, 180, 720, 1440, 90, IDS_INCH3_NOLOC, FALSE),//inch
  60. CUnit(1440, 180, 720, 1440, 90, IDS_INCH4_NOLOC, FALSE),//inches
  61. CUnit(568, 142, 284, 568, 142, IDS_CM_NOLOC, TRUE),//cm's
  62. CUnit(20, 120, 720, 720, 100, IDS_POINT_NOLOC, TRUE),//points
  63. CUnit(240, 240, 1440, 1440, 120, IDS_PICA_NOLOC, TRUE)//picas
  64. };
  65. const int CWordPadApp::m_nPrimaryNumUnits = 4;
  66. const int CWordPadApp::m_nNumUnits = sizeof(m_units) / sizeof(m_units[0]);
  67. /////////////////////////////////////////////////////////////////////////////
  68. // CWordPadApp
  69. BEGIN_MESSAGE_MAP(CWordPadApp, CWinApp)
  70. //{{AFX_MSG_MAP(CWordPadApp)
  71. ON_COMMAND(ID_APP_ABOUT, OnAppAbout)
  72. ON_COMMAND(ID_FILE_NEW, OnFileNew)
  73. ON_COMMAND(ID_FILE_OPEN, OnFileOpen)
  74. //}}AFX_MSG_MAP
  75. END_MESSAGE_MAP()
  76. void CWordPadCommandLineInfo::ParseParam(const char* pszParam,BOOL bFlag,BOOL bLast)
  77. {
  78. if (bFlag)
  79. {
  80. if (lstrcmpA(pszParam, "t") == 0)
  81. {
  82. m_bForceTextMode = TRUE;
  83. return;
  84. }
  85. }
  86. CCommandLineInfo::ParseParam(pszParam, bFlag, bLast);
  87. }
  88. /////////////////////////////////////////////////////////////////////////////
  89. // CWordPadApp construction
  90. CWordPadApp::CWordPadApp()
  91. : m_optionsText(0),
  92. m_optionsRTF(1),
  93. m_optionsWord(2),
  94. m_optionsWrite(2),
  95. m_optionsIP(2),
  96. m_optionsNull(0),
  97. m_initialization_phase(InitializationPending),
  98. m_pInitializationThread(NULL),
  99. m_always_convert_to_rtf(FALSE)
  100. {
  101. // _tsetlocale(LC_ALL, _T(""));
  102. setlocale(LC_ALL, ""); // change made by t-stefb
  103. DWORD dwVersion = ::GetVersion();
  104. m_bWin4 = (BYTE)dwVersion >= 4;
  105. #ifndef _UNICODE
  106. m_bWin31 = (dwVersion > 0x80000000 && !m_bWin4);
  107. #endif
  108. m_nDefFont = (m_bWin4) ? DEFAULT_GUI_FONT : ANSI_VAR_FONT;
  109. m_dcScreen.Attach(::GetDC(NULL));
  110. m_bLargeIcons = m_dcScreen.GetDeviceCaps(LOGPIXELSX) >= 120;
  111. m_bForceOEM = FALSE;
  112. }
  113. CWordPadApp::~CWordPadApp()
  114. {
  115. if (m_atomEnableCTF)
  116. GlobalDeleteAtom(m_atomEnableCTF);
  117. if (m_atomProcessCTF)
  118. GlobalDeleteAtom(m_atomProcessCTF);
  119. if (m_dcScreen.m_hDC != NULL)
  120. ::ReleaseDC(NULL, m_dcScreen.Detach());
  121. delete m_pInitializationThread;
  122. }
  123. /////////////////////////////////////////////////////////////////////////////
  124. // The one and only CWordPadApp object
  125. CWordPadApp theApp;
  126. // Register the application's document templates. Document templates
  127. // serve as the connection between documents, frame windows and views.
  128. static CSingleDocTemplate DocTemplate(
  129. IDR_MAINFRAME,
  130. RUNTIME_CLASS(CWordPadDoc),
  131. RUNTIME_CLASS(CMainFrame), // main SDI frame window
  132. RUNTIME_CLASS(CWordPadView));
  133. // This identifier was generated to be statistically unique for your app.
  134. // You may change it if you prefer to choose a specific identifier.
  135. static const CLSID BASED_CODE clsid =
  136. { 0x73FDDC80L, 0xAEA9, 0x101A, { 0x98, 0xA7, 0x00, 0xAA, 0x00, 0x37, 0x49, 0x59} };
  137. /////////////////////////////////////////////////////////////////////////////
  138. // CWordPadApp initialization
  139. BOOL CWordPadApp::InitInstance()
  140. {
  141. ParseCommandLine(cmdInfo);
  142. if (::FindWindow(szWordPadClass, NULL) && IsDocOpen(cmdInfo.m_strFileName))
  143. return FALSE;
  144. SetRegistryKey(szRegKey);
  145. // The resistry stuff shouldn't be localized so just hardcode it
  146. if (NULL != m_pszProfileName)
  147. free((void *) m_pszProfileName);
  148. m_pszProfileName = _tcsdup(TEXT("Wordpad"));
  149. LoadOptions();
  150. Enable3dControls();
  151. if (!cmdInfo.m_bRunEmbedded)
  152. {
  153. switch (m_nCmdShow)
  154. {
  155. case SW_RESTORE:
  156. case SW_SHOW:
  157. case SW_SHOWDEFAULT:
  158. case SW_SHOWNA:
  159. case SW_SHOWNOACTIVATE:
  160. case SW_SHOWNORMAL:
  161. case SW_SHOWMAXIMIZED:
  162. if (m_bMaximized)
  163. m_nCmdShow = SW_SHOWMAXIMIZED;
  164. break;
  165. }
  166. }
  167. else
  168. {
  169. //Excel 4 will start OLE servers minimized
  170. m_nCmdShow = SW_SHOWNORMAL;
  171. }
  172. int nCmdShow = m_nCmdShow;
  173. LoadAbbrevStrings();
  174. m_pszHelpFilePath = _tcsdup(WORDPAD_HELP_FILE) ;
  175. // Initialize OLE libraries
  176. if (!AfxOleInit())
  177. {
  178. AfxMessageBox(IDP_OLE_INIT_FAILED);
  179. return FALSE;
  180. }
  181. RegisterFormats();
  182. // Initialize RichEdit control
  183. if (LoadLibrary(szNewRichName) == NULL &&
  184. LoadLibrary(szRichName) == NULL)
  185. {
  186. AfxMessageBox(IDS_RICHED_LOAD_FAIL, MB_OK|MB_ICONEXCLAMATION);
  187. return FALSE;
  188. }
  189. // initialize Cicero process ATOMs
  190. m_atomEnableCTF = AddAtom(TF_ENABLE_PROCESS_ATOM);
  191. m_atomProcessCTF = AddAtom(TF_PROCESS_ATOM);
  192. // Standard initialization
  193. // If you are not using these features and wish to reduce the size
  194. // of your final executable, you should remove from the following
  195. // the specific initialization routines you do not need.
  196. LoadStdProfileSettings(); // Load standard INI file options (including MRU)
  197. // Register the application's document templates. Document templates
  198. // serve as the connection between documents, frame windows and views.
  199. DocTemplate.SetContainerInfo(IDR_CNTR_INPLACE);
  200. DocTemplate.SetServerInfo(
  201. IDR_SRVR_EMBEDDED, IDR_SRVR_INPLACE,
  202. RUNTIME_CLASS(CInPlaceFrame));
  203. // Connect the COleTemplateServer to the document template.
  204. // The COleTemplateServer creates new documents on behalf
  205. // of requesting OLE containers by using information
  206. // specified in the document template.
  207. m_server.ConnectTemplate(clsid, &DocTemplate, TRUE);
  208. //
  209. // Setup deferred initialization now so the printer can start
  210. // initializing in case we get a print or printto command at startup
  211. //
  212. m_pInitializationThread = AfxBeginThread(
  213. DoDeferredInitialization,
  214. this,
  215. THREAD_PRIORITY_IDLE,
  216. 0,
  217. CREATE_SUSPENDED);
  218. if (NULL != m_pInitializationThread)
  219. {
  220. m_pInitializationThread->m_bAutoDelete = FALSE;
  221. m_pInitializationThread->ResumeThread();
  222. }
  223. // Check to see if launched as OLE server
  224. if (cmdInfo.m_bRunEmbedded || cmdInfo.m_bRunAutomated)
  225. {
  226. // Register all OLE server (factories) as running. This enables the
  227. // OLE libraries to create objects from other applications.
  228. COleTemplateServer::RegisterAll();
  229. AfxOleSetUserCtrl(FALSE);
  230. // Application was run with /Embedding or /Automation. Don't show the
  231. // main window in this case.
  232. return TRUE;
  233. }
  234. // make sure the main window is showing
  235. m_bPromptForType = FALSE;
  236. OnFileNew();
  237. m_bPromptForType = TRUE;
  238. m_nCmdShow = -1;
  239. if (m_pMainWnd == NULL) // i.e. OnFileNew failed
  240. return FALSE;
  241. TRY
  242. {
  243. if (!cmdInfo.m_strFileName.IsEmpty()) // open an existing document
  244. m_nCmdShow = nCmdShow;
  245. // Dispatch commands specified on the command line
  246. if (cmdInfo.m_nShellCommand != CCommandLineInfo::FileNew &&
  247. !ProcessShellCommand(cmdInfo))
  248. {
  249. return FALSE;
  250. }
  251. }
  252. CATCH(CFileException, e)
  253. {
  254. CString error;
  255. AfxFormatString1(error, AFX_IDP_FAILED_TO_OPEN_DOC, cmdInfo.m_strFileName);
  256. AfxMessageBox(error, MB_ICONEXCLAMATION, AFX_IDP_FAILED_TO_OPEN_DOC);
  257. return FALSE;
  258. }
  259. END_CATCH
  260. // Enable File Manager drag/drop open
  261. m_pMainWnd->DragAcceptFiles();
  262. //
  263. // Set the current directory to "My Documents" so that will be the default
  264. // location for the first save/open
  265. //
  266. TCHAR szDefaultPath[MAX_PATH];
  267. if (SHGetSpecialFolderPath(NULL, szDefaultPath, CSIDL_PERSONAL, FALSE))
  268. SetCurrentDirectory(szDefaultPath);
  269. return TRUE;
  270. }
  271. BOOL CWordPadApp::IsDocOpen(LPCTSTR lpszFileName)
  272. {
  273. if (lpszFileName[0] == NULL)
  274. return FALSE;
  275. TCHAR szPath[_MAX_PATH];
  276. AfxFullPath(szPath, lpszFileName);
  277. ATOM atom = GlobalAddAtom(szPath);
  278. ASSERT(atom != NULL);
  279. if (atom == NULL)
  280. return FALSE;
  281. EnumWindows(StaticEnumProc, (LPARAM)&atom);
  282. if (atom == NULL)
  283. return TRUE;
  284. DeleteAtom(atom);
  285. return FALSE;
  286. }
  287. BOOL CALLBACK CWordPadApp::StaticEnumProc(HWND hWnd, LPARAM lParam)
  288. {
  289. TCHAR szClassName[30];
  290. GetClassName(hWnd, szClassName, 30);
  291. if (lstrcmp(szClassName, szWordPadClass) != 0)
  292. return TRUE;
  293. ATOM* pAtom = (ATOM*)lParam;
  294. ASSERT(pAtom != NULL);
  295. DWORD_PTR dw = 0;
  296. ::SendMessageTimeout(hWnd, m_nOpenMsg, NULL, (LPARAM)*pAtom,
  297. SMTO_ABORTIFHUNG, 500, &dw);
  298. if (dw)
  299. {
  300. ::SetForegroundWindow(hWnd);
  301. DeleteAtom(*pAtom);
  302. *pAtom = NULL;
  303. return FALSE;
  304. }
  305. return TRUE;
  306. }
  307. void CWordPadApp::RegisterFormats()
  308. {
  309. cfEmbeddedObject = (CLIPFORMAT)::RegisterClipboardFormat(_T("Embedded Object"));
  310. cfRTF = (CLIPFORMAT)::RegisterClipboardFormat(CF_RTF);
  311. cfRTO = (CLIPFORMAT)::RegisterClipboardFormat(CF_RETEXTOBJ);
  312. }
  313. CDocOptions& CWordPadApp::GetDocOptions(int nDocType)
  314. {
  315. switch (nDocType)
  316. {
  317. case RD_WINWORD6:
  318. case RD_WORDPAD:
  319. case RD_WORD97:
  320. return m_optionsWord;
  321. case RD_RICHTEXT:
  322. return m_optionsRTF;
  323. case RD_TEXT:
  324. case RD_OEMTEXT:
  325. case RD_UNICODETEXT:
  326. return m_optionsText;
  327. case RD_WRITE:
  328. return m_optionsWrite;
  329. case RD_EMBEDDED:
  330. return m_optionsIP;
  331. }
  332. ASSERT(FALSE);
  333. return m_optionsNull;
  334. }
  335. CDockState& CWordPadApp::GetDockState(int nDocType, BOOL bPrimary)
  336. {
  337. return GetDocOptions(nDocType).GetDockState(bPrimary);
  338. }
  339. void CWordPadApp::SaveOptions()
  340. {
  341. WriteProfileInt(szSection, szWordSel, m_bWordSel);
  342. WriteProfileInt(szSection, szUnits, GetUnits());
  343. WriteProfileInt(szSection, szMaximized, m_bMaximized);
  344. WriteProfileBinary(szSection, szFrameRect, (BYTE*)&m_rectInitialFrame,
  345. sizeof(CRect));
  346. WriteProfileBinary(szSection, szPageMargin, (BYTE*)&m_rectPageMargin,
  347. sizeof(CRect));
  348. m_optionsText.SaveOptions(szTextSection);
  349. m_optionsRTF.SaveOptions(szRTFSection);
  350. m_optionsWord.SaveOptions(szWordSection);
  351. m_optionsWrite.SaveOptions(szWriteSection);
  352. m_optionsIP.SaveOptions(szIPSection);
  353. WriteProfileInt(
  354. szSection,
  355. TEXT("DefaultFormat"),
  356. CWordpadFileDialog::GetDefaultFileType());
  357. if (ShouldAlwaysConvertToRTF())
  358. WriteProfileInt(szSection, TEXT("AlwaysConvertToRTF"), TRUE);
  359. }
  360. void CWordPadApp::SetUnits(int n)
  361. {
  362. RIPMSG(n>=0 && n <m_nPrimaryNumUnits, "CWordPadApp::SetUnits - units out of bounds");
  363. if (n < 0)
  364. {
  365. n = 0;
  366. }
  367. if (n >= m_nPrimaryNumUnits)
  368. {
  369. n = m_nPrimaryNumUnits - 1;
  370. }
  371. m_nUnits = n;
  372. }
  373. void CWordPadApp::LoadOptions()
  374. {
  375. BYTE* pb = NULL;
  376. UINT nLen = 0;
  377. HKEY key;
  378. bool bNewInstall = true;
  379. if (ERROR_SUCCESS == RegOpenKeyEx(GetAppRegistryKey(), szSection, 0, KEY_READ, &key))
  380. {
  381. bNewInstall = false;
  382. RegCloseKey(key);
  383. }
  384. HFONT hFont = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
  385. if (hFont == NULL)
  386. hFont = (HFONT)GetStockObject(ANSI_VAR_FONT);
  387. VERIFY(GetObject(hFont, sizeof(LOGFONT), &m_lf));
  388. m_bWordSel = GetProfileInt(szSection, szWordSel, TRUE);
  389. TCHAR buf[2];
  390. buf[0] = NULL;
  391. GetLocaleInfo(GetUserDefaultLCID(), LOCALE_IMEASURE, buf, 2);
  392. int nDefUnits = buf[0] == _T('1') ? 0 : 1;
  393. SetUnits(GetProfileInt(szSection, szUnits, nDefUnits));
  394. m_bMaximized = GetProfileInt(szSection, szMaximized, (int)FALSE);
  395. if (GetProfileBinary(szSection, szFrameRect, &pb, &nLen))
  396. {
  397. ASSERT(nLen == sizeof(CRect));
  398. memcpy(&m_rectInitialFrame, pb, sizeof(CRect));
  399. delete [] pb;
  400. }
  401. else
  402. m_rectInitialFrame.SetRect(0,0,0,0);
  403. CRect rectScreen(0, 0, GetSystemMetrics(SM_CXSCREEN),
  404. GetSystemMetrics(SM_CYSCREEN));
  405. CRect rectInt;
  406. rectInt.IntersectRect(&rectScreen, &m_rectInitialFrame);
  407. if (rectInt.Width() < 10 || rectInt.Height() < 10)
  408. m_rectInitialFrame.SetRect(0, 0, 0, 0);
  409. if (GetProfileBinary(szSection, szPageMargin, &pb, &nLen))
  410. {
  411. ASSERT(nLen == sizeof(CRect));
  412. memcpy(&m_rectPageMargin, pb, sizeof(CRect));
  413. delete [] pb;
  414. }
  415. else
  416. m_rectPageMargin.SetRect(1800, 1440, 1800, 1440);
  417. //
  418. // Set the default format to RTF for new installs, Word6 (or whatever) was
  419. // perviously selected for upgrades
  420. //
  421. int defformat = RD_NATIVE;
  422. if (!bNewInstall)
  423. defformat = _VerifyDefaultFormat(GetProfileInt(szSection,TEXT("DefaultFormat"), RD_WORDPAD), RD_WORDPAD);
  424. CWordpadFileDialog::SetDefaultFileType(defformat);
  425. if (GetProfileInt(szSection, TEXT("AlwaysConvertToRTF"), FALSE))
  426. SetAlwaysConvertToRTF();
  427. m_nFilterIndex = GetIndexFromType(RD_DEFAULT, TRUE);
  428. m_optionsText.LoadOptions(szTextSection);
  429. m_optionsRTF.LoadOptions(szRTFSection);
  430. m_optionsWord.LoadOptions(szWordSection);
  431. m_optionsWrite.LoadOptions(szWriteSection);
  432. m_optionsIP.LoadOptions(szIPSection);
  433. }
  434. void CWordPadApp::LoadAbbrevStrings()
  435. {
  436. for (int i=0;i<m_nNumUnits;i++)
  437. m_units[i].m_strAbbrev.LoadString(m_units[i].m_nAbbrevID);
  438. }
  439. BOOL CWordPadApp::ParseMeasurement(LPTSTR buf, int& lVal)
  440. {
  441. TCHAR* pch;
  442. if (buf[0] == NULL)
  443. return FALSE;
  444. float f = (float)_tcstod(buf,&pch);
  445. // eat white space, if any
  446. while (_istspace(*pch))
  447. pch++;
  448. if (pch[0] == NULL) // default
  449. {
  450. lVal = (f < 0.f) ? (int)(f*GetTPU()-0.5f) : (int)(f*GetTPU()+0.5f);
  451. return TRUE;
  452. }
  453. for (int i=0;i<m_nNumUnits;i++)
  454. {
  455. if (lstrcmpi(pch, GetAbbrev(i)) == 0)
  456. {
  457. lVal = (f < 0.f) ? (int)(f*GetTPU(i)-0.5f) : (int)(f*GetTPU(i)+0.5f);
  458. return TRUE;
  459. }
  460. }
  461. return FALSE;
  462. }
  463. void CWordPadApp::PrintTwips(WCHAR* buf, int cchBuf, int nValue, int nDec)
  464. {
  465. ASSERT(nDec == 2);
  466. int div = GetTPU();
  467. int lval = nValue;
  468. BOOL bNeg = FALSE;
  469. int* pVal = (int *) alloca((nDec + 1) * sizeof(int));
  470. if (lval < 0)
  471. {
  472. bNeg = TRUE;
  473. lval = -lval;
  474. }
  475. for (int i=0;i<=nDec;i++)
  476. {
  477. pVal[i] = lval/div; //integer number
  478. lval -= pVal[i]*div;
  479. lval *= 10;
  480. }
  481. i--;
  482. if (lval >= div/2)
  483. pVal[i]++;
  484. while ((pVal[i] == 10) && (i != 0))
  485. {
  486. pVal[i] = 0;
  487. pVal[--i]++;
  488. }
  489. while (nDec && pVal[nDec] == 0)
  490. nDec--;
  491. StringCchPrintf(buf, cchBuf, L"%.*f", nDec, (float)nValue/(float)div);
  492. if (m_units[m_nUnits].m_bSpaceAbbrev)
  493. StringCchCat(buf, cchBuf, L" ");
  494. StringCchCat(buf, cchBuf, GetAbbrev());
  495. }
  496. /////////////////////////////////////////////////////////////////////////////
  497. // CWordPadApp commands
  498. void CWordPadApp::OnAppAbout()
  499. {
  500. CString strTitle;
  501. VERIFY(strTitle.LoadString(AFX_IDS_APP_TITLE));
  502. ShellAbout(m_pMainWnd->GetSafeHwnd(), strTitle, _T(""), LoadIcon(IDR_MAINFRAME));
  503. }
  504. int CWordPadApp::ExitInstance()
  505. {
  506. FreeLibrary(GetModuleHandle(szRichName));
  507. HMODULE hMod = GetModuleHandle(szNewRichName);
  508. if (hMod)
  509. FreeLibrary(hMod);
  510. SaveOptions();
  511. return CWinApp::ExitInstance();
  512. }
  513. void CWordPadApp::OnFileNew()
  514. {
  515. int nDocType = -1;
  516. if (!m_bPromptForType)
  517. {
  518. if (cmdInfo.m_bForceTextMode)
  519. nDocType = RD_TEXT;
  520. else if (!cmdInfo.m_strFileName.IsEmpty())
  521. {
  522. CFileException fe;
  523. nDocType = GetDocTypeFromName(cmdInfo.m_strFileName, fe);
  524. if (DocTypeDisabled(nDocType))
  525. {
  526. nDocType = RD_DEFAULT;
  527. }
  528. }
  529. if (nDocType == -1)
  530. nDocType = RD_DEFAULT;
  531. }
  532. else
  533. {
  534. CFileNewDialog dlg;
  535. if (dlg.DoModal() == IDCANCEL)
  536. return;
  537. nDocType = (dlg.m_nSel == 1) ? RD_TEXT :
  538. (dlg.m_nSel == 2) ? RD_UNICODETEXT :
  539. RD_RICHTEXT;
  540. if (nDocType != RD_TEXT)
  541. cmdInfo.m_bForceTextMode = FALSE;
  542. }
  543. m_nNewDocType = nDocType;
  544. DocTemplate.OpenDocumentFile(NULL);
  545. // if returns NULL, the user has already been alerted
  546. }
  547. // prompt for file name - used for open and save as
  548. // static function called from app
  549. BOOL CWordPadApp::PromptForFileName(CString& fileName, UINT nIDSTitle,
  550. DWORD dwFlags, BOOL bOpenFileDialog, int* pType)
  551. {
  552. ScanForConverters();
  553. CWordpadFileDialog dlgFile(bOpenFileDialog);
  554. CString title;
  555. VERIFY(title.LoadString(nIDSTitle));
  556. dlgFile.m_ofn.Flags |= dwFlags;
  557. int nIndex = m_nFilterIndex;
  558. if (!bOpenFileDialog)
  559. {
  560. int nDocType = (pType != NULL) ? *pType : RD_DEFAULT;
  561. nIndex = GetIndexFromType(nDocType, bOpenFileDialog);
  562. if (nIndex == -1)
  563. nIndex = GetIndexFromType(RD_DEFAULT, bOpenFileDialog);
  564. if (nIndex == -1)
  565. nIndex = GetIndexFromType(RD_NATIVE, bOpenFileDialog);
  566. ASSERT(nIndex != -1);
  567. nIndex++;
  568. }
  569. dlgFile.m_ofn.nFilterIndex = nIndex;
  570. // strDefExt is necessary to hold onto the memory from GetExtFromType
  571. CString strDefExt = GetExtFromType(GetTypeFromIndex(nIndex-1, bOpenFileDialog));
  572. //
  573. // The open file dialog doesn't want the extension to start with '.' but
  574. // thats how GetExtFromType gives it to us.
  575. //
  576. dlgFile.m_ofn.lpstrDefExt = strDefExt;
  577. ASSERT(TEXT('.') == *dlgFile.m_ofn.lpstrDefExt);
  578. ++dlgFile.m_ofn.lpstrDefExt;
  579. CString strFilter = GetFileTypes(bOpenFileDialog);
  580. dlgFile.m_ofn.lpstrFilter = strFilter;
  581. dlgFile.m_ofn.lpstrTitle = title;
  582. dlgFile.m_ofn.lpstrFile = fileName.GetBuffer(_MAX_PATH);
  583. BOOL bRet;
  584. int namelen;
  585. do
  586. {
  587. bRet = (dlgFile.DoModal() == IDOK) ? TRUE : FALSE;
  588. if (!bRet)
  589. break;
  590. // The converters only speak ansi so make sure the filename isn't to
  591. // long for DBCS.
  592. namelen = WideCharToMultiByte(CP_ACP, 0, fileName, -1, NULL, 0,NULL,NULL);
  593. if (namelen > MAX_PATH - 2)
  594. {
  595. CString message;
  596. AfxFormatString1(message, IDS_FILENAME_TO_LONG, fileName);
  597. AfxMessageBox(message);
  598. }
  599. }
  600. while (namelen > MAX_PATH - 2);
  601. fileName.ReleaseBuffer();
  602. if (bRet)
  603. {
  604. if (bOpenFileDialog)
  605. m_nFilterIndex = dlgFile.m_ofn.nFilterIndex;
  606. if (pType != NULL)
  607. {
  608. int nIndex = (int)dlgFile.m_ofn.nFilterIndex - 1;
  609. ASSERT(nIndex >= 0);
  610. *pType = GetTypeFromIndex(nIndex, bOpenFileDialog);
  611. }
  612. }
  613. return bRet;
  614. }
  615. void CWordPadApp::OnFileOpen()
  616. {
  617. // prompt the user (with all document templates)
  618. CString newName;
  619. int nType = RD_DEFAULT;
  620. if (!PromptForFileName(newName, AFX_IDS_OPENFILE,
  621. OFN_HIDEREADONLY | OFN_FILEMUSTEXIST, TRUE, &nType))
  622. return; // open cancelled
  623. if (nType == RD_OEMTEXT)
  624. m_bForceOEM = TRUE;
  625. OpenDocumentFile(newName);
  626. m_bForceOEM = FALSE;
  627. // if returns NULL, the user has already been alerted
  628. }
  629. BOOL CWordPadApp::OnDDECommand(LPTSTR /*lpszCommand*/)
  630. {
  631. return FALSE;
  632. }
  633. /////////////////////////////////////////////////////////////////////////////
  634. // DDE and ShellExecute support
  635. //HKEY_CLASSES_ROOT\.RTF = rtffile
  636. //HKEY_CLASSES_ROOT\rtffile =
  637. //HKEY_CLASSES_ROOT\rtffile\CLSID = {73FDDC80-AEA9-101A-98A7-00AA00374959}
  638. //HKEY_CLASSES_ROOT\rtffile\protocol\StdFileEditing\server = WORDPAD.EXE
  639. //HKEY_CLASSES_ROOT\rtffile\protocol\StdFileEditing\verb\0 = &Edit
  640. //HKEY_CLASSES_ROOT\rtffile\shell\open\command = WORDPAD.EXE %1
  641. //HKEY_CLASSES_ROOT\rtffile\shell\print\command = WORDPAD.EXE /p %1
  642. #define REGENTRY(key, value) _T(key) _T("\0\0") _T(value)
  643. #define REGENTRYX(key, valuename, value) _T(key) _T("\0") _T(valuename) _T("\0") _T(value)
  644. static const TCHAR sz00[] = REGENTRY("%2", "%5");
  645. static const TCHAR sz01[] = REGENTRY("%2\\CLSID", "%1");
  646. static const TCHAR sz02[] = REGENTRY("%2\\Insertable", "");
  647. static const TCHAR sz03[] = REGENTRY("%2\\protocol\\StdFileEditing\\verb\\0", "&Edit");
  648. static const TCHAR sz04[] = REGENTRY("%2\\protocol\\StdFileEditing\\server", "%3");
  649. static const TCHAR sz05[] = REGENTRY("CLSID\\%1", "%5");
  650. static const TCHAR sz06[] = REGENTRY("CLSID\\%1\\ProgID", "%2");
  651. static const TCHAR sz07[] = REGENTRY("CLSID\\%1\\InprocHandler32", "ole32.dll");
  652. static const TCHAR sz08[] = REGENTRY("CLSID\\%1\\LocalServer32", "%3");
  653. static const TCHAR sz09[] = REGENTRY("CLSID\\%1\\Verb\\0", "&Edit,0,2");
  654. static const TCHAR sz10[] = REGENTRY("CLSID\\%1\\Verb\\1", "&Open,0,2");
  655. static const TCHAR sz11[] = REGENTRY("CLSID\\%1\\Insertable", "");
  656. static const TCHAR sz12[] = REGENTRY("CLSID\\%1\\AuxUserType\\2", "%4");
  657. static const TCHAR sz13[] = REGENTRY("CLSID\\%1\\AuxUserType\\3", "%6");
  658. static const TCHAR sz14[] = REGENTRY("CLSID\\%1\\DefaultIcon", "%3,1");
  659. static const TCHAR sz15[] = REGENTRY("CLSID\\%1\\MiscStatus", "0");
  660. static const TCHAR sz16[] = REGENTRY("%2\\shell\\open\\command", "%3 \"%%1\"");
  661. static const TCHAR sz17[] = REGENTRY("%2\\shell\\print\\command", "%3 /p \"%%1\"");
  662. static const TCHAR sz18[] = REGENTRY("%7", "%2");
  663. static const TCHAR sz19[] = REGENTRY("%2", ""); // like sz00 only no long type name
  664. static const TCHAR sz20[] = REGENTRY("%2\\shell\\printto\\command", "%3 /pt \"%%1\" \"%%2\" \"%%3\" \"%%4\"");
  665. static const TCHAR sz21[] = REGENTRY("%2\\DefaultIcon", "%3,%8");
  666. static const TCHAR sz22[] = REGENTRYX("%7\\ShellNew", "NullFile", "true");
  667. static const TCHAR sz23[] = REGENTRYX("%7\\ShellNew", "Data", "{\\rtf1}");
  668. // %1 - class ID
  669. // %2 - class name WordPad.Document.1
  670. // %3 - SFN executable path C:\PROGRA~1\ACCESS~1\WORDPAD.EXE
  671. // %4 - short type name Document
  672. // %5 - long type name Microsoft WordPad Document
  673. // %6 - long application name Microsoft WordPad
  674. // %7 = extension .rtf
  675. // %8 = default icon 0,1,2,3
  676. #define NUM_REG_ARGS 8
  677. static const LPCTSTR rglpszWordPadRegister[] =
  678. {sz00, sz02, sz03, sz05, sz09, sz10, sz11, sz15, NULL};
  679. static const LPCTSTR rglpszWordPadOverwrite[] =
  680. {sz01, sz04, sz06, sz07, sz08, sz12, sz13, sz14, sz16, sz17, sz20, NULL};
  681. //static const LPCTSTR rglpszExtRegister[] =
  682. //{sz00, sz18, NULL};
  683. //static const LPCTSTR rglpszExtOverwrite[] =
  684. //{sz01, sz16, sz17, sz21, NULL};
  685. static const LPCTSTR rglpszWriExtRegister[] =
  686. {sz18, NULL};
  687. static const LPCTSTR rglpszWriRegister[] =
  688. {sz00, sz01, sz16, sz17, sz20, sz21, NULL};
  689. static const LPCTSTR rglpszRtfExtRegister[] =
  690. {sz18, sz23, NULL};
  691. static const LPCTSTR rglpszRtfRegister[] =
  692. {sz00, sz01, sz16, sz17, sz20, sz21, NULL};
  693. static const LPCTSTR rglpszTxtExtRegister[] =
  694. {sz18, sz22, NULL};
  695. static const LPCTSTR rglpszTxtRegister[] =
  696. {sz00, sz01, sz16, sz17, sz20, sz21, NULL};
  697. static const LPCTSTR rglpszDocExtRegister[] =
  698. {sz18, sz22, NULL};
  699. static const LPCTSTR rglpszDocRegister[] =
  700. {sz00, sz01, sz16, sz17, sz20, sz21, NULL};
  701. static void RegisterExt(LPCTSTR lpszExt, LPCTSTR lpszProgID, UINT nIDTypeName,
  702. LPCTSTR* rglpszSymbols, LPCTSTR* rglpszExtRegister,
  703. LPCTSTR* rglpszRegister, int nIcon)
  704. {
  705. // don't overwrite anything with the extensions
  706. CString strWhole;
  707. VERIFY(strWhole.LoadString(nIDTypeName));
  708. CString str;
  709. AfxExtractSubString(str, strWhole, DOCTYPE_PROGID);
  710. rglpszSymbols[1] = lpszProgID;
  711. rglpszSymbols[4] = str;
  712. rglpszSymbols[6] = lpszExt;
  713. WCHAR buf[12];
  714. EVAL(SUCCEEDED(StringCchPrintf(buf, ARRAYSIZE(buf), L"%d", nIcon))); // Can never fail
  715. rglpszSymbols[7] = buf;
  716. // check for .ext and progid
  717. CKey key;
  718. if (!key.Open(HKEY_CLASSES_ROOT, lpszExt, KEY_READ)) // .ext doesn't exist
  719. RegisterHelper(rglpszExtRegister, rglpszSymbols, TRUE);
  720. key.Close();
  721. if (!key.Open(HKEY_CLASSES_ROOT, lpszProgID, KEY_READ)) // ProgID doesn't exist (i.e. txtfile)
  722. RegisterHelper(rglpszRegister, rglpszSymbols, TRUE);
  723. }
  724. void CWordPadApp::UpdateRegistry()
  725. {
  726. // If stuff is already initialized, don't overwrite it
  727. HKEY rtfkey;
  728. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CLASSES_ROOT, TEXT(".rtf"), 0, KEY_READ, &rtfkey))
  729. {
  730. // .rtf is already registered, assume the rest are as well
  731. RegCloseKey(rtfkey);
  732. return;
  733. }
  734. USES_CONVERSION;
  735. LPOLESTR lpszClassID = NULL;
  736. CDocTemplate* pDocTemplate = &DocTemplate;
  737. // get registration info from doc template string
  738. CString strServerName;
  739. CString strLocalServerName;
  740. CString strLocalShortName;
  741. if (!pDocTemplate->GetDocString(strServerName,
  742. CDocTemplate::regFileTypeId) || strServerName.IsEmpty())
  743. {
  744. TRACE0("Error: not enough information in DocTemplate to register OLE server.\n");
  745. return;
  746. }
  747. if (!pDocTemplate->GetDocString(strLocalServerName,
  748. CDocTemplate::regFileTypeName))
  749. strLocalServerName = strServerName; // use non-localized name
  750. if (!pDocTemplate->GetDocString(strLocalShortName,
  751. CDocTemplate::fileNewName))
  752. strLocalShortName = strLocalServerName; // use long name
  753. ASSERT(strServerName.Find(' ') == -1); // no spaces allowed
  754. ::StringFromCLSID(clsid, &lpszClassID);
  755. ASSERT (lpszClassID != NULL);
  756. // get path name to server
  757. TCHAR szLongPathName[_MAX_PATH];
  758. TCHAR szShortPathName[_MAX_PATH];
  759. ::GetModuleFileName(AfxGetInstanceHandle(), szLongPathName, _MAX_PATH);
  760. ::GetShortPathName(szLongPathName, szShortPathName, _MAX_PATH);
  761. LPCTSTR rglpszSymbols[NUM_REG_ARGS];
  762. rglpszSymbols[0] = OLE2CT(lpszClassID);
  763. rglpszSymbols[1] = strServerName;
  764. rglpszSymbols[2] = szShortPathName;
  765. rglpszSymbols[3] = strLocalShortName;
  766. rglpszSymbols[4] = strLocalServerName;
  767. rglpszSymbols[5] = m_pszAppName; // will usually be long, readable name
  768. rglpszSymbols[6] = NULL;
  769. if (RegisterHelper((LPCTSTR*)rglpszWordPadRegister, rglpszSymbols, FALSE))
  770. RegisterHelper((LPCTSTR*)rglpszWordPadOverwrite, rglpszSymbols, TRUE);
  771. // RegisterExt(_T(".txt"), _T("txtfile"), IDS_TEXT_DOC, rglpszSymbols,
  772. // (LPCTSTR*)rglpszTxtExtRegister, (LPCTSTR*)rglpszTxtRegister, 3);
  773. RegisterExt(_T(".rtf"), _T("rtffile"), IDS_RICHTEXT_DOC, rglpszSymbols,
  774. (LPCTSTR*)rglpszRtfExtRegister, (LPCTSTR*)rglpszRtfRegister, 1);
  775. RegisterExt(_T(".wri"), _T("wrifile"), IDS_WRITE_DOC, rglpszSymbols,
  776. (LPCTSTR*)rglpszWriExtRegister, (LPCTSTR*)rglpszWriRegister, 2);
  777. RegisterExt(_T(".doc"), _T("WordPad.Document.1"), IDS_WINWORD6_DOC, rglpszSymbols,
  778. (LPCTSTR*)rglpszDocExtRegister, (LPCTSTR*)rglpszDocRegister, 1);
  779. // free memory for class ID
  780. ASSERT(lpszClassID != NULL);
  781. CoTaskMemFree(lpszClassID);
  782. }
  783. BOOL RegisterHelper(LPCTSTR* rglpszRegister, LPCTSTR* rglpszSymbols,
  784. BOOL bReplace)
  785. {
  786. ASSERT(rglpszRegister != NULL);
  787. ASSERT(rglpszSymbols != NULL);
  788. WCHAR szKey[256];
  789. WCHAR szValue[256];
  790. LPCTSTR pszValueName;
  791. BOOL bResult = TRUE;
  792. while (*rglpszRegister != NULL)
  793. {
  794. LPCTSTR lpszKey = *rglpszRegister++;
  795. if (*lpszKey == '\0')
  796. continue;
  797. LPCTSTR lpszValueName = lpszKey + lstrlen(lpszKey) + 1;
  798. LPCTSTR lpszValue = lpszValueName + lstrlen(lpszValueName) + 1;
  799. DWORD dwRes;
  800. // lpszKey is a safe format string - see REGENTRY
  801. dwRes = FormatMessage(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY,
  802. lpszKey, NULL, NULL, szKey, ARRAYSIZE(szKey), (va_list*)rglpszSymbols);
  803. if (dwRes == 0)
  804. continue;
  805. pszValueName = lpszValueName;
  806. // lpszValue is safe format string - see REGENTRY
  807. dwRes = FormatMessage(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY,
  808. lpszValue, NULL, NULL, szValue, ARRAYSIZE(szValue), (va_list*)rglpszSymbols);
  809. if (dwRes == 0)
  810. continue;
  811. if (!szKey[0])
  812. {
  813. TRACE1("Warning: skipping empty key '%s'.\n", lpszKey);
  814. continue;
  815. }
  816. CKey key;
  817. VERIFY(key.Create(HKEY_CLASSES_ROOT, szKey, KEY_ALL_ACCESS));
  818. if (!bReplace)
  819. {
  820. CString str;
  821. if (key.GetStringValue(str, pszValueName) && !str.IsEmpty())
  822. continue;
  823. }
  824. if (!key.SetStringValue(szValue, pszValueName))
  825. {
  826. TRACE2("Error: failed setting key '%s' to value '%s'.\n", szKey, szValue);
  827. bResult = FALSE;
  828. break;
  829. }
  830. }
  831. return bResult;
  832. }
  833. void CWordPadApp::WinHelp(DWORD dwData, UINT nCmd)
  834. {
  835. if (g_fDisableStandardHelp)
  836. {
  837. return ;
  838. }
  839. if ( (nCmd == HELP_FINDER) || (nCmd == HELP_CONTENTS) || (nCmd == HELP_INDEX) )
  840. {
  841. ::HtmlHelpA( ::GetDesktopWindow(), "wordpad.chm", HH_DISPLAY_TOPIC, 0L );
  842. return;
  843. }
  844. CWinApp::WinHelp(dwData, nCmd);
  845. }
  846. BOOL CWordPadApp::PreTranslateMessage(MSG* pMsg)
  847. {
  848. if (pMsg->message == WM_PAINT)
  849. return FALSE;
  850. // CWinApp::PreTranslateMessage does nothing but call base
  851. return CWinThread::PreTranslateMessage(pMsg);
  852. }
  853. void CWordPadApp::NotifyPrinterChanged(BOOL bUpdatePrinterSelection)
  854. {
  855. if (bUpdatePrinterSelection)
  856. UpdatePrinterSelection(TRUE);
  857. POSITION pos = m_listPrinterNotify.GetHeadPosition();
  858. while (pos != NULL)
  859. {
  860. HWND hWnd = m_listPrinterNotify.GetNext(pos);
  861. ::SendMessage(hWnd, m_nPrinterChangedMsg, 0, 0);
  862. }
  863. }
  864. BOOL CWordPadApp::IsIdleMessage(MSG* pMsg)
  865. {
  866. if (pMsg->message == WM_MOUSEMOVE || pMsg->message == WM_NCMOUSEMOVE)
  867. return FALSE;
  868. return CWinApp::IsIdleMessage(pMsg);
  869. }
  870. #define DN_PADDINGCHARS 16
  871. HGLOBAL CWordPadApp::CreateDevNames()
  872. {
  873. HGLOBAL hDev = NULL;
  874. CString strDriverName;
  875. CString strPrinterName;
  876. CString strPortName;
  877. if (!cmdInfo.m_strPrinterName.IsEmpty())
  878. {
  879. strDriverName = cmdInfo.m_strDriverName;
  880. strPrinterName = cmdInfo.m_strPrinterName;
  881. strPortName = cmdInfo.m_strPortName;
  882. }
  883. else
  884. {
  885. PRINTDLG printdlg;
  886. DEVNAMES *devnames;
  887. if (!GetPrinterDeviceDefaults(&printdlg))
  888. return NULL;
  889. devnames = (DEVNAMES *) ::GlobalLock(printdlg.hDevNames);
  890. if (NULL == devnames)
  891. return NULL;
  892. strDriverName = (LPTSTR) ((BYTE *) devnames) + devnames->wDriverOffset;
  893. strPrinterName = (LPTSTR) ((BYTE *) devnames) + devnames->wDeviceOffset;
  894. strPortName = (LPTSTR) ((BYTE *) devnames) + devnames->wOutputOffset;
  895. ::GlobalUnlock(printdlg.hDevNames);
  896. }
  897. DWORD cbDevNames ;
  898. int cchDriverName = strDriverName.GetLength() + 1;
  899. int cchPrinterName = strPrinterName.GetLength() + 1;
  900. int cchPortName = strPortName.GetLength() + 1;
  901. cbDevNames = cchDriverName + cchPrinterName + cchPortName + DN_PADDINGCHARS ;
  902. cbDevNames *= sizeof(TCHAR) ;
  903. cbDevNames += sizeof(DEVNAMES) ;
  904. hDev = GlobalAlloc(GPTR, cbDevNames) ;
  905. if (NULL == hDev)
  906. return NULL;
  907. LPDEVNAMES lpDev = (LPDEVNAMES)GlobalLock(hDev) ;
  908. // Sufficient memory was allocated for these strcpy's above.
  909. lpDev->wDriverOffset = sizeof(DEVNAMES) / sizeof(TCHAR) ;
  910. StringCchCopy((LPTSTR) lpDev + lpDev->wDriverOffset, cchDriverName, strDriverName) ;
  911. lpDev->wDeviceOffset = (WORD) (lpDev->wDriverOffset
  912. + strDriverName.GetLength() + 1);
  913. StringCchCopy((LPTSTR) lpDev + lpDev->wDeviceOffset, cchPrinterName, strPrinterName) ;
  914. lpDev->wOutputOffset = (WORD) (lpDev->wDeviceOffset
  915. + strPrinterName.GetLength() + 1);
  916. StringCchCopy((LPTSTR) lpDev + lpDev->wOutputOffset, cchPortName, strPortName) ;
  917. lpDev->wDefault = 0;
  918. return hDev;
  919. }
  920. //+---------------------------------------------------------------------------
  921. //
  922. // Method: CWordPadApp::DoDeferredInitialization, static
  923. //
  924. // Synopsis: Thread entry point for low priority initialization
  925. //
  926. // Parameters: [pvWordPadApp] -- Pointer to to CWordPadApp
  927. //
  928. // Returns: Thread exit code
  929. //
  930. //---------------------------------------------------------------------------
  931. UINT AFX_CDECL CWordPadApp::DoDeferredInitialization(LPVOID pvWordPadApp)
  932. {
  933. ASSERT(NULL != pvWordPadApp);
  934. CWordPadApp *pWordPadApp = (CWordPadApp *) pvWordPadApp;
  935. pWordPadApp->m_initialization_phase = InitializingPrinter;
  936. pWordPadApp->m_hDevNames = pWordPadApp->CreateDevNames();
  937. pWordPadApp->m_initialization_phase = UpdatingPrinterRelatedUI;
  938. pWordPadApp->NotifyPrinterChanged( ((pWordPadApp->m_hDevNames) == NULL) );
  939. pWordPadApp->m_initialization_phase = UpdatingRegistry;
  940. pWordPadApp->UpdateRegistry();
  941. pWordPadApp->m_initialization_phase = InitializationComplete;
  942. return 0;
  943. }
  944. //+--------------------------------------------------------------------------
  945. //
  946. // Method: CWordPadApp::EnsurePrinterIsInitialized
  947. //
  948. // Synopsis: Make sure the printer is done initializing
  949. //
  950. // Parameters: None
  951. //
  952. // Returns: void
  953. //
  954. // Notes: We'll only wait two minutes. If the printer takes that long
  955. // to initialize printing probably is going to be flakey anyway.
  956. //
  957. // The main purpose of doing printer initialization on a different
  958. // thread is so that it doesn't get in the way of doing real work.
  959. // On the other hand if printing is the real work we should try to
  960. // get things moving so bump it up from idle priority.
  961. //
  962. //---------------------------------------------------------------------------
  963. void CWordPadApp::EnsurePrinterIsInitialized()
  964. {
  965. int nWaits = 0;
  966. BOOL bBumpedPriority = FALSE;
  967. if (NULL == m_pInitializationThread)
  968. {
  969. ASSERT(NULL != m_pInitializationThread);
  970. bBumpedPriority = TRUE;
  971. }
  972. while (m_initialization_phase <= InitializingPrinter && nWaits < 1200)
  973. {
  974. if (!bBumpedPriority)
  975. {
  976. m_pInitializationThread->SetThreadPriority(
  977. THREAD_PRIORITY_ABOVE_NORMAL);
  978. bBumpedPriority = TRUE;
  979. }
  980. Sleep(100);
  981. ++nWaits;
  982. }
  983. if (bBumpedPriority)
  984. m_pInitializationThread->SetThreadPriority(THREAD_PRIORITY_IDLE);
  985. }
  986. // Free with delete []
  987. LPSTR WideToAnsiNewArray(LPCWSTR pwsz)
  988. {
  989. LPSTR psz = NULL;
  990. int cbBuf = WideCharToMultiByte(CP_ACP, 0, pwsz, -1, NULL, 0, NULL, NULL);
  991. if (cbBuf)
  992. {
  993. psz = new char[cbBuf];
  994. if (psz)
  995. {
  996. cbBuf = WideCharToMultiByte(CP_ACP, 0, pwsz, -1, psz, cbBuf, NULL, NULL);
  997. if (!cbBuf)
  998. {
  999. // Conversion failed?
  1000. delete [] psz;
  1001. psz = NULL;
  1002. }
  1003. }
  1004. }
  1005. return psz;
  1006. }
  1007. // Free with delete []
  1008. LPWSTR AnsiToWideNewArray(LPCSTR psz)
  1009. {
  1010. LPWSTR pwsz = NULL;
  1011. int cchBuf = MultiByteToWideChar(CP_ACP, 0, psz, -1, NULL, 0);
  1012. if (cchBuf)
  1013. {
  1014. pwsz = new WCHAR[cchBuf];
  1015. if (pwsz)
  1016. {
  1017. cchBuf = MultiByteToWideChar(CP_ACP, 0, psz, -1, pwsz, cchBuf);
  1018. if (!cchBuf)
  1019. {
  1020. // Conversion failed?
  1021. delete [] pwsz;
  1022. pwsz = NULL;
  1023. }
  1024. }
  1025. }
  1026. return pwsz;
  1027. }