\ high-level commands

: quit_calc			\ exit spreadsheet
	y/n			\ ask again to be sure
	if	pos2 ." bye" previous previous
		quit-spread
	then  ;

variable marker
: forget_to_mark		\ forget formulas
	marker @ here - allot ;

: new				\ clear existing spreadsheet
	y/n			\ ask again if yes clear it
	if	0 0 spcells         
		row_max col_max bytes/cell
		* * erase	\ erase cells array
		0 row_names	\ erase row_name array
		row_max row_name_len * erase  
		0 col_names	\ erase col_name array
		col_max col_name_len * erase  
		forget_to_mark	\ erase all formulas
		row_disp off
		col_disp off	\ set marker to origin
		p" noname" application-name "copy
		dis_screen	\ display cleared screen
	then  ;

: mode				\ set auto-calculation mode
	pos1 ." set auto-calculation mode"
	pos2 ." normal=0 or auto=1: "
	skey [char] 1 = mode_flag ! ;	\ set mode_flag accordingly

: perform_calc				\ force calculations
	calc_cells  dis_data ;

: format				\ select a format
	pos1 ." select input number format"
	pos2 ." normal=0 or dollars/cents=1: "
	skey [char] 1 = format_flag !
	dis_data ;
: input_application
	pos1 ." Enter name of this spreadsheet"
	pos2 application-name char+ 10 expect  span @ application-name c!
	application-name count lower
	dis_screen ;


: again_repl				\ replicate column data
	cell_ptr cell+ @		\ bring cell data to tos
	pos1 ."  cell+column replicate cell data"
	pos2 ."  cell+number of columns: "
	#in ?dup cell+			\ get # of columns
	if	0 cell+			\ if answer <> 0
		do right_arrow		\ move right
		   dup cell_ptr cell+ !	\ and store data
		loop
		drop dis_data		\ display the new data
	then ;				\ else ignore if col=0

: cur_col_max		( -- n )
	col_max cols/page -  ;
: set_col		( col# -- )
	dup cur_col_max >  ( col# )
	if	cur_col_max tuck -  ( cur_col col_disp )
	else	0
	then
	col_disp !   cur_col ! ;
: cur_row_max	( -- n )
	row_max rows/page -  ;
: set_row	( row# -- )
	dup cur_row_max >  ( col# )
	if	cur_row_max tuck -  ( cur_col col_disp )
	else	0
	then
	row_disp !   cur_row ! ;
variable new_row
variable new_col

: do_go_to  ( row column -- )
	0 max  col_max 1- min  new_col !
	0 max  row_max 1- min  new_row !
	new_row @  row     dup rows/page +  within
	new_col @  column  dup cols/page +  within and
	if		\ Target is on screen; just move marker
		erase_cell_marker
		new_row @  row    -  row_disp !
		new_col @  column -  col_disp !
		place_cell_marker
		exit
	then
	new_row @ row  dup rows/page +  within
	if		\ Row is on screen; redisplay columns
		erase_cell_marker
		new_row @  row    -  row_disp !
		new_col @  set_col
		dis_col_change
		place_cell_marker
		exit
	then
	new_col @  column  dup cols/page +  within
	if		\ Column is on screen; redisplay rows
		erase_cell_marker
		new_row @  set_row
		new_col @  column -  col_disp !
		dis_row_change
		place_cell_marker
		exit
	then
	\ Target is off screen; reframe the whole show
	erase_cell_marker
	new_row @ set_row
	new_col @ set_col
	dis_row_names
	dis_row_labels
	dis_col_names
	dis_col_labels
	dis_data
	place_cell_marker ;
: go_to					\ go to specified row/col
	pos1 ." row(0-99): "		\ prompt for row #
	#in dup 0 row_max within	\ check for proper range
	if	( row# )		\ if ok store it
		pos2 ." column(a-z): "	\ prompt for col # (a-z)
		skey upc [char] A - dup	\ check for proper range
		0 col_max within	\ if ok goto data window
		if do_go_to else 2drop then
	else	drop
	then  ;

: the_row	( -- row# )	row     row-disp +  ;
: the_col	( -- col# )	column  col-disp +  ;

: first_col	the_row 0 do_go_to  ;
: last_col	the_row col_max 1-  do_go_to  ;
: top_row	0 the_col do_go_to  ;
: bottom_row	row_max 1- the_col  do_go_to  ;
: left_page	the_row the_col cols/page -  do_go_to  ;
: right_page	the_row the_col cols/page +  do_go_to  ;
: down_page	the_row rows/page +  the_col do_go_to  ;
: up_page	the_row rows/page -  the_col do_go_to  ;

\ operator input processing

decimal
: dispatch	( key -- )
	case
		[char] A of again_repl		endof
		[char] C of input_col_names	endof
		[char] D of input_cell_data	endof
		[char] E of input_equ		endof
		[char] F of format		endof
		[char] G of go_to		endof
		[char] M of mode		endof
		[char] N of new			endof
		[char] O of calc_order		endof
		[char] P of perform_calc	endof
		[char] Q of quit_calc		endof
		[char] R of input_row_names	endof
		[char] S of input_application	endof
		control B of left_arrow		endof
		control F of right_arrow	endof
		control N of down_arrow		endof
		control P of up_arrow		endof
		control A of first_col		endof
		control E of last_col		endof
		control Y of left_page		endof
		control U of right_page		endof
		control V of down_page		endof
		control T of up_page		endof
		control L of perform_calc	endof
		control Z of quit_calc		endof
		beep
	endcase ;
