[PATCH xcalc] Add bitwise ops and base conversion (DEC/OCT/HEX) in TI mode

Tim Hentenaar tim at hentenaar.com
Sat Mar 22 07:21:27 PDT 2014


These operations implicitly truncate their parameters, and result to
integers:

* not
* and
* or
* xor
* shl
* shr
* mod
* trunc

Binary (base 2) was left out of the base conversion code intentionally
as it would require making the UI at least one third wider and the
benefits would be negligible.

I've also bound the Return key to the equal() action.

Signed-off-by: Tim Hentenaar <tim at hentenaar.com>
---
 actions.c          |  98 +++++++++++++++++++++++++-
 app-defaults/XCalc | 202 ++++++++++++++++++++++++++++++++++++++---------------
 math.c             | 177 +++++++++++++++++++++++++++++++++++++---------
 xcalc.c            |  19 ++++-
 xcalc.h            |  19 +++++
 5 files changed, 424 insertions(+), 91 deletions(-)

diff --git a/actions.c b/actions.c
index 50bf7b4..2857f96 100644
--- a/actions.c
+++ b/actions.c
@@ -46,7 +46,9 @@ from the X Consortium.
 #endif

 static void add(Widget w, XEvent *ev, String *vector, Cardinal *count);
+static void and(Widget w, XEvent *ev, String *vector, Cardinal *count);
 static void back(Widget w, XEvent *ev, String *vector, Cardinal *count);
+static void base(Widget w, XEvent *ev, String *vector, Cardinal *count);
 static void bell(Widget w, XEvent *ev, String *vector, Cardinal *count);
 static void clearit(Widget w, XEvent *ev, String *vector, Cardinal *count);
 static void cosine(Widget w, XEvent *ev, String *vector, Cardinal *count);
@@ -63,11 +65,14 @@ static void factorial(Widget w, XEvent *ev, String
*vector, Cardinal *count);
 static void inverse(Widget w, XEvent *ev, String *vector, Cardinal *count);
 static void leftParen(Widget w, XEvent *ev, String *vector, Cardinal *count);
 static void logarithm(Widget w, XEvent *ev, String *vector, Cardinal *count);
+static void mod(Widget w, XEvent *ev, String *vector, Cardinal *count);
 static void multiply(Widget w, XEvent *ev, String *vector, Cardinal *count);
 static void naturalLog(Widget w, XEvent *ev, String *vector, Cardinal *count);
 static void negate(Widget w, XEvent *ev, String *vector, Cardinal *count);
 static void nop(Widget w, XEvent *ev, String *vector, Cardinal *count);
+static void not(Widget w, XEvent *ev, String *vector, Cardinal *count);
 static void off(Widget w, XEvent *ev, String *vector, Cardinal *count);
+static void or(Widget w, XEvent *ev, String *vector, Cardinal *count);
 static void pi(Widget w, XEvent *ev, String *vector, Cardinal *count);
 static void power(Widget w, XEvent *ev, String *vector, Cardinal *count);
 static void quit(Widget w, XEvent *ev, String *vector, Cardinal *count);
@@ -77,6 +82,8 @@ static void rightParen(Widget w, XEvent *ev, String
*vector, Cardinal *count);
 static void roll(Widget w, XEvent *ev, String *vector, Cardinal *count);
 static void scientific(Widget w, XEvent *ev, String *vector, Cardinal *count);
 static void selection(Widget w, XEvent *ev, String *vector, Cardinal *count);
+static void shl(Widget w, XEvent *ev, String *vector, Cardinal *count);
+static void shr(Widget w, XEvent *ev, String *vector, Cardinal *count);
 static void sine(Widget w, XEvent *ev, String *vector, Cardinal *count);
 static void square(Widget w, XEvent *ev, String *vector, Cardinal *count);
 static void squareRoot(Widget w, XEvent *ev, String *vector, Cardinal *count);
@@ -85,6 +92,8 @@ static void subtract(Widget w, XEvent *ev, String
*vector, Cardinal *count);
 static void sum(Widget w, XEvent *ev, String *vector, Cardinal *count);
 static void tangent(Widget w, XEvent *ev, String *vector, Cardinal *count);
 static void tenpower(Widget w, XEvent *ev, String *vector, Cardinal *count);
+static void xtrunc(Widget w, XEvent *ev, String *vector, Cardinal *count);
+static void xor(Widget w, XEvent *ev, String *vector, Cardinal *count);
 static void XexchangeY(Widget w, XEvent *ev, String *vector, Cardinal *count);

 /*
@@ -93,7 +102,9 @@ static void XexchangeY(Widget w, XEvent *ev, String
*vector, Cardinal *count);

 XtActionsRec Actions[] = {
 {"add", add}, /* addition */
+{"and", and}, /* bitwise and */
 {"back", back}, /* HP-specific backspace */
+{"base", base}, /* base conversion */
 {"bell", bell}, /* ring bell */
 {"clear", clearit}, /* TI-specific clear calculator state */
 {"cosine", cosine}, /* trigonometric function cosine */
