Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate
Photo

Reverse Polish Notation (RPN) calculator (very basic)


  • Please log in to reply
1 reply to this topic
SoLong&Thx4AllTheFish
  • Members
  • 4999 posts
  • Last active:
  • Joined: 27 May 2007
Thanks to Infogulch's SimpleArray it was quite easy to
make this Reverse Polish Notation (RPN) calculator. There are some good freeware RPN
calculators or HP emulators available on the internet but I like the
simplicity of this.
; RPN calculator - proof of concept (HugoV)
; Very basic RPN calculator using SimpleArray v3 by Infogulch
; see http://www.autohotkey.com/forum/viewtopic.php?p=216134#216134
; More about RPN http://en.wikipedia.org/wiki/Reverse_Polish_notation
; can only add/substract/divide/multiply
; If there is only one item on the stack that value will be used as "second" stack item
; so typing 5 Numpad+ will place 10 on the stack 5 Numpad* 25 etc
; example, to add 4 + 7 type:
; 4 ENTER 7 [ENTER] Numpad+ (no need for the second enter but is optional)

#NoEnv ; Recommended for performance and compatibility with future AutoHotkey releases.
SendMode Input ; Recommended for new scripts due to its superior speed and reliability.
SetBatchLines, -1

help=
(
RPN HOTKEYS:

(Numpad)Enter:	add value to stack or duplicate last stack item if empty
Numpad+		add
Numpad-		substract
Numpad*		multiply
Numpad/		divide
^Numpad/	Inverse value (5 -> 0.2, 0.2 -> 5)
^Numpad-	toggle +/- value (5 becomes -5 or -5 becomes 5)
^Numpad+	toggle +/- value (5 becomes -5 or -5 becomes 5)
^DEL, ^BS or 
  ^NumpadDot(.)	remove last item from stack
Del		backspace in Edit
^Up/^Down	swap last stack items
UP/DOWN+Enter	Select item from stack with up/down keys, pressing enter moves item to last position in stack
^c		copy last item from stack to clipboard (usualy the answer of your calculation)
^e		edit last stack
^s		save stack.txt
^l		load stack.txt

LIB: SimpleArray v3 by Infogulch
http://www.autohotkey.com/forum/viewtopic.php?p=216134#216134
)


Gui, Add, Listbox, x5 y5 w195 h120,
Gui, Add, Edit, +Right x5 yp+115 w195 h25 vEntry,
Gui, Add, Text, x5 yp+30 w195 h20 vSize, Stack size: 0
Gui, Show, w205 h170, RPN
ControlFocus, Edit1, RPN
Return

#IfWinActive RPN
Enter::
NumpadEnter::
Gui, Submit, NoHide
If (Entry = "")
Entry:=SA_Get(Stack, -1)
; here we check if the focus is on the listbox to see if we need to move it
SendMessage, 0x188, 0, 0, ListBox1, RPN ; 0x188 is LB_GETCURSEL (for a ListBox).
ChoicePos = %ErrorLevel% ; It will be -1 if there is no item selected.
ChoicePos += 1 ; Convert from 0-based to 1-based, i.e. so that the first item is known as 1, not 0.
If (ChoicePos = 4294967296) ; focus is not on listbox1
ChoicePos=0
If (ChoicePos > 0) ; focus was is on listbox1, move selected item to bottom of stack
{
Entry:=SA_Get(Stack, ChoicePos)
Stack:=SA_Del(Stack, ChoicePos)
}
Stack:=SA_Set(Stack, Entry)
Entry=
Gosub, UpdateGui
Return

NumpadAdd::
Gui, Submit, Nohide
If (Entry <> "")
	Stack:=SA_Set(Stack, Entry)
UpdateStack(2,SA_Get(Stack, -2) + SA_Get(Stack, -1))
Gosub, UpdateGui
Return

^NumpadDiv::
Gui, Submit, Nohide
If (Entry <> "")
	Stack:=SA_Set(Stack, Entry)
UpdateStack(1,1 / SA_Get(Stack, -1))
Gosub, UpdateGui
Return

NumpadDiv::
Gui, Submit, Nohide
If (Entry <> "")
Stack:=SA_Set(Stack, Entry)
UpdateStack(2,SA_Get(Stack, -2) / SA_Get(Stack, -1))
Gosub, UpdateGui
Return

