docmgr.cpp 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998
  1. // This is a part of the Microsoft Foundation Classes C++ library.
  2. // Copyright (C) 1992-1998 Microsoft Corporation
  3. // All rights reserved.
  4. //
  5. // This source code is only intended as a supplement to the
  6. // Microsoft Foundation Classes Reference and related
  7. // electronic documentation provided with the library.
  8. // See these sources for detailed information regarding the
  9. // Microsoft Foundation Classes product.
  10. #include "stdafx.h"
  11. #ifdef AFX_INIT_SEG
  12. #pragma code_seg(AFX_INIT_SEG)
  13. #endif
  14. #ifdef _DEBUG
  15. #undef THIS_FILE
  16. static char THIS_FILE[] = __FILE__;
  17. #endif
  18. AFX_STATIC_DATA const TCHAR _afxShellOpenFmt[] = _T("%s\\shell\\open\\%s");
  19. AFX_STATIC_DATA const TCHAR _afxShellPrintFmt[] = _T("%s\\shell\\print\\%s");
  20. AFX_STATIC_DATA const TCHAR _afxShellPrintToFmt[] = _T("%s\\shell\\printto\\%s");
  21. AFX_STATIC_DATA const TCHAR _afxDefaultIconFmt[] = _T("%s\\DefaultIcon");
  22. AFX_STATIC_DATA const TCHAR _afxShellNewFmt[] = _T("%s\\ShellNew");
  23. #define DEFAULT_ICON_INDEX 0
  24. AFX_STATIC_DATA const TCHAR _afxIconIndexFmt[] = _T(",%d");
  25. AFX_STATIC_DATA const TCHAR _afxCommand[] = _T("command");
  26. AFX_STATIC_DATA const TCHAR _afxOpenArg[] = _T(" \"%1\"");
  27. AFX_STATIC_DATA const TCHAR _afxPrintArg[] = _T(" /p \"%1\"");
  28. AFX_STATIC_DATA const TCHAR _afxPrintToArg[] = _T(" /pt \"%1\" \"%2\" \"%3\" \"%4\"");
  29. AFX_STATIC_DATA const TCHAR _afxDDEArg[] = _T(" /dde");
  30. AFX_STATIC_DATA const TCHAR _afxDDEExec[] = _T("ddeexec");
  31. AFX_STATIC_DATA const TCHAR _afxDDEOpen[] = _T("[open(\"%1\")]");
  32. AFX_STATIC_DATA const TCHAR _afxDDEPrint[] = _T("[print(\"%1\")]");
  33. AFX_STATIC_DATA const TCHAR _afxDDEPrintTo[] = _T("[printto(\"%1\",\"%2\",\"%3\",\"%4\")]");
  34. AFX_STATIC_DATA const TCHAR _afxShellNewValueName[] = _T("NullFile");
  35. AFX_STATIC_DATA const TCHAR _afxShellNewValue[] = _T("");
  36. // recursively remove a registry key if and only if it has no subkeys
  37. BOOL AFXAPI _AfxDeleteRegKey(LPCTSTR lpszKey)
  38. {
  39. // copy the string
  40. LPTSTR lpszKeyCopy = _tcsdup(lpszKey);
  41. LPTSTR lpszLast = lpszKeyCopy + lstrlen(lpszKeyCopy);
  42. // work until the end of the string
  43. while (lpszLast != NULL)
  44. {
  45. *lpszLast = '\0';
  46. lpszLast = _tcsdec(lpszKeyCopy, lpszLast);
  47. // try to open that key
  48. HKEY hKey;
  49. if (::RegOpenKey(HKEY_CLASSES_ROOT, lpszKeyCopy, &hKey) != ERROR_SUCCESS)
  50. break;
  51. // enumerate the keys underneath
  52. TCHAR szScrap[_MAX_PATH+1];
  53. DWORD dwLen = _countof(szScrap);
  54. BOOL bItExists = FALSE;
  55. if (::RegEnumKey(hKey, 0, szScrap, dwLen) == ERROR_SUCCESS)
  56. bItExists = TRUE;
  57. ::RegCloseKey(hKey);
  58. // found one? quit looping
  59. if (bItExists)
  60. break;
  61. // otherwise, delete and find the previous backwhack
  62. ::RegDeleteKey(HKEY_CLASSES_ROOT, lpszKeyCopy);
  63. lpszLast = _tcsrchr(lpszKeyCopy, '\\');
  64. }
  65. // release the string and return
  66. free(lpszKeyCopy);
  67. return TRUE;
  68. }
  69. AFX_STATIC BOOL AFXAPI
  70. _AfxSetRegKey(LPCTSTR lpszKey, LPCTSTR lpszValue, LPCTSTR lpszValueName = NULL)
  71. {
  72. if (lpszValueName == NULL)
  73. {
  74. if (::RegSetValue(HKEY_CLASSES_ROOT, lpszKey, REG_SZ,
  75. lpszValue, lstrlen(lpszValue) * sizeof(TCHAR)) != ERROR_SUCCESS)
  76. {
  77. TRACE1("Warning: registration database update failed for key '%s'.\n",
  78. lpszKey);
  79. return FALSE;
  80. }
  81. return TRUE;
  82. }
  83. else
  84. {
  85. HKEY hKey;
  86. if(::RegCreateKey(HKEY_CLASSES_ROOT, lpszKey, &hKey) == ERROR_SUCCESS)
  87. {
  88. LONG lResult = ::RegSetValueEx(hKey, lpszValueName, 0, REG_SZ,
  89. (CONST BYTE*)lpszValue, (lstrlen(lpszValue) + 1) * sizeof(TCHAR));
  90. if(::RegCloseKey(hKey) == ERROR_SUCCESS && lResult == ERROR_SUCCESS)
  91. return TRUE;
  92. }
  93. TRACE1("Warning: registration database update failed for key '%s'.\n", lpszKey);
  94. return FALSE;
  95. }
  96. }
  97. CDocManager::CDocManager()
  98. {
  99. }
  100. void CDocManager::UnregisterShellFileTypes()
  101. {
  102. ASSERT(!m_templateList.IsEmpty()); // must have some doc templates
  103. CString strPathName, strTemp;
  104. AfxGetModuleShortFileName(AfxGetInstanceHandle(), strPathName);
  105. POSITION pos = m_templateList.GetHeadPosition();
  106. for (int nTemplateIndex = 1; pos != NULL; nTemplateIndex++)
  107. {
  108. CDocTemplate* pTemplate = (CDocTemplate*)m_templateList.GetNext(pos);
  109. CString strFilterExt, strFileTypeId, strFileTypeName;
  110. if (pTemplate->GetDocString(strFileTypeId,
  111. CDocTemplate::regFileTypeId) && !strFileTypeId.IsEmpty())
  112. {
  113. // enough info to register it
  114. if (!pTemplate->GetDocString(strFileTypeName,
  115. CDocTemplate::regFileTypeName))
  116. strFileTypeName = strFileTypeId; // use id name
  117. ASSERT(strFileTypeId.Find(' ') == -1); // no spaces allowed
  118. strTemp.Format(_afxDefaultIconFmt, (LPCTSTR)strFileTypeId);
  119. _AfxDeleteRegKey(strTemp);
  120. // If MDI Application
  121. if (!pTemplate->GetDocString(strTemp, CDocTemplate::windowTitle) ||
  122. strTemp.IsEmpty())
  123. {
  124. // path\shell\open\ddeexec = [open("%1")]
  125. strTemp.Format(_afxShellOpenFmt, (LPCTSTR)strFileTypeId,
  126. (LPCTSTR)_afxDDEExec);
  127. _AfxDeleteRegKey(strTemp);
  128. // path\shell\print\ddeexec = [print("%1")]
  129. strTemp.Format(_afxShellPrintFmt, (LPCTSTR)strFileTypeId,
  130. (LPCTSTR)_afxDDEExec);
  131. _AfxDeleteRegKey(strTemp);
  132. // path\shell\printto\ddeexec = [printto("%1","%2","%3","%4")]
  133. strTemp.Format(_afxShellPrintToFmt, (LPCTSTR)strFileTypeId,
  134. (LPCTSTR)_afxDDEExec);
  135. _AfxDeleteRegKey(strTemp);
  136. }
  137. // path\shell\open\command = path filename
  138. strTemp.Format(_afxShellOpenFmt, (LPCTSTR)strFileTypeId,
  139. (LPCTSTR)_afxCommand);
  140. _AfxDeleteRegKey(strTemp);
  141. // path\shell\print\command = path /p filename
  142. strTemp.Format(_afxShellPrintFmt, (LPCTSTR)strFileTypeId,
  143. (LPCTSTR)_afxCommand);
  144. _AfxDeleteRegKey(strTemp);
  145. // path\shell\printto\command = path /pt filename printer driver port
  146. strTemp.Format(_afxShellPrintToFmt, (LPCTSTR)strFileTypeId,
  147. (LPCTSTR)_afxCommand);
  148. _AfxDeleteRegKey(strTemp);
  149. pTemplate->GetDocString(strFilterExt, CDocTemplate::filterExt);
  150. if (!strFilterExt.IsEmpty())
  151. {
  152. ASSERT(strFilterExt[0] == '.');
  153. LONG lSize = _MAX_PATH * 2;
  154. LONG lResult = ::RegQueryValue(HKEY_CLASSES_ROOT, strFilterExt,
  155. strTemp.GetBuffer(lSize), &lSize);
  156. strTemp.ReleaseBuffer();
  157. if (lResult != ERROR_SUCCESS || strTemp.IsEmpty() ||
  158. strTemp == strFileTypeId)
  159. {
  160. strTemp.Format(_afxShellNewFmt, (LPCTSTR)strFilterExt);
  161. _AfxDeleteRegKey(strTemp);
  162. // no association for that suffix
  163. _AfxDeleteRegKey(strFilterExt);
  164. }
  165. }
  166. }
  167. }
  168. }
  169. void CDocManager::RegisterShellFileTypes(BOOL bCompat)
  170. {
  171. ASSERT(!m_templateList.IsEmpty()); // must have some doc templates
  172. CString strPathName, strTemp;
  173. AfxGetModuleShortFileName(AfxGetInstanceHandle(), strPathName);
  174. POSITION pos = m_templateList.GetHeadPosition();
  175. for (int nTemplateIndex = 1; pos != NULL; nTemplateIndex++)
  176. {
  177. CDocTemplate* pTemplate = (CDocTemplate*)m_templateList.GetNext(pos);
  178. CString strOpenCommandLine = strPathName;
  179. CString strPrintCommandLine = strPathName;
  180. CString strPrintToCommandLine = strPathName;
  181. CString strDefaultIconCommandLine = strPathName;
  182. if (bCompat)
  183. {
  184. CString strIconIndex;
  185. HICON hIcon = ::ExtractIcon(AfxGetInstanceHandle(), strPathName, nTemplateIndex);
  186. if (hIcon != NULL)
  187. {
  188. strIconIndex.Format(_afxIconIndexFmt, nTemplateIndex);
  189. DestroyIcon(hIcon);
  190. }
  191. else
  192. {
  193. strIconIndex.Format(_afxIconIndexFmt, DEFAULT_ICON_INDEX);
  194. }
  195. strDefaultIconCommandLine += strIconIndex;
  196. }
  197. CString strFilterExt, strFileTypeId, strFileTypeName;
  198. if (pTemplate->GetDocString(strFileTypeId,
  199. CDocTemplate::regFileTypeId) && !strFileTypeId.IsEmpty())
  200. {
  201. // enough info to register it
  202. if (!pTemplate->GetDocString(strFileTypeName,
  203. CDocTemplate::regFileTypeName))
  204. strFileTypeName = strFileTypeId; // use id name
  205. ASSERT(strFileTypeId.Find(' ') == -1); // no spaces allowed
  206. // first register the type ID of our server
  207. if (!_AfxSetRegKey(strFileTypeId, strFileTypeName))
  208. continue; // just skip it
  209. if (bCompat)
  210. {
  211. // path\DefaultIcon = path,1
  212. strTemp.Format(_afxDefaultIconFmt, (LPCTSTR)strFileTypeId);
  213. if (!_AfxSetRegKey(strTemp, strDefaultIconCommandLine))
  214. continue; // just skip it
  215. }
  216. // If MDI Application
  217. if (!pTemplate->GetDocString(strTemp, CDocTemplate::windowTitle) ||
  218. strTemp.IsEmpty())
  219. {
  220. // path\shell\open\ddeexec = [open("%1")]
  221. strTemp.Format(_afxShellOpenFmt, (LPCTSTR)strFileTypeId,
  222. (LPCTSTR)_afxDDEExec);
  223. if (!_AfxSetRegKey(strTemp, _afxDDEOpen))
  224. continue; // just skip it
  225. if (bCompat)
  226. {
  227. // path\shell\print\ddeexec = [print("%1")]
  228. strTemp.Format(_afxShellPrintFmt, (LPCTSTR)strFileTypeId,
  229. (LPCTSTR)_afxDDEExec);
  230. if (!_AfxSetRegKey(strTemp, _afxDDEPrint))
  231. continue; // just skip it
  232. // path\shell\printto\ddeexec = [printto("%1","%2","%3","%4")]
  233. strTemp.Format(_afxShellPrintToFmt, (LPCTSTR)strFileTypeId,
  234. (LPCTSTR)_afxDDEExec);
  235. if (!_AfxSetRegKey(strTemp, _afxDDEPrintTo))
  236. continue; // just skip it
  237. // path\shell\open\command = path /dde
  238. // path\shell\print\command = path /dde
  239. // path\shell\printto\command = path /dde
  240. strOpenCommandLine += _afxDDEArg;
  241. strPrintCommandLine += _afxDDEArg;
  242. strPrintToCommandLine += _afxDDEArg;
  243. }
  244. else
  245. {
  246. strOpenCommandLine += _afxOpenArg;
  247. }
  248. }
  249. else
  250. {
  251. // path\shell\open\command = path filename
  252. // path\shell\print\command = path /p filename
  253. // path\shell\printto\command = path /pt filename printer driver port
  254. strOpenCommandLine += _afxOpenArg;
  255. if (bCompat)
  256. {
  257. strPrintCommandLine += _afxPrintArg;
  258. strPrintToCommandLine += _afxPrintToArg;
  259. }
  260. }
  261. // path\shell\open\command = path filename
  262. strTemp.Format(_afxShellOpenFmt, (LPCTSTR)strFileTypeId,
  263. (LPCTSTR)_afxCommand);
  264. if (!_AfxSetRegKey(strTemp, strOpenCommandLine))
  265. continue; // just skip it
  266. if (bCompat)
  267. {
  268. // path\shell\print\command = path /p filename
  269. strTemp.Format(_afxShellPrintFmt, (LPCTSTR)strFileTypeId,
  270. (LPCTSTR)_afxCommand);
  271. if (!_AfxSetRegKey(strTemp, strPrintCommandLine))
  272. continue; // just skip it
  273. // path\shell\printto\command = path /pt filename printer driver port
  274. strTemp.Format(_afxShellPrintToFmt, (LPCTSTR)strFileTypeId,
  275. (LPCTSTR)_afxCommand);
  276. if (!_AfxSetRegKey(strTemp, strPrintToCommandLine))
  277. continue; // just skip it
  278. }
  279. pTemplate->GetDocString(strFilterExt, CDocTemplate::filterExt);
  280. if (!strFilterExt.IsEmpty())
  281. {
  282. ASSERT(strFilterExt[0] == '.');
  283. LONG lSize = _MAX_PATH * 2;
  284. LONG lResult = ::RegQueryValue(HKEY_CLASSES_ROOT, strFilterExt,
  285. strTemp.GetBuffer(lSize), &lSize);
  286. strTemp.ReleaseBuffer();
  287. if (lResult != ERROR_SUCCESS || strTemp.IsEmpty() ||
  288. strTemp == strFileTypeId)
  289. {
  290. // no association for that suffix
  291. if (!_AfxSetRegKey(strFilterExt, strFileTypeId))
  292. continue;
  293. if (bCompat)
  294. {
  295. strTemp.Format(_afxShellNewFmt, (LPCTSTR)strFilterExt);
  296. (void)_AfxSetRegKey(strTemp, _afxShellNewValue, _afxShellNewValueName);
  297. }
  298. }
  299. }
  300. }
  301. }
  302. }
  303. #ifdef AFX_CORE3_SEG
  304. #pragma code_seg(AFX_CORE3_SEG)
  305. #endif
  306. AFX_STATIC void AFXAPI _AfxAppendFilterSuffix(CString& filter, OPENFILENAME& ofn,
  307. CDocTemplate* pTemplate, CString* pstrDefaultExt)
  308. {
  309. ASSERT_VALID(pTemplate);
  310. ASSERT_KINDOF(CDocTemplate, pTemplate);
  311. CString strFilterExt, strFilterName;
  312. if (pTemplate->GetDocString(strFilterExt, CDocTemplate::filterExt) &&
  313. !strFilterExt.IsEmpty() &&
  314. pTemplate->GetDocString(strFilterName, CDocTemplate::filterName) &&
  315. !strFilterName.IsEmpty())
  316. {
  317. // a file based document template - add to filter list
  318. ASSERT(strFilterExt[0] == '.');
  319. if (pstrDefaultExt != NULL)
  320. {
  321. // set the default extension
  322. *pstrDefaultExt = ((LPCTSTR)strFilterExt) + 1; // skip the '.'
  323. ofn.lpstrDefExt = (LPTSTR)(LPCTSTR)(*pstrDefaultExt);
  324. ofn.nFilterIndex = ofn.nMaxCustFilter + 1; // 1 based number
  325. }
  326. // add to filter
  327. filter += strFilterName;
  328. ASSERT(!filter.IsEmpty()); // must have a file type name
  329. filter += (TCHAR)'\0'; // next string please
  330. filter += (TCHAR)'*';
  331. filter += strFilterExt;
  332. filter += (TCHAR)'\0'; // next string please
  333. ofn.nMaxCustFilter++;
  334. }
  335. }
  336. // Get the best document template for the named file
  337. class CNewTypeDlg : public CDialog
  338. {
  339. protected:
  340. CPtrList* m_pList; // actually a list of doc templates
  341. public:
  342. CDocTemplate* m_pSelectedTemplate;
  343. public:
  344. //{{AFX_DATA(CNewTypeDlg)
  345. enum { IDD = AFX_IDD_NEWTYPEDLG };
  346. //}}AFX_DATA
  347. CNewTypeDlg(CPtrList* pList) : CDialog(CNewTypeDlg::IDD)
  348. {
  349. m_pList = pList;
  350. m_pSelectedTemplate = NULL;
  351. }
  352. ~CNewTypeDlg() { }
  353. protected:
  354. BOOL OnInitDialog();
  355. void OnOK();
  356. //{{AFX_MSG(CNewTypeDlg)
  357. //}}AFX_MSG
  358. DECLARE_MESSAGE_MAP()
  359. };
  360. BEGIN_MESSAGE_MAP(CNewTypeDlg, CDialog)
  361. //{{AFX_MSG_MAP(CNewTypeDlg)
  362. ON_LBN_DBLCLK(AFX_IDC_LISTBOX, OnOK)
  363. //}}AFX_MSG_MAP
  364. END_MESSAGE_MAP()
  365. BOOL CNewTypeDlg::OnInitDialog()
  366. {
  367. CListBox* pListBox = (CListBox*)GetDlgItem(AFX_IDC_LISTBOX);
  368. ASSERT(pListBox != NULL);
  369. // fill with document templates in list
  370. pListBox->ResetContent();
  371. POSITION pos = m_pList->GetHeadPosition();
  372. // add all the CDocTemplates in the list by name
  373. while (pos != NULL)
  374. {
  375. CDocTemplate* pTemplate = (CDocTemplate*)m_pList->GetNext(pos);
  376. ASSERT_KINDOF(CDocTemplate, pTemplate);
  377. CString strTypeName;
  378. if (pTemplate->GetDocString(strTypeName, CDocTemplate::fileNewName) &&
  379. !strTypeName.IsEmpty())
  380. {
  381. // add it to the listbox
  382. int nIndex = pListBox->AddString(strTypeName);
  383. if (nIndex == -1)
  384. {
  385. EndDialog(-1);
  386. return FALSE;
  387. }
  388. pListBox->SetItemDataPtr(nIndex, pTemplate);
  389. }
  390. }
  391. int nTemplates = pListBox->GetCount();
  392. if (nTemplates == 0)
  393. {
  394. TRACE0("Error: no document templates to select from!\n");
  395. EndDialog(-1); // abort
  396. }
  397. else if (nTemplates == 1)
  398. {
  399. // get the first/only item
  400. m_pSelectedTemplate = (CDocTemplate*)pListBox->GetItemDataPtr(0);
  401. ASSERT_VALID(m_pSelectedTemplate);
  402. ASSERT_KINDOF(CDocTemplate, m_pSelectedTemplate);
  403. EndDialog(IDOK); // done
  404. }
  405. else
  406. {
  407. // set selection to the first one (NOT SORTED)
  408. pListBox->SetCurSel(0);
  409. }
  410. return CDialog::OnInitDialog();
  411. }
  412. void CNewTypeDlg::OnOK()
  413. {
  414. CListBox* pListBox = (CListBox*)GetDlgItem(AFX_IDC_LISTBOX);
  415. ASSERT(pListBox != NULL);
  416. // if listbox has selection, set the selected template
  417. int nIndex;
  418. if ((nIndex = pListBox->GetCurSel()) == -1)
  419. {
  420. // no selection
  421. m_pSelectedTemplate = NULL;
  422. }
  423. else
  424. {
  425. m_pSelectedTemplate = (CDocTemplate*)pListBox->GetItemDataPtr(nIndex);
  426. ASSERT_VALID(m_pSelectedTemplate);
  427. ASSERT_KINDOF(CDocTemplate, m_pSelectedTemplate);
  428. }
  429. CDialog::OnOK();
  430. }
  431. /////////////////////////////////////////////////////////////////////////////
  432. // CDocManager
  433. void CDocManager::AddDocTemplate(CDocTemplate* pTemplate)
  434. {
  435. if (pTemplate == NULL)
  436. {
  437. if (pStaticList != NULL)
  438. {
  439. POSITION pos = pStaticList->GetHeadPosition();
  440. while (pos != NULL)
  441. {
  442. CDocTemplate* pTemplate =
  443. (CDocTemplate*)pStaticList->GetNext(pos);
  444. AddDocTemplate(pTemplate);
  445. }
  446. delete pStaticList;
  447. pStaticList = NULL;
  448. }
  449. bStaticInit = FALSE;
  450. }
  451. else
  452. {
  453. ASSERT_VALID(pTemplate);
  454. ASSERT(m_templateList.Find(pTemplate, NULL) == NULL);// must not be in list
  455. pTemplate->LoadTemplate();
  456. m_templateList.AddTail(pTemplate);
  457. }
  458. }
  459. POSITION CDocManager::GetFirstDocTemplatePosition() const
  460. {
  461. return m_templateList.GetHeadPosition();
  462. }
  463. CDocTemplate* CDocManager::GetNextDocTemplate(POSITION& pos) const
  464. {
  465. return (CDocTemplate*)m_templateList.GetNext(pos);
  466. }
  467. BOOL CDocManager::SaveAllModified()
  468. {
  469. POSITION pos = m_templateList.GetHeadPosition();
  470. while (pos != NULL)
  471. {
  472. CDocTemplate* pTemplate = (CDocTemplate*)m_templateList.GetNext(pos);
  473. ASSERT_KINDOF(CDocTemplate, pTemplate);
  474. if (!pTemplate->SaveAllModified())
  475. return FALSE;
  476. }
  477. return TRUE;
  478. }
  479. void CDocManager::CloseAllDocuments(BOOL bEndSession)
  480. {
  481. POSITION pos = m_templateList.GetHeadPosition();
  482. while (pos != NULL)
  483. {
  484. CDocTemplate* pTemplate = (CDocTemplate*)m_templateList.GetNext(pos);
  485. ASSERT_KINDOF(CDocTemplate, pTemplate);
  486. pTemplate->CloseAllDocuments(bEndSession);
  487. }
  488. }
  489. BOOL CDocManager::DoPromptFileName(CString& fileName, UINT nIDSTitle, DWORD lFlags, BOOL bOpenFileDialog, CDocTemplate* pTemplate)
  490. {
  491. CFileDialog dlgFile(bOpenFileDialog);
  492. CString title;
  493. VERIFY(title.LoadString(nIDSTitle));
  494. dlgFile.m_ofn.Flags |= lFlags;
  495. CString strFilter;
  496. CString strDefault;
  497. if (pTemplate != NULL)
  498. {
  499. ASSERT_VALID(pTemplate);
  500. _AfxAppendFilterSuffix(strFilter, dlgFile.m_ofn, pTemplate, &strDefault);
  501. }
  502. else
  503. {
  504. // do for all doc template
  505. POSITION pos = m_templateList.GetHeadPosition();
  506. BOOL bFirst = TRUE;
  507. while (pos != NULL)
  508. {
  509. CDocTemplate* pTemplate = (CDocTemplate*)m_templateList.GetNext(pos);
  510. _AfxAppendFilterSuffix(strFilter, dlgFile.m_ofn, pTemplate,
  511. bFirst ? &strDefault : NULL);
  512. bFirst = FALSE;
  513. }
  514. }
  515. // append the "*.*" all files filter
  516. CString allFilter;
  517. VERIFY(allFilter.LoadString(AFX_IDS_ALLFILTER));
  518. strFilter += allFilter;
  519. strFilter += (TCHAR)'\0'; // next string please
  520. strFilter += _T("*.*");
  521. strFilter += (TCHAR)'\0'; // last string
  522. dlgFile.m_ofn.nMaxCustFilter++;
  523. dlgFile.m_ofn.lpstrFilter = strFilter;
  524. dlgFile.m_ofn.lpstrTitle = title;
  525. dlgFile.m_ofn.lpstrFile = fileName.GetBuffer(_MAX_PATH);
  526. int nResult = dlgFile.DoModal();
  527. fileName.ReleaseBuffer();
  528. return nResult == IDOK;
  529. }
  530. int CDocManager::GetDocumentCount()
  531. {
  532. // count all documents
  533. int nCount = 0;
  534. POSITION pos = m_templateList.GetHeadPosition();
  535. while (pos != NULL)
  536. {
  537. CDocTemplate* pTemplate = (CDocTemplate*)m_templateList.GetNext(pos);
  538. POSITION pos2 = pTemplate->GetFirstDocPosition();
  539. while (pos2 != NULL)
  540. {
  541. pTemplate->GetNextDoc(pos2);
  542. ++nCount;
  543. }
  544. }
  545. return nCount;
  546. }
  547. BOOL CDocManager::OnDDECommand(LPTSTR lpszCommand)
  548. {
  549. CString strCommand = lpszCommand;
  550. CDocument* pDoc = NULL;
  551. // open format is "[open("%s")]" - no whitespace allowed, one per line
  552. // print format is "[print("%s")]" - no whitespace allowed, one per line
  553. // print to format is "[printto("%s","%s","%s","%s")]" - no whitespace allowed, one per line
  554. CCommandLineInfo cmdInfo;
  555. cmdInfo.m_nShellCommand = CCommandLineInfo::FileDDE;
  556. if (strCommand.Left(7) == _T("[open(\""))
  557. {
  558. cmdInfo.m_nShellCommand = CCommandLineInfo::FileOpen;
  559. strCommand = strCommand.Right(strCommand.GetLength() - 7);
  560. }
  561. else if (strCommand.Left(8) == _T("[print(\""))
  562. {
  563. cmdInfo.m_nShellCommand = CCommandLineInfo::FilePrint;
  564. strCommand = strCommand.Right(strCommand.GetLength() - 8);
  565. }
  566. else if (strCommand.Left(10) == _T("[printto(\""))
  567. {
  568. cmdInfo.m_nShellCommand = CCommandLineInfo::FilePrintTo;\
  569. strCommand = strCommand.Right(strCommand.GetLength() - 10);
  570. }
  571. else
  572. return FALSE; // not a command we handle
  573. int i = strCommand.Find('"');
  574. if (i == -1)
  575. return FALSE; // illegally terminated
  576. cmdInfo.m_strFileName = strCommand.Left(i);
  577. strCommand = strCommand.Right(strCommand.GetLength() - i);
  578. CCommandLineInfo* pOldInfo = NULL;
  579. BOOL bRetVal = TRUE;
  580. // If we were started up for DDE retrieve the Show state
  581. if (AfxGetApp()->m_pCmdInfo != NULL)
  582. {
  583. AfxGetApp()->m_nCmdShow = (int)AfxGetApp()->m_pCmdInfo;
  584. AfxGetApp()->m_pCmdInfo = &cmdInfo;
  585. }
  586. else
  587. pOldInfo = AfxGetApp()->m_pCmdInfo;
  588. if (cmdInfo.m_nShellCommand == CCommandLineInfo::FileOpen)
  589. {
  590. // show the application window
  591. CWnd* pMainWnd = AfxGetApp()->m_pMainWnd;
  592. int nCmdShow = AfxGetApp()->m_nCmdShow;
  593. if (nCmdShow == -1 || nCmdShow == SW_SHOWNORMAL)
  594. {
  595. if (pMainWnd->IsIconic())
  596. nCmdShow = SW_RESTORE;
  597. else
  598. nCmdShow = SW_SHOW;
  599. }
  600. pMainWnd->ShowWindow(nCmdShow);
  601. if (nCmdShow != SW_MINIMIZE)
  602. pMainWnd->SetForegroundWindow();
  603. // then open the document
  604. AfxGetApp()->OpenDocumentFile(cmdInfo.m_strFileName);
  605. // user is now "in control" of the application
  606. if (!AfxOleGetUserCtrl())
  607. AfxOleSetUserCtrl(TRUE);
  608. // next time, show the window as default
  609. AfxGetApp()->m_nCmdShow = -1;
  610. goto RestoreAndReturn;
  611. }
  612. if (cmdInfo.m_nShellCommand == CCommandLineInfo::FilePrintTo)
  613. {
  614. if (strCommand.Left(3) != _T("\",\""))
  615. {
  616. bRetVal = FALSE;
  617. goto RestoreAndReturn;
  618. }
  619. else
  620. {
  621. strCommand = strCommand.Right(strCommand.GetLength() - 3);
  622. i = strCommand.Find('"');
  623. if (i == -1)
  624. {
  625. bRetVal = FALSE;
  626. goto RestoreAndReturn;
  627. }
  628. else
  629. {
  630. cmdInfo.m_strPrinterName = strCommand.Left(i);
  631. strCommand = strCommand.Right(strCommand.GetLength() - i);
  632. }
  633. }
  634. if (strCommand.Left(3) != _T("\",\""))
  635. {
  636. bRetVal = FALSE;
  637. goto RestoreAndReturn;
  638. }
  639. else
  640. {
  641. strCommand = strCommand.Right(strCommand.GetLength() - 3);
  642. i = strCommand.Find('"');
  643. if (i == -1)
  644. {
  645. bRetVal = FALSE;
  646. goto RestoreAndReturn;
  647. }
  648. else
  649. {
  650. cmdInfo.m_strDriverName = strCommand.Left(i);
  651. strCommand = strCommand.Right(strCommand.GetLength() - i);
  652. }
  653. }
  654. if (strCommand.Left(3) != _T("\",\""))
  655. {
  656. bRetVal = FALSE;
  657. goto RestoreAndReturn;
  658. }
  659. else
  660. {
  661. strCommand = strCommand.Right(strCommand.GetLength() - 3);
  662. i = strCommand.Find('"');
  663. if (i == -1)
  664. {
  665. bRetVal = FALSE;
  666. goto RestoreAndReturn;
  667. }
  668. else
  669. {
  670. cmdInfo.m_strPortName = strCommand.Left(i);
  671. strCommand = strCommand.Right(strCommand.GetLength() - i);
  672. }
  673. }
  674. }
  675. // get document count before opening it
  676. int nOldCount; nOldCount = GetDocumentCount();
  677. // open the document, then print it.
  678. pDoc = AfxGetApp()->OpenDocumentFile(cmdInfo.m_strFileName);
  679. AfxGetApp()->m_pCmdInfo = &cmdInfo;
  680. AfxGetApp()->m_pMainWnd->SendMessage(WM_COMMAND, ID_FILE_PRINT_DIRECT);
  681. AfxGetApp()->m_pCmdInfo = NULL;
  682. // close the document if it wasn't open previously (based on doc count)
  683. if (GetDocumentCount() > nOldCount)
  684. pDoc->OnCloseDocument();
  685. // if the app was only started to process this command then close
  686. if (!AfxOleGetUserCtrl())
  687. AfxGetApp()->m_pMainWnd->PostMessage(WM_CLOSE);
  688. RestoreAndReturn:
  689. AfxGetApp()->m_pCmdInfo = pOldInfo;
  690. return bRetVal;
  691. }
  692. void CDocManager::OnFileNew()
  693. {
  694. if (m_templateList.IsEmpty())
  695. {
  696. TRACE0("Error: no document templates registered with CWinApp.\n");
  697. AfxMessageBox(AFX_IDP_FAILED_TO_CREATE_DOC);
  698. return;
  699. }
  700. CDocTemplate* pTemplate = (CDocTemplate*)m_templateList.GetHead();
  701. if (m_templateList.GetCount() > 1)
  702. {
  703. // more than one document template to choose from
  704. // bring up dialog prompting user
  705. CNewTypeDlg dlg(&m_templateList);
  706. int nID = dlg.DoModal();
  707. if (nID == IDOK)
  708. pTemplate = dlg.m_pSelectedTemplate;
  709. else
  710. return; // none - cancel operation
  711. }
  712. ASSERT(pTemplate != NULL);
  713. ASSERT_KINDOF(CDocTemplate, pTemplate);
  714. pTemplate->OpenDocumentFile(NULL);
  715. // if returns NULL, the user has already been alerted
  716. }
  717. void CDocManager::OnFileOpen()
  718. {
  719. // prompt the user (with all document templates)
  720. CString newName;
  721. if (!DoPromptFileName(newName, AFX_IDS_OPENFILE,
  722. OFN_HIDEREADONLY | OFN_FILEMUSTEXIST, TRUE, NULL))
  723. return; // open cancelled
  724. AfxGetApp()->OpenDocumentFile(newName);
  725. // if returns NULL, the user has already been alerted
  726. }
  727. #ifdef _DEBUG
  728. void CDocManager::AssertValid() const
  729. {
  730. CObject::AssertValid();
  731. POSITION pos = m_templateList.GetHeadPosition();
  732. while (pos != NULL)
  733. {
  734. CDocTemplate* pTemplate = (CDocTemplate*)m_templateList.GetNext(pos);
  735. ASSERT_VALID(pTemplate);
  736. }
  737. }
  738. void CDocManager::Dump(CDumpContext& dc) const
  739. {
  740. CObject::Dump(dc);
  741. if (dc.GetDepth() != 0)
  742. {
  743. dc << "\nm_templateList[] = {";
  744. POSITION pos = m_templateList.GetHeadPosition();
  745. while (pos != NULL)
  746. {
  747. CDocTemplate* pTemplate =
  748. (CDocTemplate*)m_templateList.GetNext(pos);
  749. dc << "\ntemplate " << pTemplate;
  750. }
  751. dc << "}";
  752. }
  753. dc << "\n";
  754. }
  755. #endif
  756. #ifdef AFX_CORE2_SEG
  757. #pragma code_seg(AFX_CORE2_SEG)
  758. #endif
  759. CDocument* CDocManager::OpenDocumentFile(LPCTSTR lpszFileName)
  760. {
  761. // find the highest confidence
  762. POSITION pos = m_templateList.GetHeadPosition();
  763. CDocTemplate::Confidence bestMatch = CDocTemplate::noAttempt;
  764. CDocTemplate* pBestTemplate = NULL;
  765. CDocument* pOpenDocument = NULL;
  766. TCHAR szPath[_MAX_PATH];
  767. ASSERT(lstrlen(lpszFileName) < _countof(szPath));
  768. TCHAR szTemp[_MAX_PATH];
  769. if (lpszFileName[0] == '\"')
  770. ++lpszFileName;
  771. lstrcpyn(szTemp, lpszFileName, _MAX_PATH);
  772. LPTSTR lpszLast = _tcsrchr(szTemp, '\"');
  773. if (lpszLast != NULL)
  774. *lpszLast = 0;
  775. AfxFullPath(szPath, szTemp);
  776. TCHAR szLinkName[_MAX_PATH];
  777. if (AfxResolveShortcut(AfxGetMainWnd(), szPath, szLinkName, _MAX_PATH))
  778. lstrcpy(szPath, szLinkName);
  779. while (pos != NULL)
  780. {
  781. CDocTemplate* pTemplate = (CDocTemplate*)m_templateList.GetNext(pos);
  782. ASSERT_KINDOF(CDocTemplate, pTemplate);
  783. CDocTemplate::Confidence match;
  784. ASSERT(pOpenDocument == NULL);
  785. match = pTemplate->MatchDocType(szPath, pOpenDocument);
  786. if (match > bestMatch)
  787. {
  788. bestMatch = match;
  789. pBestTemplate = pTemplate;
  790. }
  791. if (match == CDocTemplate::yesAlreadyOpen)
  792. break; // stop here
  793. }
  794. if (pOpenDocument != NULL)
  795. {
  796. POSITION pos = pOpenDocument->GetFirstViewPosition();
  797. if (pos != NULL)
  798. {
  799. CView* pView = pOpenDocument->GetNextView(pos); // get first one
  800. ASSERT_VALID(pView);
  801. CFrameWnd* pFrame = pView->GetParentFrame();
  802. if (pFrame != NULL)
  803. pFrame->ActivateFrame();
  804. else
  805. TRACE0("Error: Can not find a frame for document to activate.\n");
  806. CFrameWnd* pAppFrame;
  807. if (pFrame != (pAppFrame = (CFrameWnd*)AfxGetApp()->m_pMainWnd))
  808. {
  809. ASSERT_KINDOF(CFrameWnd, pAppFrame);
  810. pAppFrame->ActivateFrame();
  811. }
  812. }
  813. else
  814. {
  815. TRACE0("Error: Can not find a view for document to activate.\n");
  816. }
  817. return pOpenDocument;
  818. }
  819. if (pBestTemplate == NULL)
  820. {
  821. AfxMessageBox(AFX_IDP_FAILED_TO_OPEN_DOC);
  822. return NULL;
  823. }
  824. return pBestTemplate->OpenDocumentFile(szPath);
  825. }
  826. int CDocManager::GetOpenDocumentCount()
  827. {
  828. int nOpen = 0;
  829. POSITION pos = m_templateList.GetHeadPosition();
  830. while (pos != NULL)
  831. {
  832. CDocTemplate* pTemplate = (CDocTemplate*)m_templateList.GetNext(pos);
  833. POSITION pos2 = pTemplate->GetFirstDocPosition();
  834. while (pos2)
  835. {
  836. if (pTemplate->GetNextDoc(pos2) != NULL)
  837. nOpen++;
  838. }
  839. }
  840. return nOpen;
  841. }
  842. #ifdef AFX_TERM_SEG
  843. #pragma code_seg(AFX_TERM_SEG)
  844. #endif
  845. CDocManager::~CDocManager()
  846. {
  847. // for cleanup - delete all document templates
  848. POSITION pos = m_templateList.GetHeadPosition();
  849. while (pos != NULL)
  850. {
  851. POSITION posTemplate = pos;
  852. CDocTemplate* pTemplate = (CDocTemplate*)m_templateList.GetNext(pos);
  853. if (pTemplate->m_bAutoDelete)
  854. {
  855. m_templateList.RemoveAt(posTemplate);
  856. delete (CDocTemplate*)pTemplate;
  857. }
  858. }
  859. }
  860. #ifdef AFX_INIT_SEG
  861. #pragma code_seg(AFX_INIT_SEG)
  862. #endif
  863. IMPLEMENT_DYNAMIC(CDocManager, CObject)
  864. /////////////////////////////////////////////////////////////////////////////