@@ -110,11 +121,14 @@ XtActionsRec Actions[] = {
 {"inverse", inverse}, /* inverse */
 {"leftParen", leftParen}, /* TI-specific left parenthesis */
 {"logarithm", logarithm}, /* logarithm base 10 */
+{"mod", mod}, /* modulus */
 {"multiply", multiply}, /* multiplication */
 {"naturalLog", naturalLog}, /* natural logarithm base e */
 {"negate", negate}, /* change sign */
 {"nop", nop}, /* no operation, rings bell */
+{"not", not}, /* bitwise not */
 {"off", off}, /* clear state */
+{"or", or}, /* bitwise or */
 {"pi", pi}, /* the number pi */
 {"power", power}, /* raise to an arbitrary power */
 {"quit", quit}, /* quit */
@@ -124,6 +138,8 @@ XtActionsRec Actions[] = {
 {"roll", roll}, /* HP-specific roll stack */
 {"scientific", scientific}, /* scientfic notation (EE) */
 {"selection", selection}, /* copy selection */
+{"shl", shl}, /* arithmetic shift left */
+{"shr", shr}, /* arithmetic shift right */
 {"sine", sine}, /* trigonometric function sine */
 {"square", square}, /* square */
 {"squareRoot", squareRoot}, /* square root */
@@ -132,6 +148,8 @@ XtActionsRec Actions[] = {
 {"sum", sum}, /* memory summation */
 {"tangent", tangent}, /* trigonometric function tangent */
 {"tenpower", tenpower}, /* 10 raised to to an arbitrary power */
+{"trunc", xtrunc}, /* truncate to integer */
+{"xor", xor}, /* bitwise xor */
 {"XexchangeY", XexchangeY} /* HP-specific exchange X and Y registers */
 };

@@ -146,6 +164,14 @@ static void add(Widget w, XEvent *ev, String
*vector, Cardinal *count)
 }

 /*ARGSUSED*/
+static void and(Widget w, XEvent *ev, String *vector, Cardinal *count)
+{
+    XCALC_PRE_OP(kAND);
+    rpn ? twof(kAND) : twoop(kAND);
+    post_op();
+}
+
+/*ARGSUSED*/
 static void back(Widget w, XEvent *ev, String *vector, Cardinal *count)
 {
     XCALC_PRE_OP(kBKSP);
@@ -154,6 +180,14 @@ static void back(Widget w, XEvent *ev, String
*vector, Cardinal *count)
 }

 /*ARGSUSED*/
+static void base(Widget w, XEvent *ev, String *vector, Cardinal *count)
+{
+    XCALC_PRE_OP(kBASE);
+    change_base();
+    post_op();
+}
+
+/*ARGSUSED*/
 static void bell(Widget w, XEvent *ev, String *vector, Cardinal *count)
 {
     ringbell();
@@ -196,6 +230,7 @@ static void digit(Widget w, XEvent *ev, String
*vector, Cardinal *count)
 {
     switch (vector[0][0])
     {
+      case '0': XCALC_PRE_OP(kZERO); numeric(kZERO); break;
       case '1': XCALC_PRE_OP(kONE); numeric(kONE); break;
       case '2': XCALC_PRE_OP(kTWO); numeric(kTWO); break;
       case '3': XCALC_PRE_OP(kTHREE); numeric(kTHREE); break;
@@ -205,7 +240,12 @@ static void digit(Widget w, XEvent *ev, String
*vector, Cardinal *count)
       case '7': XCALC_PRE_OP(kSEVEN); numeric(kSEVEN); break;
       case '8': XCALC_PRE_OP(kEIGHT); numeric(kEIGHT); break;
       case '9': XCALC_PRE_OP(kNINE); numeric(kNINE); break;
-      case '0': XCALC_PRE_OP(kZERO); numeric(kZERO); break;
+      case 'A': XCALC_PRE_OP(kxA); numeric(kxA); break;
+      case 'B': XCALC_PRE_OP(kxB); numeric(kxB); break;
+      case 'C': XCALC_PRE_OP(kxC); numeric(kxC); break;
+      case 'D': XCALC_PRE_OP(kxD); numeric(kxD); break;
+      case 'E': XCALC_PRE_OP(kxE); numeric(kxE); break;
+      case 'F': XCALC_PRE_OP(kxF); numeric(kxF); break;
     }
     post_op();
 }
@@ -291,6 +331,14 @@ static void logarithm(Widget w, XEvent *ev,
String *vector, Cardinal *count)
 }

 /*ARGSUSED*/
+static void mod(Widget w, XEvent *ev, String *vector, Cardinal *count)
+{
+    XCALC_PRE_OP(kMOD);
+    rpn ? twof(kMOD) : twoop(kMOD);
+    post_op();
+}
+
+/*ARGSUSED*/
 static void multiply(Widget w, XEvent *ev, String *vector, Cardinal *count)
 {
     XCALC_PRE_OP(kMUL);
@@ -321,6 +369,14 @@ static void nop(Widget w, XEvent *ev, String
*vector, Cardinal *count)
 }

 /*ARGSUSED*/
+static void not(Widget w, XEvent *ev, String *vector, Cardinal *count)
+{
+    XCALC_PRE_OP(kNOT);
+    oneop(kNOT);
+    post_op();
+}
+
+/*ARGSUSED*/
 static void off(Widget w, XEvent *ev, String *vector, Cardinal *count)
 {
     XCALC_PRE_OP(kOFF);
@@ -329,6 +385,14 @@ static void off(Widget w, XEvent *ev, String
*vector, Cardinal *count)
 }

 /*ARGSUSED*/
+static void or(Widget w, XEvent *ev, String *vector, Cardinal *count)
+{
+    XCALC_PRE_OP(kOR);
+    rpn ? twof(kOR) : twoop(kOR);
+    post_op();
+}
+
+/*ARGSUSED*/
 static void pi(Widget w, XEvent *ev, String *vector, Cardinal *count)
 {
     XCALC_PRE_OP(kPI);
@@ -400,6 +464,22 @@ static void selection(Widget w, XEvent *ev,
String *vector, Cardinal *count)
 }

 /*ARGSUSED*/
+static void shl(Widget w, XEvent *ev, String *vector, Cardinal *count)
+{
+    XCALC_PRE_OP(kSHL);
+    rpn ? twof(kSHL) : twoop(kSHL);
+    post_op();
+}
+
+/*ARGSUSED*/
+static void shr(Widget w, XEvent *ev, String *vector, Cardinal *count)
+{
+    XCALC_PRE_OP(kSHR);
+    rpn ? twof(kSHR) : twoop(kSHR);
+    post_op();
+}
+
+/*ARGSUSED*/
 static void sine(Widget w, XEvent *ev, String *vector, Cardinal *count)
 {
     XCALC_PRE_OP(kSIN);
@@ -464,6 +544,22 @@ static void tenpower(Widget w, XEvent *ev, String
*vector, Cardinal *count)
 }

 /*ARGSUSED*/
+static void xtrunc(Widget w, XEvent *ev, String *vector, Cardinal *count)
+{
+    XCALC_PRE_OP(kTRUNC);
+    oneop(kTRUNC);
+    post_op();
+}
+
+/*ARGSUSED*/
+static void xor(Widget w, XEvent *ev, String *vector, Cardinal *count)
+{
+    XCALC_PRE_OP(kXOR);
+    rpn ? twof(kXOR) : twoop(kXOR);
+    post_op();
+}
+
+/*ARGSUSED*/
 static void XexchangeY(Widget w, XEvent *ev, String *vector, Cardinal *count)
 {
     XCALC_PRE_OP(kXXY);
diff --git a/app-defaults/XCalc b/app-defaults/XCalc
index 540df58..15843c2 100644
--- a/app-defaults/XCalc
+++ b/app-defaults/XCalc
@@ -42,6 +42,15 @@ XCalc*bevel.screen.P.label: ()
 XCalc*bevel.screen.P.fromHoriz: GRAD
 XCalc*bevel.screen.P.fromVert: LCD
 XCalc*bevel.screen.P.horizDistance: 2
+XCalc*bevel.screen.HEX.fromHoriz: P
+XCalc*bevel.screen.HEX.fromVert: LCD
+XCalc*bevel.screen.HEX.horizDistance: 1
+XCalc*bevel.screen.DEC.fromHoriz: P
+XCalc*bevel.screen.DEC.fromVert: LCD
+XCalc*bevel.screen.DEC.horizDistance: 1
+XCalc*bevel.screen.OCT.fromHoriz: P
+XCalc*bevel.screen.OCT.fromVert: LCD
+XCalc*bevel.screen.OCT.horizDistance: 1

 !XCalc*ti.Geometry: 171x252
 XCalc*ti.bevel.screen.LCD.width: 186
@@ -59,6 +68,12 @@ XCalc*ti.bevel.screen.LCD.translations: #replace\n\
  None<Key>7:digit(7)\n\
  None<Key>8:digit(8)\n\
  None<Key>9:digit(9)\n\
+ Shift<Key>a:digit(A)\n\
+ Shift<Key>b:digit(B)\n\
+ Shift<Key>c:digit(C)\n\
+ Shift<Key>d:digit(D)\n\
+ Shift<Key>e:digit(E)\n\
+ Shift<Key>f:digit(F)\n\
  <Key>KP_0:digit(0)\n\
  <Key>KP_1:digit(1)\n\
  <Key>KP_2:digit(2)\n\
@@ -71,6 +86,7 @@ XCalc*ti.bevel.screen.LCD.translations: #replace\n\
  <Key>KP_9:digit(9)\n\
  <Key>KP_Enter:equal()\n\
  <Key>KP_Equal:equal()\n\
+ <Key>Return:equal()\n\
  <Key>KP_Multiply:multiply()\n\
  <Key>KP_Add:add()\n\
  <Key>KP_Subtract:subtract()\n\
@@ -87,6 +103,13 @@ XCalc*ti.bevel.screen.LCD.translations: #replace\n\
  :<Key>(:leftParen()\n\
  :<Key>):rightParen()\n\
  :<Key>!:factorial()\n\
+ :<Key>|:or()\n\
+ :<Key>&:and()\n\
+ :<Key><:shl()\n\
+ :<Key>>:shr()\n\
+ :<Key>~:not()\n\
+ :<Key>%:mod()\n\
+ <Key>x:xor()\n\
  <Key>e:e()\n\
  :<Key>^:power()\n\
  <Key>p:pi()\n\
@@ -140,62 +163,95 @@ XCalc*ti.button14.translations:
#override<Btn1Down>,<Btn1Up>:naturalLog()unset()
 XCalc*ti.button15.label: y^x
 XCalc*ti.button15.translations: #override<Btn1Down>,<Btn1Up>:power()unset()

-XCalc*ti.button16.font: -adobe-symbol-*-*-*-*-*-120-*-*-*-*-*-*
-XCalc*ti.button16.label: \160
-XCalc*ti.button16.translations: #override<Btn1Down>,<Btn1Up>:pi()unset()
-XCalc*ti.button17.label: x!
-XCalc*ti.button17.translations: #override<Btn1Down>,<Btn1Up>:factorial()unset()
-XCalc*ti.button18.label: (
-XCalc*ti.button18.translations: #override<Btn1Down>,<Btn1Up>:leftParen()unset()
-XCalc*ti.button19.label: )
-XCalc*ti.button19.translations:
#override<Btn1Down>,<Btn1Up>:rightParen()unset()
-XCalc*ti.button20.font: -adobe-symbol-*-*-*-*-*-120-*-*-*-*-*-*
-XCalc*ti.button20.label: \270
-XCalc*ti.button20.translations: #override<Btn1Down>,<Btn1Up>:divide()unset()
-
-XCalc*ti.button21.label: STO
-XCalc*ti.button21.translations: #override<Btn1Down>,<Btn1Up>:store()unset()
-XCalc*ti.button22.label: 7
-XCalc*ti.button22.translations: #override<Btn1Down>,<Btn1Up>:digit(7)unset()
-XCalc*ti.button23.label: 8
-XCalc*ti.button23.translations: #override<Btn1Down>,<Btn1Up>:digit(8)unset()
-XCalc*ti.button24.label: 9
-XCalc*ti.button24.translations: #override<Btn1Down>,<Btn1Up>:digit(9)unset()
-XCalc*ti.button25.label: *
-XCalc*ti.button25.translations: #override<Btn1Down>,<Btn1Up>:multiply()unset()
-
-XCalc*ti.button26.label: RCL
-XCalc*ti.button26.translations: #override<Btn1Down>,<Btn1Up>:recall()unset()
-XCalc*ti.button27.label: 4
-XCalc*ti.button27.translations: #override<Btn1Down>,<Btn1Up>:digit(4)unset()
-XCalc*ti.button28.label: 5
-XCalc*ti.button28.translations: #override<Btn1Down>,<Btn1Up>:digit(5)unset()
-XCalc*ti.button29.label: 6
-XCalc*ti.button29.translations: #override<Btn1Down>,<Btn1Up>:digit(6)unset()
-XCalc*ti.button30.label: -
-XCalc*ti.button30.translations: #override<Btn1Down>,<Btn1Up>:subtract()unset()
-
-XCalc*ti.button31.label: SUM
-XCalc*ti.button31.translations: #override<Btn1Down>,<Btn1Up>:sum()unset()
-XCalc*ti.button32.label: 1
-XCalc*ti.button32.translations: #override<Btn1Down>,<Btn1Up>:digit(1)unset()
-XCalc*ti.button33.label: 2
-XCalc*ti.button33.translations: #override<Btn1Down>,<Btn1Up>:digit(2)unset()
-XCalc*ti.button34.label: 3
-XCalc*ti.button34.translations: #override<Btn1Down>,<Btn1Up>:digit(3)unset()
-XCalc*ti.button35.label: +
-XCalc*ti.button35.translations: #override<Btn1Down>,<Btn1Up>:add()unset()
-
-XCalc*ti.button36.label: EXC
-XCalc*ti.button36.translations: #override<Btn1Down>,<Btn1Up>:exchange()unset()
-XCalc*ti.button37.label: 0
-XCalc*ti.button37.translations: #override<Btn1Down>,<Btn1Up>:digit(0)unset()
-XCalc*ti.button38.label: .
-XCalc*ti.button38.translations: #override<Btn1Down>,<Btn1Up>:decimal()unset()
-XCalc*ti.button39.label: +/-
-XCalc*ti.button39.translations: #override<Btn1Down>,<Btn1Up>:negate()unset()
-XCalc*ti.button40.label: =
-XCalc*ti.button40.translations: #override<Btn1Down>,<Btn1Up>:equal()unset()
+XCalc*ti.button16.label: not
+XCalc*ti.button16.translations: #override<Btn1Down>,<Btn1Up>:not()unset()
+XCalc*ti.button17.label: and
+XCalc*ti.button17.translations: #override<Btn1Down>,<Btn1Up>:and()unset()
+XCalc*ti.button18.label: or
+XCalc*ti.button18.translations: #override<Btn1Down>,<Btn1Up>:or()unset()
+XCalc*ti.button19.label: xor
+XCalc*ti.button19.translations: #override<Btn1Down>,<Btn1Up>:xor()unset()
+XCalc*ti.button20.label: trunc
+XCalc*ti.button20.translations: #override<Btn1Down>,<Btn1Up>:trunc()unset()
+
+XCalc*ti.button21.font: -adobe-symbol-*-*-*-*-*-120-*-*-*-*-*-*
+XCalc*ti.button21.label: \160
+XCalc*ti.button21.translations: #override<Btn1Down>,<Btn1Up>:pi()unset()
+XCalc*ti.button22.label: x!
+XCalc*ti.button22.translations: #override<Btn1Down>,<Btn1Up>:factorial()unset()
+XCalc*ti.button23.label: (
+XCalc*ti.button23.translations: #override<Btn1Down>,<Btn1Up>:leftParen()unset()
+XCalc*ti.button24.label: )
+XCalc*ti.button24.translations:
#override<Btn1Down>,<Btn1Up>:rightParen()unset()
+XCalc*ti.button25.label: base
+XCalc*ti.button25.translations: #override<Btn1Down>,<Btn1Up>:base()unset()
+
+XCalc*ti.button26.label: shl
+XCalc*ti.button26.translations: #override<Btn1Down>,<Btn1Up>:shl()unset()
+XCalc*ti.button27.label: D
+XCalc*ti.button27.translations: #override<Btn1Down>,<Btn1Up>:digit(D)unset()
+XCalc*ti.button28.label: E
+XCalc*ti.button28.translations: #override<Btn1Down>,<Btn1Up>:digit(E)unset()
+XCalc*ti.button29.label: F
+XCalc*ti.button29.translations: #override<Btn1Down>,<Btn1Up>:digit(F)unset()
+XCalc*ti.button30.label: shr
+XCalc*ti.button30.translations: #override<Btn1Down>,<Btn1Up>:shr()unset()
+
+XCalc*ti.button31.label: mod
+XCalc*ti.button31.translations: #override<Btn1Down>,<Btn1Up>:mod()unset()
+XCalc*ti.button32.label: A
+XCalc*ti.button32.translations: #override<Btn1Down>,<Btn1Up>:digit(A)unset()
+XCalc*ti.button33.label: B
+XCalc*ti.button33.translations: #override<Btn1Down>,<Btn1Up>:digit(B)unset()
+XCalc*ti.button34.label: C
+XCalc*ti.button34.translations: #override<Btn1Down>,<Btn1Up>:digit(C)unset()
+XCalc*ti.button35.font: -adobe-symbol-*-*-*-*-*-120-*-*-*-*-*-*
+XCalc*ti.button35.label: \270
+XCalc*ti.button35.translations: #override<Btn1Down>,<Btn1Up>:divide()unset()
+
+XCalc*ti.button36.label: STO
+XCalc*ti.button36.translations: #override<Btn1Down>,<Btn1Up>:store()unset()
+XCalc*ti.button37.label: 7
+XCalc*ti.button37.translations: #override<Btn1Down>,<Btn1Up>:digit(7)unset()
+XCalc*ti.button38.label: 8
+XCalc*ti.button38.translations: #override<Btn1Down>,<Btn1Up>:digit(8)unset()
+XCalc*ti.button39.label: 9
+XCalc*ti.button39.translations: #override<Btn1Down>,<Btn1Up>:digit(9)unset()
+XCalc*ti.button40.label: *
+XCalc*ti.button40.translations: #override<Btn1Down>,<Btn1Up>:multiply()unset()
+
+XCalc*ti.button41.label: RCL
+XCalc*ti.button41.translations: #override<Btn1Down>,<Btn1Up>:recall()unset()
+XCalc*ti.button42.label: 4
+XCalc*ti.button42.translations: #override<Btn1Down>,<Btn1Up>:digit(4)unset()
+XCalc*ti.button43.label: 5
+XCalc*ti.button43.translations: #override<Btn1Down>,<Btn1Up>:digit(5)unset()
+XCalc*ti.button44.label: 6
+XCalc*ti.button44.translations: #override<Btn1Down>,<Btn1Up>:digit(6)unset()
+XCalc*ti.button45.label: -
+XCalc*ti.button45.translations: #override<Btn1Down>,<Btn1Up>:subtract()unset()
+
+XCalc*ti.button46.label: SUM
+XCalc*ti.button46.translations: #override<Btn1Down>,<Btn1Up>:sum()unset()
+XCalc*ti.button47.label: 1
+XCalc*ti.button47.translations: #override<Btn1Down>,<Btn1Up>:digit(1)unset()
+XCalc*ti.button48.label: 2
+XCalc*ti.button48.translations: #override<Btn1Down>,<Btn1Up>:digit(2)unset()
+XCalc*ti.button49.label: 3
+XCalc*ti.button49.translations: #override<Btn1Down>,<Btn1Up>:digit(3)unset()
+XCalc*ti.button50.label: +
+XCalc*ti.button50.translations: #override<Btn1Down>,<Btn1Up>:add()unset()
+
+XCalc*ti.button51.label: EXC
+XCalc*ti.button51.translations: #override<Btn1Down>,<Btn1Up>:exchange()unset()
+XCalc*ti.button52.label: 0
+XCalc*ti.button52.translations: #override<Btn1Down>,<Btn1Up>:digit(0)unset()
+XCalc*ti.button53.label: .
+XCalc*ti.button53.translations: #override<Btn1Down>,<Btn1Up>:decimal()unset()
+XCalc*ti.button54.label: +/-
+XCalc*ti.button54.translations: #override<Btn1Down>,<Btn1Up>:negate()unset()
+XCalc*ti.button55.label: =
+XCalc*ti.button55.translations: #override<Btn1Down>,<Btn1Up>:equal()unset()

 XCalc*ti.button1.horizDistance: 4
 XCalc*ti.button1.vertDistance: 12
@@ -290,6 +346,39 @@ XCalc*ti.button39.fromVert: button34
 XCalc*ti.button40.fromHoriz: button39
 XCalc*ti.button40.fromVert: button35

+XCalc*ti.button41.horizDistance: 4
+XCalc*ti.button41.fromVert: button36
+XCalc*ti.button42.fromHoriz: button41
+XCalc*ti.button42.fromVert: button37
+XCalc*ti.button43.fromHoriz: button42
+XCalc*ti.button43.fromVert: button38
+XCalc*ti.button44.fromHoriz: button43
+XCalc*ti.button44.fromVert: button39
+XCalc*ti.button45.fromHoriz: button44
+XCalc*ti.button45.fromVert: button40
+
+XCalc*ti.button46.horizDistance: 4
+XCalc*ti.button46.fromVert: button41
+XCalc*ti.button47.fromHoriz: button46
+XCalc*ti.button47.fromVert: button42
+XCalc*ti.button48.fromHoriz: button47
+XCalc*ti.button48.fromVert: button43
+XCalc*ti.button49.fromHoriz: button48
+XCalc*ti.button49.fromVert: button44
+XCalc*ti.button50.fromHoriz: button49
+XCalc*ti.button50.fromVert: button45
+
+XCalc*ti.button51.horizDistance: 4
+XCalc*ti.button51.fromVert: button46
+XCalc*ti.button52.fromHoriz: button51
+XCalc*ti.button52.fromVert: button47
+XCalc*ti.button53.fromHoriz: button52
+XCalc*ti.button53.fromVert: button48
+XCalc*ti.button54.fromHoriz: button53
+XCalc*ti.button54.fromVert: button49
+XCalc*ti.button55.fromHoriz: button54
+XCalc*ti.button55.fromVert: button50
+

 !XCalc*hp.Geometry: 336x164
 XCalc*hp.bevel.screen.LCD.width: 186
@@ -394,6 +483,7 @@ XCalc*hp.button19.translations:
#override<Btn1Down>,<Btn1Up>:digit(6)unset()
 XCalc*hp.button20.label: *
 XCalc*hp.button20.translations: #override<Btn1Down>,<Btn1Up>:multiply()unset()

+
 XCalc*hp.button21.mappedWhenManaged: False
 XCalc*hp.button22.mappedWhenManaged: False
 XCalc*hp.button23.label: Rv
diff --git a/math.c b/math.c
index aff9c6e..4e941c0 100644
--- a/math.c
+++ b/math.c
@@ -43,7 +43,7 @@ jmp_buf env;
  * functions.  Much of it is shared between the infix and rpn modes.
  */

-static int flagINV, flagPAREN, flagM, drgmode; /* display flags */
+static int flagINV, flagPAREN, flagM, drgmode, numbase; /* display flags */

 static double drg2rad=M_PI/180.0;  /* Conversion factors for trig funcs */
 static double rad2drg=180.0/M_PI;
@@ -89,22 +89,57 @@ strlcpy(char *dst, const char *src, size_t size)
 }
 #endif

+/* C89-compatible trunc() */
+#ifndef trunc
+#define trunc(x) (x > 0) ? floor(x) : ceil(x)
+#endif
+
 /*
  * The following is to deal with the unfortunate assumption that if errno
  * is non-zero then an error has occurred.  On some systems (e.g. Ultrix),
  * sscanf will call lower level routines that will set errno.
  */
-
 static void
-parse_double (const char *src, const char *fmt, double *dp)
+parse_double(double *dp)
 {
+    unsigned long int n = 0;
     int olderrno = errno;

-    (void) sscanf (src, fmt, dp);
+    switch (numbase) {
+    case 8:
+        (void)sscanf(dispstr, "%lo", &n);
+        *dp = (double)n;
+    break;
+    case 16:
+        (void)sscanf(dispstr, "%lX", &n);
+        *dp = (double)n;
+    break;
+    default:
+        (void)sscanf(dispstr, "%lf", dp);
+    }
+
     errno = olderrno;
     return;
 }

+/**
+ * Format the given double according to the
+ * selected number base.
+ */
+static void
+format_double(double n)
+{
+    switch (numbase) {
+    case 8:
+        snprintf(dispstr, sizeof(dispstr), "%lo", (long)n);
+    break;
+    case 16:
+        snprintf(dispstr, sizeof(dispstr), "%lX", (long)n);
+    break;
+    default:
+        snprintf(dispstr, sizeof(dispstr), "%.8g", n);
+    }
+}

 /*********************************/
 int pre_op(int keynum)
@@ -181,11 +216,12 @@ void post_op(void)
         }
 #endif
 }
