Notes {labels: 'NIL, viewFont: 10241} // nil=Unfiled, or specify a folder, e.g., 'Business. remove viewFont for current Styles default //ERASE! in order to erase existing entries in this folder first UPN {_proto: protoFloater, _package: { icon: :GetPictAsBits("Bitmaps", "RPN"), }, viewBounds: RelBounds (0, 30, 164, 86), viewFlags: 0x00000004, title: "UPN", declareSelf: 'base, basis: 10, beep: func() PlaySound(rom_plinkbeep), protoStack:{ values: nil, pos: 0, size:0, pop: func() begin if (pos = 0) then return 0; pos := pos-1; return values[pos]; end, push: func(v) begin if (size <= pos) then begin if not values then values := [v] else AddArraySlot(values, v); size := size+1; end else values[pos] := v; pos := pos+1; end, current: func() begin if pos = 0 then return nil; values[pos-1]; end, }, aStack: nil, viewSetupDoneScript: func() begin aStack := {_proto: protoStack, _parent: self,}; end, doEnter: func(a) begin aStack:push(a); SetValue(display, 'text, :numberToStringB(a, basis)); SetValue(anInput, 'text, nil); end, getInput: func() begin local v := nil; if (anInput.text) then v :=:stringToNumberB(anInput.text, basis); if not v then v := aStack:pop(); if (not v) then :beep(); return v; end, viewOverviewScript: func() begin local v := :getInput(); if (v and aStack.pos > 0) then begin local s := aStack:pop(); :doEnter(v); SetValue(anInput, 'text, :numberToStringB(s, basis)); end end } ---------- UPN.numberToStringB func(number, basis) begin if (number = 0) then return "0"; local r := ""; local i, digit, point, nDigits := 0, exp := 1; point := GetLocale().numberformat.decimalpoint; if (number < 0) then begin number := -number; r := "-"; end; if (number = 1) then return r & "1"; if (number > 1) then begin nDigits := Ceiling(log(Floor(number)+1)/log(basis)); exp := RintToL(Pow(basis, nDigits-1)); for i := 1 to nDigits do begin digit := number / exp; digit := Floor(digit); r := r & :representationOf(digit); number := number - digit * exp; exp := exp / basis; end; end; else r := r & "0"; if (Abs(number) < 5.e-15) then return r; r := r & point; for i := 1 to 14 - nDigits do begin number := number * basis; digit := Floor(number); r := r & :representationOf(digit); number := number - digit; if (Abs(number) < 5.e-15) then return r; end; return r; end ---------- UPN.representationOf func(val) begin if (val < 10) then return Chr(Ord($0) + val); if (val < 36) then return Chr(Ord($a) + val - 10); end ---------- UPN.smokeIt func(smokeBounds) begin local top := smokeBounds.top; local left := smokeBounds.left; local bm1 := Clone(@53); //ROM_cloud1 local bm2 := Clone(@54); //ROM_cloud2 local bm3 := Clone(@55); //ROM_cloud3 //CopyBits draw bitmaps scaled to their bounds bm1.bounds := bm2.bounds := bm3.bounds := smokeBounds; //explained below local danQuayle := BuildContext( {viewClass: clView, viewFlags: 64, // vFloating viewBounds: smokeBounds}); PlaySound(@314); //ROM_poof GetRoot():CopyBits(bm1,left,top,8); //modeMask Sleep(2); GetRoot():CopyBits(bm1,left,top,3); //modeBic GetRoot():CopyBits(bm2,left,top,8); Sleep(2); GetRoot():CopyBits(bm2,left,top,3); GetRoot():CopyBits(bm3,left,top,8); Sleep(1); GetRoot():CopyBits(bm3,left,top,3); // DirtyBox doesn't seem to work here danQuayle:Open(); danQuayle:Close(); end ---------- UPN.stringToNumberB func(r, basis) begin local point, pos, nDigits, exp := 1, length, number := 0; point := GetLocale().numberformat.decimalpoint; r := TrimString(r); pos := StrPos(r, point, 0); length := StrLen(r); if (pos) then nDigits := pos; else nDigits := length; exp := RintToL(Pow(basis, nDigits - 1)); for i := 0 to length - 1 do if (i <> pos) then begin local v := :valueOf(r[i]); if v >= basis then return nil; number := number + v * exp; exp := exp / basis; end; return if not pos then Round(number) else number; end ---------- UPN.valueOf func(arg) begin if (arg >= $0 and arg <= $9) then return Ord(arg) - Ord($0); if (arg >= $a and arg <= $z) then return Ord(arg) - Ord($a) + 10; if (arg >= $A and arg <= $Z) then return Ord(arg) - Ord($A) + 10; return -1; end ---------- UPN+anInput {_proto: protoInputLine, viewBounds: RelBounds (4, 32, 152, 36), viewFlags: 10753, //vClickable+vNumbersAllowed+vVisible+vGesturesAllowed, //viewLineSpacing: 24, viewJustify: 8, //vjBottomv textFlags: 2, //vNoSpaces, viewFont: { family: 'espy, face: 1, size: 10,}, last: "", viewChangedScript: func(value, view) begin if value <> 'text then return; if (not text) then begin last := ""; return; end; if not BeginsWith(text, last) then return; local i, w := last, x := Clone(text); text := Clone(last); for i := StrLen(last) to StrLen(x) - 1 do if :charScript(x[i], x) then w := w & x[i]; if text then begin text := w; last := Clone(w); end; end, basisChanged: func(b, c) if text and StrLen(text) > 0 then begin local v := :stringToNumberB(text, b); if v then SetValue(self, 'text, :numberToStringB(v, c)); else :beep(); end, charScript: func(c, v) begin if Ord(c) = 32 or Ord(c) = 13 then begin if Ord(c) = 13 then enter:buttonClickScript(); return nil; end; if c = $+ then begin plus:buttonClickScript(); return nil; end; if c = $- then begin minus:buttonClickScript(); return nil; end; if c = $/ then begin divide:buttonClickScript(); return nil; end; if c = $* then begin times:buttonClickScript(); return nil; end; if c = $= then begin enter:buttonClickScript(); return nil; end; return True; end, } ---------- UPN+aTitle { _proto: protoTitle, text: "UPN", } ---------- UPN+basePicker {_proto: protoLabelPicker, viewBounds: RelBounds ( 4, 4, 38, 12), text: "hex", labelValues: [16, 10, 8, 2], labelCommands: ["hex", "dec", "oct", "bin"], viewFont: { family: 'espy, face: 1, size: 10,}, textSetup: func() begin if basis = 10 then return "dec" else if basis = 16 then return "hex" else if basis = 8 then return "oct" else if basis = 2 then return "bin" else begin basis := 10; return "dec"; end; end, viewSetupDoneScript: func() begin text := $\uFC01 & :textSetup(); end, labelActionScript: func(index) begin local b := basis; SetValue(self, 'text, $\uFC01 & labelCommands[index]); SetValue(:parent(), 'basis, labelValues[index]); :parent().display:basisChanged(b, basis); :parent().anInput:basisChanged(b, basis); end, } ---------- UPN+closeBox { _proto: protoLargeCloseBox, } ---------- UPN+display { viewClass: clParagraphView, viewBounds: RelBounds (4, 15, 152, 25), viewFlags: vClickable+vGesturesAllowed+vVisible+vReadOnly, viewJustify: 9, //vjRightH + vjBottomV viewFont: {family: 'espy, face: 1, size: 10 }, text: "0", viewDrawScript: func() begin :DrawShape(MakeLine(0, 13, 152, 13),nil); end, viewGestureScript: func(unit, gesture) if gesture = 13 then begin local bounds := StrokeBounds(unit); local qWidth := Max(10, (bounds.right - bounds.left) div 4); local qHeight := Max(10, (bounds.bottom - bounds.top) div 4); bounds.top := bounds.top - qHeight; bounds.left := bounds.left - qWidth; bounds.bottom := bounds.bottom + qHeight; bounds.right := bounds.right + qWidth; InkOff(unit); :smokeIt(bounds); aStack:pop(); local v := aStack:current(); if not v then v := 0; SetValue(self, 'text, :numberToStringB(v, basis)); end, basisChanged: func(b, c) if text then begin local v := :stringToNumberB(text, b); SetValue(self, 'text, :numberToStringB(v, c)); end, } ---------- UPN+divide {_proto: protoTextButton, viewBounds: RelBounds (85, 68, 13, 13), text: "/", buttonClickScript: func() begin local v := :getInput(); if (not v) then return; v := aStack:pop() / v; :doEnter(v); end } ---------- UPN+enter {_proto: protoTextButton, viewBounds: RelBounds (105, 68, 34, 13), text: "enter", buttonClickScript: func() begin local v := :getInput(); if (v) then:doEnter(v); end } ---------- UPN+minus {_proto: protoTextButton, viewBounds: RelBounds (45, 68, 13, 13), text: "-", buttonClickScript: func() begin local v := :getInput(); if (not v) then return; v := aStack:pop() - v; :doEnter(v); end } ---------- UPN+plus {_proto: protoTextButton, viewBounds: RelBounds (25, 68, 13, 13), text: "+", buttonClickScript: func() begin local v := :getInput(); if (not v) then return; v := v + aStack:pop(); :doEnter(v); end } ---------- UPN+plusMinus {_proto: protoTextButton, viewBounds: RelBounds (5, 68, 13, 13), text: "±", buttonClickScript: func() begin if aStack.pos < 1 then begin // PlaySound(ROM_plinkBeep); return; end; local v := -aStack.values[aStack.pos-1]; aStack.values[aStack.pos-1] := v; SetValue(display,'text, :numberToStringB(v,basis)); end, } ---------- UPN+times {_proto: protoTextButton, viewBounds: RelBounds (65, 68, 13, 13), text: "*", buttonClickScript: func() begin local v := :getInput(); if (not v) then return; v := aStack:pop() * v; :doEnter(v); end }