"Fossies" - the Fresh Open Source Software Archive

Member "src/Main/Forms/PreferencesDialog.cpp" (10 Oct 2018, 16503 Bytes) of package /windows/misc/VeraCrypt_1.23-Hotfix-2_Source.zip:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "PreferencesDialog.cpp" see the Fossies "Dox" file reference documentation.

    1 /*
    2  Derived from source code of TrueCrypt 7.1a, which is
    3  Copyright (c) 2008-2012 TrueCrypt Developers Association and which is governed
    4  by the TrueCrypt License 3.0.
    5 
    6  Modifications and additions to the original source code (contained in this file)
    7  and all other portions of this file are Copyright (c) 2013-2017 IDRIX
    8  and are governed by the Apache License 2.0 the full text of which is
    9  contained in the file License.txt included in VeraCrypt binary and source
   10  code distribution packages.
   11 */
   12 
   13 #include "System.h"
   14 #include <wx/dynlib.h>
   15 #ifdef TC_WINDOWS
   16 #include <wx/msw/registry.h>
   17 #endif
   18 #include "Common/SecurityToken.h"
   19 #include "Main/Main.h"
   20 #include "Main/Application.h"
   21 #include "Main/GraphicUserInterface.h"
   22 #include "Volume/Cipher.h"
   23 #include "PreferencesDialog.h"
   24 
   25 namespace VeraCrypt
   26 {
   27     PreferencesDialog::PreferencesDialog (wxWindow* parent)
   28         : PreferencesDialogBase (parent),
   29         LastVirtualKeyPressed (0),
   30         Preferences (Gui->GetPreferences()),
   31         RestoreValidatorBell (false)
   32     {
   33 #define TC_CHECK_BOX_VALIDATOR(NAME) (TC_JOIN(NAME,CheckBox))->SetValidator (wxGenericValidator (&Preferences.NAME));
   34 
   35 #ifdef TC_MACOSX
   36         PreferencesNotebook->SetMinSize (wxSize (Gui->GetCharWidth (PreferencesNotebook) * 108, -1));
   37 #endif
   38         // Security
   39         TC_CHECK_BOX_VALIDATOR (DismountOnLogOff);
   40         TC_CHECK_BOX_VALIDATOR (DismountOnPowerSaving);
   41         TC_CHECK_BOX_VALIDATOR (DismountOnScreenSaver);
   42         TC_CHECK_BOX_VALIDATOR (DismountOnInactivity);
   43         DismountOnInactivitySpinCtrl->SetValidator (wxGenericValidator (&Preferences.MaxVolumeIdleTime));
   44         TC_CHECK_BOX_VALIDATOR (ForceAutoDismount);
   45         PreserveTimestampsCheckBox->SetValidator (wxGenericValidator (&Preferences.DefaultMountOptions.PreserveTimestamps));
   46         TC_CHECK_BOX_VALIDATOR (WipeCacheOnAutoDismount);
   47         TC_CHECK_BOX_VALIDATOR (WipeCacheOnClose);
   48 
   49         // Mount options
   50         CachePasswordsCheckBox->SetValidator (wxGenericValidator (&Preferences.DefaultMountOptions.CachePassword));
   51         MountReadOnlyCheckBox->SetValue (Preferences.DefaultMountOptions.Protection == VolumeProtection::ReadOnly);
   52         MountRemovableCheckBox->SetValidator (wxGenericValidator (&Preferences.DefaultMountOptions.Removable));
   53 
   54         FilesystemOptionsTextCtrl->SetValue (Preferences.DefaultMountOptions.FilesystemOptions);
   55 
   56         TrueCryptModeCheckBox->SetValidator (wxGenericValidator (&Preferences.DefaultMountOptions.TrueCryptMode));
   57 
   58         int index, prfInitialIndex = 0;
   59         Pkcs5PrfChoice->Append (LangString["AUTODETECTION"]);
   60 
   61         foreach_ref (const Pkcs5Kdf &kdf, Pkcs5Kdf::GetAvailableAlgorithms(false))
   62         {
   63             index = Pkcs5PrfChoice->Append (kdf.GetName());
   64             if (Preferences.DefaultMountOptions.Kdf
   65                 && (Preferences.DefaultMountOptions.Kdf->GetName() == kdf.GetName())
   66                 )
   67             {
   68                 prfInitialIndex = index;
   69             }
   70         }
   71         Pkcs5PrfChoice->Select (prfInitialIndex);
   72 
   73         // Keyfiles
   74         TC_CHECK_BOX_VALIDATOR (UseKeyfiles);
   75 
   76         DefaultKeyfilesPanel = new KeyfilesPanel (DefaultKeyfilesPage, make_shared <KeyfileList> (Preferences.DefaultKeyfiles));
   77         DefaultKeyfilesSizer->Add (DefaultKeyfilesPanel, 1, wxALL | wxEXPAND);
   78         DefaultKeyfilesSizer->Layout();
   79 
   80         TC_CHECK_BOX_VALIDATOR (BackgroundTaskEnabled);
   81         TC_CHECK_BOX_VALIDATOR (CloseBackgroundTaskOnNoVolumes);
   82         CloseBackgroundTaskOnNoVolumesCheckBox->Show (!Core->IsInPortableMode());
   83         TC_CHECK_BOX_VALIDATOR (BackgroundTaskMenuDismountItemsEnabled);
   84         TC_CHECK_BOX_VALIDATOR (BackgroundTaskMenuMountItemsEnabled);
   85         TC_CHECK_BOX_VALIDATOR (BackgroundTaskMenuOpenItemsEnabled);
   86 
   87         // Encryption
   88         AesHwCpuSupportedStaticText->SetLabel (
   89 #ifdef TC_AES_HW_CPU
   90             (is_aes_hw_cpu_supported() ? LangString["UISTR_YES"] : LangString["UISTR_NO"]));
   91 #else
   92             LangString["NOT_APPLICABLE_OR_NOT_AVAILABLE"]);
   93 #endif
   94         NoHardwareCryptoCheckBox->SetValidator (wxGenericValidator (&Preferences.DefaultMountOptions.NoHardwareCrypto));
   95 
   96         // Security tokens
   97         Pkcs11ModulePathTextCtrl->SetValue (wstring (Preferences.SecurityTokenModule));
   98         TC_CHECK_BOX_VALIDATOR (CloseSecurityTokenSessionsAfterMount);
   99 
  100         // System integration
  101         TC_CHECK_BOX_VALIDATOR (StartOnLogon);
  102         TC_CHECK_BOX_VALIDATOR (MountDevicesOnLogon);
  103         TC_CHECK_BOX_VALIDATOR (MountFavoritesOnLogon);
  104 
  105         TC_CHECK_BOX_VALIDATOR (CloseExplorerWindowsOnDismount);
  106         TC_CHECK_BOX_VALIDATOR (OpenExplorerWindowAfterMount);
  107 
  108         NoKernelCryptoCheckBox->SetValidator (wxGenericValidator (&Preferences.DefaultMountOptions.NoKernelCrypto));
  109 
  110 #ifdef TC_WINDOWS
  111         // Hotkeys
  112         TC_CHECK_BOX_VALIDATOR (BeepAfterHotkeyMountDismount);
  113         TC_CHECK_BOX_VALIDATOR (DisplayMessageAfterHotkeyDismount);
  114 #endif
  115 
  116         TransferDataToWindow();     // Code below relies on TransferDataToWindow() called at this point
  117 
  118 #if defined (TC_WINDOWS) || defined (TC_MACOSX)
  119         FilesystemSizer->Show (false);
  120 #else
  121         // Auto-dismount is not supported on Linux as dismount may require the user to enter admin password
  122         AutoDismountSizer->Show (false);
  123         WipeCacheOnAutoDismountCheckBox->Show (false);
  124 #endif
  125 
  126 #ifndef TC_WINDOWS
  127         LogOnSizer->Show (false);
  128         MountRemovableCheckBox->Show (false);
  129         CloseExplorerWindowsOnDismountCheckBox->Show (false);
  130 #endif
  131 
  132 #ifndef wxHAS_POWER_EVENTS
  133         DismountOnPowerSavingCheckBox->Show (false);
  134 #endif
  135 
  136 #ifdef TC_MACOSX
  137         DismountOnScreenSaverCheckBox->Show (false);
  138         DismountOnLogOffCheckBox->SetLabel (_("VeraCrypt quits"));
  139         OpenExplorerWindowAfterMountCheckBox->SetLabel (_("Open Finder window for successfully mounted volume"));
  140 
  141         MountRemovableCheckBox->Show (false);
  142         FilesystemSizer->Show (false);
  143         LogOnSizer->Show (false);
  144         CloseExplorerWindowsOnDismountCheckBox->Show (false);
  145 #endif
  146 
  147 #ifndef TC_LINUX
  148         KernelServicesSizer->Show (false);
  149 #endif
  150 
  151 #ifdef TC_WINDOWS
  152         // Hotkeys
  153         list <int> colPermilles;
  154         HotkeyListCtrl->InsertColumn (ColumnHotkeyDescription, LangString["ACTION"], wxLIST_FORMAT_LEFT, 1);
  155         colPermilles.push_back (642);
  156         HotkeyListCtrl->InsertColumn (ColumnHotkey, LangString["SHORTCUT"], wxLIST_FORMAT_LEFT, 1);
  157         colPermilles.push_back (358);
  158 
  159         vector <wstring> fields (HotkeyListCtrl->GetColumnCount());
  160 
  161         UnregisteredHotkeys = Preferences.Hotkeys;
  162         Hotkey::UnregisterList (Gui->GetMainFrame(), UnregisteredHotkeys);
  163 
  164         foreach (shared_ptr <Hotkey> hotkey, Preferences.Hotkeys)
  165         {
  166             fields[ColumnHotkeyDescription] = hotkey->Description;
  167             fields[ColumnHotkey] = hotkey->GetShortcutString();
  168             Gui->AppendToListCtrl (HotkeyListCtrl, fields, -1, hotkey.get());
  169         }
  170 
  171         Gui->SetListCtrlHeight (HotkeyListCtrl, 5);
  172 
  173         Layout();
  174         Fit();
  175         Gui->SetListCtrlColumnWidths (HotkeyListCtrl, colPermilles);
  176 
  177         RestoreValidatorBell = !wxTextValidator::IsSilent();
  178         wxTextValidator::SuppressBellOnError (true);
  179         HotkeyTextCtrl->SetValidator (wxTextValidator (wxFILTER_INCLUDE_CHAR_LIST));
  180 
  181         UpdateHotkeyButtons();
  182 #endif
  183 
  184         // Page setup
  185         for (size_t page = 0; page < PreferencesNotebook->GetPageCount(); page++)
  186         {
  187             wxNotebookPage *np = PreferencesNotebook->GetPage (page);
  188             if (np == HotkeysPage)
  189             {
  190 #ifndef TC_WINDOWS
  191                 PreferencesNotebook->RemovePage (page--);
  192                 continue;
  193 #endif
  194             }
  195 
  196             np->Layout();
  197         }
  198 
  199         Layout();
  200         Fit();
  201         Center();
  202 
  203         StdButtonsOK->SetDefault();
  204 
  205 #ifdef TC_WINDOWS
  206         // Hotkey timer
  207         class Timer : public wxTimer
  208         {
  209         public:
  210             Timer (PreferencesDialog *dialog) : Dialog (dialog) { }
  211 
  212             void Notify()
  213             {
  214                 Dialog->OnTimer();
  215             }
  216 
  217             PreferencesDialog *Dialog;
  218         };
  219 
  220         mTimer.reset (dynamic_cast <wxTimer *> (new Timer (this)));
  221         mTimer->Start (25);
  222 #endif
  223     }
  224 
  225     PreferencesDialog::~PreferencesDialog ()
  226     {
  227 #ifdef TC_WINDOWS
  228         if (RestoreValidatorBell)
  229             wxTextValidator::SuppressBellOnError (false);
  230 #endif
  231     }
  232 
  233     void PreferencesDialog::SelectPage (wxPanel *page)
  234     {
  235         for (size_t pageIndex = 0; pageIndex < PreferencesNotebook->GetPageCount(); pageIndex++)
  236         {
  237             if (PreferencesNotebook->GetPage (pageIndex) == page)
  238                 PreferencesNotebook->ChangeSelection (pageIndex);
  239         }
  240     }
  241 
  242     void PreferencesDialog::OnAssignHotkeyButtonClick (wxCommandEvent& event)
  243     {
  244 #ifdef TC_WINDOWS
  245         foreach (long item, Gui->GetListCtrlSelectedItems (HotkeyListCtrl))
  246         {
  247             Hotkey *hotkey = reinterpret_cast <Hotkey *> (HotkeyListCtrl->GetItemData (item));
  248 
  249             int mods = 0;
  250             mods |= HotkeyShiftCheckBox->IsChecked() ? wxMOD_SHIFT : 0;
  251             mods |= HotkeyControlCheckBox->IsChecked() ? wxMOD_CONTROL : 0;
  252             mods |= HotkeyAltCheckBox->IsChecked() ? wxMOD_ALT : 0;
  253             mods |= HotkeyWinCheckBox->IsChecked() ? wxMOD_WIN : 0;
  254 
  255             // F1 is help and F12 is reserved for use by the debugger at all times
  256             if (mods == 0 && (LastVirtualKeyPressed == VK_F1 || LastVirtualKeyPressed == VK_F12))
  257             {
  258                 Gui->ShowError ("CANNOT_USE_RESERVED_KEY");
  259                 return;
  260             }
  261 
  262             // Test if the hotkey can be registered
  263             if (!this->RegisterHotKey (hotkey->Id, mods, LastVirtualKeyPressed))
  264             {
  265                 Gui->ShowError (SystemException (SRC_POS));
  266                 return;
  267             }
  268             UnregisterHotKey (hotkey->Id);
  269 
  270             foreach_ref (const Hotkey &h, Preferences.Hotkeys)
  271             {
  272                 if (h.Id != hotkey->Id && h.VirtualKeyCode == LastVirtualKeyPressed && h.VirtualKeyModifiers == mods)
  273                 {
  274                     Gui->ShowError ("SHORTCUT_ALREADY_IN_USE");
  275                     return;
  276                 }
  277             }
  278 
  279             hotkey->VirtualKeyCode = LastVirtualKeyPressed;
  280             hotkey->VirtualKeyModifiers = mods;
  281 
  282             vector <wstring> fields (HotkeyListCtrl->GetColumnCount());
  283             fields[ColumnHotkeyDescription] = hotkey->Description;
  284             fields[ColumnHotkey] = hotkey->GetShortcutString();
  285             Gui->UpdateListCtrlItem (HotkeyListCtrl, item, fields);
  286 
  287             UpdateHotkeyButtons();
  288         }
  289 #endif // TC_WINDOWS
  290     }
  291 
  292     void PreferencesDialog::OnBackgroundTaskEnabledCheckBoxClick (wxCommandEvent& event)
  293     {
  294         if (!event.IsChecked())
  295             BackgroundTaskEnabledCheckBox->SetValue (!Gui->AskYesNo (LangString["CONFIRM_BACKGROUND_TASK_DISABLED"], false, true));
  296     }
  297 
  298     void PreferencesDialog::OnNoHardwareCryptoCheckBoxClick (wxCommandEvent& event)
  299     {
  300         if (event.IsChecked())
  301         {
  302             if (Gui->AskYesNo (LangString["CONFIRM_SETTING_DEGRADES_PERFORMANCE"], true, true))
  303             {
  304 #ifdef TC_LINUX
  305                 Gui->ShowWarning (_("Please note that this setting takes effect only if use of the kernel cryptographic services is disabled."));
  306 #endif
  307             }
  308             else
  309                 NoHardwareCryptoCheckBox->SetValue (false);
  310         }
  311 
  312         Gui->ShowWarning (_("Please note that any currently mounted volumes need to be remounted before they can use this setting."));
  313     }
  314 
  315     void PreferencesDialog::OnNoKernelCryptoCheckBoxClick (wxCommandEvent& event)
  316     {
  317         if (event.IsChecked())
  318             NoKernelCryptoCheckBox->SetValue (Gui->AskYesNo (_("Disabling the use of kernel cryptographic services can degrade performance.\n\nAre you sure?"), false, true));
  319     }
  320 
  321     void PreferencesDialog::OnClose (wxCloseEvent& event)
  322     {
  323 #ifdef TC_WINDOWS
  324         Hotkey::RegisterList (Gui->GetMainFrame(), UnregisteredHotkeys);
  325 #endif
  326         event.Skip();
  327     }
  328 
  329     void PreferencesDialog::OnDismountOnPowerSavingCheckBoxClick (wxCommandEvent& event)
  330     {
  331         if (event.IsChecked() && !ForceAutoDismountCheckBox->IsChecked())
  332             Gui->ShowWarning ("WARN_PREF_AUTO_DISMOUNT");
  333     }
  334 
  335     void PreferencesDialog::OnDismountOnScreenSaverCheckBoxClick (wxCommandEvent& event)
  336     {
  337         if (event.IsChecked() && !ForceAutoDismountCheckBox->IsChecked())
  338             Gui->ShowWarning ("WARN_PREF_AUTO_DISMOUNT");
  339     }
  340 
  341     void PreferencesDialog::OnForceAutoDismountCheckBoxClick (wxCommandEvent& event)
  342     {
  343         if (!event.IsChecked())
  344             ForceAutoDismountCheckBox->SetValue (!Gui->AskYesNo (LangString["CONFIRM_NO_FORCED_AUTODISMOUNT"], false, true));
  345     }
  346 
  347     void PreferencesDialog::OnHotkeyListItemDeselected (wxListEvent& event)
  348     {
  349         UpdateHotkeyButtons();
  350     }
  351 
  352     void PreferencesDialog::OnHotkeyListItemSelected (wxListEvent& event)
  353     {
  354         UpdateHotkeyButtons();
  355         HotkeyTextCtrl->ChangeValue (LangString ["PRESS_A_KEY_TO_ASSIGN"]);
  356         AssignHotkeyButton->Enable (false);
  357     }
  358 
  359     void PreferencesDialog::OnOKButtonClick (wxCommandEvent& event)
  360     {
  361 #ifdef TC_WINDOWS
  362         HotkeyTextCtrl->SetValidator (wxTextValidator (wxFILTER_NONE));
  363 #endif
  364         if (!Validate())
  365             return;
  366 
  367         shared_ptr <Pkcs5Kdf> selectedKdf;
  368         if (Pkcs5PrfChoice->GetSelection () != 0)
  369         {
  370             try
  371             {
  372                 selectedKdf = Pkcs5Kdf::GetAlgorithm (wstring (Pkcs5PrfChoice->GetStringSelection ()), TrueCryptModeCheckBox->IsChecked ());
  373             }
  374             catch (ParameterIncorrect&)
  375             {
  376                 Gui->ShowWarning ("ALGO_NOT_SUPPORTED_FOR_TRUECRYPT_MODE");
  377                 return;
  378             }
  379         }
  380 
  381         TransferDataFromWindow();
  382 
  383         Preferences.DefaultMountOptions.Protection = MountReadOnlyCheckBox->IsChecked() ? VolumeProtection::ReadOnly : VolumeProtection::None;
  384         Preferences.DefaultMountOptions.FilesystemOptions = FilesystemOptionsTextCtrl->GetValue();
  385         Preferences.DefaultKeyfiles = *DefaultKeyfilesPanel->GetKeyfiles();
  386 
  387         Preferences.DefaultMountOptions.Kdf = selectedKdf;
  388         Preferences.DefaultMountOptions.ProtectionKdf = selectedKdf;
  389 
  390         bool securityTokenModuleChanged = (Preferences.SecurityTokenModule != wstring (Pkcs11ModulePathTextCtrl->GetValue()));
  391         Preferences.SecurityTokenModule = wstring (Pkcs11ModulePathTextCtrl->GetValue());
  392 
  393         Gui->SetPreferences (Preferences);
  394 
  395         try
  396         {
  397             if (securityTokenModuleChanged)
  398             {
  399                 if (Preferences.SecurityTokenModule.IsEmpty())
  400                 {
  401                     if (SecurityToken::IsInitialized())
  402                         SecurityToken::CloseLibrary ();
  403                 }
  404                 else
  405                 {
  406                     Gui->InitSecurityTokenLibrary();
  407                 }
  408             }
  409         }
  410         catch (exception &e)
  411         {
  412             Gui->ShowError (e);
  413         }
  414 
  415 #ifdef TC_WINDOWS
  416         // Hotkeys
  417         Hotkey::RegisterList (Gui->GetMainFrame(), Preferences.Hotkeys);
  418 #endif
  419 
  420         EndModal (wxID_OK);
  421     }
  422 
  423     void PreferencesDialog::OnPreserveTimestampsCheckBoxClick (wxCommandEvent& event)
  424     {
  425 #ifdef TC_LINUX
  426         if (!event.IsChecked())
  427             Gui->ShowInfo (_("Please note that disabling this option may have no effect on volumes mounted using kernel cryptographic services."));
  428 #endif
  429     }
  430 
  431     void PreferencesDialog::OnRemoveHotkeyButtonClick (wxCommandEvent& event)
  432     {
  433 #ifdef TC_WINDOWS
  434         foreach (long item, Gui->GetListCtrlSelectedItems (HotkeyListCtrl))
  435         {
  436             Hotkey *hotkey = reinterpret_cast <Hotkey *> (HotkeyListCtrl->GetItemData (item));
  437             hotkey->VirtualKeyCode = 0;
  438             hotkey->VirtualKeyModifiers = 0;
  439 
  440             vector <wstring> fields (HotkeyListCtrl->GetColumnCount());
  441             fields[ColumnHotkeyDescription] = hotkey->Description;
  442             fields[ColumnHotkey] = hotkey->GetShortcutString();
  443             Gui->UpdateListCtrlItem (HotkeyListCtrl, item, fields);
  444 
  445             UpdateHotkeyButtons();
  446         }
  447 #endif
  448     }
  449 
  450     void PreferencesDialog::OnSelectPkcs11ModuleButtonClick (wxCommandEvent& event)
  451     {
  452         list < pair <wstring, wstring> > extensions;
  453         wxString libExtension;
  454         libExtension = wxDynamicLibrary::CanonicalizeName (L"x");
  455 
  456 #ifdef TC_MACOSX
  457         extensions.push_back (make_pair (L"dylib", LangString["DLL_FILES"].ToStdWstring()));
  458 #endif
  459         if (!libExtension.empty())
  460         {
  461             extensions.push_back (make_pair (libExtension.Mid (libExtension.find (L'.') + 1).ToStdWstring(), LangString["DLL_FILES"].ToStdWstring()));
  462             extensions.push_back (make_pair (L"*", L""));
  463         }
  464 
  465         string libDir;
  466 
  467 #ifdef TC_WINDOWS
  468 
  469         char sysDir[TC_MAX_PATH];
  470         GetSystemDirectoryA (sysDir, sizeof (sysDir));
  471         libDir = sysDir;
  472 
  473 #elif defined (TC_MACOSX)
  474         libDir = "/usr/local/lib";
  475 #elif defined (TC_UNIX)
  476         libDir = "/usr/lib";
  477 #endif
  478 
  479         Gui->ShowInfo ("SELECT_PKCS11_MODULE_HELP");
  480 
  481         FilePathList files = Gui->SelectFiles (this, LangString["SELECT_PKCS11_MODULE"], false, false, extensions, libDir);
  482         if (!files.empty())
  483             Pkcs11ModulePathTextCtrl->SetValue (wstring (*files.front()));
  484     }
  485 
  486     void PreferencesDialog::OnTimer ()
  487     {
  488 #ifdef TC_WINDOWS
  489         for (UINT vKey = 0; vKey <= 0xFF; vKey++)
  490         {
  491             if (GetAsyncKeyState (vKey) < 0)
  492             {
  493                 bool shift = wxGetKeyState (WXK_SHIFT);
  494                 bool control = wxGetKeyState (WXK_CONTROL);
  495                 bool alt = wxGetKeyState (WXK_ALT);
  496                 bool win = wxGetKeyState (WXK_WINDOWS_LEFT) || wxGetKeyState (WXK_WINDOWS_RIGHT);
  497 
  498                 if (!Hotkey::GetVirtualKeyCodeString (vKey).empty())    // If the key is allowed and its name has been resolved
  499                 {
  500                     LastVirtualKeyPressed = vKey;
  501 
  502                     HotkeyShiftCheckBox->SetValue (shift);
  503                     HotkeyControlCheckBox->SetValue (control);
  504                     HotkeyAltCheckBox->SetValue (alt);
  505                     HotkeyWinCheckBox->SetValue (win);
  506 
  507                     HotkeyTextCtrl->ChangeValue (Hotkey::GetVirtualKeyCodeString (LastVirtualKeyPressed));
  508                     UpdateHotkeyButtons();
  509                     return;
  510                 }
  511             }
  512         }
  513 #endif
  514     }
  515 
  516     void PreferencesDialog::UpdateHotkeyButtons()
  517     {
  518         AssignHotkeyButton->Enable (!HotkeyTextCtrl->IsEmpty() && HotkeyListCtrl->GetSelectedItemCount() > 0);
  519 
  520         bool remove = false;
  521         foreach (long item, Gui->GetListCtrlSelectedItems (HotkeyListCtrl))
  522         {
  523             if (reinterpret_cast <Hotkey *> (HotkeyListCtrl->GetItemData (item))->VirtualKeyCode != 0)
  524                 remove = true;
  525         }
  526         RemoveHotkeyButton->Enable (remove);
  527     }
  528 }