Fix a cut & paste bug.
[reactos.git] / reactos / dll / cpl / access / keyboard.c
index a16f527..a0b2efa 100644 (file)
@@ -1,26 +1,75 @@
 /* $Id$
  *
- * PROJECT:         ReactOS System Control Panel
+ * PROJECT:         ReactOS Accessibility Control Panel
  * LICENSE:         GPL - See COPYING in the top level directory
- * FILE:            lib/cpl/system/advanced.c
- * PURPOSE:         Memory, start-up and profiles settings
+ * FILE:            dll/cpl/access/keyboard.c
+ * PURPOSE:         Keyboard-related accessibility settings
  * COPYRIGHT:       Copyright 2004 Johannes Anderwald (j_anderw@sbox.tugraz.at)
- * UPDATE HISTORY:
- *      03-04-2004  Created
+ *                  Copyright 2007 Eric Kohl
  */
+
 #include <windows.h>
 #include <stdlib.h>
+#include <stdio.h>
 #include <commctrl.h>
 #include <prsht.h>
+#include <tchar.h>
 #include "resource.h"
 #include "access.h"
 
-typedef struct _GLOBAL_DATA
+
+#define BOUNCETICKS 5
+static INT nBounceArray[BOUNCETICKS] = {500, 700, 1000, 1500, 2000};
+
+#define DELAYTICKS 5
+static INT nDelayArray[DELAYTICKS] = {300, 700, 1000, 1500, 2000};
+
+#define REPEATTICKS 6
+static INT nRepeatArray[REPEATTICKS] = {300, 500, 700, 1000, 1500, 2000};
+
+#define WAITTICKS 10
+static INT nWaitArray[WAITTICKS] = {0, 300, 500, 700, 1000, 1500, 2000, 5000, 10000, 20000};
+
+
+static VOID
+EnableFilterKeysTest(PGLOBAL_DATA pGlobalData)
 {
-    STICKYKEYS stickyKeys;
-    FILTERKEYS filterKeys;
-    TOGGLEKEYS toggleKeys;
-} GLOBAL_DATA, *PGLOBAL_DATA;
+    pGlobalData->filterKeys.dwFlags |= FKF_FILTERKEYSON;
+    pGlobalData->filterKeys.dwFlags &= ~FKF_INDICATOR;
+
+    SystemParametersInfo(SPI_SETFILTERKEYS,
+                         sizeof(FILTERKEYS),
+                         &pGlobalData->filterKeys,
+                         0);
+}
+
+
+static VOID
+DisableFilterKeysTest(PGLOBAL_DATA pGlobalData)
+{
+    if (pGlobalData->oldFilterKeys.dwFlags & FKF_FILTERKEYSON)
+    {
+        pGlobalData->filterKeys.dwFlags |= FKF_FILTERKEYSON;
+    }
+    else
+    {
+        pGlobalData->filterKeys.dwFlags &= ~FKF_FILTERKEYSON;
+    }
+
+    if (pGlobalData->oldFilterKeys.dwFlags & FKF_INDICATOR)
+    {
+        pGlobalData->filterKeys.dwFlags |= FKF_INDICATOR;
+    }
+    else
+    {
+        pGlobalData->filterKeys.dwFlags &= ~FKF_INDICATOR;
+    }
+
+    SystemParametersInfo(SPI_SETFILTERKEYS,
+                         sizeof(FILTERKEYS),
+                         &pGlobalData->filterKeys,
+                         0);
+}
 
 
 /* Property page dialog callback */
