| home | contents | previous | next page | send comment | send link | add bookmark |

tcalc.t

spread sheet

%
%   TCALC DEMONSTRATION PROGRAM 
%

include colors.t
include keys.t

const FXmax : int := 7                      % number of columns A...G    
const FYmax : int := 21                     % number of lines   1...21 
const FW    : int := 10                     % format width of numbers

const Empty : int := 0                      % cell is empty
const Expr  : int := 1                      % cell contains an expression
const Text  : int := 2                      % cell contains text

% The spreadsheet is made out of Cells every Cell is defined as 
% the following record:

type CellRec : record
    status :   int                          % status of cell  
    contents : string                       % formula or some text 
    val :      real                         % last calculated cell value 
    dec :      int                          % decimal places        
end record

type Cells : array( FXmax, FYmax ) of CellRec

var Xpos: array( FXmax ) of int             % init to = 3,14,25,36,47,58,69
var Ypos: array( FYmax ) of int             % init to = 2...22

var Sheet :    Cells                        % the spread sheet 
var FX :       int                          % column of current cell
var FY :       int                          % row of current cell
var AutoCalc : boolean                      % recalculate after each entry?
var Run : boolean                           % run spread sheet?


program

    var key : int

    cursor( 0 )
    Run := true
    Welcome
    Init                                    % wait a few seconds
    Grid
    FX := 0
    FY := 0
  
    loop

        Goto_cell( FX, FY )
        key := getkey
    
        case key of
            value key_up_arrow:
                Move_up
            value key_down_arrow:
                Move_down
            value key_right_arrow:
                Move_right
            value key_left_arrow:
                Move_left
            value key_tab:
                Get_cell( FX, FY )
            value 47:  % '/' key
                Commands
        end case

        exit when Run = false 

    end loop

    Clr_scr
    cursor( 1 )

end program


procedure Commands

    var ch : char
    label command_exit :

    locate( 24, 0 )
    putstr( "Quit, Save, Load, Clear, Recalc, Print, Format, Auto, Help ", 
            light_gray, black )

    ch := chr( getkey )

    if ch = 'Q' or ch = 'q' then
        Run := false
        goto command_exit
    end if

    case ch of 

        value 'S', 's': 
            Save
        value 'L', 'l': 
            Load
            Recalculate
            Update
        value 'C', 'c': 
            Clear
        value 'R', 'r': 
            Recalculate
            Update
        value 'P', 'p': 
            Print
        value 'F', 'f': 
            Format
        value 'A', 'a': 
            AutoCalc := not AutoCalc
            AutoMsg
        value 'H', 'h': 
            Help

    end case
  
    command_exit :
    scroll( 24, 24, 0, 79, white, black, 1 )

end Commands


procedure Welcome

    var key : int

    Clr_scr
    Center( 9, "Welcome to TCalc.")
    Center( 10, "Press any key to start" )
    
    key := getkey

    Center( 11, "Wait..." )
    
end Welcome


procedure Init

    var i, j : int

    for i := 0...FXmax-1 do

        for j := 0...FYmax-1 do

            Sheet( i, j ).status := Empty
            Sheet( i, j ).contents := ""
            Sheet( i, j ).val := 0
            Sheet( i, j ).dec := 2

            if i = 0 then
                Ypos( j ) := j + 2
            end if

        end for

        Xpos( i ) := 3 + 11 * i
    
    end for

    AutoCalc := true
    
end Init


procedure Grid

    var i, j : int

    Clr_scr
    AutoMsg

    for j := 0 ... FXmax - 1 do
        locate( 1, Xpos(j) + 5 )
        putch( chr( j + ord( 'A' ) ), green, black )
    end for

    for i := 0 ... FYmax - 1 do 
        locate( Ypos(i), 0 )
        putstr( intstr( i+1, 2 ), green, black )
    end for

    locate( 0, 0 )
    putstr( " Type / for Commands", yellow, black )

