
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@6142 8e941d3f-bd1b-0410-a28a-d453659cc2b4
535 lines
13 KiB
ObjectPascal
535 lines
13 KiB
ObjectPascal
(* ***** BEGIN LICENSE BLOCK *****
|
|
* Version: MPL 1.1
|
|
*
|
|
* The contents of this file are subject to the Mozilla Public License Version
|
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
|
* the License. You may obtain a copy of the License at
|
|
* http://www.mozilla.org/MPL/
|
|
*
|
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
|
* for the specific language governing rights and limitations under the
|
|
* License.
|
|
*
|
|
* The Original Code is TurboPower SysTools
|
|
*
|
|
* The Initial Developer of the Original Code is
|
|
* TurboPower Software
|
|
*
|
|
* Portions created by the Initial Developer are Copyright (C) 1996-2002
|
|
* the Initial Developer. All Rights Reserved.
|
|
*
|
|
* Contributor(s):
|
|
*
|
|
* ***** END LICENSE BLOCK ***** *)
|
|
|
|
unit BcdCalU;
|
|
|
|
interface
|
|
|
|
uses
|
|
SysUtils, Windows, Classes, Graphics, Controls,
|
|
Forms, Dialogs, StdCtrls, ExtCtrls, Buttons, Menus, Clipbrd;
|
|
|
|
type
|
|
BCDCharSet = set of Char;
|
|
BCDOperSet = set of Char;
|
|
|
|
type
|
|
TBCDCalcDlg = class(TForm)
|
|
ZeroBtn: TBitBtn;
|
|
DecKey: TBitBtn;
|
|
ThreeKey: TBitBtn;
|
|
OneKey: TBitBtn;
|
|
TwoKey: TBitBtn;
|
|
SixKey: TBitBtn;
|
|
FourKey: TBitBtn;
|
|
FiveKey: TBitBtn;
|
|
NineKey: TBitBtn;
|
|
SevenKey: TBitBtn;
|
|
EightKey: TBitBtn;
|
|
SqrtBtn: TBitBtn;
|
|
LnBtn: TBitBtn;
|
|
ExpBtn: TBitBtn;
|
|
XtoYBtn: TBitBtn;
|
|
AddBtn: TBitBtn;
|
|
SubBtn: TBitBtn;
|
|
MulBtn: TBitBtn;
|
|
DivBtn: TBitBtn;
|
|
PlusMinusBtn: TBitBtn;
|
|
ClearBtn: TBitBtn;
|
|
EqualBtn: TBitBtn;
|
|
ClearEntryBtn: TBitBtn;
|
|
Bevel1: TBevel;
|
|
gb1: TGroupBox;
|
|
BCDString: TEdit;
|
|
BSBtn: TBitBtn;
|
|
Memo1: TMemo;
|
|
PopupMenu1: TPopupMenu;
|
|
Copy1: TMenuItem;
|
|
Paste1: TMenuItem;
|
|
procedure FormCreate(Sender: TObject);
|
|
procedure FormKeyPress(Sender: TObject; var Key: Char);
|
|
procedure CloseBtnClick(Sender: TObject);
|
|
procedure ClearBtnClick(Sender: TObject);
|
|
procedure ZeroBtnClick(Sender: TObject);
|
|
procedure DecKeyClick(Sender: TObject);
|
|
procedure OneKeyClick(Sender: TObject);
|
|
procedure TwoKeyClick(Sender: TObject);
|
|
procedure ThreeKeyClick(Sender: TObject);
|
|
procedure FourKeyClick(Sender: TObject);
|
|
procedure FiveKeyClick(Sender: TObject);
|
|
procedure SixKeyClick(Sender: TObject);
|
|
procedure SevenKeyClick(Sender: TObject);
|
|
procedure EightKeyClick(Sender: TObject);
|
|
procedure NineKeyClick(Sender: TObject);
|
|
procedure PlusMinusBtnClick(Sender: TObject);
|
|
procedure AddBtnClick(Sender: TObject);
|
|
procedure SubBtnClick(Sender: TObject);
|
|
procedure MulBtnClick(Sender: TObject);
|
|
procedure DivBtnClick(Sender: TObject);
|
|
procedure SqrtBtnClick(Sender: TObject);
|
|
procedure ExpBtnClick(Sender: TObject);
|
|
procedure LnBtnClick(Sender: TObject);
|
|
procedure XtoYBtnClick(Sender: TObject);
|
|
procedure EqualBtnClick(Sender: TObject);
|
|
procedure ClearEntryBtnClick(Sender: TObject);
|
|
procedure BSBtnClick(Sender: TObject);
|
|
procedure Copy1Click(Sender: TObject);
|
|
procedure Paste1Click(Sender: TObject);
|
|
private
|
|
{ Private declarations }
|
|
public
|
|
{ Public declarations }
|
|
BCDChar : BCDCharSet;
|
|
BCDOper : BCDOperSet;
|
|
PendOp : Char;
|
|
DFHold : Integer;
|
|
XBuffer : string[20];
|
|
ClearOnNext : Boolean;
|
|
|
|
procedure SendKeyPress(Sender : TObject; C : Char);
|
|
end;
|
|
|
|
|
|
var
|
|
BCDCalcDlg: TBCDCalcDlg;
|
|
|
|
implementation
|
|
|
|
{$R *.lfm}
|
|
|
|
uses
|
|
StConst,
|
|
StBase,
|
|
StStrL,
|
|
StBCD;
|
|
|
|
procedure TBCDCalcDlg.FormCreate(Sender: TObject);
|
|
begin
|
|
BCDChar := ['0'..'9', SysUtils.DecimalSeparator, 'p'];
|
|
BCDOper := ['+', '-', '/', '*', '^', 'e', 'l', 's', '='];
|
|
DecKey.Caption := FormatSettings.DecimalSeparator;
|
|
Memo1.Lines.Text := '0';
|
|
PendOp := #0;
|
|
DFHold := 0;
|
|
XBuffer := '0';
|
|
ClearOnNext := False;
|
|
end;
|
|
|
|
|
|
function BytesToString(Value : PByte; Size : Cardinal) : string;
|
|
{-convert byte array to string, no spaces or hex enunciators, e.g., '$'}
|
|
var
|
|
I,
|
|
Index : Cardinal;
|
|
S : String[3];
|
|
begin
|
|
{$IFOPT H+}
|
|
SetLength(Result,2*Size);
|
|
{$ELSE}
|
|
Result[0] := AnsiChar(Size*2);
|
|
{$ENDIF}
|
|
|
|
for I := 1 to Size do
|
|
begin
|
|
Index := I*2;
|
|
{$IFOPT H+}
|
|
S := HexBL(Byte(PAnsiChar(Value)[I-1]));
|
|
{$ELSE}
|
|
S := HexBS(Byte(PAnsiChar(Value)[I-1]);
|
|
{$ENDIF}
|
|
Result[(Index)-1] := S[1];
|
|
Result[Index] := S[2];
|
|
end;
|
|
end;
|
|
|
|
function StringToBytes(IString : string; var Value; Size : LongInt) : Boolean;
|
|
{-convert string (by groups of 2 char) to byte values}
|
|
var
|
|
Code,
|
|
Index,
|
|
I : Integer;
|
|
Q : TBcd;
|
|
S : array[1..3] of AnsiChar;
|
|
begin
|
|
if ((Length(IString) div 2) <> Size) then
|
|
begin
|
|
Result := False;
|
|
Exit;
|
|
end;
|
|
|
|
Result := True;
|
|
for I := 1 to Size do
|
|
begin
|
|
Index := (2*(I-1))+1;
|
|
S[1] := '$';
|
|
S[2] := IString[Index];
|
|
S[3] := IString[Index+1];
|
|
Val(S,Q[I-1],Code);
|
|
if (Code <> 0) then
|
|
begin
|
|
Result := False;
|
|
Exit;
|
|
end;
|
|
end;
|
|
Move(Q,Value,Size);
|
|
end;
|
|
|
|
procedure TBCDCalcDlg.FormKeyPress(Sender: TObject; var Key: Char);
|
|
var
|
|
HldOp : Char;
|
|
L : Integer;
|
|
BCD1 : TBcd;
|
|
S : string[21];
|
|
begin
|
|
if Memo1.Lines[0] = '0' then
|
|
Memo1.Lines[0] := '';
|
|
|
|
if Key = #13 then begin
|
|
if XBuffer = '0' then
|
|
XBuffer := Memo1.Lines[0]
|
|
else begin
|
|
EqualBtnClick(Sender);
|
|
XBuffer := '0';
|
|
end;
|
|
Key := #0;
|
|
ClearOnNext := True;
|
|
end;
|
|
|
|
if Key in BCDChar then begin
|
|
if (Length(Memo1.Lines[0]) = 0) and (Key = SysUtils.DecimalSeparator) then begin
|
|
Memo1.Lines[0] := '0';
|
|
end;
|
|
if (Key = 'p') then begin
|
|
S := Memo1.Lines[0];
|
|
if (S[1] <> '-') then
|
|
Insert('-',S,1)
|
|
else
|
|
Delete(S,1,1);
|
|
Memo1.Lines[0] := S;
|
|
BCD1 := ValBcd(S);
|
|
BCDString.Text := BytesToString(@BCD1,SizeOf(BCD1));
|
|
Key := #0;
|
|
end else begin
|
|
if ClearOnNext then begin
|
|
Memo1.Lines[0] := '';
|
|
ClearOnNext := False;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
if Key in BCDOper then begin
|
|
if not (Key in ['s', 'e', 'l']) then begin
|
|
if Memo1.Lines[0] = '' then
|
|
Memo1.Lines[0] := '0';
|
|
if (XBuffer <> '0') then
|
|
EqualBtnClick(Sender);
|
|
XBuffer := Memo1.Lines[0];
|
|
BCD1 := ValBcd(XBuffer);
|
|
BCDString.Text := BytesToString(@BCD1,SizeOf(BCD1));
|
|
PendOp := Key;
|
|
Key := #0;
|
|
ClearOnNext := True;
|
|
end else begin
|
|
HldOp := PendOp;
|
|
PendOp := Key;
|
|
EqualBtnClick(Sender);
|
|
PendOp := HldOp;
|
|
Key := #0;
|
|
end;
|
|
end;
|
|
|
|
if (Key in BCDChar) then begin
|
|
S := Memo1.Lines[0];
|
|
L := Length(S);
|
|
if (L < Memo1.MaxLength) then begin
|
|
Memo1.Lines[0] := S + Key;
|
|
end;
|
|
Key := #0
|
|
end;
|
|
Memo1.SetFocus;
|
|
Memo1.SelStart := Length(Memo1.Lines[0]);
|
|
Memo1.SelLength := 0;
|
|
end;
|
|
|
|
|
|
procedure TBCDCalcDlg.CloseBtnClick(Sender: TObject);
|
|
begin
|
|
Close;
|
|
end;
|
|
|
|
procedure TBCDCalcDlg.ClearBtnClick(Sender: TObject);
|
|
begin
|
|
XBuffer := '0';
|
|
Memo1.Lines[0] := '0';
|
|
BCDString.Text := '';
|
|
PendOp := #0;
|
|
ClearOnNext := True;
|
|
end;
|
|
|
|
procedure TBCDCalcDlg.ClearEntryBtnClick(Sender: TObject);
|
|
begin
|
|
Memo1.Lines[0] := '0';
|
|
ClearOnNext := True;
|
|
end;
|
|
|
|
procedure TBCDCalcDlg.SendKeyPress(Sender : TObject; C : Char);
|
|
var
|
|
KP : Char;
|
|
begin
|
|
KP := C;
|
|
FormKeyPress(Sender,KP);
|
|
end;
|
|
|
|
procedure TBCDCalcDlg.ZeroBtnClick(Sender: TObject);
|
|
begin
|
|
SendKeyPress(Sender,'0');
|
|
end;
|
|
|
|
procedure TBCDCalcDlg.DecKeyClick(Sender: TObject);
|
|
begin
|
|
SendKeyPress(Sender, SysUtils.DecimalSeparator);
|
|
end;
|
|
|
|
procedure TBCDCalcDlg.OneKeyClick(Sender: TObject);
|
|
begin
|
|
SendKeyPress(Sender,'1');
|
|
end;
|
|
|
|
procedure TBCDCalcDlg.TwoKeyClick(Sender: TObject);
|
|
begin
|
|
SendKeyPress(Sender,'2');
|
|
end;
|
|
|
|
procedure TBCDCalcDlg.ThreeKeyClick(Sender: TObject);
|
|
begin
|
|
SendKeyPress(Sender,'3');
|
|
end;
|
|
|
|
procedure TBCDCalcDlg.FourKeyClick(Sender: TObject);
|
|
begin
|
|
SendKeyPress(Sender,'4');
|
|
end;
|
|
|
|
procedure TBCDCalcDlg.FiveKeyClick(Sender: TObject);
|
|
begin
|
|
SendKeyPress(Sender,'5');
|
|
end;
|
|
|
|
procedure TBCDCalcDlg.SixKeyClick(Sender: TObject);
|
|
begin
|
|
SendKeyPress(Sender,'6');
|
|
end;
|
|
|
|
procedure TBCDCalcDlg.SevenKeyClick(Sender: TObject);
|
|
begin
|
|
SendKeyPress(Sender,'7');
|
|
end;
|
|
|
|
procedure TBCDCalcDlg.EightKeyClick(Sender: TObject);
|
|
begin
|
|
SendKeyPress(Sender,'8');
|
|
end;
|
|
|
|
procedure TBCDCalcDlg.NineKeyClick(Sender: TObject);
|
|
begin
|
|
SendKeyPress(Sender,'9');
|
|
end;
|
|
|
|
procedure TBCDCalcDlg.PlusMinusBtnClick(Sender: TObject);
|
|
begin
|
|
SendKeyPress(Sender,'p');
|
|
end;
|
|
|
|
procedure TBCDCalcDlg.AddBtnClick(Sender: TObject);
|
|
begin
|
|
SendKeyPress(Sender,'+');
|
|
end;
|
|
|
|
procedure TBCDCalcDlg.SubBtnClick(Sender: TObject);
|
|
begin
|
|
SendKeyPress(Sender,'-');
|
|
end;
|
|
|
|
procedure TBCDCalcDlg.MulBtnClick(Sender: TObject);
|
|
begin
|
|
SendKeyPress(Sender,'*');
|
|
end;
|
|
|
|
procedure TBCDCalcDlg.DivBtnClick(Sender: TObject);
|
|
begin
|
|
SendKeyPress(Sender,'/');
|
|
end;
|
|
|
|
procedure TBCDCalcDlg.SqrtBtnClick(Sender: TObject);
|
|
begin
|
|
SendKeyPress(Sender,'s');
|
|
end;
|
|
|
|
procedure TBCDCalcDlg.ExpBtnClick(Sender: TObject);
|
|
begin
|
|
SendKeyPress(Sender,'e');
|
|
end;
|
|
|
|
procedure TBCDCalcDlg.LnBtnClick(Sender: TObject);
|
|
begin
|
|
SendKeyPress(Sender,'l');
|
|
end;
|
|
|
|
procedure TBCDCalcDlg.XtoYBtnClick(Sender: TObject);
|
|
begin
|
|
SendKeyPress(Sender,'^');
|
|
end;
|
|
|
|
procedure TBCDCalcDlg.EqualBtnClick(Sender: TObject);
|
|
var
|
|
// RV : Extended;
|
|
S : string[21];
|
|
BCD : TBcd;
|
|
begin
|
|
if PendOp <> #0 then begin
|
|
S := Memo1.Lines[0];
|
|
if S = '' then begin
|
|
MessageBeep(0);
|
|
Exit;
|
|
end;
|
|
case PendOp of
|
|
'+' : begin
|
|
// RV := StrToFloat(XBuffer) + StrToFloat(S);
|
|
BCD := AddBCD(ValBCD(XBuffer), ValBCD(S));
|
|
// Memo1.Lines[0] := FloatToStr(RV);
|
|
Memo1.Lines[0] := RightTrimCharsL(Trim(StrBCD(BCD, 35, 20)), '0');
|
|
// BCD := ValBcd(Memo1.Lines[0]);
|
|
BCDString.Text := BytesToString(@BCD,SizeOf(BCD));
|
|
end;
|
|
'-' : begin
|
|
// RV := StrToFloat(XBuffer) - StrToFloat(S);
|
|
BCD := SubBCD(ValBCD(XBuffer), ValBCD(S));
|
|
// Memo1.Lines[0] := FloatToStr(RV);
|
|
Memo1.Lines[0] := RightTrimCharsL(Trim(StrBCD(BCD, 35, 20)), '0');
|
|
// BCD := ValBcd(Memo1.Lines[0]);
|
|
BCDString.Text := BytesToString(@BCD,SizeOf(BCD));
|
|
end;
|
|
'*' : begin
|
|
// RV := StrToFloat(XBuffer) * StrToFloat(S);
|
|
BCD := MulBCD(ValBCD(XBuffer), ValBCD(S));
|
|
// Memo1.Lines[0] := FloatToStr(RV);
|
|
Memo1.Lines[0] := RightTrimCharsL(Trim(StrBCD(BCD, 35, 20)), '0');
|
|
// BCD := ValBcd(Memo1.Lines[0]);
|
|
BCDString.Text := BytesToString(@BCD,SizeOf(BCD));
|
|
end;
|
|
'/' : begin
|
|
// RV := StrToFloat(S);
|
|
BCD := ValBCD(S);
|
|
// if RV = 0 then begin
|
|
if CmpBcd(BCD, ZeroBcd) = 0 then begin
|
|
Memo1.Lines[0] := 'Divide by zero error';
|
|
PendOp := #0;
|
|
ClearOnNext := False;
|
|
end else begin
|
|
// RV := StrToFloat(XBuffer) / StrToFloat(S);
|
|
BCD := DivBCD(ValBCD(XBuffer), BCD);
|
|
// Memo1.Lines[0] := FloatToStr(RV);
|
|
Memo1.Lines[0] := RightTrimCharsL(Trim(StrBCD(BCD, 35, 20)), '0');
|
|
// BCD := ValBcd(Memo1.Lines[0]);
|
|
BCDString.Text := BytesToString(@BCD,SizeOf(BCD));
|
|
end;
|
|
end;
|
|
's' : begin
|
|
// RV := Sqrt(StrToFloat(S));
|
|
BCD := SqrtBcd(ValBCD(S));
|
|
// Memo1.Lines[0] := FloatToStr(RV);
|
|
Memo1.Lines[0] := RightTrimCharsL(Trim(StrBCD(BCD, 35, 20)), '0');
|
|
// BCD := ValBcd(Memo1.Lines[0]);
|
|
BCDString.Text := BytesToString(@BCD,SizeOf(BCD));
|
|
end;
|
|
'e' : begin
|
|
// RV := Exp(StrToFloat(S));
|
|
BCD := ExpBCD(ValBCD(S));
|
|
// Memo1.Lines[0] := FloatToStr(RV);
|
|
Memo1.Lines[0] := RightTrimCharsL(Trim(StrBCD(BCD, 35, 20)), '0');
|
|
// BCD := ValBcd(Memo1.Lines[0]);
|
|
BCDString.Text := BytesToString(@BCD,SizeOf(BCD));
|
|
end;
|
|
'l' : begin
|
|
// RV := ln(StrToFloat(S));
|
|
BCD := lnBCD(ValBCD(S));
|
|
// Memo1.Lines[0] := FloatToStr(RV);
|
|
Memo1.Lines[0] := RightTrimCharsL(Trim(StrBCD(BCD, 35, 20)), '0');
|
|
// BCD := ValBcd(Memo1.Lines[0]);
|
|
BCDString.Text := BytesToString(@BCD,SizeOf(BCD));
|
|
end;
|
|
'^' : begin
|
|
// RV := exp(ln(StrToFloat(XBuffer)) * StrToFloat(S));
|
|
BCD := PowBCD(ValBCD(XBuffer), ValBCD(S));
|
|
// Memo1.Lines[0] := FloatToStr(RV);
|
|
Memo1.Lines[0] := RightTrimCharsL(Trim(StrBCD(BCD, 35, 20)), '0');
|
|
// BCD := ValBcd(Memo1.Lines[0]);
|
|
BCDString.Text := BytesToString(@BCD,SizeOf(BCD));
|
|
end;
|
|
|
|
end;
|
|
end;
|
|
PendOp := #0;
|
|
ClearOnNext := True;
|
|
Memo1.SetFocus;
|
|
Memo1.SelStart := 0;
|
|
Memo1.SelLength := 0;
|
|
end;
|
|
|
|
|
|
procedure TBCDCalcDlg.BSBtnClick(Sender: TObject);
|
|
begin
|
|
Memo1.Lines[0] := Copy(Memo1.Lines[0], 1, Length(Memo1.Lines[0]) - 1);
|
|
if Length(Memo1.Lines[0]) = 0 then
|
|
ClearBtnClick(ClearBtn);
|
|
end;
|
|
|
|
procedure TBCDCalcDlg.Copy1Click(Sender: TObject);
|
|
begin
|
|
Memo1.SelectAll;
|
|
Memo1.CopyToClipboard;
|
|
Memo1.SelStart := 0;
|
|
end;
|
|
|
|
procedure TBCDCalcDlg.Paste1Click(Sender: TObject);
|
|
var
|
|
S : string;
|
|
IsNeg : Boolean;
|
|
begin
|
|
S := Clipboard.AsText;
|
|
IsNeg := False;
|
|
if (S[1] = '-') then begin
|
|
IsNeg := True;
|
|
S := Copy(S, 2, Length(S) - 1);
|
|
end;
|
|
|
|
if IsStrNumericL(S, '0123456789' + SysUtils.DecimalSeparator) then begin
|
|
if IsNeg then S := '-' + S;
|
|
Memo1.Lines[0] := S;
|
|
end;
|
|
end;
|
|
|
|
end.
|