

{$M+}
{$E+}

PROGRAM Mock;

   {$I i:\opus.i}
   {$I i:\gctv.inc}
   
   {$I i:\gemsubs.def}
   {$I i:\globsubs.def}
   {$I i:\vdi_aes.def}
   {$I d:\pascal\opus\gemdos.def}
   {$I d:\pascal\opus\resource.def}
   {$I d:\pascal\opus\graphout.def}
   {$I d:\pascal\opus\stringfn.def}

PROCEDURE DO_PRINT ( s_row,f_row,s_col,f_col : INTEGER; hdl : INTEGER );
   EXTERNAL;

PROCEDURE HILIGHT_BLOCK;
   { either does inverse the block or restores it to normal depending on
     whether already inversed or not }
   VAR i,j : INTEGER;
   BEGIN
       Hide_Mouse;
       Work_Rect(act_hdl,x_1,y_1,w_1,h_1);
       Set_Clip(x_1,y_1,w_1,h_1);
       FOR i := start_row TO virtual_f_row DO
           FOR j := start_col TO virtual_f_col DO
               IF (i >= b_s_row) AND (i <= b_e_row) AND
                  (j >= b_s_col) AND (j <= b_e_col) THEN
                  toggle_inverse(Black,i,j);
       IF n_hdls = 2 THEN BEGIN
          switch_window;
          Send_Redraw(FALSE,0,0,screen_width,screen_height);
          switch_window
       END;
       Show_Mouse
   END; { HILIGHT_BLOCK }

FUNCTION START_BLOCK : BOOLEAN;
   VAR temp : INTEGER;
   BEGIN
       IF block_set THEN
          hilight_block;
       b_s_row := data_row;
       b_s_col := data_col;
       block_st_set := TRUE;
       IF block_end_set THEN BEGIN
          IF b_s_row > b_e_row THEN BEGIN
             temp := b_e_row;
             b_e_row := b_s_row;
             b_s_row := temp
          END;
          IF b_s_col > b_e_col THEN BEGIN
             temp := b_e_col;
             b_e_col := b_s_col;
             b_s_col := temp
          END;
          block_set := TRUE;
          hilight_block;
          adjust_menu(TRUE)
       END;   
       start_block := block_set
   END; { START_BLOCK }

FUNCTION END_BLOCK : BOOLEAN;
   VAR temp : INTEGER;
   BEGIN
       IF block_set THEN
          hilight_block;
       b_e_row := data_row;
       b_e_col := data_col;
       block_end_set := TRUE;
       IF block_st_set THEN BEGIN
          IF b_s_row > b_e_row THEN BEGIN
             temp := b_e_row;
             b_e_row := b_s_row;
             b_s_row := temp
          END;
          IF b_s_col > b_e_col THEN BEGIN
             temp := b_e_col;
             b_e_col := b_s_col;
             b_s_col := temp
          END;
          block_set := TRUE;
          hilight_block;
          adjust_menu(TRUE)
       END;   
       end_block := block_set
   END; { END_BLOCK }

FUNCTION DESELECT_BLOCK : BOOLEAN;
   VAR i,j,row,col : INTEGER;
   BEGIN
       IF block_set THEN
          hilight_block;
       adjust_menu(FALSE);
       block_set := FALSE;
       block_st_set := FALSE;
       block_end_set := FALSE;
       deselect_block := TRUE
   END; { DESELECT_BLOCK }

PROCEDURE DELETE_BLOCK;
   VAR i,j        : INTEGER;
       successful : BOOLEAN;
   BEGIN
       temp := CONCAT('[3][Do you really wish to DELETE|' ,
                          'the block? Data will be|' ,
                          'irreversibly lost!]',
                          '[ Cancel |OK]');
       IF Do_Alert(temp,2) = 2 THEN BEGIN
          Set_Mouse(M_Bee);
          delete_range(b_s_row,b_s_col,b_e_row,b_e_col,TRUE);
          successful := deselect_block;
          block_set := FALSE;
          block_st_set := FALSE;
          block_end_set := FALSE;
          Set_Mouse(M_Arrow)
       END
   END; { DELETE_BLOCK }
   