end Grid

%
% Miscellaneous utilities and commands.  
%

procedure Center( r : int,                  % row
                  s : string )              % message
    
    var c : int                             % column

    c := ( 80 - length( s ) ) div 2 
    locate( r, c )
  
    putstr( s, green, black )

end Center


procedure Msg( c : int,                     % column
               s : string )                 % message

    locate( 24, c )
    scroll( 24, 24, c, 79, white, black, 1 )
    putstr( s, white, black )

end Msg


procedure Flash( c : int,                   % column
                 s : string )               % message

    var key : int

    locate( 23, c )
    putstr( s, blink + white, black )

    key := getkey

    locate( 23, c )
    putstr( s, white, black )
    
end Flash


procedure AutoMsg

    locate( 0, 60 )
    if AutoCalc then  
        putstr( "AutoCalc: ON  ", yellow, black )
    else 
        putstr( "AutoCalc: OFF ", yellow, black )
    end if

end AutoMsg


function Is_digit( ch : char ) : boolean

    if ord( '0' ) <= ord( ch ) and ord( ch ) <= ord( '9' ) then
        return true
    else
        return false
    end if

end Is_digit


function Is_lower( ch : char ) : boolean

    if ord( 'a' ) <= ord( ch ) and ord( ch ) <= ord( 'z' ) then
        return true
    else
        return false
    end if

end Is_lower


procedure Clr_scr

    scroll( 0, 24, 0, 79, light_gray, black, 0 )

end Clr_scr


procedure FlashType

    locate( 23, 0 )
    if Empty = Sheet( FX, FY ).status then
        putstr( "Empty: ", white, black )
    elsif Expr = Sheet( FX, FY ).status  then 
        putstr( "Expr:  ", white, black )  
    elsif Text = Sheet( FX, FY ).status then 
        putstr( "Text:  ", white, black )
    end if
    
end FlashType


%
% The following procedures move between the Cells on the calc sheet.
% Each Cell is referenced by its X, Y coordinates.
%

procedure Goto_cell( x, y : int )

    var i : int
    var ch : char
    var val : real
    var dec : int
    var buffer : string

    locate( Ypos(y), Xpos(x) )
    putstr( "           ", white, blue )

    locate( Ypos(y), Xpos(x) )
    if Text = Sheet( x, y ).status then 
        
        buffer := Sheet( x, y ).contents
        for i := 0...10 do

            locate( Ypos(y), Xpos(x) + i )
            ch := buffer( i )
            exit when ch = '\0'
            putch( ch, white, blue )

        end for

        locate( 24, 0 )
        scroll( 24, 24, 0, 79, light_gray, black, 0 )
        putstr( Sheet( x, y ).contents, light_gray, black )

    elsif Expr = Sheet( x, y ).status then

        val := Sheet( x, y ).val
        dec := Sheet( x, y ).dec
    
        if dec >= 0 then 
            putstr( frealstr( val, FW, dec ), white, blue )
        else 
            putstr( realstr( val, FW ), white, blue )
        end if

        locate( 24, 0 )
        scroll( 24, 24, 0, 79, light_gray, black, 0 )
        putstr( Sheet( x, y ).contents, light_gray, black )

    else

        locate( 24, 0 )
        scroll( 24, 24, 0, 79, light_gray, black, 0 )

    end if

    FlashType
    locate( Ypos(y), Xpos(x) )

end Goto_cell


procedure Leave_cell( x, y : int )

    var i : int
    var ch : char
    var val : real
    var dec : int
    var buffer : string

    locate( Ypos(y), Xpos(x) )
    putstr( "           ", white, black )

    locate( Ypos(y), Xpos(x) )
    if Text = Sheet( x, y ).status then 

        buffer := Sheet( x, y ).contents
        for i := 0...10 do

            locate( Ypos(y), Xpos(x) + i )
            ch := buffer( i )
            exit when ch = '\0'
            putch( ch, white, black )

        end for

    elsif Expr = Sheet( x, y ).status then

        val := Sheet( x, y ).val
        dec := Sheet( x, y ).dec
    
        if dec >= 0 then 
            putstr( frealstr( val, FW, dec ), white, black )
        else 
            putstr( realstr( val, FW ), white, black )
        end if

    end if