@@ -30,16 +79,67 @@ StickyKeysDlgProc(HWND hwndDlg,
                   WPARAM wParam,
                   LPARAM lParam)
 {
+    PGLOBAL_DATA pGlobalData;
+
+    pGlobalData = (PGLOBAL_DATA)GetWindowLongPtr(hwndDlg, DWLP_USER);
+
     switch (uMsg)
     {
         case WM_INITDIALOG:
+            pGlobalData = (PGLOBAL_DATA)lParam;
+            SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pGlobalData);
+
+            memcpy(&pGlobalData->oldStickyKeys,
+                   &pGlobalData->stickyKeys,
+                   sizeof(STICKYKEYS));
+
+            CheckDlgButton(hwndDlg,
+                           IDC_STICKY_ACTIVATE_CHECK,
+                           pGlobalData->stickyKeys.dwFlags & SKF_HOTKEYACTIVE ? BST_CHECKED : BST_UNCHECKED);
+
+            CheckDlgButton(hwndDlg,
+                           IDC_STICKY_LOCK_CHECK,
+                           pGlobalData->stickyKeys.dwFlags & SKF_TRISTATE ? BST_CHECKED : BST_UNCHECKED);
+
+            CheckDlgButton(hwndDlg,
+                           IDC_STICKY_UNLOCK_CHECK,
+                           pGlobalData->stickyKeys.dwFlags & SKF_TWOKEYSOFF ? BST_CHECKED : BST_UNCHECKED);
+
+            CheckDlgButton(hwndDlg,
+                           IDC_STICKY_SOUND_CHECK,
+                           pGlobalData->stickyKeys.dwFlags & SKF_AUDIBLEFEEDBACK ? BST_CHECKED : BST_UNCHECKED);
+
+            CheckDlgButton(hwndDlg,
+                           IDC_STICKY_STATUS_CHECK,
+                           pGlobalData->stickyKeys.dwFlags & SKF_INDICATOR ? BST_CHECKED : BST_UNCHECKED);
             break;
 
         case WM_COMMAND:
             switch (LOWORD(wParam))
             {
+                case IDC_STICKY_ACTIVATE_CHECK:
+                    pGlobalData->stickyKeys.dwFlags ^= SKF_HOTKEYACTIVE;
+                    break;
+
+                case IDC_STICKY_LOCK_CHECK:
+                    pGlobalData->stickyKeys.dwFlags ^= SKF_TRISTATE;
+                    break;
+
+                case IDC_STICKY_UNLOCK_CHECK:
+                    pGlobalData->stickyKeys.dwFlags ^= SKF_TWOKEYSOFF;
+                    break;
+
+                case IDC_STICKY_SOUND_CHECK:
+                    pGlobalData->stickyKeys.dwFlags ^= SKF_AUDIBLEFEEDBACK;
+                    break;
+
+                case IDC_STICKY_STATUS_CHECK:
+                    pGlobalData->stickyKeys.dwFlags ^= SKF_INDICATOR;
+                    break;
+
                 case IDOK:
-                    EndDialog(hwndDlg, TRUE);
+                    EndDialog(hwndDlg,
+                              (pGlobalData->stickyKeys.dwFlags != pGlobalData->oldStickyKeys.dwFlags));
                     break;
 
                 case IDCANCEL:
@@ -57,54 +157,426 @@ StickyKeysDlgProc(HWND hwndDlg,
 
 
 static VOID
-OnInitDialog(IN HWND hwndDlg)
+AddComboBoxTime(HWND hwnd, INT nId, INT nTimeMs)
+{
+    TCHAR szBuffer[32];
+    TCHAR szSeconds[20];
+
+    if (LoadString(hApplet, IDS_SECONDS, szSeconds, 20) == 0)
+        lstrcpy(szSeconds, L"Seconds");
+
+    _stprintf(szBuffer, _T("%d.%d %s"),
+              nTimeMs / 1000, (nTimeMs % 1000) / 100,
+              szSeconds);
+
+    SendDlgItemMessage(hwnd, nId, CB_ADDSTRING, 0, (LPARAM)szBuffer);
+}
+
+
+INT_PTR CALLBACK
+BounceKeysDlgProc(HWND hwndDlg,
+                  UINT uMsg,
+                  WPARAM wParam,
+                  LPARAM lParam)
 {
     PGLOBAL_DATA pGlobalData;
+    INT i, n;
+
+    pGlobalData = (PGLOBAL_DATA)GetWindowLongPtr(hwndDlg, DWLP_USER);
+
+    switch (uMsg)
+    {
+        case WM_INITDIALOG:
+            pGlobalData = (PGLOBAL_DATA)lParam;
+            SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pGlobalData);
+
+            /* Determine the current bounce time */
+            if (pGlobalData->filterKeys.iBounceMSec == 0)
+                pGlobalData->filterKeys.iBounceMSec = nBounceArray[0];
+
+            for (n = 0; n < BOUNCETICKS; n++)
+            {
+                 if (pGlobalData->filterKeys.iBounceMSec < nBounceArray[n])
+                     break;
+            }
+            n--;
+
+            for (i = 0; i < BOUNCETICKS; i++)
+            {
+                 AddComboBoxTime(hwndDlg, IDC_BOUNCE_TIME_COMBO, nBounceArray[i]);
+            }
+
+            SendDlgItemMessage(hwndDlg, IDC_BOUNCE_TIME_COMBO, CB_SETCURSEL, n, 0);
+            break;
+
+        case WM_COMMAND:
+            switch (LOWORD(wParam))
+            {
+                case IDC_BOUNCE_TIME_COMBO:
+                    if (HIWORD(wParam) == CBN_SELCHANGE)
+                    {
+                        i = SendDlgItemMessage(hwndDlg, IDC_BOUNCE_TIME_COMBO, CB_GETCURSEL, 0, 0);
+                        if (i != CB_ERR)
+                        {
+                            pGlobalData->filterKeys.iBounceMSec = nBounceArray[i];
+                        }
+                    }
+                    break;
+
+                case IDC_BOUNCE_TEST_EDIT:
+                    switch (HIWORD(wParam))
+                    {
+                        case EN_SETFOCUS:
+                            EnableFilterKeysTest(pGlobalData);
+                            break;
+
+                        case EN_KILLFOCUS:
+                            DisableFilterKeysTest(pGlobalData);
+                            break;
+                    }
+                    break;
+
+                case IDOK:
+                    EndDialog(hwndDlg, TRUE);
+                    break;
+
+                case IDCANCEL:
+                    EndDialog(hwndDlg, FALSE);
+                    break;
 
-    pGlobalData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(GLOBAL_DATA));
-    if (pGlobalData == NULL)
-        return;
+                default:
+                    break;
+            }
+            break;
+    }
+
+    return FALSE;
+}
+
+
+INT_PTR CALLBACK
+RepeatKeysDlgProc(HWND hwndDlg,
+                  UINT uMsg,
+                  WPARAM wParam,
+                  LPARAM lParam)
+{
+    PGLOBAL_DATA pGlobalData;
+    INT i, n;
 
-    SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pGlobalData);
+    pGlobalData = (PGLOBAL_DATA)GetWindowLongPtr(hwndDlg, DWLP_USER);
 
-    /* Get sticky keys information */
-    pGlobalData->stickyKeys.cbSize = sizeof(STICKYKEYS);
-    if (!SystemParametersInfo(SPI_GETSTICKYKEYS,
-                              sizeof(STICKYKEYS),
-                              &pGlobalData->stickyKeys,
-                              0))
+    switch (uMsg)
     {
-        return;
+        case WM_INITDIALOG:
+            pGlobalData = (PGLOBAL_DATA)lParam;
+            SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pGlobalData);
+
+            CheckRadioButton(hwndDlg,
+                             IDC_REPEAT_NOREPEAT_RADIO,
+                             IDC_REPEAT_REPEAT_RADIO,
+                             (pGlobalData->filterKeys.iDelayMSec == 0) ? IDC_REPEAT_NOREPEAT_RADIO : IDC_REPEAT_REPEAT_RADIO);
+
+            /* Initialize the delay combobox */
+            for (n = 0; n < DELAYTICKS; n++)
+            {
+                 if (pGlobalData->filterKeys.iDelayMSec < nDelayArray[n])
+                     break;
+            }
+            n--;
+
+            for (i = 0; i < DELAYTICKS; i++)
+            {
+                 AddComboBoxTime(hwndDlg, IDC_REPEAT_DELAY_COMBO, nDelayArray[i]);
+            }
+
+            SendDlgItemMessage(hwndDlg, IDC_REPEAT_DELAY_COMBO, CB_SETCURSEL, n, 0);
+
+            /* Initialize the repeat combobox */
+            for (n = 0; n < REPEATTICKS; n++)
+            {
+                 if (pGlobalData->filterKeys.iRepeatMSec < nRepeatArray[n])
+                     break;
+            }
+            n--;
+
+            for (i = 0; i < REPEATTICKS; i++)
+            {
+                 AddComboBoxTime(hwndDlg, IDC_REPEAT_REPEAT_COMBO, nRepeatArray[i]);
+            }
+
+            SendDlgItemMessage(hwndDlg, IDC_REPEAT_REPEAT_COMBO, CB_SETCURSEL, n, 0);
+
+            /* Disable the delay and repeat comboboxes if needed */
+            if (pGlobalData->filterKeys.iDelayMSec == 0)
+            {
+                EnableWindow(GetDlgItem(hwndDlg, IDC_REPEAT_DELAY_COMBO), FALSE);
+                EnableWindow(GetDlgItem(hwndDlg, IDC_REPEAT_REPEAT_COMBO), FALSE);
+            }
+
+            /* Initialize the wait combobox */
+            for (n = 0; n < WAITTICKS; n++)
+            {
+                 if (pGlobalData->filterKeys.iWaitMSec < nWaitArray[n])
+                     break;
+            }
+            n--;
+
+            for (i = 0; i < WAITTICKS; i++)
+            {
+                 AddComboBoxTime(hwndDlg, IDC_REPEAT_WAIT_COMBO, nWaitArray[i]);
+            }
+
+            SendDlgItemMessage(hwndDlg, IDC_REPEAT_WAIT_COMBO, CB_SETCURSEL, n, 0);
+            break;
+
+        case WM_COMMAND:
+            switch (LOWORD(wParam))
+            {
+                case IDC_REPEAT_NOREPEAT_RADIO:
+                    pGlobalData->filterKeys.iDelayMSec = 0;
+                    pGlobalData->filterKeys.iRepeatMSec = 0;
+                    EnableWindow(GetDlgItem(hwndDlg, IDC_REPEAT_DELAY_COMBO), FALSE);
+                    EnableWindow(GetDlgItem(hwndDlg, IDC_REPEAT_REPEAT_COMBO), FALSE);
+                    break;
+
+                case IDC_REPEAT_REPEAT_RADIO:
+                    EnableWindow(GetDlgItem(hwndDlg, IDC_REPEAT_DELAY_COMBO), TRUE);
+                    EnableWindow(GetDlgItem(hwndDlg, IDC_REPEAT_REPEAT_COMBO), TRUE);
+                    break;
+
+                case IDC_REPEAT_DELAY_COMBO:
+                    if (HIWORD(wParam) == CBN_SELCHANGE)
+                    {
+                        i = SendDlgItemMessage(hwndDlg, IDC_REPEAT_DELAY_COMBO, CB_GETCURSEL, 0, 0);
+                        if (i != CB_ERR)
+                        {
+                            pGlobalData->filterKeys.iDelayMSec = nDelayArray[i];
+                        }
+                    }
+                    break;
+
+                case IDC_REPEAT_REPEAT_COMBO:
+                    if (HIWORD(wParam) == CBN_SELCHANGE)
+                    {
+                        i = SendDlgItemMessage(hwndDlg, IDC_REPEAT_REPEAT_COMBO, CB_GETCURSEL, 0, 0);
+                        if (i != CB_ERR)
+                        {
+                            pGlobalData->filterKeys.iRepeatMSec = nRepeatArray[i];
+                        }
+                    }
+                    break;
+
+                case IDC_REPEAT_WAIT_COMBO:
+                    if (HIWORD(wParam) == CBN_SELCHANGE)
+                    {
+                        i = SendDlgItemMessage(hwndDlg, IDC_REPEAT_WAIT_COMBO, CB_GETCURSEL, 0, 0);
+                        if (i != CB_ERR)
+                        {
+                            pGlobalData->filterKeys.iWaitMSec = nWaitArray[i];
+                        }
+                    }
+                    break;
+
+                case IDC_REPEAT_TEST_EDIT:
+                    switch (HIWORD(wParam))
+                    {
+                        case EN_SETFOCUS:
+                            EnableFilterKeysTest(pGlobalData);
+                            break;
+
+                        case EN_KILLFOCUS:
+                            DisableFilterKeysTest(pGlobalData);
+                            break;
+                    }
+                    break;
+
+                case IDOK:
+                    EndDialog(hwndDlg, TRUE);
+                    break;
+
+                case IDCANCEL:
+                    EndDialog(hwndDlg, FALSE);
+                    break;
+
+                default:
+                    break;
+            }
+            break;
     }
 
