Sync with trunk head (part 1 of 2)
[reactos.git] / base / applications / calc / winmain.c
index 86ffe56..40a3468 100644 (file)
@@ -38,10 +38,10 @@ typedef struct {
 } key2code_t;
 
 typedef struct {
-    WORD idc;  // IDC for posting message
-    CHAR key;  // Virtual key identifier
-    BYTE mask; // enable/disable into the various modes.
-    INT  col;  // color used for drawing the text
+    WORD     idc;  // IDC for posting message
+    CHAR     key;  // Virtual key identifier
+    BYTE     mask; // enable/disable into the various modes.
+    COLORREF col;  // color used for drawing the text
 } key3code_t;
 
 #define CTRL_FLAG   0x100
@@ -209,9 +209,9 @@ static const function_table_t function_table[] = {
     { 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_CANC, 0,                         0, run_canc,    NULL,        NULL,     NULL,     },
-    { IDC_BUTTON_RIGHTPAR, 0,                     1, run_rpar,    NULL,        NULL,     NULL,     },
-    { IDC_BUTTON_LEFTPAR,  0,                     0, run_lpar,    NULL,        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,     },
 };
 
 /*
@@ -223,6 +223,9 @@ static void load_config(void)
 {
     TCHAR buf[32];
     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));
@@ -239,9 +242,42 @@ static void load_config(void)
     /* memory is empty at startup */
     calc.is_memory = FALSE;
 
+#if _WIN32_WINNT >= 0x0500
+    /* empty these values */
+    calc.sDecimal[0] = TEXT('\0');
+    calc.sThousand[0] = TEXT('\0');
+
+    /* 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);
+
+        tmp = sizeof(calc.sThousand);
+        RegQueryValueEx(hKey, TEXT("sThousand"), NULL, NULL, (LPBYTE)calc.sThousand, &tmp);
+
+        /* 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(","));
+
+    /* 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
 }
 
 static void save_config(void)
@@ -266,7 +302,7 @@ static LRESULT post_key_press(LPARAM lParam, WORD idc)
         return 1;
 
     if (!_tcscmp(ClassName, TEXT("Button"))) {
-        DWORD dwStyle = GetWindowLong(hCtlWnd, GWL_STYLE) & 0xF;
+        DWORD dwStyle = GetWindowLongPtr(hCtlWnd, GWL_STYLE) & 0xF;
 
         /* Set states for press/release, but only for push buttons */
         if (dwStyle == BS_PUSHBUTTON || dwStyle == BS_DEFPUSHBUTTON || dwStyle == BS_OWNERDRAW) {
@@ -784,68 +820,18 @@ static void delete_stat_item(int n)
 
 static char *ReadConversion(const char *formula)
 {
-    unsigned int  len = 256, n;
-    char         *str;
-    char         *code = NULL;
-    const char   *p = formula;
-    char          c;
-    calc_number_t x;
-    TCHAR         buffer[SIZEOF(calc.buffer)];
-#ifdef UNICODE
-    char          cbuffer[SIZEOF(calc.buffer)];
-#endif
+    int len = strlen(formula);
+    char *str = (char *)malloc(len+3);
 
-    str = (char *)malloc(len);
     if (str == NULL)
         return NULL;
 
-    /* prepare code string */
-    rpn_alloc(&x);
-    convert_text2number(&x);
-    prepare_rpn_result(&x,
-                   buffer, SIZEOF(buffer),
-                   calc.base);
-    rpn_free(&x);
-
-#ifdef UNICODE
-    WideCharToMultiByte(CP_ACP, 0, buffer, -1, cbuffer, SIZEOF(cbuffer), NULL, NULL);
-#endif
-
     str[0] = '(';
-    n = 1;
-    while (1) {
-        if (code != NULL) {
-            c = *code++;
-            if (*code == '\0')
-                code = NULL;
-        } else
-            c = *p++;
-
-        if (c == '\0') {
-            str[n++] = ')';
-            if (n >= len-1) {
-                str = (char *)realloc(str, len += 16);
-                if (str == NULL)
-                    return NULL;
-            }
-            break;
-        } else
-        if (c == '$') {
-#ifdef UNICODE
-            code = cbuffer;
-#else
-            code = buffer;
-#endif
-            continue;
-        }
-        str[n++] = c;
-        if (n >= len-1) {
-            str = (char *)realloc(str, len += 16);
-            if (str == NULL)
-                return NULL;
-        }
-    }
-    str[n] = '\0';
+    memcpy(str+1, formula, len);
+    str[len+1] = ')';
+    str[len+2] = '\0';
+
+    _tcscpy(calc.source, (*calc.buffer == _T('\0')) ? _T("0") : calc.buffer);
 
     /* clear display content before proceeding */
     calc.ptr = calc.buffer;
@@ -854,7 +840,7 @@ static char *ReadConversion(const char *formula)
     return str;
 }
 
-static LRESULT CALLBACK DlgStatProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
+static INT_PTR CALLBACK DlgStatProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
 {
     TCHAR buffer[SIZEOF(calc.buffer)];
     DWORD n;
@@ -991,6 +977,11 @@ static char *handle_sequence_input(HWND hwnd, sequence_t *seq)
         case 'Q': PostMessage(hwnd, WM_COMMAND, (WPARAM)IDC_BUTTON_CANC, 0); break;
         case 'R': PostMessage(hwnd, WM_COMMAND, (WPARAM)IDC_BUTTON_MR, 0); break;
         }
+    } else
+    if (ch == '$') {
+        calc.ptr =
+        _tcscpy(calc.buffer, calc.source) +
+        _tcslen(calc.source);
     } else {
         for (x=0; x<SIZEOF(key2code); x++) {
             if (!(key2code[x].mask & BITMASK_IS_ASCII) ||
@@ -1145,7 +1136,7 @@ static void handle_context_menu(HWND hWnd, WPARAM wp, LPARAM lp)
         popup.rcMargins.bottom = -1;
         popup.rcMargins.left   = -1;
         popup.rcMargins.right  = -1;
-        popup.idString = GetWindowLong((HWND)wp, GWL_ID);
+        popup.idString = GetWindowLongPtr((HWND)wp, GWL_ID);
         HtmlHelp((HWND)wp, HTMLHELP_PATH("/popups.txt"), HH_DISPLAY_TEXT_POPUP, (DWORD_PTR)&popup);
     }
 #endif
@@ -1224,7 +1215,7 @@ static LRESULT CALLBACK SubclassButtonProc(HWND hWnd, WPARAM wp, LPARAM lp)
     return 1L;
 }
 
-static LRESULT CALLBACK DlgMainProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
+static INT_PTR CALLBACK DlgMainProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
 {
     unsigned int x;
     RECT         rc;
@@ -1472,7 +1463,8 @@ static LRESULT CALLBACK DlgMainProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
                         if (x == RPN_OPERATOR_EQUAL) {
                             exec_infix2postfix(&calc.code, calc.prev_operator);
                             rpn_copy(&calc.code, &calc.prev);
-                        }
+                        } else
+                            break;
                     }
 
                     /* if no change then quit silently, */