+
 /*-------------------------------------------------------------------------*/
 static void
 DrawDisplay(void)
 {
-    if (strlen(dispstr) > 12) {           /* strip out some decimal digits */
+    if (strlen(dispstr) >= MAXDISP) { /* strip out some decimal digits */
         char *estr = index(dispstr,'e');  /* search for exponent part */
         if (!estr) dispstr[12]='\0';      /* no exp, just trunc. */
         else {
@@ -204,6 +240,23 @@ DrawDisplay(void)
     setflag(XCalc_RADIAN, (drgmode==RAD));
     setflag(XCalc_GRADAM, (drgmode==GRAD));
     setflag(XCalc_PAREN, (flagPAREN));
+    setflag(XCalc_HEX, (numbase==16));
+    setflag(XCalc_DEC, (numbase==10));
+    setflag(XCalc_OCT, (numbase==8));
+}
+
+/*-------------------------------------------------------------------------*/
+void
+change_base(void)
+{
+ parse_double(&dnum);
+    switch (numbase) {
+        case 8:  numbase = 10;  break;
+        case 10: numbase = 16;  break;
+        case 16: numbase = 8; break;
+    }
+    format_double(dnum);
+    DrawDisplay();
 }

 /*-------------------------------------------------------------------------*/
@@ -238,7 +291,7 @@ numeric(int keynum)
       case kRCL:
  PushNum(dnum);
  dnum = mem[cell];
- snprintf(dispstr, sizeof(dispstr), "%.8g", dnum);
+ format_double(dnum);
  lift_enabled = 1;
         entered = 1;
  clrdisp++;
@@ -267,7 +320,9 @@ numeric(int keynum)
   if ((int) strlen(dispstr) >= MAXDISP)
     return;

+ st[0] = '\0';
     switch (keynum){
+      case kZERO: st[0] = '0'; break;
       case kONE: st[0] = '1'; break;
       case kTWO: st[0] = '2'; break;
       case kTHREE: st[0] = '3'; break;
@@ -275,10 +330,18 @@ numeric(int keynum)
       case kFIVE: st[0] = '5'; break;
       case kSIX: st[0] = '6'; break;
       case kSEVEN: st[0] = '7'; break;
-      case kEIGHT: st[0] = '8'; break;
-      case kNINE: st[0] = '9'; break;
-      case kZERO: st[0] = '0'; break;
+      case kEIGHT: if (numbase > 8)  st[0] = '8'; break;
+      case kNINE: if (numbase > 8)  st[0] = '9'; break;
+      case kxA: if (numbase > 10) st[0] = 'A'; break;
+      case kxB: if (numbase > 10) st[0] = 'B'; break;
+      case kxC: if (numbase > 10) st[0] = 'C'; break;
+      case kxD: if (numbase > 10) st[0] = 'D'; break;
+      case kxE: if (numbase > 10) st[0] = 'E'; break;
+      case kxF: if (numbase > 10) st[0] = 'F'; break;
     }
+
+    if (st[0] == '\0')
+        return;
     st[1] = '\0';
     strcat(dispstr,st);

@@ -432,7 +495,7 @@ twoop(int keynum)
   }

   if (entered==1)
-    parse_double(dispstr,"%lf",&dnum);
+    parse_double(&dnum);

   clrdisp=CLR=1;
   entered=Dpoint=exponent=0;
@@ -450,7 +513,7 @@ twoop(int keynum)
     /* now, if the current op (keynum) is of
        higher priority than the lastop, the current
        op and number are just pushed on top
-       Priorities:  (Y^X) > *,/ > +,- */
+       Priorities:  (Y^X) > *,/ > +,- > >>,<< > & > ^ > ~ */

     if (priority(keynum) > priority(lastop)) {
       PushNum(dnum);
@@ -465,10 +528,17 @@ twoop(int keynum)
       case kMUL: acc *= dnum;  break;
       case kDIV: acc /= dnum;  break;
       case kPOW: acc =  pow(acc,dnum);  break;
- }
+      case kMOD: acc = (long)acc %  (long)dnum;  break;
+      case kAND: acc = (long)acc &  (long)dnum;  break;
+      case kOR:  acc = (long)acc |  (long)dnum;  break;
+      case kXOR: acc = (long)acc ^  (long)dnum;  break;
+      case kSHL: acc = (long)acc << (long)dnum;  break;
+      case kSHR: acc = (long)acc >> (long)dnum;  break;
+      }
+
       PushNum(acc);
       PushOp(keynum);
-      snprintf(dispstr, sizeof(dispstr), "%.8g", acc);
+      format_double(acc);
       DrawDisplay();
       dnum=acc;
     }