end Leave_cell


procedure Update

    var x, y : int
         
    Msg( 0, "Updating...    " )

    for x := 0...FXmax - 1 do 
        for y := 0...FYmax - 1 do
            Leave_cell( x, y )
        end for
    end for

    Goto_cell( FX, FY )

end Update


procedure Move_down

    Leave_cell( FX, FY )

    FY := FY + 1
    if FY >= FYmax then 
       FY := 0
    end if
 
    Goto_cell( FX, FY )

end Move_down


procedure Move_up

    Leave_cell( FX, FY )

    FY := FY - 1
    if FY < 0 then 
       FY := FYmax - 1
    end if
  
    Goto_cell( FX, FY )

end Move_up


procedure Move_right

    Leave_cell( FX, FY )

    FX := FX + 1
    if FX >= FXmax then
       FX := 0
    end if

    Goto_cell( FX, FY )

end Move_right


procedure Move_left

    Leave_cell( FX, FY )

    FX := FX - 1
    if FX < 0 then
       FX := FXmax - 1
    end if
 
    Goto_cell( FX, FY )

end Move_left


%
% Read, Save, Clear, or Print a spread sheet.
% Display on-line manual.    
%

var FileName : string

procedure Get_string( col : int, var line : string )

    var i, key : int
    var buffer : string

    locate( 24, col )
    scroll( 24, 24, col, 79, white, black, 0 )

    buffer := line
    putstr( buffer, white, black )

    cursor( 1 )
    i := length( buffer )
    loop

        locate( 24, col + i )
        key := getkey 
        if key = key_back_space and i > 0 then       

            i := i - 1
            buffer( i ) := '\0'
            locate( 24, col )
            scroll( 24, 24, col, 79, white, black, 0 )
            putstr( buffer, white, black )
        
        elsif key = key_enter then  

            line := buffer
            exit

        elsif key < 32 or key > 127 then    % not text character

            % do nothing

        else

            buffer( i ) := chr( key )
            buffer( i + 1 ) := '\0'
            locate( 24, col )
            putstr( buffer, white, black )
            i := i + 1

        end if

    end loop

    cursor( 0 )

end Get_string


procedure Save

    var i, j, file : int

    Msg( 0, "Enter filename to save: " )
    FileName( 0 ) := '\0'
    Get_string( 24, FileName )
  
    if FileName ~= "" then

        file := open( FileName, "w" )
        for i := 0...FXmax-1 do
            for j := 0...FYmax-1 do
                % write Sheet( i, j ) to file
                put :file, Sheet( i, j ).status       
                put :file, Sheet( i, j ).contents    
                put :file, Sheet( i, j ).val     
                put :file, Sheet( i, j ).dec 
            end for
        end for

        if not close( file ) then
            Msg( 0, "File save failed!" )
        end if

    end if

end Save


procedure Load

    var file : int
    var item : string

    Msg( 0, "Enter filename to load: " )
    FileName( 0 ) := '\0'
    Get_string( 24, FileName )
    file := open( FileName, "r" )

    if file = 0 then

        Msg( 0, "File not Found!" )

    else

        Msg( 0, "Loading spread sheet..." )
        file := open( FileName, "r" )

        for FX := 0...FXmax-1 do
            for FY := 0...FYmax-1 do 
                % read Sheet( FX, FY ) from file
                get :file, item : *
                Sheet( FX, FY ).status := strint( item )
                get :file, item : *
                Sheet( FX, FY ).contents := item
                get :file, item : *
                Sheet( FX, FY ).val := strint( item )    
                get :file, item : *
                Sheet( FX, FY ).dec := strint( item )
            end for
        end for

        FX := 0 
        FY := 0

    end if