FUNCTION DO_PASTE ( src_row,   { nominally the row of origin }
                    dest_row,  { row number to be pasted to }
                    dest_col,  { col number to be pasted at }
                    st_r,st_c, { definitions of the source block }
                    e_r,e_c        : INTEGER;
                    do_relative,
                    draw           : BOOLEAN  ) : BOOLEAN;
   { This function is used by SHIFT_BLOCK and LOAD_FILE when "load block at
     cursor" was chosen.  It assumes that a buffer row has been built in 
     row 0, and src_row should equal the current row number within the
     source block. It operates ONE row at a time. }
   VAR col,offset    : INTEGER;
       quit          : BOOLEAN;
       ptr,ptr1,ptr2 : CellPtr;
   BEGIN   
       offset := dest_col-st_c;
       quit := FALSE;
       ptr1 := data[0];
       WHILE (ptr1 <> NIL) AND (NOT quit) DO BEGIN
          col := ptr1^.c+offset;
          IF comp_assign(0,ptr1^.c,dest_row,col,FALSE) THEN BEGIN
             ptr2 := locate_cell(dest_row,col);
             IF ptr2 <> NIL THEN
                IF (ptr2^.class = Expr) AND
                   (ptr2^.status <> Empty) THEN BEGIN
                   IF do_relative THEN { adjust refs within block }
                      IF adjust_expr(adj_refs,ptr2,src_row,ptr1^.c,
                                     dest_row,col,
                                     st_r,st_c,e_r,e_c) <> OK THEN
                         quit := TRUE; { OutOfRange error }
                   IF NOT quit THEN      
                      all_lists(add,ptr2,dest_row,col);
                END
          END
          ELSE BEGIN
             Set_Mouse ( M_Arrow );
             out_mem_cell(dest_row,ptr1^.c,'pasted to');
             alert := Do_Alert(temp,1);
             quit := TRUE
          END;
          IF draw THEN
             cell_on_screen(1,dest_row,col,TRUE);
          delete_cell(0,ptr1^.c,FALSE); { free slot in buffer }
          ptr1 := data[0] { start of list }
       END; { WHILE }
       do_paste := NOT quit;
       clear_buffer
   END; { DO_PASTE }       