^NumpadSub::
^NumpadAdd::
Gui, Submit, Nohide
If (Entry <> "")
	Stack:=SA_Set(Stack, Entry)
UpdateStack(1,SA_Get(Stack, -1) * -1)
Gosub, UpdateGui
Return

NumpadSub::
Gui, Submit, Nohide
If (Entry <> "")
	Stack:=SA_Set(Stack, Entry)
UpdateStack(2,SA_Get(Stack, -2) - SA_Get(Stack, -1))
Gosub, UpdateGui
Return

NumpadMult::
Gui, Submit, Nohide
If (Entry <> "")
	Stack:=SA_Set(Stack, Entry)
UpdateStack(2,SA_Get(Stack, -2) * SA_Get(Stack, -1))
Gosub, UpdateGui
Return

^c::
Clipboard:=SA_Get(Stack, -1)
Return

^e::
Store:=SA_Get(Stack, -1)
Stack:=SA_Del(Stack, -1)
Gosub, UpdateGui
GuiControl, , Edit1, %store%
ControlFocus, Edit1, RPN
ControlSend, Edit1, {end}, RPN
Store=
Return

^s::
FileDelete, %A_ScriptDir%\stack.txt
FileAppend, %Stack%, %A_ScriptDir%\stack.txt
Return

^l::
FileRead, Stack, %A_ScriptDir%\stack.txt
Gosub, UpdateGui
Return

Down::
ControlSend, ListBox1, {Down}, RPN
ControlFocus, ListBox, RPN
Return

Up::
ControlSend, ListBox1, {Up}, RPN
ControlFocus, ListBox, RPN
Return

Del::Send {BS}

^Del::
^BS::
^NumpadDot::
Stack:=SA_Del(Stack, -1)
Gosub, UpdateGui
Return

^Down::
^Up::
Gui, Submit, Nohide
If (Entry <> "")
	Stack:=SA_Set(Stack, Entry)
Entry:=SA_Get(Stack, -1)
Stack:=SA_Del(Stack, -1)
Store:=SA_Get(Stack, -1)
Stack:=SA_Del(Stack, -1)
Stack:=SA_Set(Stack, Entry)
Stack:=SA_Set(Stack, Store)
Store=
Gosub, UpdateGui
Return

F1::
MsgBox % Help
Return

#IfWinActive

UpdateStack(Entries, Answer) {
Global Stack
Loop, % Entries
	Stack:=SA_Del(Stack, -1)
Stack:=SA_Set(Stack, Answer)
Return
}

UpdateGui:
Size:=SA_Len(Stack)
GuiControl,, Size, Stack size: %Size%
StringReplace, StackList, Stack, , |, All
GuiControl, , Listbox1, |%StackList%
; crude fix to keep last stack item in view
ControlGet, ChildHWND, Hwnd,, ListBox1, RPN ; scrollbar to end of listbox http://www.autohotkey.com/forum/post-196306.html#196306
Loop
{
PreviousScrollPos:=DllCall("GetScrollPos", "UInt", ChildHWND, "Int", 1) ; Last parameter is 1 for SB_VERT, 0 for SB_HORZ.
SendMessage, 0x115, 1, 0, ListBox1, RPN ; Scroll down (0x115 is WM_VSCROLL).
CurrentScrollPos:=DllCall("GetScrollPos", "UInt", ChildHWND, "Int", 1) ; Last parameter is 1 for SB_VERT, 0 for SB_HORZ.
If (CurrentScrollPos = PreviousScrollPos)
Break
}
GuiControl, , Edit1,
ControlFocus, Edit1, RPN
Answer=
Size=
Stacklist=
Return

GuiEscape: ; ESC
GuiClose: ; Program is closed
ExitApp

Edit: needs SA.AHK included or in your lib, see <!-- m -->http://www.autohotke... ... 134#216134<!-- m -->

Edit2: Cleaned up version, added some new hotkeys. F1 displays help

SoLong&Thx4AllTheFish
  • Members
  • 4999 posts
  • Last active:
  • Joined: 27 May 2007
