USE CITScreen
USE CITWindow
USE CITGadgets

// Initialization variables
DIM Error OF SHORT
DIM i OF SHORT

// Working variables
DIM Display OF FLOAT
DIM Register OF FLOAT
DIM Operator OF SHORT
DIM WeightFactor OF FLOAT

WeightFactor:=1

// Make the calculator window
DIM Calculator OF CITWindow
Calculator.Size(300,150)
Calculator.Position(100,30)
Calculator.Activate
Calculator.DragBar
Calculator.CloseGadget
Calculator.Label("Calculator")
ComalScreen.InsObject(Calculator,Error)

// The display is a simple read only text gadget
DIM DisplayText OF TextGadget
DisplayText.Size(250,16)
DisplayText.Position(20,10)
DisplayText.Border
Calculator.InsObject(DisplayText,Error)

// Make the clear button
DIM ClearButton OF ButtonGadget
ClearButton.Size(55,12)
ClearButton.Position(215,35)
ClearButton.Label("CLEAR",INSIDE)
ClearButton.EventHandler(ClearEvent())
Calculator.InsObject(ClearButton,Error)

// .. all the digit buttons
DIM NumButton(0..9) OF ButtonGadget
FOR i:=0 TO 9 DO
  NumButton(i).Size(55,12)
  NumButton(i).Position(20+(i MOD 3)*65,55+(i DIV 3)*20)
  NumButton(i).EventHandler(NumEvent())
  NumButton(i).Label(CHR$(ORD("0")+((i+1) MOD 10)),INSIDE)
  NumButton(i).Id((1+i) MOD 10)
  Calculator.InsObject(NumButton(i),Error)
ENDFOR i

// .. the point button
DIM PointButton OF ButtonGadget
PointButton.Size(55,12)
PointButton.Position(85,115)
PointButton.EventHandler(PointEvent())
PointButton.Label(".",INSIDE)
Calculator.InsObject(PointButton,Error)

// .. the '=' button
DIM EqualButton OF ButtonGadget
EqualButton.Size(55,12)
EqualButton.Position(150,115)
EqualButton.EventHandler(EqualEvent())
EqualButton.Label("=",INSIDE)
Calculator.InsObject(EqualButton,Error)

// .. and the 4 operator buttons
DIM OperatorButton(0..3) OF ButtonGadget
FOR i:=0 TO 3 DO
  OperatorButton(i).Size(55,12)
  OperatorButton(i).Position(215,55+i*20)
  OperatorButton(i).Id(i+20)
  OperatorButton(i).EventHandler(OperatorEvent())
  CASE i OF
  WHEN 0
    OperatorButton(i).Label("+",INSIDE)
  WHEN 1
    OperatorButton(i).Label("-",INSIDE)
  WHEN 2
    OperatorButton(i).Label("",INSIDE)
  WHEN 3
    OperatorButton(i).Label("/",INSIDE)
  ENDCASE
  Calculator.InsObject(OperatorButton(i),Error)
ENDFOR i

DIGITS 14
WriteDisplay(0)

WHILE NOT Calculator.ClosePressed DO WAIT

ComalScreen.RemObject(Calculator)

// Event procedures

PROC NumEvent(Id OF USHORT)
  IF WeightFactor=1 THEN
    Display:=10*Display+Id
  ELSE
    Display:=Display+Id*WeightFactor
    WeightFactor:/10
  ENDIF
  WriteDisplay(Display)
ENDPROC NumEvent

PROC PointEvent(Id OF USHORT)
  IF WeightFactor=1 THEN
    WeightFactor:=0.1
  ENDIF
ENDPROC PointEvent

PROC EqualEvent(Id OF USHORT)
  Calculate
  Register:=0
  Display:=0
  Operator:=0
  WeightFactor:=1
ENDPROC EqualEvent

PROC ClearEvent(Id OF USHORT)
  IF Display=0 THEN
    Register:=0
  ELSE
    Display:=0
  ENDIF
  WriteDisplay(Display)
  WeightFactor:=1
ENDPROC ClearEvent

PROC OperatorEvent(Id OF USHORT)
  Calculate
  Register:=Display
  Display:=0
  Operator:=Id
  WeightFactor:=1
ENDPROC OperatorEvent


// Other procedures

PROC Calculate
  CASE Operator OF
  WHEN 20
    Display:=Register+Display
  WHEN 21
    Display:=Register-Display
  WHEN 22
    Display:=Register*Display
  WHEN 23
    IF Display=0 THEN
      DisplayText.Text(SPC$(20)+"E R R O R")
      RETURN
    ELSE
      Display:=Register/Display
    ENDIF
  OTHERWISE
    // No action
  ENDCASE
  WriteDisplay(Display)
ENDPROC Calculate

PROC WriteDisplay(Value OF FLOAT)
  LOCAL Text$ OF 29

  Text$:=STR$(Value)
  Text$:=SPC$(28-LEN(Text$))+Text$
  DisplayText.Text(Text$)
ENDPROC WriteDisplay