-    if (pGlobalData->stickyKeys.dwFlags & SKF_STICKYKEYSON)
-        SendDlgItemMessage(hwndDlg, IDC_STICKY_BOX, BM_SETCHECK, (WPARAM)BST_CHECKED, (LPARAM)0);
+    return FALSE;
+}
+
+
+/* Property page dialog callback */
+INT_PTR CALLBACK
+FilterKeysDlgProc(HWND hwndDlg,
+                  UINT uMsg,
+                  WPARAM wParam,
+                  LPARAM lParam)
+{
+    PGLOBAL_DATA pGlobalData;
+
+    pGlobalData = (PGLOBAL_DATA)GetWindowLongPtr(hwndDlg, DWLP_USER);
 
-    /* Get filter keys information */
-    pGlobalData->filterKeys.cbSize = sizeof(FILTERKEYS);
-    if (!SystemParametersInfo(SPI_GETFILTERKEYS,
-                              sizeof(FILTERKEYS),
-                              &pGlobalData->filterKeys,
-                              0))
+    switch (uMsg)
     {
-        return;
+        case WM_INITDIALOG:
+            pGlobalData = (PGLOBAL_DATA)lParam;
+            SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pGlobalData);
+
+            memcpy(&pGlobalData->oldFilterKeys,
+                   &pGlobalData->filterKeys,
+                   sizeof(FILTERKEYS));
+
+            CheckDlgButton(hwndDlg,
+                           IDC_FILTER_ACTIVATE_CHECK,
+                           pGlobalData->filterKeys.dwFlags & FKF_HOTKEYACTIVE ? BST_CHECKED : BST_UNCHECKED);
+
+            if (pGlobalData->filterKeys.iBounceMSec != 0)
+            {
+                CheckRadioButton(hwndDlg, IDC_FILTER_BOUNCE_RADIO, IDC_FILTER_REPEAT_RADIO, IDC_FILTER_BOUNCE_RADIO);
+                EnableWindow(GetDlgItem(hwndDlg, IDC_FILTER_BOUNCE_BUTTON), TRUE);
+                EnableWindow(GetDlgItem(hwndDlg, IDC_FILTER_REPEAT_BUTTON), FALSE);
+            }
+            else
+            {
+                CheckRadioButton(hwndDlg, IDC_FILTER_BOUNCE_RADIO, IDC_FILTER_REPEAT_RADIO, IDC_FILTER_REPEAT_RADIO);
+                EnableWindow(GetDlgItem(hwndDlg, IDC_FILTER_BOUNCE_BUTTON), FALSE);
+                EnableWindow(GetDlgItem(hwndDlg, IDC_FILTER_REPEAT_BUTTON), TRUE);
+            }
+
+            CheckDlgButton(hwndDlg,
+                           IDC_FILTER_SOUND_CHECK,
+                           pGlobalData->filterKeys.dwFlags & FKF_CLICKON ? BST_CHECKED : BST_UNCHECKED);
+
+            CheckDlgButton(hwndDlg,
+                           IDC_FILTER_STATUS_CHECK,
+                           pGlobalData->filterKeys.dwFlags & FKF_INDICATOR ? BST_CHECKED : BST_UNCHECKED);
+            break;
+
+        case WM_COMMAND:
+            switch (LOWORD(wParam))
+            {
+                case IDC_FILTER_ACTIVATE_CHECK:
+                    pGlobalData->filterKeys.dwFlags ^= FKF_HOTKEYACTIVE;
+                    break;
+
+                case IDC_FILTER_BOUNCE_RADIO:
+                    EnableWindow(GetDlgItem(hwndDlg, IDC_FILTER_BOUNCE_BUTTON), TRUE);
+                    EnableWindow(GetDlgItem(hwndDlg, IDC_FILTER_REPEAT_BUTTON), FALSE);
+                    break;
+
+                case IDC_FILTER_REPEAT_RADIO:
+                    EnableWindow(GetDlgItem(hwndDlg, IDC_FILTER_BOUNCE_BUTTON), FALSE);
+                    EnableWindow(GetDlgItem(hwndDlg, IDC_FILTER_REPEAT_BUTTON), TRUE);
+                    break;
+
+                case IDC_FILTER_BOUNCE_BUTTON:
+                    DialogBoxParam(hApplet,
+                                   MAKEINTRESOURCE(IDD_BOUNCEKEYSOPTIONS),
+                                   hwndDlg,
+                                   (DLGPROC)BounceKeysDlgProc,
+                                   (LPARAM)pGlobalData);
+                    break;
+
+                case IDC_FILTER_TEST_EDIT:
+                    switch (HIWORD(wParam))
+                    {
+                        case EN_SETFOCUS:
+                            EnableFilterKeysTest(pGlobalData);
+                            break;
+
+                        case EN_KILLFOCUS:
+                            DisableFilterKeysTest(pGlobalData);
+                            break;
+                    }
+                    break;
+
+                case IDC_FILTER_SOUND_CHECK:
+                    pGlobalData->filterKeys.dwFlags ^= FKF_CLICKON;
+                    break;
+
+                case IDC_FILTER_REPEAT_BUTTON:
+                    DialogBoxParam(hApplet,
+                                   MAKEINTRESOURCE(IDD_REPEATKEYSOPTIONS),
+                                   hwndDlg,
+                                   (DLGPROC)RepeatKeysDlgProc,
+                                   (LPARAM)pGlobalData);
+                    break;
+
+                case IDC_FILTER_STATUS_CHECK:
+                    pGlobalData->filterKeys.dwFlags ^= FKF_INDICATOR;
+                    break;
+
+                case IDOK:
+                    EndDialog(hwndDlg,
+                              (pGlobalData->filterKeys.dwFlags != pGlobalData->oldFilterKeys.dwFlags));
+                    break;
+
+                case IDCANCEL:
+                    EndDialog(hwndDlg, FALSE);
+                    break;
+
+                default:
+                    break;
+            }
+            break;
     }
 