AHK_L version of the script above, no longer requires a library as it now uses AHK_L Arrays so it should run out of the box.
; RPN calculator - proof of concept (HugoV) - AHK_L version
; http://www.autohotkey.com/forum/viewtopic.php?p=454468#454468
; Very basic RPN calculator using AHK_L Arrays
; More about RPN http://en.wikipedia.org/wiki/Reverse_Polish_notation
; can only add/substract/divide/multiply
; If there is only one item on the stack that value will be used as "second" 
; stack item, so typing 5 Numpad+ will place 10 on the stack 5 Numpad* 25 etc
; example, to add 4 + 7 type:
; 4 ENTER 7 [ENTER] Numpad+ (no need for the second enter but is optional)
; -----------------------------------------------------------------------------
; There is an AHK Basic version available here:
; http://www.autohotkey.com/forum/viewtopic.php?t=38496 which 
; using the SimpleArray v3 library by Infogulch, see
; SimpleArray http://www.autohotkey.com/forum/viewtopic.php?p=216134#216134
; -----------------------------------------------------------------------------

#NoEnv ; Recommended for performance and compatibility with future AutoHotkey releases.
#SingleInstance, Force
SendMode Input ; Recommended for new scripts due to its superior speed and reliability.
SetBatchLines, -1

Gosub, setup 
Array := Array()
Gui, Add, Listbox, x5 y5 w195 h120,
Gui, Add, Edit, +Right x5 yp+115 w195 h25 vEntry,
Gui, Add, Text, x5 yp+30 w195 h20 vSize, Stack size: 0
Gui, Show, w205 h170, RPN
ControlFocus, Edit1, RPN
Return

#IfWinActive RPN

Enter:: ; [_L ok]
NumpadEnter::
Gui, Submit, NoHide
If (Entry = "") ; edit control was empty so get the last item from the stack
	Entry:=Array[Array.MaxIndex()]
; here we check if the focus is on the listbox to see if we need to move it
SendMessage, 0x188, 0, 0, ListBox1, RPN ; 0x188 is LB_GETCURSEL (for a ListBox).
ChoicePos = %ErrorLevel% ; It will be -1 if there is no item selected.
ChoicePos += 1 ; Convert from 0-based to 1-based, i.e. so that the first item is known as 1, not 0.
If (ChoicePos = 4294967296) ; focus is not on listbox1
	ChoicePos=0
If (ChoicePos > 0) ; focus was is on listbox1, move selected item to bottom of stack
	{
	 Entry:=Array[ChoicePos]
	 Array.Remove(ChoicePos)
	}
Array.Insert(Entry)
Entry=
Gosub, UpdateGui
Return

NumpadAdd:: ; [_L ok]
Gui, Submit, Nohide
If (Entry <> "") ; Entry not empty so append to Array
   Array.Insert(Entry)
UpdateStack(2, Array[Array.MaxIndex()] + Array[Array.MaxIndex()-1])
Gosub, UpdateGui
Return

NumpadDiv:: ; [_L ok]
Gui, Submit, Nohide
If (Entry <> "") ; Entry not empty so append to Array
   Array.Insert(Entry)
UpdateStack(2,Array[Array.MaxIndex()-1] / Array[Array.MaxIndex()])
Gosub, UpdateGui
Return

^NumpadDiv:: ; [_L ok]
Gui, Submit, Nohide
If (Entry <> "") ; Entry not empty so append to Array
   Array.Insert(Entry)
UpdateStack(1,1 / Array[Array.MaxIndex()])
Gosub, UpdateGui
Return

^NumpadSub:: ; [_L ok]
^NumpadAdd::
Gui, Submit, Nohide
If (Entry <> "") ; Entry not empty so append to Array
   Array.Insert(Entry)
UpdateStack(1,Array[Array.MaxIndex()] * -1)
Gosub, UpdateGui
Return

NumpadSub:: ; [_L ok]
Gui, Submit, Nohide
If (Entry <> "") ; Entry not empty so append to Array
   Array.Insert(Entry)
UpdateStack(2,Array[Array.MaxIndex()-1] - Array[Array.MaxIndex()])
Gosub, UpdateGui
Return

NumpadMult:: ; [_L ok]
Gui, Submit, Nohide
If (Entry <> "") ; Entry not empty so append to Array
   Array.Insert(Entry)