@@ -1614,6 +1606,8 @@ static LRESULT CALLBACK DlgMainProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
                         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);
                         if (function_table[x].range & MODIFIER_INV)
                             SendDlgItemMessage(hWnd, IDC_CHECK_INV, BM_SETCHECK, 0, 0);
                         if (function_table[x].range & MODIFIER_HYP)
@@ -1650,13 +1644,15 @@ static LRESULT CALLBACK DlgMainProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
         }
         return TRUE;
     case WM_HANDLE_FROM:
-        if (handle_sequence_input(hWnd, &calc.Convert[0]) == NULL) {
+        if (calc.is_nan)
+            break;
+        if (handle_sequence_input(hWnd, &calc.Convert[0]) == NULL)
             PostMessage(hWnd, WM_START_CONV, 0,
                         MAKELPARAM(0x0001, WM_HANDLE_TO));
-        }
         return TRUE;
     case WM_HANDLE_TO:
-        handle_sequence_input(hWnd, &calc.Convert[1]);
+        if (!calc.is_nan)
+            handle_sequence_input(hWnd, &calc.Convert[1]);
         return TRUE;
     case WM_CLOSE:
         calc.action = IDC_STATIC;
@@ -1692,7 +1688,11 @@ static LRESULT CALLBACK DlgMainProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
     return FALSE;
 }
 
+#if defined(__GNUC__) && !defined(__REACTOS__)
+int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
+#else
 int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nShowCmd)
+#endif
 {
     MSG msg;
     DWORD dwLayout;
@@ -1715,7 +1715,9 @@ int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdL
         else
             dwLayout = IDD_DIALOG_STANDARD;
 
-        CreateDialog(hInstance, MAKEINTRESOURCE(dwLayout), NULL, (DLGPROC)DlgMainProc);
+        /* This call will always fail if UNICODE for Win9x */
+        if (NULL == CreateDialog(hInstance, MAKEINTRESOURCE(dwLayout), NULL, (DLGPROC)DlgMainProc))
+            break;
 
         while (GetMessage(&msg, NULL, 0, 0)) {
 #ifndef USE_KEYBOARD_HOOK