@@ -490,7 +560,7 @@ twof(int keynum)
   if (!entered)
     return;
   if (entered==1)
-    parse_double(dispstr, "%lf", &dnum);
+    parse_double(&dnum);
   acc = PopNum();
   switch(keynum) {
   case kADD: acc += dnum;  break;
@@ -498,9 +568,16 @@ twof(int keynum)
   case kMUL: acc *= dnum;  break;
   case kDIV: acc /= dnum;  break;
   case kPOW: acc =  pow(acc,dnum);  break;
-  case kXXY: PushNum(dnum);
+  case kXXY: PushNum(dnum);  break;
+  case kMOD: acc = (long)acc %  (long)dnum;  break;
+  case kAND: acc = (long)acc &  (long)dnum;  break;
+  case kOR:  acc = (long)acc |  (long)dnum;  break;
+  case kXOR: acc = (long)acc ^  (long)dnum;  break;
+  case kSHL: acc = (long)acc << (long)dnum;  break;
+  case kSHR: acc = (long)acc >> (long)dnum;  break;
   }
-  snprintf(dispstr, sizeof(dispstr), "%.8g", acc);
+
+  format_double(acc);
   DrawDisplay();
   clrdisp++;
   Dpoint = exponent = 0;
@@ -520,7 +597,7 @@ entrf(void)
   Dpoint=exponent=0;

   if (entered==1)