-    if (pGlobalData->filterKeys.dwFlags & FKF_FILTERKEYSON)
-        SendDlgItemMessage(hwndDlg, IDC_FILTER_BOX, BM_SETCHECK, (WPARAM)BST_CHECKED, (LPARAM)0);
+    return FALSE;
+}
+
 
-    /* Get toggle keys information */
-    pGlobalData->toggleKeys.cbSize = sizeof(TOGGLEKEYS);
-    if (!SystemParametersInfo(SPI_GETTOGGLEKEYS,
-                              sizeof(TOGGLEKEYS),
-                              &pGlobalData->toggleKeys,
-                              0))
+/* Property page dialog callback */
+INT_PTR CALLBACK
+ToggleKeysDlgProc(HWND hwndDlg,
+                  UINT uMsg,
+                  WPARAM wParam,
+                  LPARAM lParam)
+{
+    PGLOBAL_DATA pGlobalData;
+
+    pGlobalData = (PGLOBAL_DATA)GetWindowLongPtr(hwndDlg, DWLP_USER);
+
+    switch (uMsg)
     {
-        return;
+        case WM_INITDIALOG:
+            pGlobalData = (PGLOBAL_DATA)lParam;
+            SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pGlobalData);
+
+            memcpy(&pGlobalData->oldToggleKeys,
+                   &pGlobalData->toggleKeys,
+                   sizeof(TOGGLEKEYS));
+
+            CheckDlgButton(hwndDlg,
+                           IDC_TOGGLE_ACTIVATE_CHECK,
+                           pGlobalData->toggleKeys.dwFlags & TKF_HOTKEYACTIVE ? BST_CHECKED : BST_UNCHECKED);
+            break;
+
+        case WM_COMMAND:
+            switch (LOWORD(wParam))
+            {
+                case IDC_TOGGLE_ACTIVATE_CHECK:
+                    pGlobalData->toggleKeys.dwFlags ^= TKF_HOTKEYACTIVE;
+                    break;
+
+                case IDOK:
+                    EndDialog(hwndDlg,
+                              (pGlobalData->toggleKeys.dwFlags != pGlobalData->oldToggleKeys.dwFlags));
+                    break;
+
+                case IDCANCEL:
+                    EndDialog(hwndDlg, FALSE);
+                    break;
+
+                default:
+                    break;
+            }
+            break;
     }
 