end Load


procedure Clear

    var ch : char

    locate( 24, 0 )
    scroll( 24, 24, 0, 79, white, black, 1 )
    putstr( "Clear this worksheet? (Y/N) ", white, black )

    loop
        ch := chr( getkey )
        exit when ch = 'Y'or ch = 'y' or ch = 'N' or ch = 'n'
    end loop

    putch( ch, white, black )

    if ch = 'Y' or ch = 'y' then
        Clr_scr
        Init
        Grid
    end if

end Clear


procedure Print

    var file : int
    var i, j, k, dec : int
    var val : real
    var ch : char
    var line : string
    var buffer : string

    Msg( 0, "Printing... " )
    file := open( "prn", "w" )

    for i := 1...5 do                       % top margin
        put :file, ""
    end for

    for i := 0...79 do
        line( i ) := ' '
    end for

    line( 80 ) := '\0'

    for i := 0 ... FXmax - 1 do
        line( Xpos( i ) + 5 ) := chr( i + ord( 'A' ) )
    end for

    line( 80 ) := '\0'

    put : file, line

    for i := 0...FYmax - 1 do

        line := intstr( i + 1, 2 )

        for j := 0...FXmax - 1 do

            if Text = Sheet( j, i ).status then 
        
                buffer := Sheet( j, i ).contents

                for k := 0...10 do

                    ch := buffer( k )
                    if ch = '\0' then
                        buffer( k ) := ' '
                    end if

                end for

            elsif Expr = Sheet( j, i ).status then

                val := Sheet( j, i ).val
                dec := Sheet( j, i ).dec
    
                if dec >= 0 then 
                    buffer := frealstr( val, 11, dec )
                else 
                    buffer :=  realstr( val, 11 )
                end if

            else

                buffer := "           "     % eleven spaces

            end if

            buffer( 11 ) := '\0'            % null terminate

            line := line & buffer

        end for

        put : file, line

    end for 

    assert close( file )

end Print


procedure Format

    var buffer : string
    var i, dec : int

    Msg( 0, "Decimal places ( 0...6 ): " )
    buffer( 0 ) := '\0'
    Get_string( 26, buffer )
    dec := strint( buffer )

    if dec >= 0 or dec <= 6 then

        for i := 0...FYmax - 1 do
            Sheet( FX, i ).dec := dec
        end for

    end if

end Format


procedure Help

    var ch : char
    var hf : int
    var line : string( 80 )
    var i, j, k : int
    var bold : boolean
    var fg : int

    hf := open( "tcalc.hlp", "r" )

    if hf ~= 0 then

        loop

            Clr_scr 
            bold := false 
            fg := light_gray
            i := 0
            j := 0
            loop

                get :hf, line:*
                exit when eof( hf ) 

                for k := 0...length( line ) do
                    if line( k ) = '|' then
                        bold := not bold
                        if bold then 
                            fg := white 
                        else 
                            fg := light_gray
                        end if
                    else
                        locate( i, j )
                        putch( line( k ), fg, black )
                        j := j + 1
                    end if
                end for

                exit when i >= 19
                i := i + 1
                j := 0

            end loop

            exit when eof( hf )

            locate( 24, 0 ) 
            putstr( "Press any key... ", white, black )
            ch := chr( getkey )

        end loop

        assert close( hf )     
        locate( 24, 0 ) 
        putstr( "Done, press any key... ", white, black )
        ch := chr( getkey )
        Grid
        Update
  
    else    % Help file did not exist 

        Msg( 0, "To get help the file TCALC.HLP must be on your disk. " )
        ch := chr( getkey )

    end if

end Help

%
% This is the part of the program which runs the spread sheet by
% processing individual cells, evaluating formulas, and
% recalculating and updating spread sheet.
%