-    parse_double(dispstr,"%lf",&dnum);
+    parse_double(&dnum);
   entered=2;
   memop = kENTR;
   PushNum(dnum);
@@ -538,7 +615,7 @@ equf(void)
   Dpoint=exponent=0;

   if (entered==1)
-    parse_double(dispstr,"%lf",&dnum);
+    parse_double(&dnum);
   entered=2;

   PushNum(dnum);
@@ -561,12 +638,24 @@ equf(void)
     case kLPAR: flagPAREN--;
  PushNum(acc);
  break;
+    case kMOD:  acc = (long)acc % (long)dnum;
+ break;
+    case kAND:  acc = (long)acc & (long)dnum;
+ break;
+    case kOR:   acc = (long)acc | (long)dnum;
+ break;
+    case kXOR:  acc = (long)acc ^ (long)dnum;
+ break;
+    case kSHL:  acc = (long)acc << (long)dnum;
+ break;
+    case kSHR:  acc = (long)acc >> (long)dnum;
+ break;
     }
     dnum=acc;
     PushNum(dnum);
   }

-  snprintf(dispstr, sizeof(dispstr), "%.8g", dnum);
+  format_double(dnum);
   DrawDisplay();
 }

@@ -585,13 +674,13 @@ rollf(void)
   if (!entered)
     return;
   if (entered==1)