PROCEDURE SHIFT_BLOCK ( action,
                        dest_r,dest_c,
                        st_r,st_c,e_r,e_c  : INTEGER );
   { procedure physically moves/copies and redraws a block defined by
     the block bouds parameters. Called by transport block with action of
     mmove, mcopy; called by sheet_insert with action of mmove to insert a
     row or column }
   LABEL 1;
   VAR i,j,m,n,r,offset,
       b_row_begin,b_row_end,
       d_row_begin,d_row_end,
       row_inc,num_rows,num_cols : INTEGER;
       do_relative,dummy,done    : BOOLEAN;
       ptr                       : CellPtr;
   { use a work_cell because we need to use comp_assign which expects
     whole cell arguments and since the source str may be altered if
     it is an Expr and contains relative cell refs; this way, the 
     source is left alone, which is what we want if say, we're copying }
   BEGIN { SHIFT_BLOCK }
       num_rows := e_r-st_r+1;
       num_cols := e_c-st_c+1;
       temp:='[2][Treat cell references as:][ Absolute | Relative ]';
       IF Do_Alert(temp,2) = 2 THEN
          do_relative := TRUE
       ELSE
          do_relative := FALSE;
       IF st_r > dest_r THEN BEGIN
          b_row_begin := st_r;
          b_row_end := e_r;
          d_row_begin := dest_r;
          d_row_end := dest_r+num_rows-1;
          row_inc := 1;
       END
       ELSE BEGIN
          b_row_begin := e_r;
          b_row_end := st_r;
          d_row_begin := dest_r+num_rows-1;
          d_row_end := dest_r;
          row_inc := -1;
       END;
       done := FALSE;
       Set_Mouse(M_Bee);
       m := b_row_begin;
       i := d_row_begin;
       offset := dest_c-st_c;
       clear_buffer;
       WHILE NOT done DO BEGIN
          { build buffer area }
          ptr := data[m];
          WHILE ptr <> NIL DO BEGIN
             IF (ptr^.c >= st_c) AND (ptr^.c <= e_c) THEN BEGIN
                IF NOT comp_assign(m,ptr^.c,0,ptr^.c,FALSE) THEN BEGIN
                   int_to_string(m,temp);
                   temp := CONCAT('[3][Not enough memory to build|' ,
                                      'buffer row therefore row|' ,
                                      temp ,
                                      ' was not pasted.][ Cancel ]');
                   alert := Do_Alert(temp,1);
                   GOTO 1
                END
             END;
             ptr := ptr^.next
          END;
          { wait to delete source row until buffer row is constructed since
            if out of mem occurred, and we deleted as we went along, the row
            up to that point would be gone }
          IF action = mmove THEN 
             delete_range(m,st_c,m,e_c,TRUE);
          { delete the dest row }   
          delete_range(i,dest_c,i,dest_c+num_cols-1,TRUE);   
          { finally do the paste, deleting the buffer as we go, so chances of
            an out of mem error are exceedingly small }
          IF NOT do_paste(m,i,dest_c,st_r,st_c,e_r,e_c,
                          do_relative,TRUE) THEN
             GOTO 1;
          IF i = d_row_end THEN
             done := TRUE
          ELSE BEGIN
             i := i+row_inc;
             m := m+row_inc
          END
       END; { WHILE NOT done }
1:     clear_buffer; { just in case }
       Set_Mouse(M_Arrow)
   END; { SHIFT_BLOCK }

FUNCTION TRANSPORT_BLOCK ( action : INTEGER ) : BOOLEAN;
   { depending on action, copies or moves a marked block to another
     location, beginning at the current cell. Also copies cell_format
     regardless of action. Possible values are: mmove, mcopy }
   LABEL 2;
   VAR
       num_rows,num_cols : INTEGER;
       a,b               : STR10;
       dummy             : BOOLEAN;
   BEGIN
       num_rows := b_e_row-b_s_row+1;
       num_cols := b_e_col-b_s_col+1;
       transport_block := FALSE;
       IF (data_row+num_rows-1 <= n_rows) AND
          (data_col+num_cols-1 <= n_cols) THEN BEGIN
          IF (data_row = b_s_row) AND (data_col = b_s_col) THEN BEGIN
             temp := CONCAT('[3][You may not copy or move|' ,
                                'a block to itself! Move the|' ,
                                'cursor to a position other|' ,
                                'than the start of the block.][  OK  ]');
             alert := Do_Alert(temp,1);
             GOTO 2 { exit }
          END;
          IF action = mmove THEN
             temp := 'MOVE'
          ELSE
             temp := 'COPY';
          temp := CONCAT('[2][Really ' , temp , ' block?][ Cancel |OK]');
          IF Do_Alert(temp,2) = 2 THEN BEGIN
             shift_block(action,data_row,data_col,b_s_row,b_s_col,
                         b_e_row,b_e_col);
             IF action = mmove THEN BEGIN
                dummy := deselect_block;
                block_set := TRUE;
                block_st_set := TRUE;
                block_end_set := TRUE;
                b_s_row := data_row;
                b_s_col := data_col;
                b_e_row := data_row+num_rows-1;
                b_e_col := data_col+num_cols-1;
                adjust_menu(TRUE);
                hilight_block
             END   
          END               
          ELSE { falls through }
       END
       ELSE BEGIN
          a := col_name[n_cols-num_cols+1];
          int_to_string(n_rows-num_rows+1,b);
          block_too_big(a,b);
          transport_block := FALSE
       END;
2: END; { TRANSPORT_BLOCK }


(************************************************************************)
(*                             File IO                                  *)
(************************************************************************)



PROCEDURE ACTION_BANNER ( action : STR10 );
   BEGIN
       Hide_Mouse;
       fo_x := 512;
       IF rez = 1 THEN
          fo_y := 57
       ELSE
          fo_y := 29;
       Form_Anywhere(action_ptr,fo_x,fo_y,fo_w,fo_h);
       fo_x := fo_x-3; { now account for outline around dialog, since }
       fo_y := fo_y-3; { the width and height in the object def don't }
       fo_w := fo_w+6;
       fo_h := fo_h+6;
       Set_Text(action_ptr,actwhat,action,s1,10);
       Form_Dial(0,0,0,0,0,fo_x,fo_y,fo_w,fo_h);
       Obj_Draw(action_ptr,Root,Max_Depth,fo_x,fo_y,fo_w,fo_h);
       Show_Mouse
   END; { ACTION_BANNER }

FUNCTION FILE_TO_C ( VAR whole_name : STRING; 
                     VAR c_name     : C_STRING;
                     what           : DiskIoOps ) : BOOLEAN;
   { GEMDOS wants a "C" type string }                  
   BEGIN
       IF POS('.',whole_name) = 0 THEN
          IF what = SaveText THEN
             whole_name := CONCAT(whole_name,'.DOC')
          ELSE
             whole_name := CONCAT(whole_name,'.OPS');
       IF Filename(whole_name) THEN BEGIN
          Pascal_To_C(whole_name,c_name);
          file_to_c := TRUE
       END
       ELSE
          file_to_c := FALSE   
   END; { FILE_TO_C }
   
FUNCTION GET_FILE_NAME ( VAR c_name : C_STRING;
                         what       : DiskIoOps ) : BOOLEAN;
   { present file selector }
   VAR i : INTEGER;
   BEGIN
       get_file_name := FALSE;
       IF what = SaveText THEN
          i := 2
       ELSE
          i := 1;
       IF Get_In_File(default_path[i],current_file) THEN { user pressed OK }
          IF file_to_c(current_file,c_name,what) THEN { valid file name? }
             get_file_name := TRUE
          ELSE { oh oh }
             alert := Do_Alert('[1][Bad path/file name.][ Cancel ]',1)
   END; { GET_FILE_NAME }
   
FUNCTION CREATE_FILE ( VAR c_name : C_STRING; VAR handle : INTEGER ) : BOOLEAN;
   BEGIN
       handle := TOS_Create(c_name,0);
       IF handle >= 0 THEN
          create_file := TRUE
       ELSE BEGIN
          create_file := FALSE;
          Form_Error(handle)
       END   
   END; { CREATE_FILE }       
          
FUNCTION OPEN_FILE ( VAR c_name : C_STRING; VAR handle : INTEGER ) : BOOLEAN;
   BEGIN   
       handle := TOS_Open(c_name,0);
       IF handle >= 0 THEN
          open_file := TRUE
       ELSE BEGIN
          open_file := FALSE;
          Form_Error(handle)
       END
   END; { OPEN_FILE }

PROCEDURE CLOSE_FILE ( handle : INTEGER );
   BEGIN
       handle := TOS_Close(handle);
       IF handle < 0 THEN { probably will never happen }
          Form_Error(handle)
   END; { CLOSE_FILE }
   
PROCEDURE SAVE_FILE ( what : DiskIoOps; s_r,s_c,e_r,e_c : INTEGER );
   LABEL 1;
   VAR count                                   : BYTE;
       i,j,k,m,handle,result                   : INTEGER;
       quit                                    : BOOLEAN;
       c_name                                  : C_STRING;
       converter                               : Switcheroo;
       int_buffer                              : HundredInts;
       byte_buffer                             : ThreeHundredBytes;
       ptr                                     : CellPtr;
   FUNCTION Int_Write (     handle : INTEGER; n : LONG_INTEGER;
                        VAR buf : HundredInts ) : LONG_INTEGER;
      GEMDOS ($40);
   PROCEDURE WRITE_BYTES ( n : LONG_INTEGER; VAR buffer : ThreeHundredBytes );
      VAR bytes_written : LONG_INTEGER;
      BEGIN
          bytes_written := TOS_Write(handle,n,buffer);
          IF bytes_written <> n THEN BEGIN
             IF bytes_written >= 0 THEN
                alert := Do_Alert('[1][Not enough room on disk.][ Cancel ]',1)
             ELSE
                Form_Error(bytes_written);   
             GOTO 1 { quick exit }
          END   
      END; { WRITE_BYTES }   
   PROCEDURE WRITE_INTS ( n : LONG_INTEGER; VAR buffer : HundredInts );
      VAR ints_written : LONG_INTEGER;
      BEGIN
          ints_written := Int_Write(handle,n,buffer);
          IF ints_written <> n THEN BEGIN
             IF ints_written >= 0 THEN
                alert := Do_Alert('[1][Not enough room on disk.][ Cancel ]',1)
             ELSE
                Form_Error(ints_written);   
             GOTO 1 { quick exit }
          END   
      END; { WRITE_BYTES }   
   BEGIN
       IF what = SaveFile THEN { let user know what he's doing }
          action_banner('Save Sheet')
       ELSE
          action_banner('Save Block');
       IF get_file_name(c_name,what) THEN { valid file name? }
          IF create_file(c_name,handle) THEN BEGIN { able to write to disk? }
             Set_Mouse(M_Bee);
             byte_buffer[1] := 1;  { write some numbers to indicate it's our }
             byte_buffer[2] := 14; { file }
             byte_buffer[3] := 85;
             byte_buffer[4] := 10;
             byte_buffer[5] := 22;
             byte_buffer[6] := 84;
             write_bytes(6,byte_buffer);
             converter.str := p_title_1; { save the printer titles }
             write_bytes(LENGTH(p_title_1)+1,converter.switched);
             converter.str := p_title_2;
             write_bytes(LENGTH(p_title_2)+1,converter.switched);
             converter.str := header;
             write_bytes(LENGTH(header)+1,converter.switched);
             converter.str := footer;
             write_bytes(LENGTH(footer)+1,converter.switched);
             byte_buffer[1] := ORD(p_row_col); { print dialog variables }
             byte_buffer[2] := ORD(print_formulas);
             byte_buffer[3] := ORD(condensed_print);
             byte_buffer[4] := ORD(draft_final);
             byte_buffer[5] := ORD(grid_flag); { system variables }
             byte_buffer[6] := ORD(small_text);
             byte_buffer[7] := ORD(form_flag);
             byte_buffer[8] := ORD(auto_cursor);
             byte_buffer[9] := ORD(auto_recalc);
             byte_buffer[10] := ORD(natural);
             byte_buffer[11] := ORD(cursor_direction);
             FOR i := 12 TO n_cols+11 DO { column widths }
                 byte_buffer[i] := col_width[i-11,spaces];
             write_bytes(n_cols+11,byte_buffer); { and write it to disk }
             int_buffer[1] := default_format;
             int_buffer[2] := s_r; { the coordinates of block we are writing }
             int_buffer[3] := s_c;
             int_buffer[4] := e_r;
             int_buffer[5] := e_c;
             i := 1; { prepare to save marks }
             j := 6;
             WHILE i < 5 DO BEGIN
                int_buffer[j] := marks[i].row;
                j := j+1;
                int_buffer[j] := marks[i].col;
                j := j+1;
                i := i+1
             END;
             int_buffer[14] := freeze_row;
             int_buffer[15] := freeze_col;
             write_ints(30,int_buffer);
             FOR i := 1 TO n_rows DO BEGIN { do this way so a block may be    }
                 ptr := data[i];           { easily loaded as if it was an    }
                 count := 0;               { entire sheet. No extra data is   }
                 WHILE ptr <> NIL DO BEGIN { saved, beyond count for each row }
                    IF (i >= s_r) AND (i <= e_r) AND
                       (ptr^.c >= s_c) AND (ptr^.c <= e_c) THEN
                       count := count+1;
                    ptr := ptr^.next
                 END;
                 byte_buffer[1] := count;    { so each row 1..999 has a count }
                 write_bytes(1,byte_buffer); { of number cells in itself }
                 IF (count > 0) AND { only write to disk if we are in range }         
                    (i >= s_r) AND (i <= e_r) THEN BEGIN
                    quit := FALSE;
                    ptr := data[i];            
                    WHILE (ptr <> NIL) AND (NOT (quit)) DO BEGIN
                       WITH ptr^ DO 
                          IF (c >= s_c) AND (c <= e_c) THEN BEGIN
                             converter.c := c;
                             write_bytes(2,converter.switched);
                             converter.format := format;
                             write_bytes(2,converter.switched);
                             converter.class := class;
                             write_bytes(2,converter.switched);
                             converter.status := status;
                             write_bytes(2,converter.switched);
                             IF ((class = Val) OR (class = Expr)) AND 
                                (status = Full) THEN BEGIN
                                converter.number := num;
                                write_bytes(6,converter.switched);
                             END;
                             IF str <> NIL THEN BEGIN
                                converter.str := str^;
                                write_bytes(LENGTH(str^)+1,converter.switched)
                             END
                             ELSE BEGIN
                                byte_buffer[1] := 0;
                                write_bytes(1,byte_buffer)
                             END
                          END
                          ELSE IF c > e_c THEN
                             quit := TRUE;   
                       ptr := ptr^.next
                    END { WHILE }
                 END { IF }
             END; { FOR }
1:           close_file(handle);
             Set_Mouse(M_Arrow)
          END; { IF create_file }
       Form_Dial(3,0,0,0,0,fo_x,fo_y,fo_w,fo_h)
   END; { SAVE_FILE }

PROCEDURE LOAD_FILE ( what : DiskIoOps );
   LABEL 1,2;
   VAR count                                  : BYTE;
       d,i,j,handle,result,s_r,s_c,e_r,e_c    : INTEGER;
       did_load,at_cursor                     : BOOLEAN;
       a,b                                    : STR10;
       c_name                                 : C_STRING;
       converter                              : Switcheroo;
       int_buffer                             : HundredInts;
       byte_buffer                            : ThreeHundredBytes;
       ptr                                    : CellPtr;
   FUNCTION Int_Read (     handle : INTEGER; n : LONG_INTEGER;
                        VAR buf : HundredInts ) : LONG_INTEGER;
      GEMDOS ($3F);
   PROCEDURE MY_SEEK;
      { Seeks back one byte after finding a string length > 0 }
      VAR dis : LONG_INTEGER;
      BEGIN
          dis := TOS_Seek(-1,handle,1);
          IF dis < 0 THEN BEGIN
             Form_Error(dis);
             GOTO 1
          END
      END; { MY_SEEK }
   PROCEDURE READ_BYTES ( n : LONG_INTEGER; VAR buffer : ThreeHundredBytes );
      VAR bytes_read : LONG_INTEGER;
      BEGIN
          bytes_read := TOS_Read(handle,n,buffer);
          IF bytes_read <> n THEN BEGIN
             IF bytes_read >= 0 THEN
                Form_Error(-11)
             ELSE
                Form_Error(bytes_read);   
             GOTO 1
          END   
      END; { READ_BYTES }    
   PROCEDURE READ_INTS ( n : LONG_INTEGER; VAR buffer : HundredInts );
      VAR ints_read : LONG_INTEGER;
      BEGIN
          ints_read := Int_Read(handle,n,buffer);
          IF ints_read <> n THEN BEGIN
             IF ints_read >= 0 THEN
                Form_Error(-11)
             ELSE
                Form_Error(ints_read);    
             GOTO 1
          END   
      END; { READ_INTS }    
   PROCEDURE OUT_OF_MEM ( c : INTEGER );
      BEGIN
          Set_Mouse(M_Arrow);
          out_mem_cell(i,c,'loaded');
          GOTO 1
       END; { OUT_OF_MEM }
   PROCEDURE SET_FLAGS ( flag    : BOOLEAN;
                         menu_id : INTEGER );
      BEGIN
          IF flag THEN
             Menu_Check(main_menu,menu_id,TRUE)
          ELSE
             Menu_Check(main_menu,menu_id,FALSE)
      END;
   BEGIN { LOAD_FILE }
       did_load := FALSE;
       at_cursor := FALSE;
       IF what = LoadFile THEN
          action_banner ('Load Sheet')
       ELSE 
          action_banner ('Load Block');
       IF get_file_name(c_name,what) THEN 
          IF open_file(c_name,handle) THEN BEGIN
             IF what = LoadBlock THEN BEGIN
                temp := CONCAT('[2][1. Load at original position|' ,
                                   '2. Load at cursor][Cancel|1|2]' );
                alert := Do_Alert(temp,1);
                IF alert = 1 THEN                   
                   GOTO 2
                ELSE 
                   at_cursor := alert = 3
             END;      
             Set_Mouse(M_Bee);
             read_bytes(6,byte_buffer); { read the header }
             IF (byte_buffer[1] <> 1) OR (byte_buffer[2] <> 14) OR
                (byte_buffer[3] <> 85) OR (byte_buffer[4] <> 10) OR
                (byte_buffer[5] <> 22) OR (byte_buffer[6] <> 84) THEN BEGIN
                temp := CONCAT ('[3][Incorrect file-type or|' ,
                                     'corrupted file.][ Cancel ]');
                alert := Do_Alert(temp,1);
                GOTO 1
             END;
             IF what = LoadFile THEN
                clear_worksheet;
             block_set := FALSE;
             block_st_set := FALSE;
             block_end_set := FALSE;
             adjust_menu(FALSE);
             read_bytes(1,byte_buffer);
             IF byte_buffer[1] > 0 THEN BEGIN
                my_seek;
                read_bytes(byte_buffer[1]+1,converter.switched);
                IF what = LoadFile THEN
                   p_title_1 := converter.str
             END
             ELSE IF what = LoadFile THEN
                p_title_1 := '';
             read_bytes(1,byte_buffer);
             IF byte_buffer[1] > 0 THEN BEGIN
                my_seek;
                read_bytes(byte_buffer[1]+1,converter.switched);
                IF what = LoadFile THEN
                   p_title_2 := converter.str
             END
             ELSE IF what = LoadFile THEN
                p_title_2 := '';
             read_bytes(1,byte_buffer);
             IF byte_buffer[1] > 0 THEN BEGIN
                my_seek;
                read_bytes(byte_buffer[1]+1,converter.switched);
                IF what = LoadFile THEN
                   header := converter.str
             END
             ELSE IF what = LoadFile THEN
                header := '';
             read_bytes(1,byte_buffer);
             IF byte_buffer[1] > 0 THEN BEGIN
                my_seek;
                read_bytes(byte_buffer[1]+1,converter.switched);
                IF what = LoadFile THEN
                   footer := converter.str
             END
             ELSE IF what = LoadFile THEN
                footer := '';
             read_bytes(n_cols+11,byte_buffer);
             IF what = LoadFile THEN BEGIN
                p_row_col := byte_buffer[1] = 1;
                print_formulas := byte_buffer[2] = 1;
                condensed_print := byte_buffer[3] = 1;
                draft_final := byte_buffer[4] = 1;
                grid_flag := byte_buffer[5] = 1;
                small_text := byte_buffer[6] = 1;
                form_flag := byte_buffer[7] = 1;
                auto_cursor := byte_buffer[8] = 1;
                auto_recalc := byte_buffer[9] = 1;
                natural := byte_buffer[10] = 1;
                IF byte_buffer[11] = 1 THEN
                   cursor_direction := CursorRight
                ELSE
                   cursor_direction := CursorDown;
                set_flags(grid_flag,mshowgri);
                set_flags(form_flag,mshowfor);
                set_flags(auto_cursor,mautocur);
                set_flags(auto_recalc,mautorec);
                set_flags(natural,mnatural);
                FOR i := 12 TO n_cols+11 DO BEGIN
                    col_width[i-11,spaces] := byte_buffer[i];
                    col_width[i-11,pixels] := byte_buffer[i]*8
                END
             END;
             read_ints(30,int_buffer);
             s_r := int_buffer[2];
             s_c := int_buffer[3];
             e_r := int_buffer[4];
             e_c := int_buffer[5];
             IF (what = LoadBlock) AND (at_cursor) THEN
                IF (data_row+e_r-s_r > n_rows) OR 
                   (data_col+e_c-s_c > n_cols) THEN BEGIN
                   a := col_name[n_cols-(e_c-s_c)];
                   int_to_string(n_rows-(e_r-s_r),b);
                   block_too_big(a,b);
                   GOTO 1
                END;                      
             IF what = LoadFile THEN BEGIN
                default_format := int_buffer[1];
                i := 1;
                j := 6;
                WHILE i < 5 DO BEGIN
                   marks[i].row := int_buffer[j];
                   j := j+1;
                   marks[i].col := int_buffer[j];
                   i := i+1;
                   j := j+1
                END;
                m1s := marks[1].row > 0;
                m2s := marks[2].row > 0;
                m3s := marks[3].row > 0;
                m4s := marks[4].row > 0;
                IF m1s THEN
                   Menu_Enable(main_menu,mg1)
                ELSE
                   Menu_Disable(main_menu,mg1);
                IF m2s THEN
                   Menu_Enable(main_menu,mg2)
                ELSE
                   Menu_Disable(main_menu,mg2);
                IF m3s THEN
                   Menu_Enable(main_menu,mg3)
                ELSE
                   Menu_Disable(main_menu,mg3);
                IF m4s THEN
                   Menu_Enable(main_menu,mg4)
                ELSE
                   Menu_Disable(main_menu,mg4);
                freeze_row := int_buffer[14];
                freeze_col := int_buffer[15];
                logical_row_1 := freeze_row+1;
                logical_col_1 := freeze_col+1;
                start_row := logical_row_1;
                start_col := logical_col_1;
                data_row := start_row;
                data_col :=start_col;
                IF freeze_row > 0 THEN
                   y_margin := two_cell_h-1
                ELSE
                   y_margin := cell_height-1;
                IF freeze_col > 0 THEN
                   x_margin := 39+col_width[freeze_col,pixels]
                ELSE
                   x_margin := 38;
               { must do this so that switch will save correct finish_row &
                 col so that return_attr can recalc correct v & h_entry.
                 Failure to do this can lead to a crash when handle_message
                 tries to calculate slider positions and these entry values
                 equal n_rows or n_cols due to a non-updated finish row or
                 col }
                get_num_scr_entries(ExRight);
                IF n_hdls = 2 THEN BEGIN
                   switch_window;
                   start_row := logical_row_1;
                   start_col := logical_col_1;
                   data_row := start_row;
                   data_col := start_col;
                   get_num_scr_entries(ExRight);
                   switch_window
                END
             END;
             IF what = LoadBlock THEN
                IF at_cursor THEN
                   delete_range(data_row,data_col,
                                data_row+e_r-s_r,data_col+e_c-s_c,FALSE)
                ELSE IF (s_r = 1) AND (s_c = 1) AND { just in case... }
                        (e_r = n_rows) AND (e_c = n_cols) THEN
                   clear_worksheet
                ELSE
                   delete_range(s_r,s_c,e_r,e_c,FALSE);
             clear_buffer;
             FOR i := 1 TO n_rows DO BEGIN
                 read_bytes(1,byte_buffer);
                 count := byte_buffer[1];
                 FOR j := 1 TO count DO BEGIN
                     read_bytes(2,converter.switched);
                     IF (what = LoadBlock) AND (at_cursor) THEN
                        ptr := new_cell(0,converter.c)
                     ELSE
                        ptr := new_cell(i,converter.c);
                     IF ptr <> NIL THEN
                        WITH ptr^ DO BEGIN
                           c := converter.c;
                           read_bytes(2,converter.switched);
                           format := converter.format;
                           read_bytes(2,converter.switched);
                           class := converter.class;
                           read_bytes(2,converter.switched);
                           status := converter.status;
                           IF ((class = Val) OR (class = Expr)) AND 
                              (status = Full) THEN BEGIN
                              read_bytes(6,converter.switched);
                              num := converter.number
                           END;
                           read_bytes(1,byte_buffer);
                           IF byte_buffer[1] > 0 THEN BEGIN
                              IF str = NIL THEN
                                 IF request_memory(AString) THEN
                                    NEW(str)
                                 ELSE
                                    out_of_mem(c);
                              my_seek;
                              read_bytes(byte_buffer[1]+1,converter.switched);
                              str^ := converter.str;
                              IF NOT ((what = LoadBlock) AND (at_cursor)) THEN
                                 all_lists(add,ptr,i,c)
                           END
                        END
                     ELSE
                        out_of_mem(converter.c)
                 END; { FOR j }
                 IF (what = LoadBlock) AND (at_cursor) THEN 
                    IF count > 0 THEN
                       IF NOT do_paste(i,data_row+i-s_r,data_col,
                                       s_r,s_c,e_r,e_c,at_cursor,FALSE) THEN
                          GOTO 1;
             END; { FOR i }
             IF rez = 1 THEN BEGIN
                { do like this since the message handler flips small_text
                  from TRUE to FALSE and vice-versa }
                small_text := NOT small_text;
                simulate_message(MN_Selected,moptions,msmall)
             END
             ELSE
                small_text := FALSE;
             did_load := TRUE; 
1:           close_file(handle);
             Set_Mouse(M_Arrow)
          END; { IF open_file }
2:     Form_Dial(3,0,0,0,0,0,0,screen_width,screen_height);
       clear_buffer
   END; { LOAD_FILE }

PROCEDURE SAVE_TEXT ( s_r,s_c,e_r,e_c : INTEGER );
   VAR handle,x,y,w,h : INTEGER;
       c_name         : C_STRING;
   BEGIN
       print_spreadsheet(FALSE,'Save as Text',s_r,s_c,e_r,e_c);
       IF s_r > 0 THEN BEGIN
          action_banner('Save Text');
          x := fo_x; { because do_print will wipe out these for its own }
          y := fo_y; { nefarious purposes, i.e. displaying the page #   }
          w := fo_w;
          h := fo_h;
          IF get_file_name(c_name,SaveText) THEN
             IF create_file(c_name,handle) THEN BEGIN
                do_print(s_r,e_r,s_c,e_c,handle);
                close_file(handle)
             END;   
          Form_Dial(3,0,0,0,0,x,y,w,h)
       END   
   END; { SAVE_TEXT }

PROCEDURE DISK_IO ( what : DiskIoOps );
   VAR s_r,s_c,e_r,e_c : INTEGER;
   BEGIN
       CASE what OF
          LoadFile : load_file(LoadFile);
          SaveFile : save_file(SaveFile,1,1,n_rows,n_cols);
          LoadBlock : load_file(LoadBlock);
          SaveBlock : 
             IF ask_for_range(s_r,s_c,e_r,e_c,'Save Block') THEN
                save_file(SaveBlock,s_r,s_c,e_r,e_c);
          SaveText : save_text(s_r,s_c,e_r,e_c)
       END
   END; { DISK_IO }             


BEGIN
END.


