home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C!T ROM 2
/
ctrom_ii_b.zip
/
ctrom_ii_b
/
PROGRAM
/
PASCAL
/
30TURUTL
/
PC-CALC.PAS
< prev
next >
Wrap
Pascal/Delphi Source File
|
1985-05-30
|
20KB
|
598 lines
program calc(input, output);
{*R+}
const
ls_len = 20;
F1 = 59;
F2 = 60;
F3 = 61;
AF3 = 106;
SF3 = 86;
F4 = 62;
AF4 = 107;
SF4 = 87;
F10 = 68;
Clear_Mem = 14;
End_Key = 79;
c_op1_row = 20;
c_op1_col = 50;
c_op2_row = 22;
c_op2_col = 50;
c_opcode_row = 21;
c_opcode_col = 75;
type
calc = set of char;
ls = string[ls_len];
var
op1_col, op2_col, col : integer;
m_row, m_col : array[1..6] of integer;
done, valid, control : boolean;
prev_op,prev_char,chr_value,scan_code,blank,hold_char : char;
value_string, blank_ls, zero : ls;
memory_values : array[1..6] of ls;
operand, total : real;
operators,numbers,plus_or_minus : calc;
memory_registers : calc;
i : integer;
result : record
ax,bx,cx,dx,bp,si,di,ds,es,flags: integer;
end;
procedure getchar(var char_value, scan_code : char);
begin
result.ax := $0000;
intr($16, result);
scan_code := chr(ord(hi(result.ax)));
char_value := chr(ord(lo(result.ax)));
end; {getchar}
procedure locate(row, col : integer);
begin
row := row + 1;
col := col + 1;
GotoXY(col, row);
end; {locate}
procedure wrtattrib(row, col : integer;
char_value : char;
background, foreground : integer);
begin
GotoXY(col + 1, row + 1);
TextColor(foreground);
TextBackground(background);
write(char_value);
end; {wrtattrib}
{The following procedure emits a 440-Hertz beep for 1/4 of a second}
procedure beep;
begin
Sound(440);
Delay(250);
NoSound;
end; {beep}
procedure Clear_Memory;
forward;
procedure initialize;
var m_var : ls;
procedure m_set_up(m_var : ls; row, col, ls_len : integer);
var
i : integer;
begin {m_set_up}
for i := 1 to length(m_var) do
wrtattrib(row, col + (i - 1), m_var[i], Blue, Yellow);
col := col + 3;
wrtattrib(row, col, blank, Blue, Yellow);
for i:= 1 to ls_len-1 do
begin
col := col + 1;
wrtattrib(row, col, blank, Blue, Yellow);
end;
end; {m_set_up}
procedure set_up_2(row, col, len : integer;
background, foreground : integer);
var col_save : integer;
begin {set_up_2}
col_save := col;
col := col + 1;
for i:= 1 to len do
begin
wrtattrib(row, col, blank, background, foreground);
col := col + 1;
end;
col := col_save;
locate(row,col);
end; {set_up_2}
procedure set_up_3(st : ls);
begin {set_up_3}
set_up_2(WhereY - 1, WhereX, Length(st), Blue, Yellow);
write(st);
end; {set_up_3}
begin {initialize}
done := false;
operators := ['+','-','*','/','='];
plus_or_minus := ['+','-'];
numbers := ['0'..'9','.'];
memory_registers := ['1'..'6'];
blank := ' ';
prev_op:=chr(255); {initialize prev_op}
prev_char:=chr(255); {initialize prev_char}
TextMode(3); {CO80}
GotoXY(34, 1);
write('PC Calculator');
op1_col := c_op1_col - 1;
op2_col := c_op2_col - 1;
zero := '0.00000000';
blank_ls := ' ';
for i:= 1 to ls_len + 1 do
begin
wrtattrib(c_op1_row, op1_col, blank, Blue, Yellow);
op1_col := op1_col + 1;
end;
op1_col := c_op1_col;
for i:= 1 to ls_len + 1 do
begin
wrtattrib(c_op2_row, op2_col, blank, Blue, Yellow);
op2_col := op2_col + 1;
end;
op2_col := c_op2_col;
wrtattrib(c_opcode_row, c_opcode_col, blank, Blue, Yellow);
m_row[1] := 2; m_row[2] := 2; m_row[3] :=2;
m_row[4] := 4; m_row[5] := 4; m_row[6] :=4;
m_col[1] := 2; m_col[2] := 28; m_col[3] :=54;
m_col[4] := 2; m_col[5] := 28; m_col[6] :=54;
m_var := 'M1'; m_set_up(m_var, m_row[1], m_col[1], ls_len);
m_var := 'M2'; m_set_up(m_var, m_row[2], m_col[2], ls_len);
m_var := 'M3'; m_set_up(m_var, m_row[3], m_col[3], ls_len);
m_var := 'M4'; m_set_up(m_var, m_row[4], m_col[4], ls_len);
m_var := 'M5'; m_set_up(m_var, m_row[5], m_col[5], ls_len);
m_var := 'M6'; m_set_up(m_var, m_row[6], m_col[6], ls_len);
Clear_Memory;
GotoXY(25, 25);
write('*** Esc to terminate program ***');
set_up_2(14, 3, 3, LightGray, Red);
write(' ', chr(17), '-- ');
set_up_3('Clear Memory ');
set_up_2(WhereY - 1, WhereX + 2, 3, LightGray, Red);
write(' End ');
set_up_3(' Clear');
set_up_2(16, 3, 3, LightGray, Red);
write(' F1 ');
set_up_3(' STO ');
set_up_2(WhereY - 1, WhereX + 1, 3, LightGray, Red);
write(' F2 ');
set_up_3(' RCL ');
set_up_2(18, 3, 3, LightGray, Red);
write(' F3 ');
set_up_3(' x'+ chr(253)+ ' ');
set_up_2(WhereY - 1, WhereX + 2, 3, LightGray, Red);
write(' AF3 ');
set_up_3(' ' + chr(251) + 'x ');
set_up_2(WhereY - 1, WhereX + 2, 3, LightGray, Red);
write(' SF3 ');
set_up_3(' x' + chr(252) + ' ');
set_up_2(20, 3, 3, LightGray, Red);
write(' F4 ');
set_up_3(' ' + chr(241) + ' ');
set_up_2(WhereY - 1, WhereX + 2, 3, LightGray, Red);
write(' AF4 ');
set_up_3(' ' + chr(179) + 'x' + chr(179) + ' ');
set_up_2(WhereY - 1, WhereX + 2, 3, LightGray, Red);
write(' SF4 ');
set_up_3(' 1/x ');
set_up_2(22, 3, 3, LightGray, Red);
write(' F10 ');
set_up_3(' Clear Op. ');
locate(c_op2_row, op2_col);
for i := 1 to ls_len-1 do blank_ls := Concat(blank_ls, ' ');
end; {initialize}
procedure format_lstring (var type_ls : ls);
var
i : integer;
chk : boolean;
begin
{remove leading blanks}
while type_ls[1] = ' ' do
delete(type_ls,1,1);
{remove trailing zeroes after the decimal point}
i := length(type_ls);
chk := true;
while chk and (i > 0) do
begin {chk}
if type_ls[i] = '0' then delete(type_ls,i,1)
else chk := false;
i := length(type_ls);
end; {chk}
end; {format_lstring}
procedure chk_if_valid1; {checks if first character entered is valid}
begin {chk_if_valid1}
if (chr_value in plus_or_minus) or (chr_value in numbers) then
begin {2}
valid:=true;
prev_op := '*';
prev_char := chr_value;
operand := 0;
if (chr_value in numbers) or (chr_value = '+') then
begin
total := 1;
value_string := '0';
end
else
begin
total := -1;
value_string := '0';
end
end {2}
else
valid:=false;
end; {chk_if_valid1}
procedure chk_if_valid2;
begin
if (chr_value in operators) or
(chr_value in numbers) or
(ord(scan_code) = F1) or
(ord(scan_code) = F2) or
(ord(scan_code) = F3) or
(ord(scan_code) = AF3) or
(ord(scan_code) = SF3) or
(ord(scan_code) = F4) or
(ord(scan_code) = AF4) or
(ord(scan_code) = SF4)
then valid := true
else valid := false;
if (prev_char in operators) and (chr_value in operators)
then valid := false;
end; {chk_if_valid2}
procedure chk_if_valid;
begin
control := false;
if ord(scan_code) = End_Key then control := true; {End?}
if not control then
begin {control}
if ord(prev_op)=255 then chk_if_valid1
else
chk_if_valid2;
end; {control}
end; {chk_if_valid}
procedure End_key_pressed;
begin {End key pressed}
prev_op:=chr(255); {initialize prev_op}
prev_char:=chr(255); {initialize prev_char}
locate(c_op1_row, op1_col);
write(blank_ls);
op2_col := c_op2_col;
locate(c_op2_row, op2_col);
write(blank_ls);
locate(c_opcode_row, c_opcode_col);
write(' ');
Clear_Memory;
locate(c_op2_row, op2_col);
value_string := '';
end; {End key pressed}
procedure Clear_Memory;
var i : integer;
row, col : integer;
begin {Clear_Memory}
row := WhereY;
col := WhereX;
for i := 1 to 6 do
begin
memory_values[i] := zero;
locate(m_row[i],m_col[i] + 3);
write(blank_ls);
locate(m_row[i],m_col[i] + 3);
write(zero);
end; {end do}
locate(row, col);
end; {Clear_Memory}
procedure equal_help;
begin {equal_help}
Str(total : 18 : 8, value_string);
format_lstring(value_string);
locate(c_op1_row, op1_col);
write(blank_ls);
locate(c_op1_row, op1_col);
write(value_string);
end; {equal_help}
procedure F1_key_pressed; {store}
forward;
procedure F2_key_pressed; {RCL}
forward;
procedure Integer_Power;
forward;
procedure Equal_key_pressed;
var exit_now : boolean;
begin {Equal sign key pressed}
exit_now := false;
repeat
getchar(chr_value, scan_code);
if (chr_value in ['+', '-', '*', '/']) or
(ord(scan_code)=1) or
(ord(scan_code) = F1) or
(ord(scan_code) = F2) or
(ord(scan_code) = F3) or
(ord(scan_code) = AF3) or
(ord(scan_code) = SF3) or
(ord(scan_code) = F4) or
(ord(scan_code) = AF4) or
(ord(scan_code) = SF4) or
(ord(scan_code) = End_Key) or
(ord(scan_code) = Clear_Mem) then
else
beep;
if ord(scan_code) = F1 then F1_key_pressed;
if ord(scan_code) = F2 then F2_key_pressed;
if ord(scan_code) = F3 then
begin
total := sqr(total);
equal_help;
end;
if ord(scan_code) = AF3 then
begin
if total >= 0 then total := sqrt(total) else beep;
equal_help;
end;
if ord(scan_code) = SF3 then
begin
Integer_Power;
equal_help;
end;
if ord(scan_code) = F4 then
begin
total := - total;
equal_help;
end;
if ord(scan_code) = AF4 then
begin
total := abs(total);
equal_help;
end;
if (ord(scan_code) = SF4) then
begin
if total <> 0 then total := 1 / total else beep;
equal_help;
end;
if (ord(scan_code) = Clear_Mem) then Clear_Memory;
if (ord(scan_code) = End_Key) then
begin
End_Key_Pressed;
exit_now := true;
end;
until (chr_value in ['+', '-', '*', '/'])
or (ord(scan_code) = 1)
or (exit_now = true);
if ord(scan_code) = 1 then done := true;
if (ord(scan_code) <> End_Key) then prev_op := chr_value;
locate(c_opcode_row, c_opcode_col);
write(chr_value); {write new operator}
end; {Equal sign key pressed}
procedure F1_key_pressed; {STO}
var memory_index : integer;
begin {F1 pressed}
repeat
getchar(chr_value, scan_code);
if not (chr_value in memory_registers) then beep;
until (chr_value in memory_registers)
or (ord(scan_code) = 1); {Esc?}
if ord(scan_code) = 1 then done := true;
memory_index := ord(chr_value) - ord('0');
memory_values[memory_index] := value_string;
locate(m_row[memory_index],m_col[memory_index] + 3);
write(blank_ls);
locate(m_row[memory_index],m_col[memory_index] + 3);
write(memory_values[memory_index]);
locate(c_opcode_row, c_opcode_col);
write(' ');
Equal_key_pressed;
end; {STO}
procedure F2_key_pressed; {RCL}
var memory_index : integer;
chr_value : char;
begin {F2 pressed}
repeat
getchar(chr_value, scan_code);
if not (chr_value in memory_registers) then beep;
until (chr_value in memory_registers)
or (ord(scan_code) = 1); {Esc?}
if ord(scan_code) = 1 then done := true;
memory_index := ord(chr_value) - ord('0');
value_string := memory_values[memory_index];
op2_col := c_op2_col;
locate(c_op2_row, op2_col);
write(blank_ls);
locate(c_op2_row, op2_col);
write(memory_values[memory_index]);
end; {F2 pressed}
procedure Integer_Power;
var i, power : integer;
chr_value : char;
total_save : real;
begin {Integer_Power}
power := 0;
total_save := total;
repeat
getchar(chr_value, scan_code);
if not (chr_value in ['0'..'9', chr(13)]) then beep;
if chr_value in ['0'..'9'] then
power := power * 10 +(ord(chr_value) - ord('0'));
until (chr_value = chr(13))
or (ord(scan_code) = 1); {Esc?}
if ord(scan_code) = 1 then done := true;
if power = 0 then total := 1
else
begin
if power > 1 then
for i := 1 to power - 1 do total := total * total_save;
end;
end; {Integer_Power}
function command : boolean;
begin
command := false; {default}
if ord(scan_code) = 1 then command := true; {Esc?}
if ord(scan_code) = End_Key then command := true; {End?}
if ord(scan_code) =15 then command := true; {Clear_Memory}
end; {command}
procedure do_it2;
begin
case prev_op of
'+' : total := total + operand;
'-' : total := total - operand;
'*' : total := total * operand;
'/' : total := total / operand;
end; {end case}
end; {do_it2}
procedure do_it;
var
could_do : integer;
begin
if control and (ord(scan_code)=End_Key) then
End_key_pressed;
if not control then
begin {not control}
if (chr_value in operators) or
(ord(scan_code) = F1) or
(ord(scan_code) = F2) or
(ord(scan_code) = F3) or
(ord(scan_code) = SF3) or
(ord(scan_code) = AF3) or
(ord(scan_code) = F4) or
(ord(scan_code) = SF4) or
(ord(scan_code) = AF4)
then
begin {is operator}
{ convert string to real value }
Val(value_string, operand, could_do);
{ if could_do <> 0 then beep; }
if (prev_op in ['+', '-', '*', '/']) and
(ord(scan_code) <> F2) then do_it2;
if ord(scan_code) = F3 then
begin
total := total * total;
prev_op := chr(0);
end; {F3}
if (ord(scan_code) = SF3) then
begin
Integer_Power;
prev_op := chr(0);
end; {SF3}
if (ord(scan_code) = AF3) then
begin
if total >= 0 then total := sqrt(total) else beep;
prev_op := chr(0);
end; {AF3}
if ord(scan_code) = F4 then
begin
total := - total;
prev_op := chr(0);
end; {F4}
if ord(scan_code) = AF4 then
begin
total := abs(total);
prev_op := chr(0);
end; {AF4}
if (ord(scan_code) = SF4) then
begin
if total <> 0 then total := 1 / total else beep;
prev_op := chr(0);
end; {SF4}
equal_help;
op2_col := c_op2_col; {reset}
locate(c_op2_row, op2_col);
write(blank_ls); {clear area out}
if chr_value = '=' then Equal_key_pressed;
if ord(scan_code) = F1 then F1_key_pressed;
if (chr_value <> '=') and (ord(scan_code) <> F1)
and (ord(scan_code) <> F2)
and (ord(scan_code) <> F3)
and (ord(scan_code) <> End_Key)
then prev_op := chr_value;
locate(c_op2_row, op2_col);
value_string := '';
if ord(scan_code) = F2 then F2_key_pressed;
end {is operator}
else
if length(value_string) < ls_len
then
value_string := concat(value_string, chr_value)
else beep;
end; {not control}
end; {do_it}
begin {main program}
{ note:
Esc - terminate
End - reset
}
initialize;
repeat {until (done)}
repeat {until (ord(scan_code) <> F10)}
hold_char := prev_char; {save previous character}
prev_char := chr_value;
getchar(chr_value, scan_code);
if ord(scan_code) = Clear_mem then Clear_Memory;
if command then prev_char := hold_char; {restore}
if ord(scan_code) = 1 then done := true; {Esc pressed?}
if ord(scan_code) = F10 then
begin {F10 hit - re-set operand}
op2_col := c_op2_col;
locate(c_op2_row, c_op2_col);
write(blank_ls);
locate(c_op2_row, c_op2_col);
value_string := '';
end; {F10}
until (ord(scan_code) <> F10);
if (done = false) and (ord(scan_code) <> Clear_Mem) then
begin {done = false}
chk_if_valid;
if valid then
begin {is valid}
if chr_value in operators then
locate(c_opcode_row, c_opcode_col);
if (chr_value in operators) or
(length(value_string) < ls_len -1) then
write(chr_value);
op2_col := op2_col + 1;
do_it;
end {is valid}
else
begin {not valid}
valid := true; {reset valid indicator}
beep;
end; {not valid}
end; {done = false}
until (done);
clrScr;
end.