type code : enum( eol, err, equ, number, cell, 
                  plus, minus, star, slash,
                  left_p, right_p, 
                  absolute, arc_tangent,
                  cosine, 
                  exponent, 
                  log_e, log_10, 
                  sine, square, square_root )

var Token : code
var Token_value : real
var X, Y : int
var Error : boolean
var Ch : char
var Pos : int
var Cell : string
var Stack : array( 16 ) of real
var Tos : int

%
%   "Get_cell" is used to enter or modify the contents of a cell
%
procedure Get_cell( x : int, y : int )

    var i, j, key, error : int
    var buffer : string

    locate( 24, 0 )
    scroll( 24, 24, 0, 79, white, black, 0 )

    buffer := Sheet( x, y ).contents
    putstr( buffer, white, black )

    cursor( 1 )
    i := length( buffer )
    loop

        locate( 24, 0 )
        scroll( 24, 24, 0, 79, white, black, 0 )
        putstr( buffer, white, black )
        locate( 24, i )

        watch( i )
        watch( buffer )

        key := getkey 

        if key = key_esc then

            exit

        elsif key = key_enter then  

            if buffer( 0 ) = '=' then

                Sheet( x, y ).contents := buffer
                error := Evaluate( x, y )

                if error = 0 then

                    Sheet( x, y ).status := Expr
                    if AutoCalc then
                        cursor( 0 )
                        Recalculate
                        Update
                    end if

                else

                    Sheet( x, y ).status := Text
                    Flash( 0, "ERROR " )
                    locate( 24, error )
                    key := getkey

                end if

            else

                Sheet( x, y ).contents := buffer
                Sheet( x, y ).status := Text

            end if

            exit

        elsif key = key_back_space and i > 0 then       

            i := i - 1

            j := i
            loop
                buffer( j ) := buffer( j + 1 )
                exit when buffer( j ) = '\0'
                j := succ( j )
            end loop    

        elsif key = key_delete then       

            j := i
            loop
                buffer( j ) := buffer( j + 1 )
                exit when buffer( j ) = '\0'
                j := succ( j )
            end loop    

        elsif key = key_left_arrow and i > 0 then       

            i := i - 1

        elsif key = key_right_arrow and buffer( i ) ~= '\0' then       

            i := i + 1

        elsif key < 32 or key > 127 then    % not t

            % do nothing

        else

            j := i
            loop
                exit when buffer( j ) = '\0'
                j := succ( j )
            end loop

            loop
                buffer( j + 1 ) := buffer( j )
                exit when j = i
                j := pred( j )
            end loop    

            buffer( i ) := chr( key )
            i := i + 1

        end if

    end loop

    cursor( 0 )
    locate( 24, 0 )
    scroll( 24, 24, 0, 79, white, black, 0 )

end Get_cell


procedure Next_Ch

    Ch := Cell( Pos ) 
    Pos := Pos + 1
    watch( Ch )
        
end Next_Ch


procedure Get_Token

    loop 
        Next_Ch
        exit when Ch ~= ' '
    end loop
       
    if Ch = 'A' or Ch = 'B' or Ch = 'C' or Ch = 'D' or
       Ch = 'E' or Ch = 'F' or Ch = 'G' then
        Get_cell_number
    elsif Is_lower( Ch ) then
        Get_function
    elsif Is_digit( Ch ) then
        Token := code.number
        Get_number
    elsif Ch = '\0' then
        Token := code.eol
    elsif Ch = '=' then
        Token := code.equ
    elsif Ch = '+' then
        Token := code.plus
    elsif Ch = '-' then
        Token := code.minus
    elsif Ch = '*' then
        Token := code.star
    elsif Ch = '/' then
        Token := code.slash
    elsif Ch = '(' then
        Token := code.left_p
    elsif Ch = ')' then
        Token := code.right_p
    else
        Token := code.err
    end if

end Get_Token
 