UpdateStack(2,Array[Array.MaxIndex()-1] * Array[Array.MaxIndex()])
Gosub, UpdateGui
Return

^c:: ; [_L ok]
Clipboard:=Array[Array.MaxIndex()]
Return

^e:: ; [_L ok]
Store:=Array[Array.MaxIndex()]
Array.Remove(Array.MaxIndex())
Gosub, UpdateGui
GuiControl, , Edit1, %store%
ControlFocus, Edit1, RPN
ControlSend, Edit1, {end}, RPN
Store=
Return

^s:: ; [_L ok]
FileDelete, %A_ScriptDir%\stack.txt
FileAppend, %StackList%, %A_ScriptDir%\stack.txt
Return

^l:: ; [_L ok]
FileRead, StackList, %A_ScriptDir%\stack.txt
Array := Array()
Loop, parse, StackList, |
	Array.Insert(A_LoopField)
Gosub, UpdateGui
Return

Down:: ; [_L ok]
ControlSend, ListBox1, {Down}, RPN
ControlFocus, ListBox, RPN
Return

Up:: ; [_L ok]
ControlSend, ListBox1, {Up}, RPN
ControlFocus, ListBox, RPN
Return

Del::Send {BS}

^Del:: ; [_L ok]
^BS::
^NumpadDot::
Array.Remove(Array.MaxIndex())
Gosub, UpdateGui
Return

^Down:: ; swap last stack items
^Up::
Gui, Submit, Nohide
If (Entry <> "") ; Entry not empty so append to Array
   Array.Insert(Entry)
Entry:=Array[Array.MaxIndex()]
Array.Remove(Array.MaxIndex())
Store:=Array[Array.MaxIndex()]
Array.Remove(Array.MaxIndex())
Array.Insert(Entry)
Array.Insert(Store)
Entry=
Store=
Gosub, UpdateGui
Return

F1::
MsgBox % Help
Return

#IfWinActive

UpdateStack(Entries, Answer) {
Global
Loop, % Entries
   Array.Remove(Array.MaxIndex())
Array.Insert(Answer)
Return
}

UpdateGui:
Stacklist=
Answer=
Size=
Size:=Array.MaxIndex()
GuiControl,, Size, Stack size: %Size%
Loop, % Array.MaxIndex()
	StackList .= Array[A_Index] "|"
StringTrimRight, StackList, StackList, 1
GuiControl, , Listbox1, |%StackList%
; crude fix to keep last stack item in view
ControlGet, ChildHWND, Hwnd,, ListBox1, RPN ; scrollbar to end of listbox http://www.autohotkey.com/forum/post-196306.html#196306
Loop
	{
	PreviousScrollPos:=DllCall("GetScrollPos", "UInt", ChildHWND, "Int", 1) ; Last parameter is 1 for SB_VERT, 0 for SB_HORZ.
	SendMessage, 0x115, 1, 0, ListBox1, RPN ; Scroll down (0x115 is WM_VSCROLL).
	CurrentScrollPos:=DllCall("GetScrollPos", "UInt", ChildHWND, "Int", 1) ; Last parameter is 1 for SB_VERT, 0 for SB_HORZ.
	If (CurrentScrollPos = PreviousScrollPos)
		Break
	}
GuiControl, , Edit1,
ControlFocus, Edit1, RPN
Return

GuiEscape: ; ESC
GuiClose: ; Program is closed
ExitApp

Setup:
help=
(
RPN HOTKEYS:

(Numpad)Enter:   add value to stack or duplicate last stack item if empty
Numpad+      add
Numpad-      substract
Numpad*      multiply
Numpad/      divide
^Numpad/   Inverse value (5 -> 0.2, 0.2 -> 5)
^Numpad-   toggle +/- value (5 becomes -5 or -5 becomes 5)
^Numpad+   toggle +/- value (5 becomes -5 or -5 becomes 5)
^DEL, ^BS or
  ^NumpadDot(.)   remove last item from stack
Del      backspace in Edit
^Up/^Down   swap last stack items
UP/DOWN+Enter   Select item from stack with up/down keys, pressing enter moves item to last position in stack
^c      copy last item from stack to clipboard (usualy the answer of your calculation)
^e      edit last stack
^s      save stack.txt
^l      load stack.txt
)
Return