-    if (pGlobalData->toggleKeys.dwFlags & TKF_TOGGLEKEYSON)
-        SendDlgItemMessage(hwndDlg, IDC_TOGGLE_BOX, BM_SETCHECK, (WPARAM)BST_CHECKED, (LPARAM)0);
+    return FALSE;
 }
 
 
@@ -123,37 +595,77 @@ KeyboardPageProc(HWND hwndDlg,
     switch (uMsg)
     {
         case WM_INITDIALOG:
-            OnInitDialog(hwndDlg);
+            pGlobalData = (PGLOBAL_DATA)((LPPROPSHEETPAGE)lParam)->lParam;
+            if (pGlobalData == NULL)
+                return FALSE;
+
+            SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pGlobalData);
+
+            CheckDlgButton(hwndDlg,
+                           IDC_STICKY_BOX,
+                           pGlobalData->stickyKeys.dwFlags & SKF_STICKYKEYSON ? BST_CHECKED : BST_UNCHECKED);
+
+            CheckDlgButton(hwndDlg,
+                           IDC_FILTER_BOX,
+                           pGlobalData->filterKeys.dwFlags & FKF_FILTERKEYSON ? BST_CHECKED : BST_UNCHECKED);
+
+            CheckDlgButton(hwndDlg,
+                           IDC_TOGGLE_BOX,
+                           pGlobalData->toggleKeys.dwFlags & TKF_TOGGLEKEYSON ? BST_CHECKED : BST_UNCHECKED);
+
+            CheckDlgButton(hwndDlg,
+                           IDC_KEYBOARD_EXTRA,
+                           pGlobalData->bKeyboardPref ? BST_CHECKED : BST_UNCHECKED);
             return TRUE;
 
         case WM_COMMAND:
             switch (LOWORD(wParam))
             {
                 case IDC_STICKY_BOX:
+                    pGlobalData->stickyKeys.dwFlags ^= SKF_STICKYKEYSON;
                     PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
                     break;
 
                 case IDC_STICKY_BUTTON:
                     if (DialogBoxParam(hApplet,
-                                   MAKEINTRESOURCE(IDD_STICKYKEYSOPTIONS),
-                                   hwndDlg,
-                                   (DLGPROC)StickyKeysDlgProc,
-                                   (LPARAM)pGlobalData))
+                                       MAKEINTRESOURCE(IDD_STICKYKEYSOPTIONS),
+                                       hwndDlg,
+                                       (DLGPROC)StickyKeysDlgProc,
+                                       (LPARAM)pGlobalData))
                         PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
                     break;
 
                 case IDC_FILTER_BOX:
