home *** CD-ROM | disk | FTP | other *** search
- 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.
-