-    parse_double(dispstr, "%lf", &dnum);
+    parse_double(&dnum);
   entered = 2;
   lift_enabled = 1;
   RollNum(flagINV);
   flagINV=0;
   clrdisp++;
-  snprintf(dispstr, sizeof(dispstr), "%.8g", dnum);
+  format_double(dnum);
   DrawDisplay();
 }

@@ -609,7 +698,7 @@ rparf(void)
   Dpoint=exponent=0;

   if (entered==1)
-    parse_double(dispstr,"%lf",&dnum);
+    parse_double(&dnum);
   entered=2;

   PushNum(dnum);
@@ -628,6 +717,18 @@ rparf(void)
  break;
     case kPOW:  acc = pow(acc,dnum);
  break;
+    case kMOD:  acc = (long)acc % (long)dnum;
+ break;
+    case kAND:  acc = (long)acc & (long)dnum;
+ break;
+    case kOR:   acc = (long)acc | (long)dnum;
+ break;
+    case kXOR:  acc = (long)acc ^ (long)dnum;
+ break;
+    case kSHL:  acc = (long)acc << (long)dnum;
+ break;
+    case kSHR:  acc = (long)acc >> (long)dnum;
+ break;
     }
     dnum=acc;
     PushNum(dnum);
@@ -635,7 +736,7 @@ rparf(void)
   (void) PopNum();
   flagPAREN--;
   entered=2;