+                    pGlobalData->filterKeys.dwFlags ^= FKF_FILTERKEYSON;
                     PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
                     break;
 
                 case IDC_FILTER_BUTTON:
+                    if (DialogBoxParam(hApplet,
+                                       MAKEINTRESOURCE(IDD_FILTERKEYSOPTIONS),
+                                       hwndDlg,
+                                       (DLGPROC)FilterKeysDlgProc,
+                                       (LPARAM)pGlobalData))
+                        PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
                     break;
 
                 case IDC_TOGGLE_BOX:
+                    pGlobalData->toggleKeys.dwFlags ^= TKF_TOGGLEKEYSON;
                     PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
                     break;
 
                 case IDC_TOGGLE_BUTTON:
+                    if (DialogBoxParam(hApplet,
+                                       MAKEINTRESOURCE(IDD_TOGGLEKEYSOPTIONS),
+                                       hwndDlg,
+                                       (DLGPROC)ToggleKeysDlgProc,
+                                       (LPARAM)pGlobalData))
+                        PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
+                    break;
+
+                case IDC_KEYBOARD_EXTRA:
+                    pGlobalData->bKeyboardPref = !pGlobalData->bKeyboardPref;
+                    PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
                     break;
 
                 default:
@@ -180,13 +692,14 @@ KeyboardPageProc(HWND hwndDlg,
                                      &pGlobalData->toggleKeys,
                                      SPIF_UPDATEINIFILE | SPIF_SENDCHANGE /*0*/);
 
+                SystemParametersInfo(SPI_SETKEYBOARDPREF,
+                                     pGlobalData->bKeyboardPref,
+                                     NULL,
+                                     SPIF_UPDATEINIFILE | SPIF_SENDCHANGE /*0*/);
+
                 return TRUE;
             }
             break;
-
-        case WM_DESTROY:
-            HeapFree(GetProcessHeap(), 0, pGlobalData);
-            break;
     }
 
     return FALSE;