procedure Get_cell_number

    var j : int := 0                        % start of number string
    var number : string                     % buffer for conversion

    X := ord( Ch ) - ord( 'A' )

    loop                                    % get integer part

        Next_Ch
        number( j ) := Ch
        j := j + 1
      
        continue when Is_digit( Ch ) 

        Pos := Pos - 1                      % backup
        number( j ) := '\0'                 % null terminate string

        exit

    end loop
    
    Y := strint( number ) - 1

    watch( X )
    watch( Y )

    if Y < 0 or Y > 20 then
        Error := true
    else
        Token := code.cell
    end if

end Get_cell_number


procedure Get_function

    var buffer : string
    var i : int := 0

    loop
        exit when not Is_lower( Ch )
        buffer( i ) := Ch
        i := succ( i )
        Next_Ch 
    end loop

    Pos := Pos - 1                          % backup
    buffer( i ) := '\0'
    watch( buffer )

    if buffer = "abs" then
        Token := code.absolute
    elsif buffer = "atan" then
        Token := code.arc_tangent
    elsif buffer = "cos" then
        Token := code.cosine
    elsif buffer = "exp" then
        Token := code.exponent
    elsif buffer = "ln" then
        Token := code.log_e
    elsif buffer = "log" then
        Token := code.log_10
    elsif buffer = "sin" then
        Token := code.sine
    elsif buffer = "sqr" then
        Token := code.square
    elsif buffer = "sqrt" then
        Token := code.square_root
    else
        Token := code.err
    end if

end Get_function


procedure Get_number

    var j : int := 0                        % start of number string
    var number : string                     % buffer for conversion

    Pos := Pos-1
    loop                                    % get integer part

        Next_Ch
        number( j ) := Ch
        j := j + 1
      
        continue when Is_digit( Ch ) 

        if Ch = '.' then          

            loop                            % get fractional part

                Next_Ch
                number( j ) := Ch
                j := j + 1

                continue when Is_digit( Ch ) 

                exit

            end loop

        end if

        Pos := Pos - 1                      % backup
        number( j ) := '\0'                 % null terminate string

        exit

    end loop
    
    Token_value := strreal( number )
    watch( Token_value )

end Get_number


function Evaluate( x, y : int ) : int

    var i, err_pos : int

    Cell := Sheet( x, y ).contents
    watch( Cell )
    Pos := 0 
    Tos := 0
    Error := false
    Get_Token                               % first
    if Token = code.equ then    
       Get_Token                            % after "="
    else
       Error := true
    end if

    Expression
    if Error then 
        err_pos := Pos 
    else 
        err_pos := 0
        watch( Tos )
        watch( Stack( Tos ) )
        Sheet( x, y ).val := Stack( Tos )
    end if

    return err_pos

end Evaluate

%
%   "Expression" parses:
%
%             <term> { +,- <term> }
%
procedure Expression

    var op : code                           % an operator token
    var unary_op : code

    unary_op := code.plus

    if Token = code.plus or                 % look for a unary operator
       Token = code.minus then

        unary_op := Token
        Get_Token                           % after unary operator

    end if

    Term                                    % get first term
    if Error then
        return
    end if

    if unary_op = code.minus then

        Stack( Tos ) := - Stack( Tos )
        watch( Stack( Tos ) )

    end if

    loop

        exit when Token ~= code.plus and 
                  Token ~= code.minus 

        op := Token                         % save operator

        Get_Token                           % after operator

        Term                                % get next term(s)
        if Error then
            return
        end if

        %
        % perform the operation
        %
        if op = code.plus then
            Stack( Tos - 1 ) := Stack( Tos - 1 ) + Stack( Tos )
        else
            Stack( Tos - 1 ) := Stack( Tos - 1 ) - Stack( Tos )
        end if

        watch( Stack( Tos ) )
        Tos := Tos - 1 
        watch( Stack( Tos ) )

    end loop

end Expression

