summaryrefslogtreecommitdiff
path: root/noncore/tools/calc2/engine.cpp
Unidiff
Diffstat (limited to 'noncore/tools/calc2/engine.cpp') (more/less context) (show whitespace changes)
-rw-r--r--noncore/tools/calc2/engine.cpp214
1 files changed, 214 insertions, 0 deletions
diff --git a/noncore/tools/calc2/engine.cpp b/noncore/tools/calc2/engine.cpp
new file mode 100644
index 0000000..a9a47c4
--- a/dev/null
+++ b/noncore/tools/calc2/engine.cpp
@@ -0,0 +1,214 @@
1/**********************************************************************
2** Copyright (C) 2000 Trolltech AS. All rights reserved.
3**
4** This file is part of Qtopia Environment.
5**
6** This file may be distributed and/or modified under the terms of the
7** GNU General Public License version 2 as published by the Free Software
8** Foundation and appearing in the file LICENSE.GPL included in the
9** packaging of this file.
10**
11** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
12** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
13**
14** See http://www.trolltech.com/gpl/ for GPL licensing information.
15**
16** Contact info@trolltech.com if any conditions of this licensing are
17** not clear to you.
18**
19**********************************************************************/
20
21#include "engine.h"
22#include <qstring.h>
23#include <math.h>
24#include <qlcdnumber.h>
25
26Data Engine::evalStack (Data num, bool inbrace = FALSE)
27{
28 if (state != sError) {
29 Instruction *i;
30
31// Pop the next op from the stack
32 while (!stack.isEmpty () && (braces || !inbrace)) {
33 i = stack.pop ();
34
35// Check this ops prec vs next ops prec
36 if (!stack.isEmpty ())
37 if (i->precedence <= stack.top()->precedence)
38 i->acc = evalStack (i->acc, inbrace);
39
40// Evaluate this instruction
41 num = i->eval (num);
42
43// Error-check ( change this to work for all types )
44 if (isnan (num.dbl) || isinf (num.dbl)) {
45 qDebug ("bad result from operation");
46 state = sError;
47 clearData(&num);
48 return num;
49 }
50 }
51 }
52 return num;
53}
54
55// Plugins call this to request the stack be evaluated
56void Engine::eval ()
57{
58 num = evalStack (num);
59 if (state != sError) {
60 displayData(num);
61 state = sStart;
62 }
63// if the user didnt close all their braces, its no big deal
64 braces = 0;
65}
66
67void Engine::immediateInstruction (Instruction * i)
68{
69 if (state != sError) {
70 i->setRep(currentRep);
71 num = i->eval (num);
72 displayData(num);
73 state = sStart;
74 }
75}
76
77void Engine::pushInstruction (Instruction * i)
78{
79 if (state != sError) {
80 i->setRep(currentRep);
81 i->acc = num;
82 stack.push (i);
83 state = sStart;
84 }
85}
86
87void Engine::pushValue (char v)
88{
89 if (state == sAppend) {
90 bool ok = FALSE;
91 switch (currentRep) {
92 case rDouble:
93 displayString.append(v);
94 num.dbl=displayString.toDouble(&ok);
95 break;
96 case rFraction:
97 break;
98 default:
99 displayString.append(v);
100 num.i=displayString.toInt(&ok, calcBase());
101 };
102 if (!ok) {
103 state = sError;
104 qDebug("pushValue() - num->string conversion");
105 } else {
106 const QString constString = displayString;
107 emit(display(constString));
108 };
109
110 } else if (state == sStart) {
111 softReset();
112 displayString.truncate(0);
113 state = sAppend;
114 pushValue (v);
115 } else if (state == sError) {
116 qDebug ("in error state");
117 return;
118 }
119}
120
121void Engine::del ()
122{
123 bool ok;
124 switch (currentRep) {
125 case rDouble:
126 displayString.truncate(displayString.length());
127 num.dbl=displayString.toDouble(&ok);
128 break;
129 case rFraction:
130 qDebug("not available");
131 break;
132 default:
133 displayString.truncate(displayString.length());
134 num.i = displayString.toInt(&ok, calcBase());
135 };
136
137 if (!ok) {
138 state = sError;
139 qDebug("del() - num->string conversion");
140 } else {
141 const QString constString = displayString;
142 emit(display(constString));
143 };
144}
145
146void Engine::displayData(Data d) {
147 switch (currentRep) {
148 case rDouble:
149 displayString.setNum(d.dbl);
150 break;
151 case rFraction:
152 qDebug("fractional display not yet impl");
153 break;
154 default:
155 displayString.setNum(d.i, calcBase());
156 break;
157 };
158 const QString constString= displayString;
159 emit(display(constString));
160}
161
162// Returns the base when Rep is an integer type
163int Engine::calcBase () {
164 switch (currentRep) {
165 case rBin:
166 return 2;
167 case rOct:
168 return 8;
169 case rDec:
170 return 10;
171 case rHex:
172 return 16;
173 default:
174 state = sError;
175 qDebug("Error - attempt to calc base for non-integer");
176 return 10;
177 };
178}
179
180// Special instruction for internal use only
181class iOpenBrace:public Instruction {
182 public:
183 iOpenBrace (Engine *e):Instruction (100) {engine = e;};
184 ~iOpenBrace () {};
185
186 Data eval (Data num) {
187 engine->decBraces();
188 return num;
189 };
190 private:
191 Engine *engine;
192};
193
194void Engine::openBrace() {
195 pushInstruction(new iOpenBrace(this));
196}
197
198void Engine::closeBrace() {
199 braces++;evalStack(num,TRUE);
200}
201
202// will need to show and hide display widgets
203void Engine::setRepresentation(Representation r) {
204 currentRep = r;
205 clearData(&num);
206 clearData(&mem);
207 state = sStart;
208}
209
210void Engine::clearData(Data *d) {
211 d->i = d->fraction.numerator = d->fraction.denominator = 0;
212 d->dbl = 0;
213}
214