home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / cmd / winfe / prefs / brpref / src / brpages.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  54.0 KB  |  1,922 lines

  1. /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  2.  *
  3.  * The contents of this file are subject to the Netscape Public License
  4.  * Version 1.0 (the "NPL"); you may not use this file except in
  5.  * compliance with the NPL.  You may obtain a copy of the NPL at
  6.  * http://www.mozilla.org/NPL/
  7.  *
  8.  * Software distributed under the NPL is distributed on an "AS IS" basis,
  9.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
  10.  * for the specific language governing rights and limitations under the
  11.  * NPL.
  12.  *
  13.  * The Initial Developer of this code under the NPL is Netscape
  14.  * Communications Corporation.  Portions created by Netscape are
  15.  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  16.  * Reserved.
  17.  */
  18.  
  19. #include "pch.h"
  20. #include <assert.h>
  21. #include "dllcom.h"
  22. #include "pages.h"
  23. #include "bitmpbtn.h"
  24. #include "resource.h"
  25. #include "xp_core.h"
  26. #include "xp_help.h"
  27. #include "prefapi.h"
  28. #include "brprefid.h"
  29. #include "../../../defaults.h"
  30. #ifndef _WIN32
  31. #include <toolhelp.h>
  32. #endif
  33.  
  34. #ifndef _WIN32
  35. #define OFN_NONETWORKBUTTON          0x00020000
  36. #endif
  37.  
  38. #define IDS_ACCEPTLANG_START IDS_ACCEPTLANG_AF
  39. #define IDS_ACCEPTLANG_END   IDS_ACCEPTLANG_ESMX    // Change me if you add new string
  40.  
  41. // How to handle an external application
  42. #define HANDLE_VIA_NETSCAPE  50
  43. #define HANDLE_UNKNOWN      100
  44. #define HANDLE_EXTERNAL     200
  45. #define HANDLE_SAVE            300
  46. #define HANDLE_VIA_PLUGIN   400
  47. #define HANDLE_MOREINFO     500
  48. #define HANDLE_SHELLEXECUTE 600
  49. #define HANDLE_BY_OLE        700
  50.  
  51. /////////////////////////////////////////////////////////////////////////////
  52. // Helper routines
  53.  
  54. // Retrieve the file type class for a given extension
  55. static BOOL
  56. GetFileClass(LPCSTR lpszExtension, LPSTR lpszFileClass, LONG cbData)
  57. {
  58.     char    szKey[_MAX_EXT + 1];  // space for '.'
  59.     LONG    lResult;
  60.  
  61.     // Look up the file association key which maps a file extension
  62.     // to a file class
  63.     wsprintf(szKey, ".%s", lpszExtension);
  64.     lResult = RegQueryValue(HKEY_CLASSES_ROOT, szKey, lpszFileClass, &cbData);
  65.     
  66. #ifdef _WIN32
  67.     assert(lResult != ERROR_MORE_DATA);
  68. #endif
  69.     return lResult == ERROR_SUCCESS;
  70. }
  71.  
  72. // Get the description for a file type class
  73. static BOOL
  74. GetFileTypeDescription(LPCSTR lpszFileClass, CString &strDescription)
  75. {
  76.     LONG    cbData;
  77.     LONG    lResult;
  78.      
  79. #ifdef _WIN32
  80.     // See how much space we need
  81.     cbData = 0;
  82.     lResult = RegQueryValue(HKEY_CLASSES_ROOT, lpszFileClass, NULL, &cbData);
  83.     if (lResult == ERROR_SUCCESS && cbData > 1) {
  84.         LPSTR   lpszDescription = strDescription.BufferSetLength((int)cbData);
  85.  
  86.         if (!lpszDescription)
  87.             return FALSE;
  88.  
  89.         // Get the string
  90.         lResult = RegQueryValue(HKEY_CLASSES_ROOT, lpszFileClass, lpszDescription, &cbData);
  91.         return lResult == ERROR_SUCCESS;
  92.     }
  93. #else
  94.     // Win 3.1 RegQueryValue() doesn't support asking for the size of the data
  95.     char    szDescription[128];
  96.  
  97.     // Get the string
  98.     cbData = sizeof(szDescription);
  99.     lResult = RegQueryValue(HKEY_CLASSES_ROOT, lpszFileClass, szDescription, &cbData);
  100.     if (lResult == ERROR_SUCCESS && cbData > 1) {
  101.         strDescription = szDescription;
  102.         return TRUE;
  103.     }
  104. #endif
  105.  
  106.     return FALSE;
  107. }
  108.  
  109. // Set the description for a file type class
  110. static void
  111. SetFileTypeDescription(LPCSTR lpszFileClass, LPCSTR lpszDescription)
  112. {
  113.     HKEY    hKey;
  114.     LONG    lResult;
  115.  
  116.     lResult = RegOpenKey(HKEY_CLASSES_ROOT, lpszFileClass, &hKey);
  117.     if (lResult == ERROR_SUCCESS) {
  118.         RegSetValue(hKey, NULL, REG_SZ, lpszDescription, lstrlen(lpszDescription));
  119.         RegCloseKey(hKey);
  120.     }
  121. }
  122.  
  123. // Retrieves the HICON that's associated with the given file class
  124. static HICON
  125. GetDocumentIcon(HINSTANCE hInstance, LPCSTR lpszFileClass)
  126. {
  127.     char    szBuf[_MAX_PATH];
  128.     LONG    lResult;
  129.     HKEY    hKey;
  130. #ifdef _WIN32
  131.     DWORD    cbData;
  132.     DWORD    dwType;
  133. #else
  134.     LONG    cbData;
  135. #endif
  136.  
  137.     // Open the DefaultIcon key
  138. #ifdef _WIN32
  139.     wsprintf(szBuf, "%s\\DefaultIcon", lpszFileClass);
  140.     lResult = RegOpenKeyEx(HKEY_CLASSES_ROOT, szBuf, 0, KEY_QUERY_VALUE, &hKey);
  141. #else
  142.     wsprintf(szBuf, "%s", lpszFileClass);
  143.     lResult = RegOpenKey(HKEY_CLASSES_ROOT, szBuf, &hKey);
  144. #endif
  145.     if (lResult != ERROR_SUCCESS)
  146.         return NULL;
  147.  
  148.     // Get the default value of the key
  149.     cbData = sizeof(szBuf);
  150. #ifdef _WIN32
  151.     lResult = RegQueryValueEx(hKey, NULL, NULL, &dwType, (LPBYTE)szBuf, &cbData);
  152. #else
  153.     lResult = RegQueryValue(hKey, "DefaultIcon", (LPSTR)szBuf, &cbData);
  154. #endif
  155.     RegCloseKey(hKey);
  156.  
  157.     if (lResult == ERROR_SUCCESS) {
  158.         // The syntax is a filename and an icon number separated by a comma
  159.         LPCSTR    lpszFilename = szBuf;
  160.         LPSTR    lpszComma;
  161.         int        nIconIndex = 0;
  162.  
  163.         lpszComma = strchr(szBuf, ',');
  164.         if (lpszComma) {
  165.             *lpszComma = '\0';  // null terminate the filename
  166.  
  167.             // Get the icon index
  168.             nIconIndex = atoi(lpszComma + 1);
  169.         }
  170.  
  171.         // Get the icon
  172.         return ExtractIcon(hInstance, lpszFilename, nIconIndex);
  173.     }
  174.  
  175.     return NULL;
  176. }
  177.  
  178. static HICON
  179. GetAppIcon(HINSTANCE hInstance, LPCSTR lpszAppPath)
  180. {
  181. #ifdef _WIN32
  182.     SHFILEINFO    sfi;
  183.     LPSTR        lpszFilePart;
  184.     char        szBuf[_MAX_PATH];
  185.     
  186.     // Get a full pathname
  187.     SearchPath(NULL, lpszAppPath, ".exe", sizeof(szBuf), szBuf, &lpszFilePart);
  188.     SHGetFileInfo(szBuf, 0, &sfi, sizeof(sfi), SHGFI_ICON);
  189.     return sfi.hIcon;
  190. #else
  191.     return ExtractIcon(hInstance, lpszAppPath, 0);
  192. #endif
  193. }
  194.  
  195. // Sets the shell open command string value for the given file class
  196. static void
  197. SetShellOpenCommand(LPCSTR lpszFileClass, LPCSTR lpszCmdString)
  198. {
  199.     char    szKey[_MAX_PATH];
  200. #ifdef _WIN32
  201.     DWORD    dwDisposition;
  202. #endif
  203.     HKEY    hKey;
  204.     LONG    lResult;
  205.  
  206.     // Build the subkey string
  207.     wsprintf(szKey, "%s\\shell\\open\\command", lpszFileClass);
  208.  
  209.     // Update the shell\open\command for the file type class
  210. #ifdef _WIN32
  211.     lResult = RegCreateKeyEx(HKEY_CLASSES_ROOT, szKey, 0, NULL, 0, KEY_WRITE,
  212.         NULL, &hKey, &dwDisposition);
  213.  
  214.     if (lResult == ERROR_SUCCESS) {
  215.         RegSetValueEx(hKey, NULL, 0, REG_SZ, (CONST BYTE *)lpszCmdString,
  216.             lstrlen(lpszCmdString) + 1);
  217.         RegCloseKey(hKey);
  218.     }
  219. #else
  220.     lResult = RegCreateKey(HKEY_CLASSES_ROOT, szKey, &hKey);
  221.  
  222.     if (lResult == ERROR_SUCCESS) {
  223.         RegSetValue(hKey, NULL, REG_SZ, lpszCmdString, lstrlen(lpszCmdString));
  224.         RegCloseKey(hKey);
  225.     }
  226. #endif
  227. }
  228.  
  229. // Returns the shell open command string value (path and filename for the application
  230. // plus any command line options) associated with the given file class
  231. static BOOL
  232. GetShellOpenCommand(LPCSTR lpszFileClass, LPSTR lpszCmdString, DWORD cbCmdString)
  233. {
  234.     char    szBuf[_MAX_PATH];
  235.     LONG    lResult;
  236.     HKEY    hKey;
  237. #ifdef _WIN32
  238.     DWORD    dwType;
  239. #else
  240.     LONG    cbData;
  241. #endif
  242.  
  243.     *lpszCmdString = '\0';
  244.     
  245.     // Get the Open command string value for the file class
  246. #ifdef _WIN32
  247.     wsprintf(szBuf, "%s\\shell\\open\\command", lpszFileClass);
  248.     lResult = RegOpenKeyEx(HKEY_CLASSES_ROOT, szBuf, 0, KEY_QUERY_VALUE, &hKey);
  249. #else
  250.     wsprintf(szBuf, "%s\\shell\\open", lpszFileClass);
  251.     lResult = RegOpenKey(HKEY_CLASSES_ROOT, szBuf, &hKey);
  252. #endif
  253.     if (lResult != ERROR_SUCCESS)
  254.         return FALSE;
  255.  
  256.     // Get the value
  257. #ifdef _WIN32
  258.     lResult = RegQueryValueEx(hKey, NULL, NULL, &dwType, (LPBYTE)lpszCmdString, &cbCmdString);
  259. #else
  260.     cbData = (LONG)cbCmdString;
  261.     lResult = RegQueryValue(hKey, "command", (LPSTR)lpszCmdString, &cbData);
  262. #endif
  263.     RegCloseKey(hKey);
  264.  
  265.     return lResult == ERROR_SUCCESS;
  266. }
  267.  
  268. // lpszPath must be _MAX_PATH characters in size. Quotes the filename if
  269. // it's a long filename with a space (Win32 only)
  270. static BOOL
  271. BrowseForProgram(HINSTANCE hInstance, HWND hwndOwner, LPSTR lpszPath)
  272. {
  273.     OPENFILENAME    ofn;
  274.     CString            strFilters;
  275.  
  276.     // Load the description and file patterns for the filters
  277.     strFilters.LoadString(hInstance, IDS_FILTER_PROGRAM);
  278.     
  279.     // Replace the '\n' with '\0' before calling the common dialogs
  280.     for (LPSTR lpsz = (LPSTR)(LPCSTR)strFilters; *lpsz;) {
  281.         if (*lpsz == '\n')
  282.             *lpsz++ = '\0';
  283.         else
  284.             lpsz += IsDBCSLeadByte(*lpsz) ? 2 : 1;
  285.     }
  286.  
  287.     memset(&ofn, 0, sizeof(ofn));
  288.     ofn.lStructSize = sizeof(ofn);
  289.     ofn.hwndOwner = hwndOwner;
  290.     ofn.lpstrFilter = strFilters;
  291.     ofn.lpstrFile = lpszPath;
  292.     *lpszPath = '\0';
  293.     ofn.nMaxFile = _MAX_PATH;
  294.     ofn.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY | OFN_NONETWORKBUTTON;
  295.  
  296.     // Bring up the common dialog
  297.     if (GetOpenFileName(&ofn)) {
  298. #ifdef _WIN32
  299.         // Don't quote an already quoted string. Note: this doesn't seem to be
  300.         // an issue, because GetOpenFileName() strips leading quotes and trims
  301.         // left and right spaces
  302.         if (*lpszPath && *lpszPath != '"') {
  303.             // See if the path contains a space
  304.             if (strchr(lpszPath, ' ')) {
  305.                 int    nLen = lstrlen(lpszPath);
  306.  
  307.                 assert(nLen > 0);
  308.                 // Make sure we can do this without overwriting the buffer. Note: the
  309.                 // 3 refers to the opening/closing quotes and the terminating '\0'
  310.                 if (nLen + 3 <= _MAX_PATH) {
  311.                     // Return a quoted string
  312.                     memmove(lpszPath + 1, lpszPath, nLen);
  313.                     lpszPath[0] = '"';
  314.                     lpszPath[nLen + 1] = '"';
  315.                     lpszPath[nLen + 2] = '\0';
  316.                 }
  317.             }
  318.         }
  319. #endif
  320.         return TRUE;
  321.     }
  322.  
  323.     return FALSE;
  324. }
  325.  
  326. /////////////////////////////////////////////////////////////////////////////
  327. // CBrowserPrefs implementation
  328.  
  329. CBrowserPrefs::CBrowserPrefs()
  330.     : CBrowserPropertyPage(IDD_BROWSER, HELP_PREFS_BROWSER)
  331. {
  332. }
  333.  
  334. // Initialize member data using XP preferences
  335. STDMETHODIMP
  336. CBrowserPrefs::Activate(HWND hwndParent, LPCRECT lprc, BOOL bModal)
  337. {
  338.     if (!m_bHasBeenActivated) {
  339.         int32    n;
  340.  
  341.         PREF_GetIntPref("browser.startup.page", &n);
  342.         m_nStartsWith = (int)n;
  343.  
  344.         PREF_GetStringPref("browser.startup.homepage", m_strHomePageURL);
  345.         
  346.         PREF_GetIntPref("browser.link_expiration", &n);
  347.         m_nExpireAfter = (int)n;
  348.  
  349.         // See if there's a current page URL available
  350.         assert(m_pObject);
  351.         if (m_pObject) {
  352.             LPBROWSERPREFS lpBrowserPrefs;
  353.  
  354.             // Request the IBrowserPrefs interface from our data object
  355.             if (SUCCEEDED(m_pObject->QueryInterface(IID_IBrowserPrefs, (void **)&lpBrowserPrefs))) {
  356.                 LPOLESTR    lpoleCurrentPage;
  357.  
  358.                 lpBrowserPrefs->GetCurrentPage(&lpoleCurrentPage);
  359.                 if (lpoleCurrentPage) {
  360.                     m_strCurrentPage = lpoleCurrentPage;
  361.                     CoTaskMemFree(lpoleCurrentPage);
  362.                 }
  363.                 
  364.                 lpBrowserPrefs->Release();
  365.             }
  366.         }
  367.     }
  368.  
  369.     return CBrowserPropertyPage::Activate(hwndParent, lprc, bModal);
  370. }
  371.  
  372. BOOL
  373. CBrowserPrefs::DoTransfer(BOOL bSaveAndValidate)
  374. {
  375.     RadioButtonTransfer(IDC_RADIO1, m_nStartsWith, bSaveAndValidate);
  376.     EditFieldTransfer(IDC_EDIT1, m_strHomePageURL, bSaveAndValidate);
  377.     EditFieldTransfer(IDC_EDIT2, m_nExpireAfter, bSaveAndValidate);
  378.     return TRUE;
  379. }
  380.  
  381. // Apply changes using XP preferences
  382. BOOL
  383. CBrowserPrefs::ApplyChanges()
  384. {
  385.     PREF_SetIntPref("browser.startup.page", (int32)m_nStartsWith);
  386.     PREF_SetCharPref("browser.startup.homepage", (LPCSTR)m_strHomePageURL);
  387.     PREF_SetIntPref("browser.link_expiration", (int32)m_nExpireAfter);
  388.     return TRUE;
  389. }
  390.  
  391. BOOL
  392. CBrowserPrefs::InitDialog()
  393. {
  394.     // Only enable the Use Current Page button if we were given a URL
  395.     EnableDlgItem(IDC_BUTTON1, !m_strCurrentPage.IsEmpty());
  396.  
  397.     // Check for locked preferences
  398.     if (PREF_PrefIsLocked("browser.startup.page")) {
  399.         // Disable all the radio buttons in the group
  400.         DisableRadioButtonGroup(IDC_RADIO1);
  401.     }
  402.     
  403.     if (CheckIfLockedPref("browser.startup.homepage", IDC_EDIT1)) {
  404.         // Disable Use Current Page and Browser buttons
  405.         EnableDlgItem(IDC_BUTTON1, FALSE);
  406.         EnableDlgItem(IDC_BUTTON2, FALSE);
  407.     }
  408.  
  409.     CheckIfLockedPref("browser.link_expiration", IDC_EDIT2);
  410.  
  411.     return CBrowserPropertyPage::InitDialog();
  412. }
  413.  
  414. BOOL
  415. CBrowserPrefs::OnCommand(int id, HWND hwndCtl, UINT notifyCode)
  416. {
  417.     if (id == IDC_BUTTON1 && notifyCode == BN_CLICKED) {
  418.         assert(!m_strCurrentPage.IsEmpty());
  419.         Edit_SetText(GetDlgItem(m_hwndDlg, IDC_EDIT1), (LPCSTR)m_strCurrentPage);
  420.         return TRUE;
  421.  
  422.     } else if (id == IDC_BUTTON2 && notifyCode == BN_CLICKED) {
  423.         OPENFILENAME    ofn;
  424.         CString            strFilters;
  425.         CString            strTitle;
  426.         char            szBuf[_MAX_PATH];
  427.  
  428.         // Load the description and file patterns for the filters
  429. #ifdef _WIN32
  430.         strFilters.LoadString(m_hInstance, IDS_FILTER_HTM32);
  431. #else
  432.         strFilters.LoadString(m_hInstance, IDS_FILTER_HTM16);
  433. #endif
  434.         
  435.         // Replace the '\n' with '\0' before calling the common dialogs
  436.         for (LPSTR lpsz = (LPSTR)(LPCSTR)strFilters; *lpsz;) {
  437.             if (*lpsz == '\n')
  438.                 *lpsz++ = '\0';
  439.             else
  440.                 lpsz += IsDBCSLeadByte(*lpsz) ? 2 : 1;
  441.         }
  442.  
  443.         // Get the title for the dialog
  444.         strTitle.LoadString(m_hInstance, IDS_BROWSE_HOMEPAGE);
  445.  
  446.         memset(&ofn, 0, sizeof(ofn));
  447.         ofn.lStructSize = sizeof(ofn);
  448.         ofn.hwndOwner = m_hwndDlg;
  449.         ofn.lpstrFilter = strFilters;
  450.         ofn.lpstrFile = szBuf;
  451.         szBuf[0] = '\0';
  452.         ofn.nMaxFile = sizeof(szBuf);
  453.         ofn.lpstrTitle = strTitle;
  454.         ofn.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY | OFN_NONETWORKBUTTON;
  455.  
  456.         // Bring up the common dialog
  457.         if (GetOpenFileName(&ofn)) {
  458.             Edit_SetText(GetDlgItem(m_hwndDlg, IDC_EDIT1), szBuf);
  459.         }
  460.  
  461.         return TRUE;
  462.  
  463.     } else if (id == IDC_BUTTON3 && notifyCode == BN_CLICKED) {
  464.         CString    strText, strCaption;
  465.         int32    nSize;
  466.  
  467.         strText.LoadString(m_hInstance, IDS_CONTINUE_CLEAR_HISTORY);
  468.         strCaption.LoadString(m_hInstance, IDS_HISTORY);
  469.  
  470.         if (MessageBox(GetParent(m_hwndDlg), (LPCSTR)strText, (LPCSTR)strCaption, MB_OKCANCEL | MB_ICONQUESTION) == IDOK) {
  471.             PREF_GetIntPref("browser.link_expiration", &nSize);
  472.             PREF_SetIntPref("browser.link_expiration", 0);
  473.             PREF_SetIntPref("browser.link_expiration", nSize);
  474.         }
  475.         return TRUE;
  476.     }
  477.  
  478.     return CBrowserPropertyPage::OnCommand(id, hwndCtl, notifyCode);
  479. }
  480.  
  481. /////////////////////////////////////////////////////////////////////////////
  482. // CAddLanguagesDialog implementation
  483.  
  484. class CAddLanguagesDialog : public CDialog {
  485.     public:
  486.         CAddLanguagesDialog();
  487.  
  488.         // Returns the language that was selected
  489.         LPCSTR    GetLanguage();
  490.  
  491.     protected:
  492.         BOOL    InitDialog();
  493.         BOOL    DoTransfer(BOOL bSaveAndValidate);
  494.  
  495.         // Event processing
  496.         BOOL    OnCommand(int id, HWND hwndCtl, UINT notifyCode);
  497.  
  498.     private:
  499.         CString    m_strLanguage;
  500.         CString    m_strOther;
  501. };
  502.  
  503. CAddLanguagesDialog::CAddLanguagesDialog()
  504.     : CDialog(CComDll::m_hInstance, IDD_ADD_LANGUAGES)
  505. {
  506. }
  507.  
  508. BOOL
  509. CAddLanguagesDialog::InitDialog()
  510. {
  511.     HWND    hList;
  512.     char    szBuf[256];
  513.  
  514.     // Fill the list box
  515.     hList = GetDlgItem(m_hwndDlg, IDC_LIST1);
  516.  
  517.     // NOTE: All the strings to be added to the list box must be numbered
  518.     // consecutively
  519.     for (int i = IDS_ACCEPTLANG_START; i < IDS_ACCEPTLANG_END; i++) {
  520.         int    nLen = LoadString(m_hInstance, i, szBuf, sizeof(szBuf));
  521.         
  522.         assert(nLen > 0);
  523.         ListBox_AddString(hList, szBuf);
  524.     }
  525.  
  526.     // Limit the length of the string the user can type
  527.     Edit_LimitText(GetDlgItem(m_hwndDlg, IDC_EDIT1), 64);
  528.  
  529.     return CDialog::InitDialog();
  530. }
  531.  
  532. LPCSTR
  533. CAddLanguagesDialog::GetLanguage()
  534. {
  535.     if (!m_strOther.IsEmpty())
  536.         return (LPCSTR)m_strOther;
  537.  
  538.     return m_strLanguage.IsEmpty() ? NULL : (LPCSTR)m_strLanguage;
  539. }
  540.  
  541. BOOL
  542. CAddLanguagesDialog::DoTransfer(BOOL bSaveAndValidate)
  543. {
  544.     if (bSaveAndValidate)
  545.         ListBoxTransfer(IDC_LIST1, m_strLanguage, bSaveAndValidate);
  546.     else
  547.         ListBox_SetCurSel(GetDlgItem(m_hwndDlg, IDC_LIST1), 0);
  548.     EditFieldTransfer(IDC_EDIT1, m_strOther, bSaveAndValidate);
  549.     return TRUE;
  550. }
  551.  
  552. BOOL
  553. CAddLanguagesDialog::OnCommand(int id, HWND hwndCtl, UINT notifyCode)
  554. {
  555.     if (id == IDC_LIST1 && notifyCode == LBN_DBLCLK) {
  556.         FORWARD_WM_COMMAND(m_hwndDlg, IDOK, GetDlgItem(m_hwndDlg, IDOK), BN_CLICKED, SendMessage);
  557.         return TRUE;
  558.  
  559.     } else if (id == IDC_EDIT1 && notifyCode == EN_CHANGE) {
  560.         // Disable the list box if the user has typed something into
  561.         // the edit field
  562.         EnableDlgItem(IDC_LIST1, Edit_GetTextLength(hwndCtl) == 0);
  563.     }
  564.  
  565.     return CDialog::OnCommand(id, hwndCtl, notifyCode);
  566. }
  567.  
  568. /////////////////////////////////////////////////////////////////////////////
  569. // CLanguagesPrefs implementation
  570.  
  571. CLanguagesPrefs::CLanguagesPrefs()
  572.     : CBrowserPropertyPage(IDD_LANGUAGES, HELP_PREFS_BROWSER_LANGUAGES)
  573. {
  574. }
  575.  
  576. // Initialize member data using XP preferences
  577. STDMETHODIMP
  578. CLanguagesPrefs::Activate(HWND hwndParent, LPCRECT lprc, BOOL bModal)
  579. {
  580.     if (!m_bHasBeenActivated) {
  581.         PREF_GetStringPref("intl.accept_languages", m_strAcceptLangs);
  582.     }
  583.  
  584.     return CBrowserPropertyPage::Activate(hwndParent, lprc, bModal);
  585. }
  586.  
  587. // XXX - move into cdialog.h
  588. static void
  589. ListBox_GetString(HWND hwndList, int nIndex, CString &str)
  590. {
  591.     assert(nIndex >= 0);
  592.     ListBox_GetText(hwndList, nIndex,
  593.         str.BufferSetLength(ListBox_GetTextLen(hwndList, nIndex)));
  594. }
  595.  
  596. BOOL
  597. CLanguagesPrefs::DoTransfer(BOOL bSaveAndValidate)
  598. {
  599.     if (bSaveAndValidate) {
  600.         HWND    hwndList = GetDlgItem(m_hwndDlg, IDC_LIST1);
  601.         int        nListCount = ListBox_GetCount(hwndList);
  602.         CString    strText;
  603.         
  604.         // Build up the list of accept languages
  605.         m_strAcceptLangs.Empty();
  606.  
  607.         if (nListCount != LB_ERR) {
  608.             for (int i = 0; i < nListCount; i++) {
  609.                 ListBox_GetString(hwndList, i, strText);
  610.  
  611.                 if (i == 0)
  612.                     m_strAcceptLangs = strText;
  613.                 else
  614.                     m_strAcceptLangs += ',' + strText;
  615.             }
  616.         }
  617.         
  618.     }
  619.  
  620.     if (!bSaveAndValidate)
  621.         CheckButtons();
  622.  
  623.     return TRUE;
  624. }
  625.  
  626. // Apply changes using XP preferences
  627. BOOL
  628. CLanguagesPrefs::ApplyChanges()
  629. {
  630.     PREF_SetCharPref("intl.accept_languages", (LPCSTR)m_strAcceptLangs);
  631.     return TRUE;
  632. }
  633.  
  634. BOOL
  635. CLanguagesPrefs::InitDialog()
  636. {
  637.     // Load the bitmaps
  638. #ifdef _WIN32
  639.     m_hUpBitmap = LoadImage(m_hInstance, MAKEINTRESOURCE(IDB_UPARROW), IMAGE_BITMAP,
  640.         0, 0, LR_LOADTRANSPARENT | LR_LOADMAP3DCOLORS);
  641.     m_hDownBitmap = LoadImage(m_hInstance, MAKEINTRESOURCE(IDB_DOWNARROW), IMAGE_BITMAP,
  642.         0, 0, LR_LOADTRANSPARENT | LR_LOADMAP3DCOLORS);
  643. #else
  644.     m_hUpBitmap = LoadTransparentBitmap(m_hInstance, IDB_UPARROW);
  645.     m_hDownBitmap = LoadTransparentBitmap(m_hInstance, IDB_DOWNARROW);
  646. #endif
  647.  
  648.     // Create the memory DC we'll need
  649.     m_hMemDC = CreateCompatibleDC(NULL);
  650.  
  651.     // Size the buttons to fit the bitmaps
  652.     SizeToFitBitmapButton(GetDlgItem(m_hwndDlg, IDC_BUTTON3), m_hUpBitmap);
  653.     SizeToFitBitmapButton(GetDlgItem(m_hwndDlg, IDC_BUTTON4), m_hDownBitmap);
  654.  
  655.     // We don't receive the WM_MEASUREITEM message, because it's sent before
  656.     // the WM_INITDIALOG, so set the height of the list box items now
  657.     SetLBoxItemHeight();
  658.  
  659.     // Fill the list box with the list of accept languages
  660.     FillListBox();
  661.  
  662.     EnableDlgItem(IDC_LIST1, !PREF_PrefIsLocked("intl.accept_languages"));
  663.     EnableDlgItem(IDC_BUTTON1, !PREF_PrefIsLocked("intl.accept_languages"));
  664.     EnableDlgItem(IDC_BUTTON2, !PREF_PrefIsLocked("intl.accept_languages"));
  665.     EnableDlgItem(IDC_BUTTON3, !PREF_PrefIsLocked("intl.accept_languages"));
  666.     EnableDlgItem(IDC_BUTTON4, !PREF_PrefIsLocked("intl.accept_languages"));
  667.  
  668.  
  669.     return CBrowserPropertyPage::InitDialog();
  670. }
  671.  
  672. void
  673. CLanguagesPrefs::FillListBox()
  674. {
  675.     if (!m_strAcceptLangs.IsEmpty()) {
  676.         HWND    hwndList = GetDlgItem(m_hwndDlg, IDC_LIST1);
  677.         int        nIndex;
  678.         CString    strTmp(m_strAcceptLangs);
  679.  
  680.         while ((nIndex = strTmp.Find(',')) != -1) {
  681.             ListBox_AddString(hwndList, (LPCSTR)strTmp.Left(nIndex));
  682.             strTmp = strTmp.Mid(nIndex + 1);
  683.         }
  684.  
  685.         ListBox_AddString(hwndList, (LPCSTR)strTmp);  // add last string
  686.     }
  687. }
  688.  
  689. BOOL
  690. CLanguagesPrefs::OnCommand(int id, HWND hwndCtl, UINT notifyCode)
  691. {
  692.     switch (id) {
  693.         case IDC_BUTTON1:
  694.             if (notifyCode == BN_CLICKED) {
  695.                 CAddLanguagesDialog    dlg;
  696.         
  697.                 // Display the "Add Languages" dialog box
  698.                 if (dlg.DoModal(GetParent(m_hwndDlg)) == IDOK) {
  699.                     HWND     hList = GetDlgItem(m_hwndDlg, IDC_LIST1);
  700.                     int        nIndex;
  701.         
  702.                     // See if the string is already in the list. If it is then just
  703.                     // select the existing list item
  704.                     nIndex = ListBox_FindStringExact(hList, 0, dlg.GetLanguage());
  705.  
  706.                     if (nIndex != LB_ERR)
  707.                         ListBox_SetCurSel(hList, nIndex);
  708.  
  709.                     else {
  710.                         nIndex = ListBox_AddString(hList, dlg.GetLanguage());
  711.                         ListBox_SetCurSel(hList, nIndex);
  712.                         CheckButtons();
  713.                     }
  714.                 }
  715.             }
  716.             return TRUE;
  717.  
  718.         case IDC_BUTTON2:
  719.             if (notifyCode == BN_CLICKED) {
  720.                 HWND     hList = GetDlgItem(m_hwndDlg, IDC_LIST1);
  721.                 int        nCurSel = ListBox_GetCurSel(hList);
  722.  
  723.                 // Delete the selected list box item
  724.                 assert(nCurSel != LB_ERR);
  725.                 if (nCurSel != LB_ERR) {
  726.                     ListBox_DeleteString(hList, nCurSel);
  727.                     if (ListBox_GetCount(hList) > 0)
  728.                         ListBox_SetCurSel(hList, nCurSel > 0 ? nCurSel - 1 : 0);
  729.                     CheckButtons();
  730.                 }
  731.             }
  732.             return TRUE;
  733.  
  734.         case IDC_BUTTON3:
  735.         case IDC_BUTTON4:
  736.             if (notifyCode == BN_CLICKED || notifyCode == BN_DOUBLECLICKED) {
  737.                 HWND     hList = GetDlgItem(m_hwndDlg, IDC_LIST1);
  738.                 int        nCurSel = ListBox_GetCurSel(hList);
  739.  
  740.                 // Move the selected list box item up or down
  741.                 assert(nCurSel != LB_ERR);
  742.                 if (nCurSel != LB_ERR) {
  743.                     CString    strItem;
  744.                     int        nLen = ListBox_GetTextLen(hList, nCurSel);
  745.                     int        nIndex;
  746.  
  747.                     ListBox_GetText(hList, nCurSel, strItem.BufferSetLength(nLen));
  748.                     ListBox_DeleteString(hList, nCurSel);
  749.                     nIndex = ListBox_InsertString(hList, id == IDC_BUTTON3 ? nCurSel - 1 :
  750.                         nCurSel + 1, (LPCSTR)strItem);
  751.                     ListBox_SetCurSel(hList, nIndex);
  752.                     CheckButtons();
  753.                 }
  754.  
  755.             }
  756.             return TRUE;
  757.  
  758.         case IDC_LIST1:
  759.             if (notifyCode == LBN_SELCHANGE)
  760.                 CheckButtons();
  761.             return TRUE;
  762.     }
  763.  
  764.     return CBrowserPropertyPage::OnCommand(id, hwndCtl, notifyCode);
  765. }
  766.  
  767. void
  768. CLanguagesPrefs::SetLBoxItemHeight()
  769. {
  770.     TEXTMETRIC    tm;
  771.     HWND        hwndCtl = GetDlgItem(m_hwndDlg, IDC_LIST1);
  772.     HFONT        hFont = GetWindowFont(hwndCtl);
  773.     HDC            hDC = GetDC(hwndCtl);
  774.     HFONT        hOldFont = NULL;
  775.  
  776.     if (hFont)
  777.         hOldFont = SelectFont(hDC, hFont);
  778.  
  779.     GetTextMetrics(hDC, &tm);
  780.  
  781.     // Cleanup and release the HDC
  782.     if (hOldFont)
  783.         SelectObject(hDC, hOldFont);
  784.     ReleaseDC(hwndCtl, hDC);
  785.  
  786.     // Compute the tab stops. The second tab stop is left aligned
  787.     // with the "Language" column heading
  788.     HWND    hStatic = GetDlgItem(m_hwndDlg, IDC_LANGUAGE_HEADING);
  789.     RECT    r;
  790.  
  791.     m_nTabStops[0] = 2 * tm.tmAveCharWidth;
  792.     assert(hStatic);
  793.     GetWindowRect(hStatic, &r);
  794.     MapWindowPoints(NULL, hwndCtl, (LPPOINT)&r, 2);
  795.     m_nTabStops[1] = r.left;
  796.  
  797.     // Set the height of a single item
  798.     ListBox_SetItemHeight(hwndCtl, 0, tm.tmHeight);
  799. }
  800.  
  801. void
  802. CLanguagesPrefs::DrawLBoxItem(LPDRAWITEMSTRUCT lpdis)
  803. {
  804.     char    szBuf[256];
  805.     int        nLen;
  806.     int     nColorIndex;
  807.     HWND    hwndFocus = GetFocus();  // don't trust ODS_FOCUS
  808.  
  809.     switch (lpdis->itemAction) {
  810.         case ODA_DRAWENTIRE:
  811.         case ODA_SELECT:
  812.         case ODA_FOCUS:
  813.             nColorIndex = COLOR_WINDOWTEXT;
  814.             if ((lpdis->itemState & ODS_SELECTED) && (hwndFocus == lpdis->hwndItem))
  815.                 nColorIndex = COLOR_HIGHLIGHTTEXT;
  816.             SetTextColor(lpdis->hDC, GetSysColor(nColorIndex));
  817.  
  818.             // Behave like a 32-bit list view and use a different color to indicate
  819.             // selection when we don't have the focus
  820.             nColorIndex = COLOR_WINDOW;
  821.             if (lpdis->itemState & ODS_SELECTED)
  822.                 nColorIndex = (hwndFocus == lpdis->hwndItem ? COLOR_HIGHLIGHT : COLOR_BTNFACE);
  823.             SetBkColor(lpdis->hDC, GetSysColor(nColorIndex));
  824.     
  825.             assert(lpdis->itemID != (UINT)-1);
  826.  
  827.             // Draw the order number. Paint the list item rect at the same time
  828.             wsprintf(szBuf, "%i", lpdis->itemID + 1);
  829.             ExtTextOut(lpdis->hDC, lpdis->rcItem.left + m_nTabStops[0], lpdis->rcItem.top,
  830.                 ETO_OPAQUE, &lpdis->rcItem, szBuf, lstrlen(szBuf), NULL);
  831.     
  832.             // Draw the language. Because this is an owner-draw list box, we need to
  833.             // ask the list box for the string
  834.             nLen = ListBox_GetTextLen(lpdis->hwndItem, lpdis->itemID);
  835.     
  836.             if (nLen < sizeof(szBuf)) {
  837.                 ListBox_GetText(lpdis->hwndItem, lpdis->itemID, szBuf);
  838.             
  839.                 ExtTextOut(lpdis->hDC, lpdis->rcItem.left + m_nTabStops[1], lpdis->rcItem.top,
  840.                 0, &lpdis->rcItem, szBuf, nLen, NULL);
  841.             }
  842.             
  843.             // Draw the focus rect if necessary
  844.             if (lpdis->itemState & ODS_FOCUS)
  845.                 ::DrawFocusRect(lpdis->hDC, &lpdis->rcItem);
  846.             break;
  847.     }
  848. }
  849.  
  850. LRESULT
  851. CLanguagesPrefs::WindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
  852. {
  853.     LPDRAWITEMSTRUCT    lpdis;
  854.  
  855.     switch (uMsg) {
  856.         case WM_DESTROY:
  857.             DeleteBitmap(m_hUpBitmap);
  858.             DeleteBitmap(m_hDownBitmap);
  859.             DeleteDC(m_hMemDC);
  860.             break;
  861.  
  862.         case WM_DRAWITEM:
  863.             lpdis = (LPDRAWITEMSTRUCT)lParam;
  864.  
  865.             if (lpdis->CtlID == IDC_LIST1)
  866.                 DrawLBoxItem(lpdis);
  867.             else
  868.                 DrawBitmapButton(lpdis, lpdis->CtlID == IDC_BUTTON3 ? m_hUpBitmap :
  869.                     m_hDownBitmap, m_hMemDC);
  870.             return TRUE;
  871.     }
  872.  
  873.     return CBrowserPropertyPage::WindowProc(uMsg, wParam, lParam);
  874. }
  875.  
  876. void
  877. CLanguagesPrefs::CheckButtons()
  878. {
  879.     HWND    hwndList = GetDlgItem(m_hwndDlg, IDC_LIST1);
  880.     int        nListCount, nCurSel;
  881.     HWND    hwndUpBtn, hwndDownBtn, hwndFocus;
  882.  
  883.     assert(hwndList);
  884.     nListCount = ListBox_GetCount(hwndList);
  885.     nCurSel = ListBox_GetCurSel(hwndList);
  886.  
  887.     // Enable the Delete button if there's something selected in
  888.     // the list box
  889.     EnableDlgItem(IDC_BUTTON2, nCurSel != LB_ERR);
  890.  
  891.     // Enable the Up/Down buttons
  892.     hwndUpBtn = GetDlgItem(m_hwndDlg, IDC_BUTTON3);
  893.     hwndDownBtn = GetDlgItem(m_hwndDlg, IDC_BUTTON4);
  894.     hwndFocus = GetFocus();
  895.     
  896.     if (nListCount <= 1 || nCurSel == LB_ERR) {
  897.         EnableWindow(hwndUpBtn, FALSE);
  898.         EnableWindow(hwndDownBtn, FALSE);
  899.     
  900.         // Make sure there's still a focus window. If one of the buttons had
  901.         // focus, and we disabled that button then no one has the focus
  902.         if (hwndFocus == hwndUpBtn || hwndFocus == hwndDownBtn)
  903.             SetFocus(hwndList);
  904.  
  905.     } else {
  906.         EnableWindow(hwndUpBtn, nCurSel > 0);
  907.         EnableWindow(hwndDownBtn, nCurSel != LB_ERR && nCurSel < (nListCount - 1));
  908.         
  909.         // Make sure there's still a focus window. If one of the buttons had
  910.         // focus, and we disabled that button then no one has the focus
  911.         if (hwndFocus == hwndUpBtn && !IsWindowEnabled(hwndUpBtn))
  912.             SetFocus(hwndDownBtn);
  913.  
  914.         if (hwndFocus == hwndDownBtn && !IsWindowEnabled(hwndDownBtn))
  915.             SetFocus(hwndUpBtn);
  916.     }
  917. }
  918.  
  919. /////////////////////////////////////////////////////////////////////////////
  920. // CEditTypeDialog implementation
  921.  
  922. class CEditTypeDialog : public CDialog {
  923.     public:
  924.         CEditTypeDialog();
  925.  
  926.     protected:
  927.         BOOL    InitDialog();
  928.         BOOL    DoTransfer(BOOL bSaveAndValidate);
  929.  
  930.         // Event processing
  931.         BOOL    OnCommand(int id, HWND hwndCtl, UINT notifyCode);
  932.     
  933.     public:
  934.         HICON        m_hDocIcon;
  935.         CString        m_strDescription;
  936.         CString        m_strExtension;
  937.         CString        m_strMimeType;
  938.         int            m_nHowToHandle;
  939.         BOOL        m_bConfirmBeforeOpening;
  940.         CString        m_strOpenCmd;
  941.         BOOL        m_bURLProtocol;
  942.  
  943.     private:
  944.         void    CheckControls();
  945. };
  946.  
  947. CEditTypeDialog::CEditTypeDialog()
  948.     : CDialog(CComDll::m_hInstance, IDD_EDIT_TYPE)
  949. {
  950.     m_bConfirmBeforeOpening = TRUE;
  951.     m_bURLProtocol = FALSE;
  952. }
  953.  
  954. BOOL
  955. CEditTypeDialog::InitDialog()
  956. {
  957.     // Set the description, document icon, and list of extensions
  958.     Static_SetText(GetDlgItem(m_hwndDlg, IDC_DESCRIPTION), m_strDescription);
  959.     Static_SetText(GetDlgItem(m_hwndDlg, IDC_EXTENSION), m_strExtension);
  960.     if (m_hDocIcon)
  961.         Static_SetIcon(GetDlgItem(m_hwndDlg, IDC_ICON1), m_hDocIcon);
  962.  
  963.     // Only enable the option to have Navigator handle it if it's one of
  964.     // the types we know how to view
  965.     if (strcmp(m_strMimeType, TEXT_HTML) == 0 || 
  966.         strcmp(m_strMimeType, TEXT_PLAIN) == 0 ||
  967.         strcmp(m_strMimeType, IMAGE_GIF) == 0 || 
  968.         strcmp(m_strMimeType, IMAGE_JPG) == 0 || 
  969.         strcmp(m_strMimeType, IMAGE_XBM) == 0) {
  970.  
  971.         EnableDlgItem(IDC_RADIO1, TRUE);
  972.     }
  973.  
  974.     // See if it's a URL protocol
  975.     if (m_bURLProtocol) {
  976.         EnableDlgItem(IDC_EDIT1, FALSE);
  977.         EnableDlgItem(IDC_RADIO2, FALSE);
  978.         EnableDlgItem(IDC_CHECK1, FALSE);
  979.     }
  980.  
  981.     return CDialog::InitDialog();
  982. }
  983.  
  984. void
  985. CEditTypeDialog::CheckControls()
  986. {
  987.     int    nHowToHandle;
  988.  
  989.     // Only enable the check box if we're launching a helper app, i.e. not if
  990.     // Netscape is handling it internally or it's set as save to disk
  991.     RadioButtonTransfer(IDC_RADIO1, nHowToHandle, TRUE);
  992.     EnableDlgItem(IDC_CHECK1, nHowToHandle == 2);
  993. }
  994.  
  995. BOOL
  996. CEditTypeDialog::DoTransfer(BOOL bSaveAndValidate)
  997. {
  998.     int        nRadio;
  999.  
  1000.     if (!bSaveAndValidate) {
  1001.         // Map from the values the browser uses
  1002.         switch (m_nHowToHandle) {
  1003.             case HANDLE_VIA_NETSCAPE:
  1004.                 nRadio = 0;
  1005.                 break;
  1006.  
  1007.             case HANDLE_SAVE:
  1008.                 nRadio = 1;
  1009.                 break;
  1010.  
  1011.             case HANDLE_EXTERNAL:
  1012.             case HANDLE_SHELLEXECUTE:
  1013.             case HANDLE_BY_OLE:
  1014.                 nRadio = 2;
  1015.                 break;
  1016.         }
  1017.     }
  1018.  
  1019.     RadioButtonTransfer(IDC_RADIO1, nRadio, bSaveAndValidate);
  1020.     EditFieldTransfer(IDC_EDIT1, m_strMimeType, bSaveAndValidate);
  1021.     EditFieldTransfer(IDC_EDIT2, m_strOpenCmd, bSaveAndValidate);
  1022.     CheckBoxTransfer(IDC_CHECK1, m_bConfirmBeforeOpening, bSaveAndValidate);
  1023.  
  1024.     if (bSaveAndValidate) {
  1025.         // Map it back to the values the browser uses
  1026.         switch (nRadio) {
  1027.             case 0:
  1028.                 m_nHowToHandle = HANDLE_VIA_NETSCAPE;
  1029.                 break;
  1030.  
  1031.             case 1:
  1032.                 m_nHowToHandle = HANDLE_SAVE;
  1033.                 break;
  1034.  
  1035.             case 2:
  1036.                 if (m_nHowToHandle != HANDLE_EXTERNAL)
  1037.                     m_nHowToHandle = HANDLE_SHELLEXECUTE;
  1038.                 break;
  1039.  
  1040.             default:
  1041.                 assert(FALSE);
  1042.                 break;
  1043.         }
  1044.  
  1045.     } else {
  1046.         // Check whether the check box to prompt before opening a downloaded
  1047.         // file should be enabled
  1048.         CheckControls();
  1049.     }
  1050.  
  1051.     return TRUE;
  1052. }
  1053.  
  1054. BOOL
  1055. CEditTypeDialog::OnCommand(int id, HWND hwndCtl, UINT notifyCode)
  1056. {
  1057.     if (id == IDC_BUTTON1 && notifyCode == BN_CLICKED) {
  1058.         char    szPath[_MAX_PATH];
  1059.  
  1060.         if (BrowseForProgram(m_hInstance, m_hwndDlg, szPath))
  1061.             Edit_SetText(GetDlgItem(m_hwndDlg, IDC_EDIT2), szPath);
  1062.         return TRUE;
  1063.  
  1064.     } else if ((id == IDC_RADIO1 || id == IDC_RADIO2 || id == IDC_RADIO3) && (notifyCode == BN_CLICKED)) {
  1065.         // Check whether the check box to prompt before opening a downloaded
  1066.         // file should be enabled
  1067.         CheckControls();
  1068.     }
  1069.  
  1070.     return CDialog::OnCommand(id, hwndCtl, notifyCode);
  1071. }
  1072.  
  1073. /////////////////////////////////////////////////////////////////////////////
  1074. // CNewTypeDialog implementation
  1075.  
  1076. class CNewTypeDialog : public CDialog {
  1077.     public:
  1078.         CNewTypeDialog();
  1079.  
  1080.     protected:
  1081.         BOOL    DoTransfer(BOOL bSaveAndValidate);
  1082.         
  1083.         // Event processing
  1084.         BOOL    OnCommand(int id, HWND hwndCtl, UINT notifyCode);
  1085.  
  1086.     public:
  1087.         CString        m_strDescription;
  1088.         CString        m_strExtension;
  1089.         CString        m_strMimeType;
  1090.         CString        m_strOpenCmd;
  1091.  
  1092.     private:
  1093.         void    DisplayMessageBox(UINT nID);
  1094. };
  1095.  
  1096. CNewTypeDialog::CNewTypeDialog()
  1097.     : CDialog(CComDll::m_hInstance, IDD_NEW_TYPE)
  1098. {
  1099. }
  1100.  
  1101. void
  1102. CNewTypeDialog::DisplayMessageBox(UINT nID)
  1103. {
  1104.     char    szCaption[256];
  1105.     char    szText[256];
  1106.  
  1107.     // Load the caption for the message box
  1108.     LoadString(m_hInstance, IDS_FILE_TYPES, szCaption, sizeof(szCaption));
  1109.  
  1110.     // Load the text to display
  1111.     LoadString(m_hInstance, nID, szText, sizeof(szText));
  1112.  
  1113.     // Display the message box
  1114.     MessageBox(m_hwndDlg, szText, szCaption, MB_OK | MB_ICONSTOP);
  1115. }
  1116.  
  1117. #ifdef _WIN32
  1118. static BOOL
  1119. HasMimeType(LPCSTR lpszExtension)
  1120. {
  1121.     char    szKey[_MAX_EXT + 1];  // space for '.'
  1122.     HKEY    hKey;
  1123.     LONG    lResult;
  1124.  
  1125.     // Build the file association key. It must begin with a '.'
  1126.     wsprintf(szKey, ".%s", lpszExtension);
  1127.     
  1128.     // See if the extension has a mime type (Content Type).
  1129.     lResult = RegOpenKeyEx(HKEY_CLASSES_ROOT, szKey, 0, KEY_QUERY_VALUE, &hKey);
  1130.     if (lResult == ERROR_SUCCESS) {
  1131.         DWORD    dwType;
  1132.         DWORD    cbData;
  1133.         
  1134.         // Get the size of the data for the Content Type value
  1135.         cbData = 0;
  1136.         lResult = RegQueryValueEx(hKey, "Content Type", NULL, &dwType, NULL, &cbData);
  1137.         RegCloseKey(hKey);
  1138.         return lResult == ERROR_SUCCESS && cbData > 1;
  1139.     }
  1140.     
  1141.     return FALSE;
  1142. }
  1143. #endif
  1144.  
  1145. BOOL
  1146. CNewTypeDialog::DoTransfer(BOOL bSaveAndValidate)
  1147. {
  1148.     EditFieldTransfer(IDC_EDIT1, m_strDescription, bSaveAndValidate);
  1149.     EditFieldTransfer(IDC_EDIT2, m_strExtension, bSaveAndValidate);
  1150.     EditFieldTransfer(IDC_EDIT3, m_strMimeType, bSaveAndValidate);
  1151.     EditFieldTransfer(IDC_EDIT4, m_strOpenCmd, bSaveAndValidate);
  1152.  
  1153.     // Validate the data
  1154.     if (bSaveAndValidate) {
  1155.         char    szFileClass[80];
  1156.         
  1157.         // See if the extension begins with a leading '.' If it does strip
  1158.         // it off
  1159.         while (m_strExtension[0] == '.') {
  1160.             m_strExtension = m_strExtension.Mid(1);
  1161.  
  1162.             // Update what's displayed so the user sees we changed the extension
  1163.             Edit_SetText(GetDlgItem(m_hwndDlg, IDC_EDIT2), (LPCSTR)m_strExtension);
  1164.         }
  1165.  
  1166.         if (m_strExtension.IsEmpty()) {
  1167.             DisplayMessageBox(IDS_NO_EXTENSION);
  1168.             SetFocus(GetDlgItem(m_hwndDlg, IDC_EDIT2));
  1169.             return FALSE;
  1170.         }
  1171.  
  1172.         if (m_strMimeType.IsEmpty()) {
  1173.             DisplayMessageBox(IDS_NO_MIME_TYPE);
  1174.             SetFocus(GetDlgItem(m_hwndDlg, IDC_EDIT3));
  1175.             return FALSE;
  1176.         }
  1177.         
  1178.         if (m_strOpenCmd.IsEmpty()) {
  1179.             DisplayMessageBox(IDS_NO_OPEN_CMD);
  1180.             SetFocus(GetDlgItem(m_hwndDlg, IDC_EDIT4));
  1181.             return FALSE;
  1182.         }
  1183.  
  1184. #ifdef _WIN32
  1185.         // See if there's a file type class already associated with this extension.
  1186.         // Note that we're checking for a file class, and not just whether the extension
  1187.         // exists
  1188.         if (GetFileClass((LPCSTR)m_strExtension, szFileClass, sizeof(szFileClass))) {
  1189.             CString strDescription;
  1190.             char    szCaption[256];
  1191.             char    szMessage[256];
  1192.             LPSTR   lpszText;
  1193.         
  1194.             // We allow a file extension to have more than one MIME type, so see whether this
  1195.             // extension already has a MIME type. If it does then the user is adding an
  1196.             // additional MIME type and that's okay
  1197.             //
  1198.             // If there is no MIME type then we pref they edit the existing type, and specify
  1199.             // specify the MIME type rather than creating a brand new type. The only reason for
  1200.             // this is that we want to avoid having two entries in the list, one with no MIME
  1201.             // type
  1202.             //
  1203.             // Note: on Win16 the mapping from MIME type to suffix isn't stored in the registry so
  1204.             // we don't bother with this. We could scan through the list of NET_cdataStruct
  1205.             // structures, but that wouldn't necessarily tell us whether there's a MIME type
  1206.             // specified in the Netscape specific suffix information
  1207.             //
  1208.             // Some day when we switch to using XP prefs for the Netscape specific information
  1209.             // this will be easy to do for Win16 as well
  1210.             if (!HasMimeType((LPCSTR)m_strExtension)) {
  1211.                 // Get the description of the existig file type
  1212.                 GetFileTypeDescription(szFileClass, strDescription);
  1213.     
  1214.                 // Load the caption for the message box and message string
  1215.                 LoadString(m_hInstance, IDS_FILE_TYPES, szCaption, sizeof(szCaption));
  1216.                 LoadString(m_hInstance, IDS_EXT_IN_USE, szMessage, sizeof(szMessage));
  1217.             
  1218.                 // Format the text
  1219.                 lpszText = (LPSTR)CoTaskMemAlloc(lstrlen(szMessage) + m_strExtension.GetLength() + strDescription.GetLength());
  1220.                 wsprintf(lpszText, szMessage, (LPCSTR)m_strExtension, (LPCSTR)strDescription);
  1221.             
  1222.                 // Display the message box
  1223.                 MessageBox(m_hwndDlg, lpszText, szCaption, MB_OK | MB_ICONSTOP);
  1224.                 CoTaskMemFree(lpszText);
  1225.                 SetFocus(GetDlgItem(m_hwndDlg, IDC_EDIT2));
  1226.                 return FALSE;
  1227.             }
  1228.         }
  1229. #endif
  1230.     }
  1231.  
  1232.     return TRUE;
  1233. }
  1234.  
  1235. BOOL
  1236. CNewTypeDialog::OnCommand(int id, HWND hwndCtl, UINT notifyCode)
  1237. {
  1238.     if (id == IDC_BUTTON1 && notifyCode == BN_CLICKED) {
  1239.         char    szPath[_MAX_PATH];
  1240.  
  1241.         if (BrowseForProgram(m_hInstance, m_hwndDlg, szPath))
  1242.             Edit_SetText(GetDlgItem(m_hwndDlg, IDC_EDIT4), szPath);
  1243.         return TRUE;
  1244.  
  1245.     } else if (id == IDC_EDIT2 && notifyCode == EN_KILLFOCUS) {
  1246.         CString    strExtension;
  1247.         char    szFileClass[80];
  1248.  
  1249.         // The edit control for specifying the extension has lost focus.
  1250.         // See if there's an existing file type class for the extension, and
  1251.         // pre-fill the open command edit control
  1252.         EditFieldTransfer(IDC_EDIT2, strExtension, TRUE);
  1253.  
  1254.         // See if the extension begins with a leading '.' If it does strip
  1255.         // it off
  1256.         while (strExtension[0] == '.') {
  1257.             strExtension = strExtension.Mid(1);
  1258.  
  1259.             // Update what's displayed so the user sees we changed the extension
  1260.             Edit_SetText(GetDlgItem(m_hwndDlg, IDC_EDIT2), (LPCSTR)strExtension);
  1261.         }
  1262.  
  1263.         // Look up the file type class for the extension
  1264.         if (GetFileClass((LPCSTR)strExtension, szFileClass, sizeof(szFileClass))) {
  1265.             char    szOpenCmd[_MAX_PATH + 32];
  1266.     
  1267.             // Get the shell open command
  1268.             if (GetShellOpenCommand(szFileClass, szOpenCmd, sizeof(szOpenCmd))) {
  1269.                 // Pre-fill the open command edit control
  1270.                 Edit_SetText(GetDlgItem(m_hwndDlg, IDC_EDIT4), szOpenCmd);
  1271.             }
  1272.  
  1273.             // If the user didn't specify a description then pre-fill that, too
  1274.             if (Edit_GetTextLength(GetDlgItem(m_hwndDlg, IDC_EDIT1)) == 0) {
  1275.                 CString    strDescription;
  1276.  
  1277.                 if (GetFileTypeDescription(szFileClass, strDescription)) {
  1278.                     // Pre-fill the description edit control
  1279.                     Edit_SetText(GetDlgItem(m_hwndDlg, IDC_EDIT1), (LPCSTR)strDescription);
  1280.                 }
  1281.             }
  1282.         }
  1283.  
  1284.         return TRUE;
  1285.     }
  1286.  
  1287.     return CDialog::OnCommand(id, hwndCtl, notifyCode);
  1288. }
  1289.  
  1290. /////////////////////////////////////////////////////////////////////////////
  1291. // CApplicationsPrefs implementation
  1292.  
  1293. CApplicationsPrefs::CApplicationsPrefs()
  1294.     : CBrowserPropertyPage(IDD_APPLICATIONS, HELP_PREFS_BROWSER_APPLICATIONS)
  1295. {
  1296.     m_lpBrowserPrefs = NULL;
  1297. }
  1298.  
  1299.  
  1300. // Override SetObjects() member function to acquire/release the IBrowserPrefs
  1301. // interface pointer
  1302. STDMETHODIMP
  1303. CApplicationsPrefs::SetObjects(ULONG cObjects, LPUNKNOWN FAR* ppunk)
  1304. {
  1305.     HRESULT    hres = CBrowserPropertyPage::SetObjects(cObjects, ppunk);
  1306.  
  1307.     if (SUCCEEDED(hres)) {
  1308.         if (cObjects == 0) {
  1309.             assert(m_lpBrowserPrefs);
  1310.             if (m_lpBrowserPrefs) {
  1311.                 // Release the interface pointer
  1312.                 m_lpBrowserPrefs->Release();
  1313.                 m_lpBrowserPrefs = NULL;
  1314.             }
  1315.  
  1316.         } else {
  1317.             assert(!m_lpBrowserPrefs);
  1318.             if (!m_lpBrowserPrefs) {
  1319.                 m_pObject->QueryInterface(IID_IBrowserPrefs, (void **)&m_lpBrowserPrefs);
  1320.                 assert(m_lpBrowserPrefs);
  1321.             }
  1322.         }
  1323.     }
  1324.  
  1325.     return hres;
  1326. }
  1327.  
  1328. BOOL
  1329. CApplicationsPrefs::DoTransfer(BOOL bSaveAndValidate)
  1330. {
  1331.     return TRUE;
  1332. }
  1333.  
  1334. // Apply changes using XP preferences
  1335. BOOL
  1336. CApplicationsPrefs::ApplyChanges()
  1337. {
  1338.     return TRUE;
  1339. }
  1340.  
  1341. BOOL
  1342. CApplicationsPrefs::InitDialog()
  1343. {
  1344.     HWND    hList = GetDlgItem(m_hwndDlg, IDC_LIST1);
  1345.     int        nIndex;
  1346.  
  1347.     // We don't receive the WM_MEASUREITEM message, because it's sent before
  1348.     // the WM_INITDIALOG, so set the height of the list box items now
  1349.     SetLBoxItemHeight();
  1350.     
  1351.     // Fill the list box with the list of helper applications
  1352.     assert(m_lpBrowserPrefs);
  1353.     if (m_lpBrowserPrefs) {
  1354.         LPENUMHELPERS    pEnumHelpers;
  1355.  
  1356.         if (SUCCEEDED(m_lpBrowserPrefs->EnumHelpers(&pEnumHelpers))) {
  1357.             NET_cdataStruct    *cdata;
  1358.         
  1359.             while (pEnumHelpers->Next(&cdata) == NOERROR) {
  1360.                 assert(cdata->ci.desc);
  1361.                 nIndex = ListBox_AddString(hList, cdata->ci.desc);
  1362.                 ListBox_SetItemData(hList, nIndex, cdata);
  1363.             }
  1364.         
  1365.             pEnumHelpers->Release();
  1366.         }
  1367.     }
  1368.  
  1369.     // Add telnet and tn3270 items. Store the file class in the type field
  1370.     memset(&m_telnet, 0, sizeof(m_telnet));
  1371.     m_telnet.ci.type = "telnet";
  1372.     if (!GetFileTypeDescription("telnet", m_strTelnet))
  1373.         m_strTelnet.LoadString(m_hInstance, IDS_TELNET);
  1374.     m_telnet.ci.desc = (LPSTR)(LPCSTR)m_strTelnet;
  1375.     nIndex = ListBox_AddString(hList, m_telnet.ci.desc);
  1376.     ListBox_SetItemData(hList, nIndex, &m_telnet);
  1377.  
  1378.     memset(&m_tn3270, 0, sizeof(m_tn3270));
  1379.     m_tn3270.ci.type = "tn3270";
  1380.     if (!GetFileTypeDescription("tn3270", m_strTN3270))
  1381.         m_strTN3270.LoadString(m_hInstance, IDS_TN3270);
  1382.     m_tn3270.ci.desc = (LPSTR)(LPCSTR)m_strTN3270;
  1383.     nIndex = ListBox_AddString(hList, m_tn3270.ci.desc);
  1384.     ListBox_SetItemData(hList, nIndex, &m_tn3270);
  1385.  
  1386.     // Select the first item in the list and update the file details
  1387.     ListBox_SetCurSel(hList, 0);
  1388.     DisplayFileDetails();
  1389.     
  1390.     return CBrowserPropertyPage::InitDialog();
  1391. }
  1392.  
  1393. static void
  1394. GetAppPath(LPCSTR lpszOpenCmd, LPSTR lpszAppPath)
  1395. {
  1396.     LPSTR   lpszEnd;
  1397.     
  1398.     // The command string value specifies the path and filename of the application
  1399.     // and includes command-line options. Do what the shell does which is assume
  1400.     // that the path and filename ends at the first space. Long filenames that
  1401.     // include spaces will be in quotes
  1402.     if (*lpszOpenCmd == '"') {
  1403.         // Skip the beginning quote
  1404.         lstrcpy(lpszAppPath, lpszOpenCmd + 1);
  1405.  
  1406.         // Look for the terminating quote
  1407.         lpszEnd = strchr(lpszAppPath, '"');
  1408.  
  1409.         if (lpszEnd)
  1410.             *lpszEnd = '\0';  // null terminate at the closing quote
  1411.  
  1412.     } else {
  1413.         lstrcpy(lpszAppPath, lpszOpenCmd);
  1414.  
  1415.         // Look for the first space
  1416.         lpszEnd = strchr(lpszAppPath, ' ');
  1417.         
  1418.         if (lpszEnd)
  1419.             *lpszEnd = '\0';  // null terminate at the space
  1420.     }
  1421.  
  1422.     // Ignore a filename that is "%1". This happens for things like MS-DOS
  1423.     // Batch Files which just expand into the name of the file and a command
  1424.     // line option
  1425.     if (strcmp(lpszAppPath, "%1") == 0)
  1426.         lpszAppPath[0] = '\0';
  1427. }
  1428.  
  1429. // Build the file extension list
  1430. static void
  1431. BuildExtensionList(NET_cdataStruct *pcdata, CString &strExts)
  1432. {
  1433.     for (int i = 0; i < pcdata->num_exts; i++) {
  1434.         if (i > 0)
  1435.             strExts += ' ';
  1436.  
  1437.         strExts += pcdata->exts[i];
  1438.     }
  1439.     
  1440.     strExts.MakeUpper();
  1441. }
  1442.  
  1443. static HICON
  1444. GetNavigatorAppIcon(HINSTANCE hInstance)
  1445. {
  1446.     char    szFilename[_MAX_PATH];
  1447.  
  1448. #ifdef _WIN32
  1449.     SHFILEINFO    sfi;
  1450.  
  1451.     GetModuleFileName(NULL, szFilename, sizeof(szFilename));
  1452.     SHGetFileInfo(szFilename, 0, &sfi, sizeof(sfi), SHGFI_ICON);
  1453.     return sfi.hIcon;
  1454. #else
  1455.     TASKENTRY    te;
  1456.  
  1457.     te.dwSize = sizeof(te);
  1458.     if (TaskFindHandle(&te, GetCurrentTask())) {
  1459.         GetModuleFileName(te.hModule, szFilename, sizeof(szFilename));
  1460.         return ExtractIcon(hInstance, szFilename, 0);
  1461.     }
  1462. #endif
  1463.  
  1464.     return NULL;
  1465. }
  1466.                         
  1467. // Given the Open command returns the base filename without any extension and
  1468. // the associated application icon
  1469. static void
  1470. GetAppNameAndIcon(HINSTANCE hInstance, LPCSTR lpszOpenCmd, CString &strFilename, HICON &hIcon)
  1471. {
  1472.     char    szAppPath[_MAX_PATH];
  1473.     char    szFile[_MAX_FNAME];
  1474.  
  1475.     // Get the app path and filename
  1476.     GetAppPath(lpszOpenCmd, szAppPath);
  1477.  
  1478.     // Get the base filename without extension
  1479.     _splitpath(szAppPath, NULL, NULL, szFile, NULL);
  1480.     strFilename = szFile;
  1481.     strFilename.MakeUpper();
  1482.  
  1483.     // Get the icon associated with the application
  1484. #ifdef _WIN32
  1485.     SHFILEINFO    sfi;
  1486.     LPSTR        lpszFilePart;
  1487.     char        szBuf[MAX_PATH];
  1488.  
  1489.     // Get a full pathname
  1490.     SearchPath(NULL, szAppPath, ".exe", sizeof(szBuf), szBuf, &lpszFilePart);
  1491.     SHGetFileInfo(szBuf, 0, &sfi, sizeof(sfi), SHGFI_ICON);
  1492.     hIcon = sfi.hIcon;
  1493. #else
  1494.     hIcon = ExtractIcon(hInstance, szAppPath, 0);
  1495. #endif
  1496. }
  1497.  
  1498. void
  1499. CApplicationsPrefs::DisplayFileDetails()
  1500. {
  1501.     HICON             hDocIcon = NULL, hAppIcon = NULL;
  1502. #ifndef _WIN32
  1503.     HICON             hOldDocIcon = NULL, hOldAppIcon = NULL;
  1504. #endif
  1505.     NET_cdataStruct    *cdata;
  1506.     HWND             hList = GetDlgItem(m_hwndDlg, IDC_LIST1);
  1507.     HELPERINFO         info;
  1508.     int                 nIndex;
  1509.     CString             strHandledBy, strExts;
  1510.     LPCSTR             lpszMimeType = "";
  1511.     BOOL             bIsPlugin = FALSE;
  1512. //Begin CRN_MIME
  1513.     BOOL             bIsLocked = FALSE; 
  1514.     XP_Bool             bAddEnabled = TRUE;
  1515.     XP_Bool             bEditEnabled = TRUE;
  1516.     XP_Bool             bRemoveEnabled = TRUE;
  1517.  
  1518.     PREF_GetBoolPref("mime.table.allow_add", &bAddEnabled);
  1519.     PREF_GetBoolPref("mime.table.allow_edit", &bEditEnabled);
  1520.     PREF_GetBoolPref("mime.table.allow_remove", &bRemoveEnabled);
  1521. //End CRN_MIME
  1522.  
  1523.     // Get the currently selected item
  1524.     nIndex = ListBox_GetCurSel(hList);
  1525.     assert(nIndex != LB_ERR);
  1526.  
  1527.     // Get the netlib data structure
  1528.     cdata = (NET_cdataStruct *)ListBox_GetItemData(hList, nIndex);
  1529.     assert(cdata);
  1530.  
  1531.     // If there's no front-end data structure then it's one of the special
  1532.     // items (telnet or tn3270)
  1533.     if (cdata->ci.fe_data) {
  1534.         // Get the MIME type
  1535.         if (strncmp(cdata->ci.type, SZ_WINASSOC, lstrlen(SZ_WINASSOC)) != 0)
  1536.             lpszMimeType = cdata->ci.type;
  1537.         
  1538.         // Get some information about the helper app
  1539.         assert(m_lpBrowserPrefs);
  1540.         if (m_lpBrowserPrefs && m_lpBrowserPrefs->GetHelperInfo(cdata, &info) == ERROR_SUCCESS) {
  1541.             switch (info.nHowToHandle) {
  1542.                 case HANDLE_VIA_NETSCAPE:
  1543.                     strHandledBy.LoadString(m_hInstance, IDS_INTERNAL);
  1544.     
  1545.                     // Get the application icon
  1546.                     hAppIcon = GetNavigatorAppIcon(m_hInstance);
  1547.                     break;
  1548.     
  1549.                 case HANDLE_UNKNOWN:
  1550.                 case HANDLE_MOREINFO:
  1551.                     assert(FALSE);
  1552.                     break;
  1553.     
  1554.                 case HANDLE_EXTERNAL:
  1555.                 case HANDLE_SHELLEXECUTE:
  1556.                 case HANDLE_BY_OLE:
  1557.                     if (*info.szOpenCmd != '\0') {
  1558.                         // Get the name to display in the handled by field (no extension),
  1559.                         // and the application icon
  1560.                         GetAppNameAndIcon(m_hInstance, info.szOpenCmd, strHandledBy, hAppIcon);
  1561.                     }
  1562.                     break;
  1563.     
  1564.                 case HANDLE_SAVE:
  1565.                     strHandledBy.LoadString(m_hInstance, IDS_SAVE_TO_DISK);
  1566.                     break;
  1567.     
  1568.                 case HANDLE_VIA_PLUGIN:
  1569.                     strHandledBy.LoadString(m_hInstance, IDS_PLUGIN);
  1570.                     bIsPlugin = TRUE;
  1571.                     break;
  1572.             }
  1573.  
  1574.             bIsLocked = info.bIsLocked; //CRN_MIME
  1575.         }
  1576.  
  1577.     } else {
  1578.         char    szOpenCmd[_MAX_PATH + 32];
  1579.  
  1580.         // It's either telnet or tn3270
  1581.         assert(cdata->ci.type);
  1582.         hDocIcon = GetDocumentIcon(m_hInstance, cdata->ci.type);
  1583.         
  1584.         if (GetShellOpenCommand(cdata->ci.type, szOpenCmd, sizeof(szOpenCmd))) {
  1585.             // Get the name to display in the handled by field (no extension),
  1586.             // and the application icon
  1587.             GetAppNameAndIcon(m_hInstance, szOpenCmd, strHandledBy, hAppIcon);
  1588.         }
  1589.     }
  1590.     
  1591.     // Build the file extension list
  1592.     BuildExtensionList(cdata, strExts);
  1593.  
  1594.     // Get the document icon
  1595.     if (cdata->num_exts > 0) {
  1596. #ifdef _WIN32
  1597.         char        szBuf[_MAX_PATH];
  1598.         SHFILEINFO    sfi;
  1599.  
  1600.         wsprintf(szBuf, "file.%s", cdata->exts[0]);
  1601.         SHGetFileInfo(szBuf, 0, &sfi, sizeof(sfi), SHGFI_ICON | SHGFI_USEFILEATTRIBUTES);
  1602.         hDocIcon = sfi.hIcon;
  1603. #else
  1604.         char    szFileClass[80];
  1605.         
  1606.         if (GetFileClass(cdata->exts[0], szFileClass, sizeof(szFileClass)))
  1607.             hDocIcon = GetDocumentIcon(m_hInstance, szFileClass);
  1608.  
  1609.         if (!hDocIcon)
  1610.             hDocIcon = LoadIcon(m_hInstance, MAKEINTRESOURCE(IDI_DOCUMENT));
  1611. #endif
  1612.     }
  1613.  
  1614.     // Update the file type details
  1615.     Static_SetText(GetDlgItem(m_hwndDlg, IDC_MIME_TYPE), lpszMimeType);
  1616.     Static_SetText(GetDlgItem(m_hwndDlg, IDC_EXTENSION), (LPCSTR)strExts);
  1617.     Static_SetText(GetDlgItem(m_hwndDlg, IDC_HANDLED_BY), (LPCSTR)strHandledBy);
  1618. #ifndef _WIN32
  1619.     Static_GetIcon(GetDlgItem(m_hwndDlg, IDC_ICON1), hOldDocIcon);
  1620.     Static_GetIcon(GetDlgItem(m_hwndDlg, IDC_ICON2), hOldAppIcon);
  1621. #endif
  1622.     Static_SetIcon(GetDlgItem(m_hwndDlg, IDC_ICON1), hDocIcon);
  1623.     Static_SetIcon(GetDlgItem(m_hwndDlg, IDC_ICON2), hAppIcon);
  1624. #ifndef _WIN32
  1625.     // Minimize system resource usage by destroying the previously displayed icons
  1626.     if (hOldDocIcon && (hOldDocIcon != hDocIcon))
  1627.         DestroyIcon(hOldDocIcon);
  1628.     if (hOldAppIcon && (hOldAppIcon != hAppIcon))
  1629.         DestroyIcon(hOldAppIcon);
  1630. #endif
  1631.  
  1632.     EnableDlgItem(IDC_BUTTON1, bAddEnabled); //This is the "New Type.." button.    CRN_MIME 
  1633.  
  1634.     // Disable the Edit and Remove buttons if the item is handled by a plug-in,
  1635.     // because changing or removing the item won't actually do anything
  1636.     EnableDlgItem(IDC_BUTTON2, !bIsPlugin && !bIsLocked && bEditEnabled); //CRN_MIME Added "&& !bIsLocked && bEditEnabled
  1637.     EnableDlgItem(IDC_BUTTON3, !bIsPlugin && !bIsLocked && bRemoveEnabled); //CRN_MIME Added "&& !bIsLocked && bRemoveEnabled
  1638. }
  1639.  
  1640. void
  1641. CApplicationsPrefs::OnEditItem()
  1642. {
  1643.     NET_cdataStruct    *cdata;
  1644.     CEditTypeDialog     dlg;
  1645.     HWND             hList = GetDlgItem(m_hwndDlg, IDC_LIST1);
  1646.     HELPERINFO         info;
  1647.     int                 nIndex;
  1648.  
  1649.     // Get the currently selected item
  1650.     nIndex = ListBox_GetCurSel(hList);
  1651.     assert(nIndex != LB_ERR);
  1652.  
  1653.     // Get the netlib data structure
  1654.     cdata = (NET_cdataStruct *)ListBox_GetItemData(hList, nIndex);
  1655.     assert(cdata);
  1656.  
  1657.     // Get some information about the helper app
  1658.     if (!cdata->ci.fe_data) {
  1659.         char    szOpenCmd[_MAX_PATH + 32];
  1660.  
  1661.         // This is telnet or tn3270
  1662.         dlg.m_bURLProtocol = TRUE;
  1663.         dlg.m_nHowToHandle = HANDLE_SHELLEXECUTE;
  1664.         if (GetShellOpenCommand(cdata->ci.type, szOpenCmd, sizeof(szOpenCmd)))
  1665.             dlg.m_strOpenCmd = szOpenCmd;
  1666.  
  1667.     } else {
  1668.         assert(m_lpBrowserPrefs);
  1669.         if (m_lpBrowserPrefs && m_lpBrowserPrefs->GetHelperInfo(cdata, &info) == ERROR_SUCCESS) {
  1670.             dlg.m_nHowToHandle = info.nHowToHandle;
  1671.             dlg.m_strOpenCmd = info.szOpenCmd;
  1672.             dlg.m_bConfirmBeforeOpening = info.bAskBeforeOpening;
  1673.         }
  1674.         
  1675.         dlg.m_strMimeType = strncmp(cdata->ci.type, SZ_WINASSOC, lstrlen(SZ_WINASSOC)) == 0 ?
  1676.             "" : cdata->ci.type;
  1677.     }
  1678.     
  1679.     dlg.m_hDocIcon = Static_GetIcon(GetDlgItem(m_hwndDlg, IDC_ICON1), hOldDocIcon);
  1680.     dlg.m_strDescription = cdata->ci.desc;
  1681.     
  1682.     // Build the file extension list
  1683.     BuildExtensionList(cdata, dlg.m_strExtension);
  1684.  
  1685.     // Display the dialog
  1686.     if (dlg.DoModal(GetParent(m_hwndDlg)) == IDOK) {
  1687.         if (!cdata->ci.fe_data) {
  1688.             CString    strDescription;
  1689.  
  1690.             // This is telnet or tn3270
  1691.             assert(cdata->ci.type);
  1692.             SetShellOpenCommand(cdata->ci.type, (LPCSTR)dlg.m_strOpenCmd);
  1693.  
  1694.             // Make sure there's a description for the file type class
  1695.             if (!GetFileTypeDescription(cdata->ci.type, strDescription))
  1696.                 SetFileTypeDescription(cdata->ci.type, cdata->ci.desc);
  1697.             
  1698.             // Update the file details
  1699.             DisplayFileDetails();
  1700.  
  1701.         } else {
  1702.             // Call browser to change the type
  1703.             assert(m_lpBrowserPrefs);
  1704.             if (m_lpBrowserPrefs) {
  1705.                 HELPERINFO    info;
  1706.  
  1707.                 info.nHowToHandle = dlg.m_nHowToHandle;
  1708.                 lstrcpy(info.szOpenCmd, (LPCSTR)dlg.m_strOpenCmd);
  1709.                 info.bAskBeforeOpening = dlg.m_bConfirmBeforeOpening;
  1710.                 info.lpszMimeType = (LPCSTR)dlg.m_strMimeType;
  1711.  
  1712.                 if (m_lpBrowserPrefs->SetHelperInfo(cdata, &info) == NOERROR)
  1713.                     DisplayFileDetails();
  1714.             }
  1715.         }
  1716.     }
  1717. }
  1718.  
  1719. void
  1720. CApplicationsPrefs::OnNewItem()
  1721. {
  1722.     CNewTypeDialog    dlg;
  1723.  
  1724.     if (dlg.DoModal(GetParent(m_hwndDlg)) == IDOK) {
  1725.         // If the user didn't supply a description then create one
  1726.         // based on the file extension
  1727.         if (dlg.m_strDescription.IsEmpty()) {
  1728.             char    szFile[256];
  1729.  
  1730.             dlg.m_strDescription = dlg.m_strExtension;
  1731.             dlg.m_strDescription.MakeUpper();
  1732.             dlg.m_strDescription += ' ';
  1733.             LoadString(m_hInstance, IDS_FILE, szFile, sizeof(szFile));
  1734.             dlg.m_strDescription += szFile;
  1735.         }
  1736.  
  1737.         // Call browser to create the new type
  1738.         assert(m_lpBrowserPrefs);
  1739.         if (m_lpBrowserPrefs) {
  1740.             NET_cdataStruct    *cdata;
  1741.             int                 nIndex;
  1742.  
  1743.             if (m_lpBrowserPrefs->NewFileType((LPCSTR)dlg.m_strDescription,
  1744.                                               (LPCSTR)dlg.m_strExtension,
  1745.                                               (LPCSTR)dlg.m_strMimeType,
  1746.                                               (LPCSTR)dlg.m_strOpenCmd,
  1747.                                               &cdata) == NOERROR) {
  1748.  
  1749.                 HWND    hList = GetDlgItem(m_hwndDlg, IDC_LIST1);
  1750.  
  1751.                 // Add a new list box item
  1752.                 assert(cdata && cdata->ci.desc);
  1753.                 nIndex = ListBox_AddString(hList, cdata->ci.desc);
  1754.                 ListBox_SetItemData(hList, nIndex, cdata);
  1755.  
  1756.                 // Select the item and update the file details
  1757.                 ListBox_SetCurSel(hList, nIndex);
  1758.                 DisplayFileDetails();
  1759.             }
  1760.         }
  1761.     }
  1762. }
  1763.  
  1764. void
  1765. CApplicationsPrefs::OnRemoveItem()
  1766. {
  1767.     NET_cdataStruct    *cdata;
  1768.     HWND             hList = GetDlgItem(m_hwndDlg, IDC_LIST1);
  1769.     int                 nCurSel;
  1770.     char             szTitle[256];
  1771.     char             szCaption[256];
  1772.  
  1773.     // Get the currently selected item
  1774.     nCurSel = ListBox_GetCurSel(hList);
  1775.     assert(nCurSel != LB_ERR);
  1776.  
  1777.     // Get the netlib data structure
  1778.     cdata = (NET_cdataStruct *)ListBox_GetItemData(hList, nCurSel);
  1779.     assert(cdata);
  1780.  
  1781.     // Ask the user to confirm
  1782.     LoadString(m_hInstance, IDS_CONFIRM_REMOVE, szTitle, sizeof(szTitle));
  1783.     LoadString(m_hInstance, IDS_FILE_TYPES, szCaption, sizeof(szCaption));
  1784.     if (MessageBox(GetParent(m_hwndDlg), szTitle, szCaption, MB_YESNO | MB_ICONQUESTION) == IDYES) {
  1785.         // Call browser to remove the item
  1786.         assert(m_lpBrowserPrefs);
  1787.         if (m_lpBrowserPrefs) {
  1788.             if (m_lpBrowserPrefs->RemoveFileType(cdata) == NOERROR) {
  1789.                 // Remove this item from the list
  1790.                 ListBox_DeleteString(hList, nCurSel);
  1791.                 if (ListBox_GetCount(hList) > 0)
  1792.                     ListBox_SetCurSel(hList, nCurSel > 0 ? nCurSel - 1 : 0);
  1793.                 DisplayFileDetails();
  1794.             }
  1795.         }
  1796.     }
  1797. }
  1798.  
  1799. BOOL
  1800. CApplicationsPrefs::OnCommand(int id, HWND hwndCtl, UINT notifyCode)
  1801. {
  1802.     if (id == IDC_LIST1 && notifyCode == LBN_SELCHANGE) {
  1803.         DisplayFileDetails();
  1804.         return TRUE;
  1805.  
  1806.     } else if (id == IDC_BUTTON1 && notifyCode == BN_CLICKED) {
  1807.         OnNewItem();
  1808.         return TRUE;
  1809.     
  1810.     } else if (id == IDC_BUTTON2 && notifyCode == BN_CLICKED) {
  1811.         OnEditItem();
  1812.         return TRUE;
  1813.     
  1814.     } else if (id == IDC_BUTTON3 && notifyCode == BN_CLICKED) {
  1815.         OnRemoveItem();
  1816.         return TRUE;
  1817.     }
  1818.  
  1819.     return CBrowserPropertyPage::OnCommand(id, hwndCtl, notifyCode);
  1820. }
  1821.  
  1822. void
  1823. CApplicationsPrefs::SetLBoxItemHeight()
  1824. {
  1825.     TEXTMETRIC    tm;
  1826.     HWND        hwndCtl = GetDlgItem(m_hwndDlg, IDC_LIST1);
  1827.     HFONT        hFont = GetWindowFont(hwndCtl);
  1828.     HDC            hDC = GetDC(hwndCtl);
  1829.     HFONT        hOldFont = NULL;
  1830.  
  1831.     if (hFont)
  1832.         hOldFont = SelectFont(hDC, hFont);
  1833.  
  1834.     GetTextMetrics(hDC, &tm);
  1835.  
  1836.     // Cleanup and release the HDC
  1837.     if (hOldFont)
  1838.         SelectObject(hDC, hOldFont);
  1839.     ReleaseDC(hwndCtl, hDC);
  1840.  
  1841.     // Set the height of a single item
  1842.     ListBox_SetItemHeight(hwndCtl, 0, tm.tmHeight + 3);
  1843. }
  1844.  
  1845. #define LEFT_PADDING    2
  1846. #define TOP_PADDING        1
  1847. #define RIGHT_PADDING    5
  1848.  
  1849. void
  1850. CApplicationsPrefs::DrawLBoxItem(LPDRAWITEMSTRUCT lpdis)
  1851. {
  1852.     NET_cdataStruct *cdata;
  1853.     int                 nColorIndex;
  1854.     HWND             hwndFocus = GetFocus();  // don't trust ODS_FOCUS
  1855.     int                 nStrLen;
  1856.     SIZE             size;
  1857.  
  1858.     switch (lpdis->itemAction) {
  1859.         case ODA_DRAWENTIRE:
  1860.         case ODA_SELECT:
  1861.         case ODA_FOCUS:
  1862.             nColorIndex = COLOR_WINDOWTEXT;
  1863.             if ((lpdis->itemState & ODS_SELECTED) && (hwndFocus == lpdis->hwndItem))
  1864.                 nColorIndex = COLOR_HIGHLIGHTTEXT;
  1865.             SetTextColor(lpdis->hDC, GetSysColor(nColorIndex));
  1866.  
  1867.             // Behave like a 32-bit list view and use a different color to indicate
  1868.             // selection when we don't have the focus
  1869.             nColorIndex = COLOR_WINDOW;
  1870.             if (lpdis->itemState & ODS_SELECTED)
  1871.                 nColorIndex = (hwndFocus == lpdis->hwndItem ? COLOR_HIGHLIGHT : COLOR_BTNFACE);
  1872.             SetBkColor(lpdis->hDC, GetSysColor(nColorIndex));
  1873.     
  1874.             assert(lpdis->itemID != (UINT)-1);
  1875.             cdata = (NET_cdataStruct *)lpdis->itemData;
  1876.  
  1877.             // Display the description
  1878.             nStrLen = lstrlen(cdata->ci.desc);
  1879. #ifdef _WIN32
  1880.             GetTextExtentPoint32(lpdis->hDC, cdata->ci.desc, nStrLen, &size);
  1881. #else
  1882.             GetTextExtentPoint(lpdis->hDC, cdata->ci.desc, nStrLen, &size);
  1883. #endif
  1884.             lpdis->rcItem.right = lpdis->rcItem.left + size.cx + LEFT_PADDING + RIGHT_PADDING;
  1885.  
  1886.             ExtTextOut(lpdis->hDC, lpdis->rcItem.left + LEFT_PADDING, lpdis->rcItem.top + TOP_PADDING,
  1887.                 ETO_OPAQUE, &lpdis->rcItem, cdata->ci.desc, nStrLen, NULL);
  1888.             
  1889.             // Draw the focus rect if necessary
  1890.             if (lpdis->itemState & ODS_FOCUS)
  1891.                 ::DrawFocusRect(lpdis->hDC, &lpdis->rcItem);
  1892.             break;
  1893.     }
  1894. }
  1895.  
  1896. LRESULT
  1897. CApplicationsPrefs::WindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
  1898. {
  1899.     LPDRAWITEMSTRUCT    lpdis;
  1900.     LPCOMPAREITEMSTRUCT    lpcis;
  1901.  
  1902.     switch (uMsg) {
  1903.         case WM_DRAWITEM:
  1904.             lpdis = (LPDRAWITEMSTRUCT)lParam;
  1905.  
  1906.             if (lpdis->CtlID == IDC_LIST1)
  1907.                 DrawLBoxItem(lpdis);
  1908.             return TRUE;
  1909.  
  1910.         case WM_COMPAREITEM:
  1911.             lpcis = (LPCOMPAREITEMSTRUCT)lParam;
  1912.             if (lpcis->CtlID == IDC_LIST1) {
  1913.                 return lstrcmp(((NET_cdataStruct *)lpcis->itemData1)->ci.desc,
  1914.                                ((NET_cdataStruct *)lpcis->itemData2)->ci.desc);
  1915.             }
  1916.             return TRUE;
  1917.     }
  1918.  
  1919.     return CBrowserPropertyPage::WindowProc(uMsg, wParam, lParam);
  1920. }
  1921.  
  1922.