%
%   "Term" parses:
%
%             <factor> { *,/ <factor> }
%
procedure Term

    var op : code                           % an operator token

    Factor                                  % get first factor
    if Error then
        return
    end if

    loop

        exit when Token ~= code.star and
                  Token ~= code.slash

        op := Token                         % save operator

        Get_Token                           % after operator

        Factor                              % get next factor
        if Error then
            return
        end if

        %
        % perform the operation
        %
        if op = code.star then

            Stack( Tos - 1 ) := Stack( Tos - 1 ) * Stack( Tos )

        else

            if Stack( Tos ) = 0 then
                Error := true               % division by zero
                return
            end if
                   
            Stack( Tos - 1 ) := Stack( Tos - 1 ) / Stack( Tos )

        end if

        watch( Stack( Tos ) )
        Tos := Tos - 1
        watch( Stack( Tos ) )

    end loop

end Term

%
%   "Factor" processes any of:
%
%             a cell reference
%             a function call
%             a literal real
%
procedure Factor

    case Token of

        value code.number:
            Tos := Tos + 1
            Stack( Tos ) := Token_value 
            Get_Token                       % after <number>

        value code.cell:
            if Sheet( X, Y ).status = Expr then
                Tos := Tos + 1
                Stack( Tos ) := Sheet( X, Y ).val
                Get_Token
            else
                Error := true
            end if

        value code.absolute,
              code.arc_tangent,
              code.cosine,
              code.exponent,
              code.log_e,
              code.log_10,
              code.sine,
              code.square,
              code.square_root:
            Call_function

        value code.left_p:
            Get_Token                       % after "("
            Expression                      % and get next token
            if Error then
                return
            elsif Token = code.right_p then
                Get_Token                   % after ")"
            else
                Error := true
            end if

        value:
            Error := true

    end case

    watch( Stack( Tos ) )

end Factor


procedure Call_function

    var fn : code

    fn := Token                             % save function code

    Get_Token

    if Token = code.left_p then

        Get_Token
        Expression                          % and get next token

        if Error then
            return
        elsif Token = code.right_p then
            Exc_function( fn )
            Get_Token                       % after ")"
        else
            Error := true
            return
        end if

    else

        Error := true
        return

    end if

end Call_function


procedure Exc_function( fn : code )

    case fn of

        value code.absolute:
            Stack( Tos ) := abs( Stack( Tos ) )

        value code.arc_tangent:
            Stack( Tos ) := arctan( Stack( Tos ) )

        value code.cosine:
            Stack( Tos ) := cos( Stack( Tos ) )

        value code.exponent:
            Stack( Tos ) := exp( Stack( Tos ) )

        value code.log_e:
            Stack( Tos ) := ln( Stack( Tos ) )

        value code.log_10:
            Stack( Tos ) := log10( Stack( Tos ) )

        value code.sine:
            Stack( Tos ) := sin( Stack( Tos ) )

        value code.square:
            Stack( Tos ) := Stack( Tos ) * Stack( Tos )

        value code.square_root:
            Stack( Tos ) := sqrt( Stack( Tos ) )

        value:
            assert false

   end case

end Exc_function


procedure Recalculate

    var x, y, error, key : int

    Msg( 0, "Calculating... " )

    for y := 0...FYmax-1 do 

        for x := 0...FXmax-1 do

            if Sheet( x, y ).status = Expr then

                error := Evaluate( x, y )
                if error = 0 then
                    Sheet( x, y ).status := Expr
                else
                    Sheet( x, y ).status := Text
                    Goto_cell( x, y )
                    Flash( 0, "ERROR " )
                    locate( 24, error )
                    key := getkey
                end if

            end if

        end for

    end for

