[CALC] Enable support for HTMLHELP (#1877)
[reactos.git] / base / applications / calc / winmain.c
index 589a453..6bf11a3 100644 (file)
@@ -1,10 +1,26 @@
-#include "calc.h"
+/*
+ * ReactOS Calc (main program)
+ *
+ * Copyright 2007-2017, Carlo Bramini
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
 
-#include <winbase.h>
-#include <wingdi.h>
-#include <winreg.h>
+#include "calc.h"
 
-#define HTMLHELP_PATH(_pt)  TEXT("%systemroot%\\Help\\calc.chm::") TEXT(_pt)
+#define HTMLHELP_PATH(_pt)  _T("%systemroot%\\Help\\calc.chm::") _T(_pt)
 
 #define MAKE_BITMASK4(_show_b16, _show_b10, _show_b8, _show_b2) \
     (((_show_b2)  << 0) | \
@@ -32,9 +48,9 @@
 #define BITMASK_OCT_MASK    0x02
 #define BITMASK_BIN_MASK    0x01
 
-#define CALC_CLR_RED        0x000000FF
-#define CALC_CLR_BLUE       0x00FF0000
-#define CALC_CLR_PURP       0x00FF00FF
+#define CALC_CLR_RED        RGB(0xFF, 0x00, 0x00)
+#define CALC_CLR_BLUE       RGB(0x00, 0x00, 0xFF)
+#define CALC_CLR_PURP       RGB(0xFF, 0x00, 0xFF)
 
 typedef struct {
     CHAR key; // Virtual key identifier
@@ -164,6 +180,8 @@ static const WORD operator_codes[] = {
     IDC_BUTTON_MULT,    // RPN_OPERATOR_MULT
     IDC_BUTTON_DIV,     // RPN_OPERATOR_DIV
     IDC_BUTTON_MOD,     // RPN_OPERATOR_MOD
+    IDC_BUTTON_XeY,     // RPN_OPERATOR_POW
+    IDC_BUTTON_XrY,     // RPN_OPERATOR_SQR
 };
 
 typedef void (*rpn_callback1)(calc_number_t *);
@@ -178,8 +196,6 @@ typedef struct {
     rpn_callback1   inv_hyp;
 } function_table_t;
 
-static void run_pow(calc_number_t *number);
-static void run_sqr(calc_number_t *number);
 static void run_fe(calc_number_t *number);
 static void run_dat_sta(calc_number_t *number);
 static void run_mp(calc_number_t *c);
@@ -203,94 +219,139 @@ static const function_table_t function_table[] = {
     { IDC_BUTTON_LN,   MODIFIER_INV,              1, rpn_ln,      rpn_exp,     NULL,     NULL      },
     { IDC_BUTTON_LOG,  MODIFIER_INV,              1, rpn_log,     rpn_exp10,   NULL,     NULL      },
     { IDC_BUTTON_NF,   0,                         1, rpn_fact,    NULL,        NULL,     NULL      },
-    { IDC_BUTTON_AVE,  0,                         0, rpn_ave,     NULL,        NULL,     NULL      },
-    { IDC_BUTTON_SUM,  0,                         0, rpn_sum,     NULL,        NULL,     NULL      },
+    { IDC_BUTTON_AVE,  MODIFIER_INV,              0, rpn_ave,     rpn_ave2,    NULL,     NULL      },
+    { IDC_BUTTON_SUM,  MODIFIER_INV,              0, rpn_sum,     rpn_sum2,    NULL,     NULL      },
     { IDC_BUTTON_S,    MODIFIER_INV,              0, rpn_s_m1,    rpn_s,       NULL,     NULL      },
-    { IDC_BUTTON_XeY,  MODIFIER_INV,              1, run_pow,     run_sqr,     NULL,     NULL      },
     { IDC_BUTTON_SQRT, MODIFIER_INV,              1, rpn_sqrt,    NULL,        NULL,     NULL      },
     { IDC_BUTTON_DMS,  MODIFIER_INV,              1, rpn_dec2dms, rpn_dms2dec, NULL,     NULL      },
     { IDC_BUTTON_FE,   0,                         1, run_fe,      NULL,        NULL,     NULL      },
     { IDC_BUTTON_DAT,  0,                         1, run_dat_sta, NULL,        NULL,     NULL,     },
-    { IDC_BUTTON_MP,   MODIFIER_INV,              1, run_mp,      run_mm,      NULL,     NULL,     },
-    { IDC_BUTTON_MS,   MODIFIER_INV,              1, run_ms,      run_mw,      NULL,     NULL,     },
+    { IDC_BUTTON_MP,   MODIFIER_INV|NO_CHAIN,     1, run_mp,      run_mm,      NULL,     NULL,     },
+    { IDC_BUTTON_MS,   MODIFIER_INV|NO_CHAIN,     1, run_ms,      run_mw,      NULL,     NULL,     },
     { IDC_BUTTON_CANC, NO_CHAIN,                  0, run_canc,    NULL,        NULL,     NULL,     },
     { IDC_BUTTON_RIGHTPAR, NO_CHAIN,              1, run_rpar,    NULL,        NULL,     NULL,     },
     { IDC_BUTTON_LEFTPAR,  NO_CHAIN,              0, run_lpar,    NULL,        NULL,     NULL,     },
 };
 
+/* Sub-classing information for theming support */
+typedef struct{
+    BOOL    bHover;
+    WNDPROC oldProc;
+} BTNINFO,*LPBTNINFO;
+
+
 /*
-*/
+ * Global variable declaration
+ */
 
-calc_t calc;
+calc_t  calc;
 
-static void load_config(void)
+/* Hot-state info for theming support */
+BTNINFO BtnInfo[255];
+UINT    BtnCount;
+
+static void UpdateNumberIntl(void)
 {
-    TCHAR buf[32];
+    /* Get current user defaults */
+    if (!GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SDECIMAL, calc.sDecimal, SIZEOF(calc.sDecimal)))
+        _tcscpy(calc.sDecimal, _T("."));
+
+    if (!GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_STHOUSAND, calc.sThousand, SIZEOF(calc.sThousand)))
+        _tcscpy(calc.sThousand, _T(","));
+
+    /* get the string lengths */
+    calc.sDecimal_len = _tcslen(calc.sDecimal);
+    calc.sThousand_len = _tcslen(calc.sThousand);
+}
+
+static int LoadRegInt(LPCTSTR lpszApp, LPCTSTR lpszKey, int iDefault)
+{
+    HKEY  hKey;
+    int   iValue;
     DWORD tmp;
-#if _WIN32_WINNT >= 0x0500
-    HKEY hKey;
-#endif
 
-    /* Try to load last selected layout */
-    GetProfileString(TEXT("SciCalc"), TEXT("layout"), TEXT("0"), buf, SIZEOF(buf));
-    if (_stscanf(buf, TEXT("%lu"), &calc.layout) != 1)
-        calc.layout = CALC_LAYOUT_STANDARD;
+    if (RegOpenKeyEx(HKEY_CURRENT_USER, lpszApp, 0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS)
+    {
+        /* Try to load integer value */
+        tmp = sizeof(int);
 
-    /* Try to load last selected formatting option */
-    GetProfileString(TEXT("SciCalc"), TEXT("UseSep"), TEXT("0"), buf, SIZEOF(buf));
-    if (_stscanf(buf, TEXT("%lu"), &tmp) != 1)
-        calc.usesep = FALSE;
-    else
-        calc.usesep = (tmp == 1) ? TRUE : FALSE;
+        if (RegQueryValueEx(hKey, lpszKey, NULL, NULL, (LPBYTE)&iValue, &tmp) == ERROR_SUCCESS)
+            iDefault = iValue;
 
-    /* memory is empty at startup */
-    calc.is_memory = FALSE;
+        /* close the key */
+        RegCloseKey(hKey);
+    }
 
-#if _WIN32_WINNT >= 0x0500
-    /* empty these values */
-    calc.sDecimal[0] = TEXT('\0');
-    calc.sThousand[0] = TEXT('\0');
+    return iDefault;
+}
 
-    /* try to open the registry */
-    if (RegOpenKeyEx(HKEY_CURRENT_USER, 
-                     TEXT("Control Panel\\International"),
-                     0,
-                     KEY_QUERY_VALUE,
-                     &hKey) == ERROR_SUCCESS) {
-        /* get these values (ignore errors) */
-        tmp = sizeof(calc.sDecimal);
-        RegQueryValueEx(hKey, TEXT("sDecimal"), NULL, NULL, (LPBYTE)calc.sDecimal, &tmp);
+static void SaveRegInt(LPCTSTR lpszApp, LPCTSTR lpszKey, int iValue)
+{
+    HKEY hKey;
 
-        tmp = sizeof(calc.sThousand);
-        RegQueryValueEx(hKey, TEXT("sThousand"), NULL, NULL, (LPBYTE)calc.sThousand, &tmp);
+    if (RegCreateKeyEx(HKEY_CURRENT_USER, lpszApp, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, NULL, &hKey, NULL) == ERROR_SUCCESS)
+    {
+        RegSetValueEx(hKey, lpszKey, 0, REG_DWORD, (const BYTE*)&iValue, sizeof(int));
 
         /* close the key */
         RegCloseKey(hKey);
     }
-    /* if something goes wrong, let's apply the defaults */
-    if (calc.sDecimal[0] == TEXT('\0'))
-        _tcscpy(calc.sDecimal, TEXT("."));
+}
+
+static void load_config(void)
+{
+    OSVERSIONINFO osvi;
 
-    if (calc.sThousand[0] == TEXT('\0'))
-        _tcscpy(calc.sThousand, TEXT(","));
+    osvi.dwOSVersionInfoSize = sizeof(osvi);
+    GetVersionEx(&osvi);
 
-    /* get the string lengths */
-    calc.sDecimal_len = _tcslen(calc.sDecimal);
-    calc.sThousand_len = _tcslen(calc.sThousand);
-#else
-    /* acquire regional settings */
-    calc.sDecimal_len  = GetProfileString(TEXT("intl"), TEXT("sDecimal"), TEXT("."), calc.sDecimal, SIZEOF(calc.sDecimal));
-    calc.sThousand_len = GetProfileString(TEXT("intl"), TEXT("sThousand"), TEXT(","), calc.sThousand, SIZEOF(calc.sThousand));
-#endif
+    switch (osvi.dwPlatformId) {
+    case VER_PLATFORM_WIN32s:
+    case VER_PLATFORM_WIN32_WINDOWS:
+        /* Try to load last selected layout */
+        calc.layout = GetProfileInt(_T("SciCalc"), _T("layout"), CALC_LAYOUT_STANDARD);
+
+        /* Try to load last selected formatting option */
+        calc.usesep = (GetProfileInt(_T("SciCalc"), _T("UseSep"), FALSE)) ? TRUE : FALSE;
+        break;
+
+    default: /* VER_PLATFORM_WIN32_NT */
+        /* Try to load last selected layout */
+        calc.layout = LoadRegInt(_T("SOFTWARE\\Microsoft\\Calc"), _T("layout"), CALC_LAYOUT_STANDARD);
+
+        /* Try to load last selected formatting option */
+        calc.usesep = (LoadRegInt(_T("SOFTWARE\\Microsoft\\Calc"), _T("UseSep"), FALSE)) ? TRUE : FALSE;
+        break;
+    }
+
+    /* memory is empty at startup */
+    calc.is_memory = FALSE;
+
+    /* Get locale info for numbers */
+    UpdateNumberIntl();
 }
 
 static void save_config(void)
 {
     TCHAR buf[32];
+    OSVERSIONINFO osvi;
+
+    osvi.dwOSVersionInfoSize = sizeof(osvi);
+    GetVersionEx(&osvi);
 
-    _stprintf(buf, TEXT("%lu"), calc.layout);
-    WriteProfileString(TEXT("SciCalc"), TEXT("layout"), buf);
-    WriteProfileString(TEXT("SciCalc"), TEXT("UseSep"), (calc.usesep==TRUE) ? TEXT("1") : TEXT("0"));
+    switch (osvi.dwPlatformId) {
+    case VER_PLATFORM_WIN32s:
+    case VER_PLATFORM_WIN32_WINDOWS:
+        _stprintf(buf, _T("%lu"), calc.layout);
+        WriteProfileString(_T("SciCalc"), _T("layout"), buf);
+        WriteProfileString(_T("SciCalc"), _T("UseSep"), (calc.usesep==TRUE) ? _T("1") : _T("0"));
+        break;
+
+    default: /* VER_PLATFORM_WIN32_NT */
+        SaveRegInt(_T("SOFTWARE\\Microsoft\\Calc"), _T("layout"), calc.layout);
+        SaveRegInt(_T("SOFTWARE\\Microsoft\\Calc"), _T("UseSep"), calc.usesep);
+        break;
+    }
 }
 
 static LRESULT post_key_press(LPARAM lParam, WORD idc)
@@ -305,7 +366,7 @@ static LRESULT post_key_press(LPARAM lParam, WORD idc)
     if (!GetClassName(hCtlWnd, ClassName, SIZEOF(ClassName)))
         return 1;
 
-    if (!_tcscmp(ClassName, TEXT("Button"))) {
+    if (!_tcscmp(ClassName, WC_BUTTON)) {
         DWORD dwStyle = GetWindowLongPtr(hCtlWnd, GWL_STYLE) & 0xF;
 
         /* Set states for press/release, but only for push buttons */
@@ -428,26 +489,29 @@ KeyboardHookProc(int nCode, WPARAM wParam, LPARAM lParam)
 static void update_lcd_display(HWND hwnd)
 {
     /*
-     * muliply size of calc.buffer by 2 because it may
+     * multiply size of calc.buffer by 2 because it may
      * happen that separator is used between each digit.
      * Also added little additional space for dot and '\0'.
      */
-    TCHAR *tmp = (TCHAR *)alloca(sizeof(calc.buffer)*2+2*sizeof(TCHAR));
+    TCHAR tmp[MAX_CALC_SIZE * 2 + 2];
 
-    if (calc.buffer[0] == TEXT('\0'))
-        _tcscpy(tmp, TEXT("0"));
+    if (calc.buffer[0] == _T('\0'))
+        _tcscpy(tmp, _T("0"));
     else
         _tcscpy(tmp, calc.buffer);
-    /* add final '.' in decimal mode (if it's missing) */
-    if (calc.base == IDC_RADIO_DEC) {
-        if (_tcschr(tmp, TEXT('.')) == NULL)
-            _tcscat(tmp, TEXT("."));
+
+    /* Add final '.' in decimal mode (if it's missing), but
+     * only if it's a result: no append if it prints "ERROR".
+     */
+    if (calc.base == IDC_RADIO_DEC && !calc.is_nan) {
+        if (_tcschr(tmp, _T('.')) == NULL)
+            _tcscat(tmp, _T("."));
     }
     /* if separator mode is on, let's add an additional space */
     if (calc.usesep && !calc.sci_in && !calc.sci_out && !calc.is_nan) {
         /* go to the integer part of the string */
-        TCHAR *p = _tcschr(tmp, TEXT('.'));
-        TCHAR *e = _tcschr(tmp, TEXT('\0'));
+        TCHAR *p = _tcschr(tmp, _T('.'));
+        TCHAR *e = _tcschr(tmp, _T('\0'));
         int    n=0, t;
 
         if (p == NULL) p = e;
@@ -464,21 +528,21 @@ static void update_lcd_display(HWND hwnd)
             break;
         }
         while (--p > tmp) {
-            if (++n == t && *(p-1) != TEXT('-')) {
+            if (++n == t && *(p-1) != _T('-')) {
                 memmove(p+1, p, (e-p+1)*sizeof(TCHAR));
                 e++;
-                *p = TEXT(' ');
+                *p = _T(' ');
                 n = 0;
             }
         }
         /* if decimal mode, apply regional settings */
         if (calc.base == IDC_RADIO_DEC) {
             TCHAR *p = tmp;
-            TCHAR *e = _tcschr(tmp, TEXT('.'));
+            TCHAR *e = _tcschr(tmp, _T('.'));
 
             /* searching for thousands default separator */
             while (p < e) {
-                if (*p == TEXT(' ')) {
+                if (*p == _T(' ')) {
                     memmove(p+calc.sThousand_len, p+1, _tcslen(p)*sizeof(TCHAR));
                     memcpy(p, calc.sThousand, calc.sThousand_len*sizeof(TCHAR));
                     p += calc.sThousand_len;
@@ -490,7 +554,7 @@ static void update_lcd_display(HWND hwnd)
             memcpy(p, calc.sDecimal, calc.sDecimal_len*sizeof(TCHAR));
         }
     } else {
-        TCHAR *p = _tcschr(tmp, TEXT('.'));
+        TCHAR *p = _tcschr(tmp, _T('.'));
 
         /* update decimal point when usesep is false */
         if (p != NULL) {
@@ -498,7 +562,7 @@ static void update_lcd_display(HWND hwnd)
             memcpy(p, calc.sDecimal, calc.sDecimal_len*sizeof(TCHAR));
         }
     }
-    SendDlgItemMessage(hwnd, IDC_TEXT_OUTPUT, WM_SETTEXT, (WPARAM)0, (LPARAM)tmp);
+    SetDlgItemText(hwnd, IDC_TEXT_OUTPUT, tmp);
 }
 
 static void update_parent_display(HWND hWnd)
@@ -507,10 +571,10 @@ static void update_parent_display(HWND hWnd)
     int   n = eval_parent_count();
 
     if (!n)
-        str[0] = TEXT('\0');
+        str[0] = _T('\0');
     else
-        _stprintf(str,TEXT("(=%d"), n);
-    SendDlgItemMessage(hWnd, IDC_TEXT_PARENT, WM_SETTEXT, 0, (LPARAM)str);
+        _stprintf(str,_T("(=%d"), n);
+    SetDlgItemText(hWnd, IDC_TEXT_PARENT, str);
 }
 
 static void build_operand(HWND hwnd, DWORD idc)
@@ -520,14 +584,14 @@ static void build_operand(HWND hwnd, DWORD idc)
     if (idc == IDC_BUTTON_DOT) {
         /* if dot is the first char, it's added automatically */
         if (calc.buffer == calc.ptr) {
-            *calc.ptr++ = TEXT('0');
-            *calc.ptr++ = TEXT('.');
-            *calc.ptr   = TEXT('\0');
+            *calc.ptr++ = _T('0');
+            *calc.ptr++ = _T('.');
+            *calc.ptr   = _T('\0');
             update_lcd_display(hwnd);
             return;
         }
         /* if pressed dot and it's already in the string, then return */
-        if (_tcschr(calc.buffer, TEXT('.')) != NULL)
+        if (_tcschr(calc.buffer, _T('.')) != NULL)
             return;
     }
     if (idc != IDC_STATIC) {
@@ -536,8 +600,8 @@ static void build_operand(HWND hwnd, DWORD idc)
     n = calc.ptr - calc.buffer;
     if (idc == IDC_BUTTON_0 && n == 0) {
         /* no need to put the dot because it's handled by update_lcd_display() */
-        calc.buffer[0] = TEXT('0');
-        calc.buffer[1] = TEXT('\0');
+        calc.buffer[0] = _T('0');
+        calc.buffer[1] = _T('\0');
         update_lcd_display(hwnd);
         return;
     }
@@ -553,12 +617,12 @@ static void build_operand(HWND hwnd, DWORD idc)
             if (idc != IDC_STATIC)
                 calc.esp = (calc.esp * 10 + (key2code[i].key-'0')) % LOCAL_EXP_SIZE;
             if (calc.ptr == calc.buffer)
-                _stprintf(calc.ptr, TEXT("0.e%+d"), calc.esp);
+                _stprintf(calc.ptr, _T("0.e%+d"), calc.esp);
             else {
                 /* adds the dot at the end if the number has no decimal part */
-                if (!_tcschr(calc.buffer, TEXT('.')))
-                    *calc.ptr++ = TEXT('.');
-                _stprintf(calc.ptr, TEXT("e%+d"), calc.esp);
+                if (!_tcschr(calc.buffer, _T('.')))
+                    *calc.ptr++ = _T('.');
+                _stprintf(calc.ptr, _T("e%+d"), calc.esp);
             }
             update_lcd_display(hwnd);
             return;
@@ -573,7 +637,7 @@ static void build_operand(HWND hwnd, DWORD idc)
             return;
         break;
     }
-    calc.ptr += _stprintf(calc.ptr, TEXT("%C"), key2code[i].key);
+    calc.ptr += _stprintf(calc.ptr, _T("%C"), key2code[i].key);
     update_lcd_display(hwnd);
 }
 
@@ -587,23 +651,28 @@ static void prepare_rpn_result(calc_number_t *rpn, TCHAR *buffer, int size, int
     prepare_rpn_result_2(rpn, buffer, size, base);
 }
 
-static void display_rpn_result(HWND hwnd, calc_number_t *rpn)
+static void set_rpn_result(HWND hwnd, calc_number_t *rpn)
 {
     calc.sci_in = FALSE;
     prepare_rpn_result(rpn, calc.buffer, SIZEOF(calc.buffer), calc.base);
     calc.ptr = calc.buffer + _tcslen(calc.buffer);
     update_lcd_display(hwnd);
-    calc.ptr = calc.buffer;
     update_parent_display(hwnd);
 }
 
-static int get_modifiers(HWND hwnd)
+static void display_rpn_result(HWND hwnd, calc_number_t *rpn)
+{
+    set_rpn_result(hwnd, rpn);
+    calc.ptr = calc.buffer;
+}
+
+static int get_modifiers(HWND hWnd)
 {
     int modifiers = 0;
 
-    if (SendDlgItemMessage(hwnd, IDC_CHECK_INV, BM_GETCHECK, 0, 0))
+    if (IsDlgButtonChecked(hWnd, IDC_CHECK_INV) == BST_CHECKED)
         modifiers |= MODIFIER_INV;
-    if (SendDlgItemMessage(hwnd, IDC_CHECK_HYP, BM_GETCHECK, 0, 0))
+    if (IsDlgButtonChecked(hWnd, IDC_CHECK_HYP) == BST_CHECKED)
         modifiers |= MODIFIER_HYP;
 
     return modifiers;
@@ -615,8 +684,8 @@ static void convert_text2number(calc_number_t *a)
     /* the operand is taken from the last input */
     if (calc.buffer == calc.ptr) {
         /* if pushed valued is ZERO then we should grab it */
-        if (!_tcscmp(calc.buffer, TEXT("0.")) ||
-            !_tcscmp(calc.buffer, TEXT("0")))
+        if (!_tcscmp(calc.buffer, _T("0.")) ||
+            !_tcscmp(calc.buffer, _T("0")))
             /* this zero is good for both integer and decimal */
             rpn_zero(a);
         else
@@ -652,18 +721,18 @@ static const struct _update_check_menus {
     { &calc.size, IDM_VIEW_BYTE,  IDC_RADIO_BYTE, },
 };
 
-static void update_menu(HWND hwnd)
+static void update_menu(HWND hWnd)
 {
-    HMENU        hMenu = GetSubMenu(GetMenu(hwnd), 1);
+    HMENU        hMenu = GetSubMenu(GetMenu(hWnd), 1);
     unsigned int x;
 
     for (x=0; x<SIZEOF(upd); x++) {
         if (*(upd[x].sel) != upd[x].idc) {
             CheckMenuItem(hMenu, upd[x].idm, MF_BYCOMMAND|MF_UNCHECKED);
-            SendMessage((HWND)GetDlgItem(hwnd,upd[x].idc),BM_SETCHECK,FALSE,0L);
+            CheckDlgButton(hWnd, upd[x].idc, BST_UNCHECKED);
         } else {
             CheckMenuItem(hMenu, upd[x].idm, MF_BYCOMMAND|MF_CHECKED);
-            SendMessage((HWND)GetDlgItem(hwnd,upd[x].idc),BM_SETCHECK,TRUE,0L);
+            CheckDlgButton(hWnd, upd[x].idc, BST_CHECKED);
         }
     }
     CheckMenuItem(hMenu, IDM_VIEW_GROUP, MF_BYCOMMAND|(calc.usesep ? MF_CHECKED : MF_UNCHECKED));
@@ -767,25 +836,26 @@ static void update_radio(HWND hwnd, unsigned int base)
         enable_allowed_controls(hwnd, base);
     }
 
-    SendDlgItemMessage(hwnd, calc.base, BM_SETCHECK, BST_CHECKED, 0);
+    CheckRadioButton(hwnd, IDC_RADIO_HEX, IDC_RADIO_BIN, calc.base);
+
     if (base == IDC_RADIO_DEC)
-        SendDlgItemMessage(hwnd, calc.degr, BM_SETCHECK, BST_CHECKED, 0);
+        CheckRadioButton(hwnd, IDC_RADIO_DEG, IDC_RADIO_GRAD, calc.degr);
     else
-        SendDlgItemMessage(hwnd, calc.size, BM_SETCHECK, BST_CHECKED, 0);
+        CheckRadioButton(hwnd, IDC_RADIO_QWORD, IDC_RADIO_BYTE, calc.size);
 }
 
 static void update_memory_flag(HWND hWnd, BOOL mem_flag)
 {
     calc.is_memory = mem_flag;
-    SendDlgItemMessage(hWnd, IDC_TEXT_MEMORY, WM_SETTEXT, 0, (LPARAM)(mem_flag ? TEXT("M") : TEXT("")));
+    SetDlgItemText(hWnd, IDC_TEXT_MEMORY, mem_flag ? _T("M") : _T(""));
 }
 
 static void update_n_stats_items(HWND hWnd, TCHAR *buffer)
 {
     unsigned int n = SendDlgItemMessage(hWnd, IDC_LIST_STAT, LB_GETCOUNT, 0, 0); 
 
-    _stprintf(buffer, TEXT("n=%d"), n);
-    SendDlgItemMessage(hWnd, IDC_TEXT_NITEMS, WM_SETTEXT, 0, (LPARAM)buffer);
+    _stprintf(buffer, _T("n=%u"), n);
+    SetDlgItemText(hWnd, IDC_TEXT_NITEMS, buffer);
 }
 
 static void clean_stat_list(void)
@@ -824,7 +894,7 @@ static void delete_stat_item(int n)
 
 static char *ReadConversion(const char *formula)
 {
-    int len = strlen(formula);
+    size_t len = strlen(formula);
     char *str = (char *)malloc(len+3);
 
     if (str == NULL)
@@ -839,7 +909,7 @@ static char *ReadConversion(const char *formula)
 
     /* clear display content before proceeding */
     calc.ptr = calc.buffer;
-    calc.buffer[0] = TEXT('\0');
+    calc.buffer[0] = _T('\0');
 
     return str;
 }
@@ -863,13 +933,13 @@ static INT_PTR CALLBACK DlgStatProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
             return TRUE;
         case IDC_BUTTON_LOAD:
             n = SendDlgItemMessage(hWnd, IDC_LIST_STAT, LB_GETCURSEL, 0, 0);
-            if (n == (DWORD)-1)
+            if (n == LB_ERR)
                 return TRUE;
             PostMessage(GetParent(hWnd), WM_LOAD_STAT, (WPARAM)n, 0);
             return TRUE;
         case IDC_BUTTON_CD:
             n = SendDlgItemMessage(hWnd, IDC_LIST_STAT, LB_GETCURSEL, 0, 0);
-            if (n == (DWORD)-1)
+            if (n == LB_ERR)
                 return TRUE;
             SendDlgItemMessage(hWnd, IDC_LIST_STAT, LB_DELETESTRING, (WPARAM)n, 0);
             update_n_stats_items(hWnd, buffer);
@@ -883,10 +953,10 @@ static INT_PTR CALLBACK DlgStatProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
         }
         break;
     case WM_CLOSE:
-        clean_stat_list();
         DestroyWindow(hWnd);
         return TRUE;
     case WM_DESTROY:
+        clean_stat_list();
         PostMessage(GetParent(hWnd), WM_CLOSE_STATS, 0, 0);
         return TRUE;
     case WM_INSERT_STAT:
@@ -933,11 +1003,14 @@ static void CopyMemToClipboard(void *ptr)
 
 static void handle_copy_command(HWND hWnd)
 {
-    TCHAR display[sizeof(calc.buffer)];
+    TCHAR display[MAX_CALC_SIZE];
+    UINT  n;
+
+    n = GetDlgItemText(hWnd, IDC_TEXT_OUTPUT, display, SIZEOF(display));
 
-    SendDlgItemMessage(hWnd, IDC_TEXT_OUTPUT, WM_GETTEXT, (WPARAM)SIZEOF(display), (LPARAM)display);
     if (calc.base == IDC_RADIO_DEC && _tcschr(calc.buffer, _T('.')) == NULL)
-        display[_tcslen(display)-calc.sDecimal_len] = TEXT('\0');
+        display[n - calc.sDecimal_len] = _T('\0');
+
     CopyMemToClipboard(display);
 }
 
@@ -951,7 +1024,7 @@ static char *ReadClipboard(void)
 
         if (hData != NULL) {
             fromClipboard = (char *)GlobalLock(hData);
-            if (strlen(fromClipboard))
+            if (fromClipboard[0])
                 buffer = _strupr(_strdup(fromClipboard));
             GlobalUnlock( hData );
         }
@@ -997,10 +1070,12 @@ static char *handle_sequence_input(HWND hwnd, sequence_t *seq)
             }
         }
     }
-    seq->ptr = ptr;
+
     if (*ptr != '\0')
+    {
+        seq->ptr = ptr;
         PostMessage(hwnd, seq->wm_msg, 0, 0);
-    else {
+    else {
         free(seq->data);
         seq->data = seq->ptr = ptr = NULL;
     }
@@ -1095,19 +1170,9 @@ static statistic_t *upload_stat_number(int n)
     return p;
 }
 
-static void run_pow(calc_number_t *number)
-{
-    exec_infix2postfix(number, RPN_OPERATOR_POW);
-}
-
-static void run_sqr(calc_number_t *number)
-{
-    exec_infix2postfix(number, RPN_OPERATOR_SQR);
-}
-
 static void run_fe(calc_number_t *number)
 {
-    calc.sci_out = ((calc.sci_out == TRUE) ? FALSE : TRUE);
+    calc.sci_out = ((calc.sci_out != FALSE) ? FALSE : TRUE);
 }
 
 static void handle_context_menu(HWND hWnd, WPARAM wp, LPARAM lp)
@@ -1141,7 +1206,7 @@ static void handle_context_menu(HWND hWnd, WPARAM wp, LPARAM lp)
         popup.rcMargins.left   = -1;
         popup.rcMargins.right  = -1;
         popup.idString = GetWindowLongPtr((HWND)wp, GWL_ID);
-        HtmlHelp((HWND)wp, HTMLHELP_PATH("/popups.txt"), HH_DISPLAY_TEXT_POPUP, (DWORD_PTR)&popup);
+        calc_HtmlHelp((HWND)wp, HTMLHELP_PATH("/popups.txt"), HH_DISPLAY_TEXT_POPUP, (DWORD_PTR)&popup);
     }
 #else
     (void)idm;
@@ -1152,12 +1217,14 @@ static void run_canc(calc_number_t *c)
 {
     flush_postfix();
     rpn_zero(c);
+
     /* clear also scientific display modes */
     calc.sci_out = FALSE;
     calc.sci_in  = FALSE;
+
     /* clear state of inv and hyp flags */
-    SendDlgItemMessage(calc.hWnd, IDC_CHECK_INV, BM_SETCHECK, 0, 0);
-    SendDlgItemMessage(calc.hWnd, IDC_CHECK_HYP, BM_SETCHECK, 0, 0);
+    CheckDlgButton(calc.hWnd, IDC_CHECK_INV, BST_UNCHECKED);
+    CheckDlgButton(calc.hWnd, IDC_CHECK_HYP, BST_UNCHECKED);
 }
 
 static void run_rpar(calc_number_t *c)
@@ -1173,14 +1240,58 @@ static void run_lpar(calc_number_t *c)
 static LRESULT CALLBACK SubclassButtonProc(HWND hWnd, WPARAM wp, LPARAM lp)
 {
     LPDRAWITEMSTRUCT dis = (LPDRAWITEMSTRUCT)lp;
-    DWORD            dwStyle;
     UINT             dwText;
     TCHAR            text[64];
     int              dx, dy, len;
     SIZE             size;
     POINT            pt;
 
-    if(dis->CtlType == ODT_BUTTON) {
+    if(dis->CtlType == ODT_BUTTON)
+    {
+        HTHEME hTheme = NULL;
+        LPBTNINFO lpBtnInfo;
+
+        if (calc_IsAppThemed() && calc_IsThemeActive())
+            hTheme = calc_OpenThemeData(hWnd, L"Button");
+
+        if (hTheme)
+        {
+            int iState = 0;
+
+            if ((dis->itemState & ODS_DISABLED))
+                iState |= PBS_DISABLED;
+            if ((dis->itemState & ODS_SELECTED))
+                iState |= PBS_PRESSED;
+
+            lpBtnInfo = (LPBTNINFO)GetWindowLongPtr(dis->hwndItem, GWLP_USERDATA);
+            if (lpBtnInfo != NULL)
+            {
+                if (lpBtnInfo->bHover)
+                    iState |= PBS_HOT;
+            }
+
+            if (calc_IsThemeBackgroundPartiallyTransparent(hTheme, BP_PUSHBUTTON, iState))
+            {
+                calc_DrawThemeParentBackground(dis->hwndItem, dis->hDC, &dis->rcItem);
+            }
+
+            // Draw the frame around the control
+            calc_DrawThemeBackground(hTheme, dis->hDC, BP_PUSHBUTTON, iState, &dis->rcItem, NULL);
+
+            calc_CloseThemeData(hTheme);
+        } else {
+            /* default state: unpushed */
+            DWORD dwStyle = 0;
+
+            if ((dis->itemState & ODS_SELECTED))
+                dwStyle = DFCS_PUSHED;
+
+            DrawFrameControl(dis->hDC, &dis->rcItem, DFC_BUTTON, DFCS_BUTTONPUSH | dwStyle);
+        }
+
+        /* button text to write */
+        len = GetWindowText(dis->hwndItem, text, SIZEOF(text));
+
         /*
          * little exception: 1/x has different color
          * in standard and scientific modes
@@ -1196,21 +1307,20 @@ static LRESULT CALLBACK SubclassButtonProc(HWND hWnd, WPARAM wp, LPARAM lp)
                 break;
             }
         }
-        /* button text to write */
-        len = GetWindowText(dis->hwndItem, text, SIZEOF(text));
-        /* default state: unpushed & enabled */
-        dwStyle = 0;
+
+        /* No background, to avoid corruption of the texture */
+        SetBkMode(dis->hDC, TRANSPARENT);
+
+        /* Default state: enabled */
         dwText = 0;
         if ((dis->itemState & ODS_DISABLED))
             dwText = DSS_DISABLED;
-        if ((dis->itemState & ODS_SELECTED))
-            dwStyle = DFCS_PUSHED;
 
-        DrawFrameControl(dis->hDC, &dis->rcItem, DFC_BUTTON, DFCS_BUTTONPUSH | dwStyle);
+        /* Draw the text in the button */
         GetTextExtentPoint32(dis->hDC, text, len, &size);
         dx = ((dis->rcItem.right-dis->rcItem.left) - size.cx) >> 1;
         dy = ((dis->rcItem.bottom-dis->rcItem.top) - size.cy) >> 1;
-        if ((dwStyle & DFCS_PUSHED)) {
+        if ((dis->itemState & ODS_SELECTED)) {
             dx++;
             dy++;
         }
@@ -1221,6 +1331,84 @@ static LRESULT CALLBACK SubclassButtonProc(HWND hWnd, WPARAM wp, LPARAM lp)
     return 1L;
 }
 
+static INT_PTR CALLBACK HotButtonProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
+{
+    LPBTNINFO lpBtnInfo = (LPBTNINFO)GetWindowLongPtr(hWnd, GWLP_USERDATA);
+    TRACKMOUSEEVENT mouse_event;
+
+    switch (msg) {
+    case WM_MOUSEMOVE:
+        mouse_event.cbSize = sizeof(TRACKMOUSEEVENT);
+        mouse_event.dwFlags = TME_QUERY;
+        if (!TrackMouseEvent(&mouse_event) || !(mouse_event.dwFlags & (TME_HOVER|TME_LEAVE)))
+        {
+            mouse_event.dwFlags = TME_HOVER|TME_LEAVE;
+            mouse_event.hwndTrack = hWnd;
+            mouse_event.dwHoverTime = 1;
+            TrackMouseEvent(&mouse_event);
+        }
+        break;
+
+    case WM_MOUSEHOVER:
+        lpBtnInfo->bHover = TRUE;
+        InvalidateRect(hWnd, NULL, FALSE);
+        break;
+
+    case WM_MOUSELEAVE:
+        lpBtnInfo->bHover = FALSE;
+        InvalidateRect(hWnd, NULL, FALSE);
+        break;
+    }
+
+    return CallWindowProc(lpBtnInfo->oldProc, hWnd, msg, wp, lp);
+}
+
+static BOOL CALLBACK EnumChildProc(HWND hWnd, LPARAM lParam)
+{
+    TCHAR szClass[64];
+
+    if (!GetClassName(hWnd, szClass, SIZEOF(szClass)))
+        return TRUE;
+
+    if (!_tcscmp(szClass, WC_BUTTON))
+    {
+        int *pnCtrls = (int *)lParam;
+        int nCtrls = *pnCtrls;
+
+        BtnInfo[nCtrls].oldProc = (WNDPROC)GetWindowLongPtr(hWnd, GWLP_WNDPROC);
+        BtnInfo[nCtrls].bHover  = FALSE;
+
+        SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR)&BtnInfo[nCtrls]);
+        SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)HotButtonProc);
+
+        *pnCtrls = ++nCtrls;
+    }
+    return TRUE;
+}
+
+static INT_PTR CALLBACK OnSettingChange(HWND hWnd, WPARAM wParam, LPARAM lParam)
+{
+    /* Check for user policy and area string valid */
+    if (wParam == 0 && lParam != 0)
+    {
+        LPTSTR lpArea = (LPTSTR)lParam;
+
+        /* Check if a parameter has been changed into the locale settings */
+        if (!_tcsicmp(lpArea, _T("intl")))
+        {
+            /* Re-load locale parameters */
+            UpdateNumberIntl();
+
+            /* Update text for decimal button */
+            SetDlgItemText(hWnd, IDC_BUTTON_DOT, calc.sDecimal);
+
+            /* Update text into the output display */
+            update_lcd_display(hWnd);
+        }
+    }
+    return 0;
+}
+
 static INT_PTR CALLBACK DlgMainProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
 {
     unsigned int x;
@@ -1231,7 +1419,13 @@ static INT_PTR CALLBACK DlgMainProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
         return SubclassButtonProc(hWnd, wp, lp);
 
     case WM_INITDIALOG:
+#ifdef DISABLE_HTMLHELP_SUPPORT
+        EnableMenuItem(GetMenu(hWnd), IDM_HELP_HELP, MF_BYCOMMAND | MF_GRAYED);
+#endif
         calc.hWnd=hWnd;
+        /* Enumerate children and apply hover function */
+        BtnCount = 0;
+        EnumChildWindows(hWnd, EnumChildProc, (LPARAM)&BtnCount);
 
 #ifdef USE_KEYBOARD_HOOK
         calc.hKeyboardHook=SetWindowsHookEx(
@@ -1256,10 +1450,10 @@ static INT_PTR CALLBACK DlgMainProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
         /* remove keyboard focus */
         SetFocus(GetDlgItem(hWnd, IDC_BUTTON_FOCUS));
         /* set our calc icon */
-        SendMessage(hWnd, WM_SETICON, ICON_BIG, (LPARAM)LoadIcon(calc.hInstance, MAKEINTRESOURCE(IDI_CALC_BIG)));
-        SendMessage(hWnd, WM_SETICON, ICON_SMALL, (LPARAM)LoadIcon(calc.hInstance, MAKEINTRESOURCE(IDI_CALC_SMALL)));
+        SendMessage(hWnd, WM_SETICON, ICON_BIG,   (LPARAM)calc.hBgIcon);
+        SendMessage(hWnd, WM_SETICON, ICON_SMALL, (LPARAM)calc.hSmIcon);
         /* update text for decimal button */
-        SendDlgItemMessage(hWnd, IDC_BUTTON_DOT, WM_SETTEXT, (WPARAM)0, (LPARAM)calc.sDecimal);
+        SetDlgItemText(hWnd, IDC_BUTTON_DOT, calc.sDecimal);
         /* Fill combo box for conversion */
         if (calc.layout == CALC_LAYOUT_CONVERSION)
             ConvInit(hWnd);
@@ -1287,7 +1481,7 @@ static INT_PTR CALLBACK DlgMainProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
     case WM_COMMAND:
         /*
          * if selection of category is changed, we must
-         * updatethe content of the "from/to" combo boxes.
+         * update the content of the "from/to" combo boxes.
          */
         if (wp == MAKEWPARAM(IDC_COMBO_CATEGORY, CBN_SELCHANGE)) {
             ConvAdjust(hWnd, SendDlgItemMessage(hWnd, IDC_COMBO_CATEGORY, CB_GETCURSEL, 0, 0));
@@ -1300,30 +1494,33 @@ static INT_PTR CALLBACK DlgMainProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
             SetFocus(GetDlgItem(hWnd, IDC_BUTTON_FOCUS));
         switch (LOWORD(wp)) {
         case IDM_HELP_ABOUT:
-            DialogBox(calc.hInstance,MAKEINTRESOURCE(IDD_DIALOG_ABOUT), hWnd, AboutDlgProc);
+        {
+            TCHAR infotitle[100];
+            TCHAR infotext[200];
+            LoadString(calc.hInstance, IDS_CALC_NAME, infotitle, SIZEOF(infotitle));
+            LoadString(calc.hInstance, IDS_AUTHOR, infotext, SIZEOF(infotext));
+            ShellAbout(hWnd, infotitle, infotext, calc.hBgIcon);
             return TRUE;
+        }
         case IDM_HELP_HELP:
 #ifndef DISABLE_HTMLHELP_SUPPORT
-            HtmlHelp(hWnd, HTMLHELP_PATH("/general_information.htm"), HH_DISPLAY_TOPIC, (DWORD_PTR)NULL);
+            calc_HtmlHelp(hWnd, HTMLHELP_PATH("/general_information.htm"), HH_DISPLAY_TOPIC, (DWORD_PTR)NULL);
 #endif
             return TRUE;
         case IDM_VIEW_STANDARD:
             calc.layout = CALC_LAYOUT_STANDARD;
             calc.action = IDM_VIEW_STANDARD;
             DestroyWindow(hWnd);
-            save_config();
             return TRUE;
         case IDM_VIEW_SCIENTIFIC:
             calc.layout = CALC_LAYOUT_SCIENTIFIC;
             calc.action = IDM_VIEW_SCIENTIFIC;
             DestroyWindow(hWnd);
-            save_config();
             return TRUE;
         case IDM_VIEW_CONVERSION:
             calc.layout = CALC_LAYOUT_CONVERSION;
             calc.action = IDM_VIEW_CONVERSION;
             DestroyWindow(hWnd);
-            save_config();
             return TRUE;
         case IDM_VIEW_HEX:
         case IDM_VIEW_DEC:
@@ -1357,7 +1554,6 @@ static INT_PTR CALLBACK DlgMainProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
             calc.usesep = (calc.usesep ? FALSE : TRUE);
             update_menu(hWnd);
             update_lcd_display(hWnd);
-            save_config();
             return TRUE;
         case IDC_BUTTON_CONVERT:
             ConvExecute(hWnd);
@@ -1446,17 +1642,30 @@ static INT_PTR CALLBACK DlgMainProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
         case IDC_BUTTON_LSH:
         case IDC_BUTTON_RSH:
         case IDC_BUTTON_EQU:
+        case IDC_BUTTON_XeY:
+        case IDC_BUTTON_XrY:
             if (calc.is_nan) break;
             /*
-             * LSH button holds the RSH function too with INV modifier,
-             * but since it's a two operand operator, it must be handled here.
+             * LSH and XeY buttons hold also the RSH and XrY functions with INV modifier,
+             * but since they are two operand operators, they must be handled here.
              */
-            if (LOWORD(wp) == IDC_BUTTON_LSH &&
-                (get_modifiers(hWnd) & MODIFIER_INV)) {
-                PostMessage(hWnd, WM_COMMAND, MAKEWPARAM(IDC_BUTTON_RSH, BN_CLICKED), 0);
-                SendDlgItemMessage(hWnd, IDC_CHECK_INV, BM_SETCHECK, 0, 0);
-                break;
+            if ((get_modifiers(hWnd) & MODIFIER_INV))
+            {
+                WPARAM IdcSim = IDC_STATIC;
+
+                switch (LOWORD(wp)) {
+                case IDC_BUTTON_LSH: IdcSim = MAKEWPARAM(IDC_BUTTON_RSH, BN_CLICKED); break;
+                case IDC_BUTTON_XeY: IdcSim = MAKEWPARAM(IDC_BUTTON_XrY, BN_CLICKED); break;
+                }
+
+                if (IdcSim != IDC_STATIC)
+                {
+                    PostMessage(hWnd, WM_COMMAND, IdcSim, 0);
+                    CheckDlgButton(hWnd, IDC_CHECK_INV, BST_UNCHECKED);
+                    break;
+                }
             }
+
             for (x=0; x<SIZEOF(operator_codes); x++) {
                 if (LOWORD(wp) == operator_codes[x]) {
                     convert_text2number(&calc.code);
@@ -1489,9 +1698,9 @@ static INT_PTR CALLBACK DlgMainProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
                     TCHAR *ptr;
 
                     calc.sci_in = FALSE;
-                    ptr = _tcschr(calc.ptr, TEXT('e'));
+                    ptr = _tcschr(calc.ptr, _T('e'));
                     if (ptr)
-                        *ptr = TEXT('\0');
+                        *ptr = _T('\0');
                     update_lcd_display(hWnd);
                 } else {
                     calc.esp /= 10;
@@ -1499,12 +1708,12 @@ static INT_PTR CALLBACK DlgMainProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
                 }
             } else
             if (calc.ptr != calc.buffer) {
-                *--calc.ptr = TEXT('\0');
-                if (!_tcscmp(calc.buffer, TEXT("-")) ||
-                    !_tcscmp(calc.buffer, TEXT("-0")) ||
-                    !_tcscmp(calc.buffer, TEXT("0"))) {
+                *--calc.ptr = _T('\0');
+                if (!_tcscmp(calc.buffer, _T("-")) ||
+                    !_tcscmp(calc.buffer, _T("-0")) ||
+                    !_tcscmp(calc.buffer, _T("0"))) {
                     calc.ptr = calc.buffer;
-                    calc.buffer[0] = TEXT('\0');
+                    calc.buffer[0] = _T('\0');
                 }
                 update_lcd_display(hWnd);
             }
@@ -1532,22 +1741,22 @@ static INT_PTR CALLBACK DlgMainProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
                 calc.esp = 0-calc.esp;
                 build_operand(hWnd, IDC_STATIC);
             } else {
-                if (calc.is_nan || calc.buffer[0] == TEXT('\0'))
+                if (calc.is_nan || calc.buffer[0] == _T('\0'))
                     break;
 
-                if (calc.buffer[0] == TEXT('-')) {
+                if (calc.buffer[0] == _T('-')) {
                     /* make the number positive */
                     memmove(calc.buffer, calc.buffer+1, sizeof(calc.buffer)-1);
                     if (calc.buffer != calc.ptr)
                         calc.ptr--;
                 } else {
                     /* if first char is '0' and no dot, it isn't valid */
-                    if (calc.buffer[0] == TEXT('0') &&
-                        calc.buffer[1] != TEXT('.'))
+                    if (calc.buffer[0] == _T('0') &&
+                        calc.buffer[1] != _T('.'))
                         break;
                     /* make the number negative */
                     memmove(calc.buffer+1, calc.buffer, sizeof(calc.buffer)-1);
-                    calc.buffer[0] = TEXT('-');
+                    calc.buffer[0] = _T('-');
                     if (calc.buffer != calc.ptr)
                         calc.ptr++;
                 }
@@ -1583,7 +1792,6 @@ static INT_PTR CALLBACK DlgMainProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
         case IDC_BUTTON_SIN:
         case IDC_BUTTON_COS:
         case IDC_BUTTON_TAN:
-        case IDC_BUTTON_XeY:
         case IDC_BUTTON_MS:
             for (x=0; x<SIZEOF(function_table); x++) {
                 if (LOWORD(wp) == function_table[x].idc) {
@@ -1611,14 +1819,20 @@ static INT_PTR CALLBACK DlgMainProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
                     if (cb != NULL) {
                         convert_text2number(&calc.code);
                         cb(&calc.code);
-                        display_rpn_result(hWnd, &calc.code);
-                        if (!(function_table[x].range & NO_CHAIN))
-                            exec_infix2postfix(&calc.code, RPN_OPERATOR_NONE);
+//                        display_rpn_result(hWnd, &calc.code);
+                        set_rpn_result(hWnd, &calc.code);
+
+                        if ((function_table[x].range & NO_CHAIN))
+                            calc.ptr = calc.buffer;
+
+//                        if (!(function_table[x].range & NO_CHAIN))
+//                            exec_infix2postfix(&calc.code, RPN_OPERATOR_NONE);
                         if (function_table[x].range & MODIFIER_INV)
-                            SendDlgItemMessage(hWnd, IDC_CHECK_INV, BM_SETCHECK, 0, 0);
+                            CheckDlgButton(hWnd, IDC_CHECK_INV, BST_UNCHECKED);
                         if (function_table[x].range & MODIFIER_HYP)
-                            SendDlgItemMessage(hWnd, IDC_CHECK_HYP, BM_SETCHECK, 0, 0);
+                            CheckDlgButton(hWnd, IDC_CHECK_HYP, BST_UNCHECKED);
                     }
+                    break;
                 }
             }
             return TRUE;
@@ -1635,6 +1849,7 @@ static INT_PTR CALLBACK DlgMainProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
         }
         break;
     case WM_CLOSE_STATS:
+        calc.hStatWnd = NULL;
         enable_allowed_controls(hWnd, calc.base);
         return TRUE;
     case WM_LOAD_STAT:
@@ -1664,6 +1879,7 @@ static INT_PTR CALLBACK DlgMainProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
         calc.action = IDC_STATIC;
         DestroyWindow(hWnd);
         return TRUE;
+
     case WM_DESTROY:
         /* Get (x,y) position of the calculator */
         GetWindowRect(hWnd, &rc);
@@ -1690,6 +1906,13 @@ static INT_PTR CALLBACK DlgMainProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
     case WM_EXITMENULOOP:
         calc.is_menu_on = FALSE;
         break;
+
+    case WM_SETTINGCHANGE:
+        return OnSettingChange(hWnd, wp, lp);
+
+    case WM_THEMECHANGED:
+        InvalidateRect(hWnd, NULL, FALSE);
+        break;
     }
     return FALSE;
 }
@@ -1703,6 +1926,9 @@ int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdL
     MSG msg;
     DWORD dwLayout;
 
+    /* Initialize controls for theming & manifest support */
+    InitCommonControls();
+
     calc.hInstance = hInstance;
 
     calc.x_coord = -1;
@@ -1711,6 +1937,26 @@ int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdL
     load_config();
     start_rpn_engine();
 
+    HtmlHelp_Start(hInstance);
+
+    Theme_Start(hInstance);
+
+    calc.hBgIcon = LoadImage(
+                    hInstance,
+                    MAKEINTRESOURCE(IDI_CALC),
+                    IMAGE_ICON,
+                    GetSystemMetrics(SM_CXICON),
+                    GetSystemMetrics(SM_CYICON),
+                    0);
+
+    calc.hSmIcon = LoadImage(
+                    hInstance,
+                    MAKEINTRESOURCE(IDI_CALC),
+                    IMAGE_ICON,
+                    GetSystemMetrics(SM_CXSMICON),
+                    GetSystemMetrics(SM_CYSMICON),
+                    0);
+
     do {
         /* ignore hwnd: dialogs are already visible! */
         if (calc.layout == CALC_LAYOUT_SCIENTIFIC)
@@ -1735,9 +1981,20 @@ int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdL
             TranslateMessage(&msg);
             DispatchMessage(&msg);
         }
+
+        save_config();
     } while (calc.action != IDC_STATIC);
 
+    if (calc.hBgIcon != NULL)
+        DestroyIcon(calc.hBgIcon);
+
+    if (calc.hSmIcon != NULL)
+        DestroyIcon(calc.hSmIcon);
+
     stop_rpn_engine();
 
+    Theme_Stop();
+    HtmlHelp_Stop();
+
     return 0;
 }