-  snprintf(dispstr, sizeof(dispstr), "%.8g", dnum);
+  format_double(dnum);
   DrawDisplay();
 }

@@ -644,7 +745,7 @@ drgf(void)
 {
   if (flagINV) {
     if (entered==1)
-      parse_double(dispstr,"%lf",&dnum);
+      parse_double(&dnum);
     switch (drgmode) {
     case DEG:  dnum=dnum*M_PI/180.0;    break;
     case RAD:  dnum=dnum*200.0/M_PI;    break;
@@ -653,7 +754,7 @@ drgf(void)
     entered=2;
     clrdisp=1;
     flagINV=0;
-    snprintf(dispstr, sizeof(dispstr), "%.8g", dnum);
+    format_double(dnum);
   }

   flagINV=0;
@@ -684,7 +785,7 @@ memf(int keynum)
 {
     memop = keynum;
     if (entered==1)
-      parse_double(dispstr,"%lf",&dnum);
+      parse_double(&dnum);
     entered = 2;
     clrdisp++;
     lift_enabled = 0;
@@ -697,7 +798,7 @@ oneop(int keynum)
   double dtmp;

   if (entered==1)
-    parse_double(dispstr,"%lf",&dnum);
+    parse_double(&dnum);
   entered = 2;

   switch (keynum) {  /* do the actual math fn. */
@@ -740,6 +841,8 @@ oneop(int keynum)
        for (j=1,dnum=1.0; j<=i; j++)
  dnum*=(float) j;
        break;
+  case kNOT:   dnum = ~(long)dnum;  break;
+  case kTRUNC: dnum = trunc(dnum);  break;
   }

   if (entered==3) {  /* error */
@@ -752,7 +855,7 @@ oneop(int keynum)
   clrdisp=1;
   flagINV=0;
   lift_enabled = 1;
-  snprintf(dispstr, sizeof(dispstr), "%.8g", dnum);
+  format_double(dnum);
   DrawDisplay();
 }

@@ -899,12 +1002,18 @@ priority(int op)
 /*******/
 {
     switch (op) {
-        case kPOW: return(2);
+        case kPOW: return(6);
         case kMUL:
-        case kDIV: return(1);
+        case kDIV:
+        case kMOD: return(5);
         case kADD:
-        case kSUB: return(0);
-        }
+        case kSUB: return(4);
+        case kSHL:
+        case kSHR: return(3);
+        case kAND: return(2);
+        case kXOR: return(1);
+        case kOR:  return(0);
+    }
     return 0;
 }

@@ -915,12 +1024,16 @@ ResetCalc(void)
 /********/
 {
     flagM=flagINV=flagPAREN=0;  drgmode=DEG;
+    numbase=(!numbase ? 10 : numbase);
     setflag(XCalc_MEMORY, False);
     setflag(XCalc_INVERSE, False);
     setflag(XCalc_PAREN, False);
     setflag(XCalc_RADIAN, False);
     setflag(XCalc_GRADAM, False);
     setflag(XCalc_DEGREE, True);
+    setflag(XCalc_HEX, False);
+    setflag(XCalc_DEC, True);
+    setflag(XCalc_OCT, False);
     strlcpy(dispstr, "0", sizeof(dispstr));
     draw(dispstr);
     ClearStacks();
diff --git a/xcalc.c b/xcalc.c
index bc262b6..af39d77 100644
--- a/xcalc.c
+++ b/xcalc.c
@@ -74,7 +74,7 @@ static Display *dpy = NULL; /* connection to the X server */
 static Widget toplevel=NULL;   /* top level shell widget */
 static Widget   calculator=NULL; /* an underlying form widget */
 static Widget LCD = NULL; /* liquid crystal display */
-static Widget ind[6]; /* mode indicators in the screen */
+static Widget ind[9]; /* mode indicators in the screen */
 static char selstr[LCD_STR_LEN]; /* storage for selections from the LCD */
  /* checkerboard used in mono mode */
 static XtAppContext xtcontext; /* Toolkit application context */
@@ -221,6 +221,18 @@ static void create_display(Widget parent)
     /* () - the parenthesis indicator */
     ind[XCalc_PAREN] = XtCreateManagedWidget("P", labelWidgetClass, screen,
      args, XtNumber(args));
+
+    /* HEX - the hexadecimal (base 16) indicator */
+    ind[XCalc_HEX] = XtCreateManagedWidget("HEX", labelWidgetClass, screen,
+     args, XtNumber(args));
+
+    /* DEC - the hexadecimal (base 16) indicator */
+    ind[XCalc_DEC] = XtCreateManagedWidget("DEC", labelWidgetClass, screen,
+     args, XtNumber(args));
+
+    /* OCT - the octal (base 8) indicator */
+    ind[XCalc_OCT] = XtCreateManagedWidget("OCT", labelWidgetClass, screen,
+     args, XtNumber(args));
 }

 /*
@@ -240,7 +252,10 @@ static void create_keypad(Widget parent)
  "button21","button22","button23","button24","button25",
  "button26","button27","button28","button29","button30",
  "button31","button32","button33","button34","button35",
- "button36","button37","button38","button39","button40"
+ "button36","button37","button38","button39","button40",
+ "button41","button42","button43","button44","button45",
+ "button46","button47","button48","button49","button50",
+ "button51","button52","button53","button54","button55",
  };
     register int i;
     int n = XtNumber(Keyboard);
diff --git a/xcalc.h b/xcalc.h
index 1492a01..3772ad5 100644
--- a/xcalc.h
+++ b/xcalc.h
@@ -102,6 +102,21 @@ from the X Consortium.
 #define kROLL  44 /* roll stack */
 #define kNOP   45 /* no operation */
 #define kBKSP  46 /* backspace */
+#define kAND   47 /* bitwise and */
+#define kBASE  48 /* base conversion */
+#define kMOD   49 /* modulus */
+#define kNOT   50 /* bitwise not (ones compliment) */
+#define kOR    51 /* bitwise or */
+#define kSHL   52 /* arithmetic shift left */
+#define kSHR   53 /* arithmetic shift right */
+#define kXOR   54 /* bitwise xor */
+#define kTRUNC 55 /* truncate to integer */
+#define kxA    56 /* 0xa */
+#define kxB    57 /* 0xb */
+#define kxC    58 /* 0xc */
+#define kxD    59 /* 0xd */
+#define kxE    60 /* 0xe */
+#define kxF    61 /* 0xf */

 #define XCalc_MEMORY 0 /* memory indicator */
 #define XCalc_INVERSE   1 /* inverse function indicator */
@@ -109,6 +124,9 @@ from the X Consortium.
 #define XCalc_RADIAN 3 /* radian indicator */
 #define XCalc_GRADAM 4 /* grad indicator */
 #define XCalc_PAREN 5 /* parenthesis indicator */
+#define XCalc_HEX 6 /* hexadecimal (base 16) indicator */
+#define XCalc_DEC 7 /* decimal (base 10) indicator */
+#define XCalc_OCT 8 /* octal (base 8) indicator */

 /* actions.c */
 extern XtActionsRec Actions[];
@@ -121,6 +139,7 @@ extern void fail_op(void);
 extern int pre_op(int keynum);
 extern void post_op(void);

+extern void change_base(void);
 extern void numeric(int keynum);
 extern void bkspf(void);
 extern void decf(void);
-- 
1.8.3.2


More information about the xorg-devel mailing list