end Recalculate
colors.t
%
% color codes for graphics functions
%
const black         : int := 0
const blue          : int := 1
const green         : int := 2
const cyan          : int := 3
const red           : int := 4
const magenta       : int := 5
const brown         : int := 6
const light_gray    : int := 7
const dark_gray     : int := 8
const light_blue    : int := 9
const light_green   : int := 10
const light_cyan    : int := 11
const light_red     : int := 12
const light_magenta : int := 13
const yellow        : int := 14
const white         : int := 15
const blink         : int := 128
keys.t
%
% key board key codes returned by getkey standard function
%
const key_back_space  : int :=   8
const key_tab         : int :=   9
const key_enter       : int :=  13
const key_esc         : int :=  27
const key_home        : int := 327
const key_up_arrow    : int := 328
const key_page_up     : int := 329
const key_left_arrow  : int := 331
const key_right_arrow : int := 333
const key_end         : int := 335
const key_down_arrow  : int := 336
const key_page_down   : int := 337
const key_insert      : int := 338
const key_delete      : int := 339
tcalc.hlp
                    |INTRODUCTION|


TCalc is a tiny spread sheet program.  It is provided as an example program
to help you learn the T programming language.  It may have some bugs in it.

The spread sheet is an electronic piece of paper on which you can 
enter text and arithmetic expressions with calculations done 
automatically or manually on command.

|Since it is only a demonstation program, it does have some limitations:
You cannot:|

  - copy from cells to other cells,

  - insert or delete lines or columns,

  - change cell widths.


|In spite of its limitations TCalc does provide some useful features.
You can:|

  - use built in mathematical functions ( abs, cos, ln, exp ... ),

  - save spread sheets to disk,

  - load spread sheets from disk,

  - print spread sheets,

  - clear spread sheets,

  - automatically or manually recalculate cell values,

  - change the numerical precision of cell values.




|This is what the spread sheet looks like:|

       A          B         C         D      . . . .
 1   14.00
 2    7.00
 3    4.00
 4    3.00
 5   28.00
 .
 .

|Expr:|
= A1 + A2 + A3 + A4

In the example the active cell is  |A5|  which contains the 
expression: = A1 + A2 + A3 + A4  shown in the text entry window.

The resulting value of the expression is shown on the spread sheet.


|Entering data|

A cell may contain an arithmetic expression or text. The type of the cell
is shown in the bottom left corner of the screen above the text entry line:

|Empty:|  - current cell is empty, neither text nor expression

|Text: |  - current cell contains text

|Expr: |  - current cell contains an arithmetic expression

To enter data in any field select the active cell using the arrow keys,
press |Tab|, and enter data at the cursor location.  

If you enter "=" at the extreme left, the line is assumed to be 
an arithmetic expression; otherwise it is assumed to be text.




|The following are examples of valid expressions:|

= 2
= 3.14159
= A1 / ( B2 - C7 )   
= sin( A1 ) * cos( A2 )
= 1.2 * ln( A1 + B1 ) + C1

|operators:|

+   add  
-   subtract
*   multiply
/   divide

|standard functions:|

abs, atan, cos, exp, ln, log, sin, sqr, sqrt


|Editing data|

To edit an existing formula or text simply move to the cell and
press |Tab|, make your changes and press |Enter|.  If you make
a mistake you can press |Esc|; the contents of the cell will
not be changed.

|When editing a field|

    |left arrow|   moves cursor to the left.
    |right arrow|  moves cursor to the right.
    |Back Space|   deletes the charater to the left of the cursor.
    |Delete|       deletes the character at the cursor.
    |Esc|          exits without changes to the cell.
    |Enter|        exits and processes changes to the cell.





|Commands:|

    |Q|uit TCalc

    |S|ave a spread sheet on the disk.

    |L|oad a spread sheet from the disk.

    |C|lear the current spread sheet.

    |R|ecalculate the values of the spread sheet.

    |P|rint the spread sheet.

    |F|ormat the numerical precision of values.

    |A|utomatic/manual recalculation mode switch.


| home | contents | previous | next page | send comment | send link | add bookmark |

Copyright © 2004, Stephen R. Schmitt