184614957604253d51296e06c97daced699a0a9deHans Boehm/*
284614957604253d51296e06c97daced699a0a9deHans Boehm * Copyright (C) 2015 The Android Open Source Project
384614957604253d51296e06c97daced699a0a9deHans Boehm *
484614957604253d51296e06c97daced699a0a9deHans Boehm * Licensed under the Apache License, Version 2.0 (the "License");
584614957604253d51296e06c97daced699a0a9deHans Boehm * you may not use this file except in compliance with the License.
684614957604253d51296e06c97daced699a0a9deHans Boehm * You may obtain a copy of the License at
784614957604253d51296e06c97daced699a0a9deHans Boehm *
884614957604253d51296e06c97daced699a0a9deHans Boehm *   http://www.apache.org/licenses/LICENSE-2.0
984614957604253d51296e06c97daced699a0a9deHans Boehm *
1084614957604253d51296e06c97daced699a0a9deHans Boehm * Unless required by applicable law or agreed to in writing, software
1184614957604253d51296e06c97daced699a0a9deHans Boehm * distributed under the License is distributed on an "AS IS" BASIS,
1284614957604253d51296e06c97daced699a0a9deHans Boehm * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1384614957604253d51296e06c97daced699a0a9deHans Boehm * See the License for the specific language governing permissions and
1484614957604253d51296e06c97daced699a0a9deHans Boehm * limitations under the License.
1584614957604253d51296e06c97daced699a0a9deHans Boehm */
1684614957604253d51296e06c97daced699a0a9deHans Boehm
1784614957604253d51296e06c97daced699a0a9deHans Boehmpackage com.android.calculator2;
1884614957604253d51296e06c97daced699a0a9deHans Boehm
1984614957604253d51296e06c97daced699a0a9deHans Boehmimport android.content.res.Resources;
2084614957604253d51296e06c97daced699a0a9deHans Boehmimport android.content.Context;
214a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehmimport android.app.Activity;
224a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehmimport android.util.Log;
2384614957604253d51296e06c97daced699a0a9deHans Boehmimport android.view.View;
244a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehmimport android.widget.Button;
254a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm
2684614957604253d51296e06c97daced699a0a9deHans Boehmimport java.text.DecimalFormatSymbols;
274a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehmimport java.util.HashMap;
284a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehmimport java.util.Locale;
2984614957604253d51296e06c97daced699a0a9deHans Boehm
300b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm/**
310b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm * Collection of mapping functions between key ids, characters, internationalized
32e2711cbb1569ab6c7a7c4506505ec403286d5ab4Justin Klaassen * and non-internationalized characters, etc.
330b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm * <p>
340b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm * KeyMap instances are not meaningful; everything here is static.
350b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm * All functions are either pure, or are assumed to be called only from a single UI thread.
360b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm */
3784614957604253d51296e06c97daced699a0a9deHans Boehmpublic class KeyMaps {
380b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm    /**
390b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm     * Map key id to corresponding (internationalized) display string.
400b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm     * Pure function.
410b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm     */
42e2711cbb1569ab6c7a7c4506505ec403286d5ab4Justin Klaassen    public static String toString(Context context, int id) {
4384614957604253d51296e06c97daced699a0a9deHans Boehm        switch(id) {
440b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm            case R.id.const_pi:
45e2711cbb1569ab6c7a7c4506505ec403286d5ab4Justin Klaassen                return context.getString(R.string.const_pi);
460b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm            case R.id.const_e:
47e2711cbb1569ab6c7a7c4506505ec403286d5ab4Justin Klaassen                return context.getString(R.string.const_e);
480b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm            case R.id.op_sqrt:
49e2711cbb1569ab6c7a7c4506505ec403286d5ab4Justin Klaassen                return context.getString(R.string.op_sqrt);
500b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm            case R.id.op_fact:
51e2711cbb1569ab6c7a7c4506505ec403286d5ab4Justin Klaassen                return context.getString(R.string.op_fact);
52e2711cbb1569ab6c7a7c4506505ec403286d5ab4Justin Klaassen            case R.id.op_pct:
53e2711cbb1569ab6c7a7c4506505ec403286d5ab4Justin Klaassen                return context.getString(R.string.op_pct);
540b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm            case R.id.fun_sin:
55e2711cbb1569ab6c7a7c4506505ec403286d5ab4Justin Klaassen                return context.getString(R.string.fun_sin) + context.getString(R.string.lparen);
560b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm            case R.id.fun_cos:
57e2711cbb1569ab6c7a7c4506505ec403286d5ab4Justin Klaassen                return context.getString(R.string.fun_cos) + context.getString(R.string.lparen);
580b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm            case R.id.fun_tan:
59e2711cbb1569ab6c7a7c4506505ec403286d5ab4Justin Klaassen                return context.getString(R.string.fun_tan) + context.getString(R.string.lparen);
600b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm            case R.id.fun_arcsin:
61e2711cbb1569ab6c7a7c4506505ec403286d5ab4Justin Klaassen                return context.getString(R.string.fun_arcsin) + context.getString(R.string.lparen);
620b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm            case R.id.fun_arccos:
63e2711cbb1569ab6c7a7c4506505ec403286d5ab4Justin Klaassen                return context.getString(R.string.fun_arccos) + context.getString(R.string.lparen);
640b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm            case R.id.fun_arctan:
65e2711cbb1569ab6c7a7c4506505ec403286d5ab4Justin Klaassen                return context.getString(R.string.fun_arctan) + context.getString(R.string.lparen);
660b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm            case R.id.fun_ln:
67e2711cbb1569ab6c7a7c4506505ec403286d5ab4Justin Klaassen                return context.getString(R.string.fun_ln) + context.getString(R.string.lparen);
680b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm            case R.id.fun_log:
69e2711cbb1569ab6c7a7c4506505ec403286d5ab4Justin Klaassen                return context.getString(R.string.fun_log) + context.getString(R.string.lparen);
704db31b490443e4454d98a5ae2bc44b87149accfeHans Boehm            case R.id.fun_exp:
714db31b490443e4454d98a5ae2bc44b87149accfeHans Boehm                // Button label doesn't work.
724db31b490443e4454d98a5ae2bc44b87149accfeHans Boehm                return context.getString(R.string.exponential) + context.getString(R.string.lparen);
730b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm            case R.id.lparen:
74e2711cbb1569ab6c7a7c4506505ec403286d5ab4Justin Klaassen                return context.getString(R.string.lparen);
750b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm            case R.id.rparen:
76e2711cbb1569ab6c7a7c4506505ec403286d5ab4Justin Klaassen                return context.getString(R.string.rparen);
770b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm            case R.id.op_pow:
78e2711cbb1569ab6c7a7c4506505ec403286d5ab4Justin Klaassen                return context.getString(R.string.op_pow);
790b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm            case R.id.op_mul:
80e2711cbb1569ab6c7a7c4506505ec403286d5ab4Justin Klaassen                return context.getString(R.string.op_mul);
810b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm            case R.id.op_div:
82e2711cbb1569ab6c7a7c4506505ec403286d5ab4Justin Klaassen                return context.getString(R.string.op_div);
830b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm            case R.id.op_add:
84e2711cbb1569ab6c7a7c4506505ec403286d5ab4Justin Klaassen                return context.getString(R.string.op_add);
854db31b490443e4454d98a5ae2bc44b87149accfeHans Boehm            case R.id.op_sqr:
864db31b490443e4454d98a5ae2bc44b87149accfeHans Boehm                // Button label doesn't work.
874db31b490443e4454d98a5ae2bc44b87149accfeHans Boehm                return context.getString(R.string.squared);
880b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm            case R.id.op_sub:
89e2711cbb1569ab6c7a7c4506505ec403286d5ab4Justin Klaassen                return context.getString(R.string.op_sub);
900b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm            case R.id.dec_point:
91e2711cbb1569ab6c7a7c4506505ec403286d5ab4Justin Klaassen                return context.getString(R.string.dec_point);
920b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm            case R.id.digit_0:
93e2711cbb1569ab6c7a7c4506505ec403286d5ab4Justin Klaassen                return context.getString(R.string.digit_0);
940b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm            case R.id.digit_1:
95e2711cbb1569ab6c7a7c4506505ec403286d5ab4Justin Klaassen                return context.getString(R.string.digit_1);
960b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm            case R.id.digit_2:
97e2711cbb1569ab6c7a7c4506505ec403286d5ab4Justin Klaassen                return context.getString(R.string.digit_2);
980b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm            case R.id.digit_3:
99e2711cbb1569ab6c7a7c4506505ec403286d5ab4Justin Klaassen                return context.getString(R.string.digit_3);
1000b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm            case R.id.digit_4:
101e2711cbb1569ab6c7a7c4506505ec403286d5ab4Justin Klaassen                return context.getString(R.string.digit_4);
1020b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm            case R.id.digit_5:
103e2711cbb1569ab6c7a7c4506505ec403286d5ab4Justin Klaassen                return context.getString(R.string.digit_5);
1040b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm            case R.id.digit_6:
105e2711cbb1569ab6c7a7c4506505ec403286d5ab4Justin Klaassen                return context.getString(R.string.digit_6);
1060b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm            case R.id.digit_7:
107e2711cbb1569ab6c7a7c4506505ec403286d5ab4Justin Klaassen                return context.getString(R.string.digit_7);
1080b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm            case R.id.digit_8:
109e2711cbb1569ab6c7a7c4506505ec403286d5ab4Justin Klaassen                return context.getString(R.string.digit_8);
1100b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm            case R.id.digit_9:
111e2711cbb1569ab6c7a7c4506505ec403286d5ab4Justin Klaassen                return context.getString(R.string.digit_9);
1120b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm            default:
113e2711cbb1569ab6c7a7c4506505ec403286d5ab4Justin Klaassen                return "";
11484614957604253d51296e06c97daced699a0a9deHans Boehm        }
11584614957604253d51296e06c97daced699a0a9deHans Boehm    }
11684614957604253d51296e06c97daced699a0a9deHans Boehm
1170b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm    /**
1188a4f81c5b30edd4e62d222a17f4e0e2140bfd99dHans Boehm     * Map key id to corresponding (internationalized) descriptive string that can be used
1198a4f81c5b30edd4e62d222a17f4e0e2140bfd99dHans Boehm     * to correctly read back a formula.
1208a4f81c5b30edd4e62d222a17f4e0e2140bfd99dHans Boehm     * Only used for operators and individual characters; not used inside constants.
1218a4f81c5b30edd4e62d222a17f4e0e2140bfd99dHans Boehm     * Returns null when we don't need a descriptive string.
1228a4f81c5b30edd4e62d222a17f4e0e2140bfd99dHans Boehm     * Pure function.
1238a4f81c5b30edd4e62d222a17f4e0e2140bfd99dHans Boehm     */
1248a4f81c5b30edd4e62d222a17f4e0e2140bfd99dHans Boehm    public static String toDescriptiveString(Context context, int id) {
1258a4f81c5b30edd4e62d222a17f4e0e2140bfd99dHans Boehm        switch(id) {
1268a4f81c5b30edd4e62d222a17f4e0e2140bfd99dHans Boehm            case R.id.op_fact:
1278a4f81c5b30edd4e62d222a17f4e0e2140bfd99dHans Boehm                return context.getString(R.string.desc_op_fact);
1288a4f81c5b30edd4e62d222a17f4e0e2140bfd99dHans Boehm            case R.id.fun_sin:
1298a4f81c5b30edd4e62d222a17f4e0e2140bfd99dHans Boehm                return context.getString(R.string.desc_fun_sin)
1308a4f81c5b30edd4e62d222a17f4e0e2140bfd99dHans Boehm                        + " " + context.getString(R.string.desc_lparen);
1318a4f81c5b30edd4e62d222a17f4e0e2140bfd99dHans Boehm            case R.id.fun_cos:
1328a4f81c5b30edd4e62d222a17f4e0e2140bfd99dHans Boehm                return context.getString(R.string.desc_fun_cos)
1338a4f81c5b30edd4e62d222a17f4e0e2140bfd99dHans Boehm                        + " " + context.getString(R.string.desc_lparen);
1348a4f81c5b30edd4e62d222a17f4e0e2140bfd99dHans Boehm            case R.id.fun_tan:
1358a4f81c5b30edd4e62d222a17f4e0e2140bfd99dHans Boehm                return context.getString(R.string.desc_fun_tan)
1368a4f81c5b30edd4e62d222a17f4e0e2140bfd99dHans Boehm                        + " " + context.getString(R.string.desc_lparen);
1378a4f81c5b30edd4e62d222a17f4e0e2140bfd99dHans Boehm            case R.id.fun_arcsin:
1388a4f81c5b30edd4e62d222a17f4e0e2140bfd99dHans Boehm                return context.getString(R.string.desc_fun_arcsin)
1398a4f81c5b30edd4e62d222a17f4e0e2140bfd99dHans Boehm                        + " " + context.getString(R.string.desc_lparen);
1408a4f81c5b30edd4e62d222a17f4e0e2140bfd99dHans Boehm            case R.id.fun_arccos:
1418a4f81c5b30edd4e62d222a17f4e0e2140bfd99dHans Boehm                return context.getString(R.string.desc_fun_arccos)
1428a4f81c5b30edd4e62d222a17f4e0e2140bfd99dHans Boehm                        + " " + context.getString(R.string.desc_lparen);
1438a4f81c5b30edd4e62d222a17f4e0e2140bfd99dHans Boehm            case R.id.fun_arctan:
1448a4f81c5b30edd4e62d222a17f4e0e2140bfd99dHans Boehm                return context.getString(R.string.desc_fun_arctan)
1458a4f81c5b30edd4e62d222a17f4e0e2140bfd99dHans Boehm                        + " " + context.getString(R.string.desc_lparen);
1468a4f81c5b30edd4e62d222a17f4e0e2140bfd99dHans Boehm            case R.id.fun_ln:
1478a4f81c5b30edd4e62d222a17f4e0e2140bfd99dHans Boehm                return context.getString(R.string.desc_fun_ln)
1488a4f81c5b30edd4e62d222a17f4e0e2140bfd99dHans Boehm                        + " " + context.getString(R.string.desc_lparen);
1498a4f81c5b30edd4e62d222a17f4e0e2140bfd99dHans Boehm            case R.id.fun_log:
1508a4f81c5b30edd4e62d222a17f4e0e2140bfd99dHans Boehm                return context.getString(R.string.desc_fun_log)
1518a4f81c5b30edd4e62d222a17f4e0e2140bfd99dHans Boehm                        + " " + context.getString(R.string.desc_lparen);
1528a4f81c5b30edd4e62d222a17f4e0e2140bfd99dHans Boehm            case R.id.fun_exp:
1538a4f81c5b30edd4e62d222a17f4e0e2140bfd99dHans Boehm                return context.getString(R.string.desc_fun_exp)
1548a4f81c5b30edd4e62d222a17f4e0e2140bfd99dHans Boehm                        + " " + context.getString(R.string.desc_lparen);
1558a4f81c5b30edd4e62d222a17f4e0e2140bfd99dHans Boehm            case R.id.lparen:
1568a4f81c5b30edd4e62d222a17f4e0e2140bfd99dHans Boehm                return context.getString(R.string.desc_lparen);
1578a4f81c5b30edd4e62d222a17f4e0e2140bfd99dHans Boehm            case R.id.rparen:
1588a4f81c5b30edd4e62d222a17f4e0e2140bfd99dHans Boehm                return context.getString(R.string.desc_rparen);
1598a4f81c5b30edd4e62d222a17f4e0e2140bfd99dHans Boehm            case R.id.op_pow:
1608a4f81c5b30edd4e62d222a17f4e0e2140bfd99dHans Boehm                return context.getString(R.string.desc_op_pow);
1618a4f81c5b30edd4e62d222a17f4e0e2140bfd99dHans Boehm            case R.id.dec_point:
1628a4f81c5b30edd4e62d222a17f4e0e2140bfd99dHans Boehm                return context.getString(R.string.desc_dec_point);
1638a4f81c5b30edd4e62d222a17f4e0e2140bfd99dHans Boehm            default:
1648a4f81c5b30edd4e62d222a17f4e0e2140bfd99dHans Boehm                return null;
1658a4f81c5b30edd4e62d222a17f4e0e2140bfd99dHans Boehm        }
1668a4f81c5b30edd4e62d222a17f4e0e2140bfd99dHans Boehm    }
1678a4f81c5b30edd4e62d222a17f4e0e2140bfd99dHans Boehm
1688a4f81c5b30edd4e62d222a17f4e0e2140bfd99dHans Boehm    /**
1690b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm     * Does a button id correspond to a binary operator?
1700b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm     * Pure function.
1710b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm     */
17284614957604253d51296e06c97daced699a0a9deHans Boehm    public static boolean isBinary(int id) {
17384614957604253d51296e06c97daced699a0a9deHans Boehm        switch(id) {
1740b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm            case R.id.op_pow:
1750b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm            case R.id.op_mul:
1760b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm            case R.id.op_div:
1770b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm            case R.id.op_add:
1780b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm            case R.id.op_sub:
179017de9893efd33e179db10bc71189e150bc3486dHans Boehm                return true;
180017de9893efd33e179db10bc71189e150bc3486dHans Boehm            default:
181017de9893efd33e179db10bc71189e150bc3486dHans Boehm                return false;
182017de9893efd33e179db10bc71189e150bc3486dHans Boehm        }
183017de9893efd33e179db10bc71189e150bc3486dHans Boehm    }
184017de9893efd33e179db10bc71189e150bc3486dHans Boehm
185017de9893efd33e179db10bc71189e150bc3486dHans Boehm    /**
186017de9893efd33e179db10bc71189e150bc3486dHans Boehm     * Does a button id correspond to a function that introduces an implicit lparen?
187017de9893efd33e179db10bc71189e150bc3486dHans Boehm     * Pure function.
188017de9893efd33e179db10bc71189e150bc3486dHans Boehm     */
189017de9893efd33e179db10bc71189e150bc3486dHans Boehm    public static boolean isFunc(int id) {
190017de9893efd33e179db10bc71189e150bc3486dHans Boehm        switch(id) {
191017de9893efd33e179db10bc71189e150bc3486dHans Boehm            case R.id.fun_sin:
192017de9893efd33e179db10bc71189e150bc3486dHans Boehm            case R.id.fun_cos:
193017de9893efd33e179db10bc71189e150bc3486dHans Boehm            case R.id.fun_tan:
194017de9893efd33e179db10bc71189e150bc3486dHans Boehm            case R.id.fun_arcsin:
195017de9893efd33e179db10bc71189e150bc3486dHans Boehm            case R.id.fun_arccos:
196017de9893efd33e179db10bc71189e150bc3486dHans Boehm            case R.id.fun_arctan:
197017de9893efd33e179db10bc71189e150bc3486dHans Boehm            case R.id.fun_ln:
198017de9893efd33e179db10bc71189e150bc3486dHans Boehm            case R.id.fun_log:
199017de9893efd33e179db10bc71189e150bc3486dHans Boehm            case R.id.fun_exp:
200017de9893efd33e179db10bc71189e150bc3486dHans Boehm                return true;
201017de9893efd33e179db10bc71189e150bc3486dHans Boehm            default:
202017de9893efd33e179db10bc71189e150bc3486dHans Boehm                return false;
203017de9893efd33e179db10bc71189e150bc3486dHans Boehm        }
204017de9893efd33e179db10bc71189e150bc3486dHans Boehm    }
205017de9893efd33e179db10bc71189e150bc3486dHans Boehm
206017de9893efd33e179db10bc71189e150bc3486dHans Boehm    /**
207017de9893efd33e179db10bc71189e150bc3486dHans Boehm     * Does a button id correspond to a prefix operator?
208017de9893efd33e179db10bc71189e150bc3486dHans Boehm     * Pure function.
209017de9893efd33e179db10bc71189e150bc3486dHans Boehm     */
210017de9893efd33e179db10bc71189e150bc3486dHans Boehm    public static boolean isPrefix(int id) {
211017de9893efd33e179db10bc71189e150bc3486dHans Boehm        switch(id) {
212017de9893efd33e179db10bc71189e150bc3486dHans Boehm            case R.id.op_sqrt:
213017de9893efd33e179db10bc71189e150bc3486dHans Boehm            case R.id.op_sub:
2140b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm                return true;
2150b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm            default:
2160b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm                return false;
21784614957604253d51296e06c97daced699a0a9deHans Boehm        }
21884614957604253d51296e06c97daced699a0a9deHans Boehm    }
21984614957604253d51296e06c97daced699a0a9deHans Boehm
2200b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm    /**
2210b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm     * Does a button id correspond to a suffix operator?
2220b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm     */
22384614957604253d51296e06c97daced699a0a9deHans Boehm    public static boolean isSuffix(int id) {
224e2711cbb1569ab6c7a7c4506505ec403286d5ab4Justin Klaassen        switch (id) {
225e2711cbb1569ab6c7a7c4506505ec403286d5ab4Justin Klaassen            case R.id.op_fact:
226e2711cbb1569ab6c7a7c4506505ec403286d5ab4Justin Klaassen            case R.id.op_pct:
2274db31b490443e4454d98a5ae2bc44b87149accfeHans Boehm            case R.id.op_sqr:
228e2711cbb1569ab6c7a7c4506505ec403286d5ab4Justin Klaassen                return true;
229e2711cbb1569ab6c7a7c4506505ec403286d5ab4Justin Klaassen            default:
230e2711cbb1569ab6c7a7c4506505ec403286d5ab4Justin Klaassen                return false;
231e2711cbb1569ab6c7a7c4506505ec403286d5ab4Justin Klaassen        }
23284614957604253d51296e06c97daced699a0a9deHans Boehm    }
23384614957604253d51296e06c97daced699a0a9deHans Boehm
23484614957604253d51296e06c97daced699a0a9deHans Boehm    public static final int NOT_DIGIT = 10;
23584614957604253d51296e06c97daced699a0a9deHans Boehm
23608e8f322b0d93e06aaa2a15acc869dfd70791461Hans Boehm    public static final String ELLIPSIS = "\u2026";
23708e8f322b0d93e06aaa2a15acc869dfd70791461Hans Boehm
2380b9806f624f25e7e0302da4cf55eda21f8c28163Hans Boehm    public static final char MINUS_SIGN = '\u2212';
2390b9806f624f25e7e0302da4cf55eda21f8c28163Hans Boehm
2400b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm    /**
2410b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm     * Map key id to digit or NOT_DIGIT
2420b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm     * Pure function.
2430b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm     */
24484614957604253d51296e06c97daced699a0a9deHans Boehm    public static int digVal(int id) {
24584614957604253d51296e06c97daced699a0a9deHans Boehm        switch (id) {
24684614957604253d51296e06c97daced699a0a9deHans Boehm        case R.id.digit_0:
24784614957604253d51296e06c97daced699a0a9deHans Boehm            return 0;
24884614957604253d51296e06c97daced699a0a9deHans Boehm        case R.id.digit_1:
24984614957604253d51296e06c97daced699a0a9deHans Boehm            return 1;
25084614957604253d51296e06c97daced699a0a9deHans Boehm        case R.id.digit_2:
25184614957604253d51296e06c97daced699a0a9deHans Boehm            return 2;
25284614957604253d51296e06c97daced699a0a9deHans Boehm        case R.id.digit_3:
25384614957604253d51296e06c97daced699a0a9deHans Boehm            return 3;
25484614957604253d51296e06c97daced699a0a9deHans Boehm        case R.id.digit_4:
25584614957604253d51296e06c97daced699a0a9deHans Boehm            return 4;
25684614957604253d51296e06c97daced699a0a9deHans Boehm        case R.id.digit_5:
25784614957604253d51296e06c97daced699a0a9deHans Boehm            return 5;
25884614957604253d51296e06c97daced699a0a9deHans Boehm        case R.id.digit_6:
25984614957604253d51296e06c97daced699a0a9deHans Boehm            return 6;
26084614957604253d51296e06c97daced699a0a9deHans Boehm        case R.id.digit_7:
26184614957604253d51296e06c97daced699a0a9deHans Boehm            return 7;
26284614957604253d51296e06c97daced699a0a9deHans Boehm        case R.id.digit_8:
26384614957604253d51296e06c97daced699a0a9deHans Boehm            return 8;
26484614957604253d51296e06c97daced699a0a9deHans Boehm        case R.id.digit_9:
26584614957604253d51296e06c97daced699a0a9deHans Boehm            return 9;
26684614957604253d51296e06c97daced699a0a9deHans Boehm        default:
26784614957604253d51296e06c97daced699a0a9deHans Boehm            return NOT_DIGIT;
26884614957604253d51296e06c97daced699a0a9deHans Boehm        }
26984614957604253d51296e06c97daced699a0a9deHans Boehm    }
27084614957604253d51296e06c97daced699a0a9deHans Boehm
2710b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm    /**
2720b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm     * Map digit to corresponding key.  Inverse of above.
2730b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm     * Pure function.
2740b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm     */
27584614957604253d51296e06c97daced699a0a9deHans Boehm    public static int keyForDigVal(int v) {
27684614957604253d51296e06c97daced699a0a9deHans Boehm        switch(v) {
27784614957604253d51296e06c97daced699a0a9deHans Boehm        case 0:
27884614957604253d51296e06c97daced699a0a9deHans Boehm            return R.id.digit_0;
27984614957604253d51296e06c97daced699a0a9deHans Boehm        case 1:
28084614957604253d51296e06c97daced699a0a9deHans Boehm            return R.id.digit_1;
28184614957604253d51296e06c97daced699a0a9deHans Boehm        case 2:
28284614957604253d51296e06c97daced699a0a9deHans Boehm            return R.id.digit_2;
28384614957604253d51296e06c97daced699a0a9deHans Boehm        case 3:
28484614957604253d51296e06c97daced699a0a9deHans Boehm            return R.id.digit_3;
28584614957604253d51296e06c97daced699a0a9deHans Boehm        case 4:
28684614957604253d51296e06c97daced699a0a9deHans Boehm            return R.id.digit_4;
28784614957604253d51296e06c97daced699a0a9deHans Boehm        case 5:
28884614957604253d51296e06c97daced699a0a9deHans Boehm            return R.id.digit_5;
28984614957604253d51296e06c97daced699a0a9deHans Boehm        case 6:
29084614957604253d51296e06c97daced699a0a9deHans Boehm            return R.id.digit_6;
29184614957604253d51296e06c97daced699a0a9deHans Boehm        case 7:
29284614957604253d51296e06c97daced699a0a9deHans Boehm            return R.id.digit_7;
29384614957604253d51296e06c97daced699a0a9deHans Boehm        case 8:
29484614957604253d51296e06c97daced699a0a9deHans Boehm            return R.id.digit_8;
29584614957604253d51296e06c97daced699a0a9deHans Boehm        case 9:
29684614957604253d51296e06c97daced699a0a9deHans Boehm            return R.id.digit_9;
29784614957604253d51296e06c97daced699a0a9deHans Boehm        default:
29884614957604253d51296e06c97daced699a0a9deHans Boehm            return View.NO_ID;
29984614957604253d51296e06c97daced699a0a9deHans Boehm        }
30084614957604253d51296e06c97daced699a0a9deHans Boehm    }
30184614957604253d51296e06c97daced699a0a9deHans Boehm
302425ed0a15c7c755a94701457b671b8b86765dc59Hans Boehm    // The following two are only used for recognizing additional
303425ed0a15c7c755a94701457b671b8b86765dc59Hans Boehm    // input characters from a physical keyboard.  They are not used
304425ed0a15c7c755a94701457b671b8b86765dc59Hans Boehm    // for output internationalization.
305425ed0a15c7c755a94701457b671b8b86765dc59Hans Boehm    private static char mDecimalPt;
306ffda52845ca6cca5f72795706988a11f6bcf5b03Hans Boehm
307ffda52845ca6cca5f72795706988a11f6bcf5b03Hans Boehm    private static char mPiChar;
30884614957604253d51296e06c97daced699a0a9deHans Boehm
309ffda52845ca6cca5f72795706988a11f6bcf5b03Hans Boehm    /**
3100b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm     * Character used as a placeholder for digits that are currently unknown in a result that
3110b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm     * is being computed.  We initially generate blanks, and then use this as a replacement
3120b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm     * during final translation.
313ffda52845ca6cca5f72795706988a11f6bcf5b03Hans Boehm     * <p/>
314ffda52845ca6cca5f72795706988a11f6bcf5b03Hans Boehm     * Note: the character must correspond closely to the width of a digit,
315ffda52845ca6cca5f72795706988a11f6bcf5b03Hans Boehm     * otherwise the UI will visibly shift once the computation is finished.
316ffda52845ca6cca5f72795706988a11f6bcf5b03Hans Boehm     */
317ffda52845ca6cca5f72795706988a11f6bcf5b03Hans Boehm    private static final char CHAR_DIGIT_UNKNOWN = '\u2007';
3184a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm
3190b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm    /**
3200b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm     * Map typed function name strings to corresponding button ids.
3210b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm     * We (now redundantly?) include both localized and English names.
3220b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm     */
323ffda52845ca6cca5f72795706988a11f6bcf5b03Hans Boehm    private static HashMap<String, Integer> sKeyValForFun;
3244a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm
3250b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm    /**
3260b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm     * Result string corresponding to a character in the calculator result.
3270b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm     * The string values in the map are expected to be one character long.
3280b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm     */
329ffda52845ca6cca5f72795706988a11f6bcf5b03Hans Boehm    private static HashMap<Character, String> sOutputForResultChar;
330013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm
3310b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm    /**
3320b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm     * Locale string corresponding to preceding map and character constants.
3330b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm     * We recompute the map if this is not the current locale.
3340b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm     */
335ffda52845ca6cca5f72795706988a11f6bcf5b03Hans Boehm    private static String sLocaleForMaps = "none";
3364a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm
3370b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm    /**
3380b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm     * Activity to use for looking up buttons.
3390b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm     */
3400b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm    private static Activity mActivity;
341013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm
3420b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm    /**
3430b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm     * Set acttivity used for looking up button labels.
3440b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm     * Call only from UI thread.
3450b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm     */
346013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm    public static void setActivity(Activity a) {
347013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm        mActivity = a;
348013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm    }
349013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm
3500b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm    /**
3510b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm     * Return the button id corresponding to the supplied character or return NO_ID.
3520b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm     * Called only by UI thread.
3530b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm     */
354013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm    public static int keyForChar(char c) {
355013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm        validateMaps();
35684614957604253d51296e06c97daced699a0a9deHans Boehm        if (Character.isDigit(c)) {
35784614957604253d51296e06c97daced699a0a9deHans Boehm            int i = Character.digit(c, 10);
35884614957604253d51296e06c97daced699a0a9deHans Boehm            return KeyMaps.keyForDigVal(i);
35984614957604253d51296e06c97daced699a0a9deHans Boehm        }
36084614957604253d51296e06c97daced699a0a9deHans Boehm        switch (c) {
3610b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm            case '.':
3620b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm            case ',':
3630b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm                return R.id.dec_point;
3640b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm            case '-':
3650b9806f624f25e7e0302da4cf55eda21f8c28163Hans Boehm            case MINUS_SIGN:
3660b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm                return R.id.op_sub;
3670b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm            case '+':
3680b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm                return R.id.op_add;
3690b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm            case '*':
3700b9806f624f25e7e0302da4cf55eda21f8c28163Hans Boehm            case '\u00D7': // MULTIPLICATION SIGN
3710b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm                return R.id.op_mul;
3720b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm            case '/':
3730b9806f624f25e7e0302da4cf55eda21f8c28163Hans Boehm            case '\u00F7': // DIVISION SIGN
3740b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm                return R.id.op_div;
3750b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm            // We no longer localize function names, so they can't start with an 'e' or 'p'.
3760b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm            case 'e':
3770b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm            case 'E':
3780b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm                return R.id.const_e;
3790b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm            case 'p':
3800b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm            case 'P':
3810b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm                return R.id.const_pi;
3820b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm            case '^':
3830b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm                return R.id.op_pow;
3840b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm            case '!':
3850b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm                return R.id.op_fact;
386e2711cbb1569ab6c7a7c4506505ec403286d5ab4Justin Klaassen            case '%':
387e2711cbb1569ab6c7a7c4506505ec403286d5ab4Justin Klaassen                return R.id.op_pct;
3880b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm            case '(':
3890b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm                return R.id.lparen;
3900b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm            case ')':
3910b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm                return R.id.rparen;
3920b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm            default:
3930b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm                if (c == mDecimalPt) return R.id.dec_point;
3940b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm                if (c == mPiChar) return R.id.const_pi;
3950b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm                    // pi is not translated, but it might be typable on a Greek keyboard,
3960b9806f624f25e7e0302da4cf55eda21f8c28163Hans Boehm                    // or pasted in, so we check ...
3970b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm                return View.NO_ID;
39884614957604253d51296e06c97daced699a0a9deHans Boehm        }
39984614957604253d51296e06c97daced699a0a9deHans Boehm    }
4004a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm
4010b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm    /**
4020b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm     * Add information corresponding to the given button id to sKeyValForFun, to be used
4030b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm     * when mapping keyboard input to button ids.
4040b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm     */
405013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm    static void addButtonToFunMap(int button_id) {
406013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm        Button button = (Button)mActivity.findViewById(button_id);
4074a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm        sKeyValForFun.put(button.getText().toString(), button_id);
4084a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm    }
4094a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm
4100b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm    /**
4110b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm     * Add information corresponding to the given button to sOutputForResultChar, to be used
4120b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm     * when translating numbers on output.
4130b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm     */
414013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm    static void addButtonToOutputMap(char c, int button_id) {
415013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm        Button button = (Button)mActivity.findViewById(button_id);
416013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm        sOutputForResultChar.put(c, button.getText().toString());
417013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm    }
418013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm
4194a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm    // Ensure that the preceding map and character constants are
4204a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm    // initialized and correspond to the current locale.
4214a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm    // Called only by a single thread, namely the UI thread.
422013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm    static void validateMaps() {
4234a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm        Locale locale = Locale.getDefault();
4244a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm        String lname = locale.toString();
425013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm        if (lname != sLocaleForMaps) {
4264a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm            Log.v ("Calculator", "Setting local to: " + lname);
4274a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm            sKeyValForFun = new HashMap<String, Integer>();
4284a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm            sKeyValForFun.put("sin", R.id.fun_sin);
4294a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm            sKeyValForFun.put("cos", R.id.fun_cos);
4304a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm            sKeyValForFun.put("tan", R.id.fun_tan);
4314a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm            sKeyValForFun.put("arcsin", R.id.fun_arcsin);
4324a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm            sKeyValForFun.put("arccos", R.id.fun_arccos);
4334a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm            sKeyValForFun.put("arctan", R.id.fun_arctan);
4344a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm            sKeyValForFun.put("asin", R.id.fun_arcsin);
4354a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm            sKeyValForFun.put("acos", R.id.fun_arccos);
4364a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm            sKeyValForFun.put("atan", R.id.fun_arctan);
4374a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm            sKeyValForFun.put("ln", R.id.fun_ln);
4384a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm            sKeyValForFun.put("log", R.id.fun_log);
4394a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm            sKeyValForFun.put("sqrt", R.id.op_sqrt); // special treatment
440013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm            addButtonToFunMap(R.id.fun_sin);
441013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm            addButtonToFunMap(R.id.fun_cos);
442013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm            addButtonToFunMap(R.id.fun_tan);
443013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm            addButtonToFunMap(R.id.fun_arcsin);
444013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm            addButtonToFunMap(R.id.fun_arccos);
445013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm            addButtonToFunMap(R.id.fun_arctan);
446013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm            addButtonToFunMap(R.id.fun_ln);
447013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm            addButtonToFunMap(R.id.fun_log);
4484a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm
4494a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm            // Set locale-dependent character "constants"
450013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm            mDecimalPt =
4514a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm                DecimalFormatSymbols.getInstance().getDecimalSeparator();
452425ed0a15c7c755a94701457b671b8b86765dc59Hans Boehm                // We recognize this in keyboard input, even if we use
453425ed0a15c7c755a94701457b671b8b86765dc59Hans Boehm                // a different character.
454013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm            Resources res = mActivity.getResources();
455425ed0a15c7c755a94701457b671b8b86765dc59Hans Boehm            mPiChar = 0;
4564a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm            String piString = res.getString(R.string.const_pi);
4570b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm            if (piString.length() == 1) {
4580b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm                mPiChar = piString.charAt(0);
4590b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm            }
4604a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm
461013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm            sOutputForResultChar = new HashMap<Character, String>();
462013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm            sOutputForResultChar.put('e', "E");
463013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm            sOutputForResultChar.put('E', "E");
464ffda52845ca6cca5f72795706988a11f6bcf5b03Hans Boehm            sOutputForResultChar.put(' ', String.valueOf(CHAR_DIGIT_UNKNOWN));
46508e8f322b0d93e06aaa2a15acc869dfd70791461Hans Boehm            sOutputForResultChar.put(ELLIPSIS.charAt(0), ELLIPSIS);
466013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm            sOutputForResultChar.put('/', "/");
467013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm                        // Translate numbers for fraction display, but not
468013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm                        // the separating slash, which appears to be
469013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm                        // universal.
470013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm            addButtonToOutputMap('-', R.id.op_sub);
471425ed0a15c7c755a94701457b671b8b86765dc59Hans Boehm            addButtonToOutputMap('.', R.id.dec_point);
472013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm            for (int i = 0; i <= 9; ++i) {
473013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm                addButtonToOutputMap((char)('0' + i), keyForDigVal(i));
474013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm            }
475013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm
476013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm            sLocaleForMaps = lname;
477013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm
4784a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm        }
4794a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm    }
4804a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm
4810b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm    /**
4820b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm     * Return function button id for the substring of s starting at pos and ending with
4830b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm     * the next "(".  Return NO_ID if there is none.
4840b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm     * We currently check for both (possibly localized) button labels, and standard
4850b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm     * English names.  (They should currently be the same, and hence this is currently redundant.)
4860b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm     * Callable only from UI thread.
4870b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm     */
488013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm    public static int funForString(String s, int pos) {
489013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm        validateMaps();
4904a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm        int parenPos = s.indexOf('(', pos);
4914a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm        if (parenPos != -1) {
4924a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm            String funString = s.substring(pos, parenPos);
4934a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm            Integer keyValue = sKeyValForFun.get(funString);
4944a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm            if (keyValue == null) return View.NO_ID;
4954a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm            return keyValue;
4964a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm        }
4974a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm        return View.NO_ID;
4984a6b7cb235c305761af5d7f40e74d4704e5058c8Hans Boehm    }
499013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm
5000b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm    /**
5010b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm     * Return the localization of the string s representing a numeric answer.
5020b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm     * Callable only from UI thread.
5030b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm     */
504013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm    public static String translateResult(String s) {
505013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm        StringBuilder result = new StringBuilder();
506013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm        int len = s.length();
507013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm        validateMaps();
508013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm        for (int i = 0; i < len; ++i) {
509013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm            char c = s.charAt(i);
510013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm            String translation = sOutputForResultChar.get(c);
511013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm            if (translation == null) {
5120b3a9fd4405fd023e4343d4ff6c8da5ffb1346f4Hans Boehm                // Should not get here.  Report if we do.
513013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm                Log.v("Calculator", "Bad character:" + c);
514013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm                result.append(String.valueOf(c));
515013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm            } else {
516013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm                result.append(translation);
517013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm            }
518013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm        }
519013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm        return result.toString();
520013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm    }
521013969e98ce9e3eb4f87ec6159b06a74d07b2592Hans Boehm
52284614957604253d51296e06c97daced699a0a9deHans Boehm}
523