-#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 <shellapi.h>
-#include <commctrl.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) | \
#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
{ 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)
{
+ /* 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;
- HKEY hKey;
-
- /* If no settings are found in the registry, then use the default options */
- calc.layout = CALC_LAYOUT_STANDARD;
- calc.usesep = FALSE;
- /* Get the configuration based on what version of Windows that's being used */
- if (RegOpenKeyEx(HKEY_CURRENT_USER, TEXT("SOFTWARE\\Microsoft\\Calc"), 0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS)
+ if (RegOpenKeyEx(HKEY_CURRENT_USER, lpszApp, 0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS)
{
- /* Try to load last selected layout */
- tmp = sizeof(calc.layout);
- if (RegQueryValueEx(hKey, TEXT("layout"), NULL, NULL, (LPBYTE)&calc.layout, &tmp) != ERROR_SUCCESS)
- calc.layout = CALC_LAYOUT_STANDARD;
+ /* Try to load integer value */
+ tmp = sizeof(int);
- /* Try to load last selected formatting option */
- tmp = sizeof(calc.usesep);
- if (RegQueryValueEx(hKey, TEXT("UseSep"), NULL, NULL, (LPBYTE)&calc.usesep, &tmp) != ERROR_SUCCESS)
- calc.usesep = FALSE;
+ if (RegQueryValueEx(hKey, lpszKey, NULL, NULL, (LPBYTE)&iValue, &tmp) == ERROR_SUCCESS)
+ iDefault = iValue;
/* close the key */
RegCloseKey(hKey);
}
- /* memory is empty at startup */
- calc.is_memory = FALSE;
+ return iDefault;
+}
- /* empty these values */
- calc.sDecimal[0] = TEXT('\0');
- calc.sThousand[0] = TEXT('\0');
+static void SaveRegInt(LPCTSTR lpszApp, LPCTSTR lpszKey, int iValue)
+{
+ HKEY hKey;
- /* try to open the registry */
- if (RegOpenKeyEx(HKEY_CURRENT_USER, TEXT("Control Panel\\International"), 0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS)
+ if (RegCreateKeyEx(HKEY_CURRENT_USER, lpszApp, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, NULL, &hKey, NULL) == ERROR_SUCCESS)
{
- /* get these values (ignore errors) */
- tmp = sizeof(calc.sDecimal);
- RegQueryValueEx(hKey, TEXT("sDecimal"), NULL, NULL, (LPBYTE)calc.sDecimal, &tmp);
-
- tmp = sizeof(calc.sThousand);
- RegQueryValueEx(hKey, TEXT("sThousand"), NULL, NULL, (LPBYTE)calc.sThousand, &tmp);
+ 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("."));
+}
- if (calc.sThousand[0] == TEXT('\0'))
- _tcscpy(calc.sThousand, TEXT(","));
+static void load_config(void)
+{
+ OSVERSIONINFO osvi;
- /* get the string lengths */
- calc.sDecimal_len = _tcslen(calc.sDecimal);
- calc.sThousand_len = _tcslen(calc.sThousand);
+ osvi.dwOSVersionInfoSize = sizeof(osvi);
+ GetVersionEx(&osvi);
+
+ 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)
{
- HKEY hKey;
- DWORD sepValue;
+ TCHAR buf[32];
+ OSVERSIONINFO osvi;
+
+ osvi.dwOSVersionInfoSize = sizeof(osvi);
+ GetVersionEx(&osvi);
+
+ 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;
- if (RegCreateKeyEx(HKEY_CURRENT_USER, TEXT("SOFTWARE\\Microsoft\\Calc"), 0, NULL, REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, NULL, &hKey, NULL) != ERROR_SUCCESS)
- {
- return;
+ default: /* VER_PLATFORM_WIN32_NT */
+ SaveRegInt(_T("SOFTWARE\\Microsoft\\Calc"), _T("layout"), calc.layout);
+ SaveRegInt(_T("SOFTWARE\\Microsoft\\Calc"), _T("UseSep"), calc.usesep);
+ break;
}
-
- sepValue = (calc.usesep) ? 1 : 0;
-
- RegSetValueEx(hKey, TEXT("layout"), 0, REG_DWORD, (const BYTE*)&calc.layout, sizeof(calc.layout));
- RegSetValueEx(hKey, TEXT("UseSep"), 0, REG_DWORD, (const BYTE*)&sepValue, sizeof(sepValue));
-
- RegCloseKey(hKey);
}
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 */
* 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;
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;
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) {
int n = eval_parent_count();
if (!n)
- str[0] = TEXT('\0');
+ str[0] = _T('\0');
else
- _stprintf(str,TEXT("(=%d"), n);
+ _stprintf(str,_T("(=%d"), n);
SendDlgItemMessage(hWnd, IDC_TEXT_PARENT, WM_SETTEXT, 0, (LPARAM)str);
}
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) {
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;
}
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;
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);
}
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 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;
/* 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
{
unsigned int n = SendDlgItemMessage(hWnd, IDC_LIST_STAT, LB_GETCOUNT, 0, 0);
- _stprintf(buffer, TEXT("n=%d"), n);
+ _stprintf(buffer, _T("n=%u"), n);
SendDlgItemMessage(hWnd, IDC_TEXT_NITEMS, WM_SETTEXT, 0, (LPARAM)buffer);
}
/* clear display content before proceeding */
calc.ptr = calc.buffer;
- calc.buffer[0] = TEXT('\0');
+ calc.buffer[0] = _T('\0');
return str;
}
}
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:
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);
}
if (hData != NULL) {
fromClipboard = (char *)GlobalLock(hData);
- if (strlen(fromClipboard))
+ if (fromClipboard[0])
buffer = _strupr(_strdup(fromClipboard));
GlobalUnlock( hData );
}
}
}
}
- 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;
}
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;
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
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++;
}
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;
return SubclassButtonProc(hWnd, wp, lp);
case WM_INITDIALOG:
- // For now, the Help dialog is disabled because of lacking of HTML Help support
+#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(
/* 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);
/* Sets the state of the option to group digits */
hMenu = GetSubMenu(GetMenu(hWnd), 1);
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));
TCHAR infotext[200];
LoadString(calc.hInstance, IDS_CALC_NAME, infotitle, SIZEOF(infotitle));
LoadString(calc.hInstance, IDS_AUTHOR, infotext, SIZEOF(infotext));
- ShellAbout(hWnd, infotitle, infotext, (HICON)LoadIcon(calc.hInstance, MAKEINTRESOURCE(IDI_CALC_BIG)));
+ 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();
CheckMenuRadioItem(GetMenu(hWnd),
IDM_VIEW_STANDARD,
calc.layout = CALC_LAYOUT_SCIENTIFIC;
calc.action = IDM_VIEW_SCIENTIFIC;
DestroyWindow(hWnd);
- save_config();
CheckMenuRadioItem(GetMenu(hWnd),
IDM_VIEW_STANDARD,
calc.layout = CALC_LAYOUT_CONVERSION;
calc.action = IDM_VIEW_CONVERSION;
DestroyWindow(hWnd);
- save_config();
CheckMenuRadioItem(GetMenu(hWnd),
IDM_VIEW_STANDARD,
calc.usesep = (calc.usesep ? FALSE : TRUE);
update_menu(hWnd);
update_lcd_display(hWnd);
- save_config();
return TRUE;
case IDC_BUTTON_CONVERT:
ConvExecute(hWnd);
{
PostMessage(hWnd, WM_COMMAND, IdcSim, 0);
CheckDlgButton(hWnd, IDC_CHECK_INV, BST_UNCHECKED);
+ break;
}
}
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;
}
} 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);
}
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++;
}
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);
if (function_table[x].range & MODIFIER_HYP)
SendDlgItemMessage(hWnd, IDC_CHECK_HYP, BM_SETCHECK, 0, 0);
}
+ break;
}
}
return TRUE;
}
break;
case WM_CLOSE_STATS:
+ calc.hStatWnd = NULL;
enable_allowed_controls(hWnd, calc.base);
return TRUE;
case WM_LOAD_STAT:
calc.action = IDC_STATIC;
DestroyWindow(hWnd);
return TRUE;
+
case WM_DESTROY:
/* Get (x,y) position of the calculator */
GetWindowRect(hWnd, &rc);
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;
}
MSG msg;
DWORD dwLayout;
+ /* Initialize controls for theming & manifest support */
InitCommonControls();
calc.hInstance = hInstance;
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)
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;
}