home *** CD-ROM | disk | FTP | other *** search
/ Turbo Toolbox / Turbo_Toolbox.iso / turbo5 / mcommand.pas < prev    next >
Pascal/Delphi Source File  |  1988-10-09  |  21KB  |  873 lines

  1.  
  2. { Copyright (c) 1985, 88 by Borland International, Inc. }
  3.  
  4. unit MCOMMAND;
  5.  
  6. interface
  7.  
  8. uses Crt, Dos, MCVars, MCUtil, MCDisply, MCParser, MCLib, MCInput;
  9.  
  10. procedure CheckForSave;
  11. { If the spreadsheet has been changed, will ask the user if they want to
  12.    save it.
  13. }
  14.  
  15. procedure MoveRowUp;
  16. { Moves up 1 row }
  17.  
  18. procedure MoveRowDown;
  19. { Moves down one row }
  20.  
  21. procedure MoveColLeft;
  22. { Moves left one column }
  23.  
  24. procedure MoveColRight;
  25. { Moves right one column }
  26.  
  27. procedure EditCell(ECell : CellPtr);
  28. { Edits a selected cell }
  29.  
  30. procedure ClearSheet;
  31. { Clears the current spreadsheet }
  32.  
  33. procedure LoadSheet(FileName : IString);
  34. { Loads a new spreadsheet }
  35.  
  36. procedure SaveSheet;
  37. { Saves the current spreadsheet }
  38.  
  39. function PageRows(Row : Word; TopPage, Border : Boolean) : Word;
  40. { Returns the number of rows to print }
  41.  
  42. function PageCols(Col, Columns : Word; Border : Boolean) : Word;
  43. { Returns the number of columns to print starting at col }
  44.  
  45. procedure PrintSheet;
  46. { Prints a copy of the spreadsheet to a file or to the printer }
  47.  
  48. procedure SetColWidth(Col : Word);
  49. { Sets the new column width for a selected column }
  50.  
  51. procedure GotoCell;
  52. { Moves to a selected cell }
  53.  
  54. procedure FormatCells;
  55. { Prompts the user for a selected format and range of cells }
  56.  
  57. procedure DeleteCol(Col : Word);
  58. { Deletes a column }
  59.  
  60. procedure InsertCol(Col : Word);
  61. { Inserts a column }
  62.  
  63. procedure DeleteRow(Row : Word);
  64. { Deletes a row }
  65.  
  66. procedure InsertRow(Row : Word);
  67. { Inserts a row }
  68.  
  69. procedure SMenu;
  70. { Executes the commands in the spreadsheet menu }
  71.  
  72. procedure CMenu;
  73. { Executes the commands in the column menu }
  74.  
  75. procedure RMenu;
  76. { Executes the commands in the row menu }
  77.  
  78. procedure UMenu;
  79. { Executes the commands in the utility menu }
  80.  
  81. procedure MainMenu;
  82. { Executes the commands in the main menu }
  83.  
  84. implementation
  85.  
  86. const
  87.   Name : String[80] = MSGNAME;
  88.  
  89. var
  90.   Rec : CellRec;
  91.  
  92. procedure CheckForSave;
  93. var
  94.   Save : Char;
  95. begin
  96.   if Changed and GetYesNo(Save, MSGSAVESHEET) and (Save = 'Y') then
  97.     SaveSheet;
  98. end; { CheckForSave }
  99.  
  100. procedure MoveRowUp;
  101. begin
  102.   DisplayCell(CurCol, CurRow, NOHIGHLIGHT, NOUPDATE);
  103.   if CurRow > TopRow then
  104.     Dec(CurRow)
  105.   else if TopRow > 1 then
  106.   begin
  107.     Scroll(DOWN, 1, Succ(LEFTMARGIN), 3, 80, ScreenRows + 2, WHITE);
  108.     Dec(TopRow);
  109.     DisplayRow(TopRow, NOUPDATE);
  110.     Dec(CurRow);
  111.     SetBottomRow;
  112.   end;
  113. end; { MoveRowUp }
  114.  
  115. procedure MoveRowDown;
  116. begin
  117.   DisplayCell(CurCol, CurRow, NOHIGHLIGHT, NOUPDATE);
  118.   if CurRow < BottomRow then
  119.     Inc(CurRow)
  120.   else if BottomRow < MAXROWS then
  121.   begin
  122.     Scroll(UP, 1, Succ(LEFTMARGIN), 3, 80, ScreenRows + 2, WHITE);
  123.     Inc(TopRow);
  124.     Inc(CurRow);
  125.     SetBottomRow;
  126.     DisplayRow(BottomRow, NOUPDATE);
  127.   end;
  128. end; { MoveRowDown }
  129.  
  130. procedure MoveColLeft;
  131. var
  132.   Col, OldLeftCol : Word;
  133.   OldColStart : array[1..SCREENCOLS] of Byte;
  134. begin
  135.   OldLeftCol := LeftCol;
  136.   Move(ColStart, OldColStart, Sizeof(ColStart));
  137.   DisplayCell(CurCol, CurRow, NOHIGHLIGHT, NOUPDATE);
  138.   if (CurCol > LeftCol) then
  139.     Dec(CurCol)
  140.   else if (LeftCol <> 1) then
  141.   begin
  142.     Dec(CurCol);
  143.     Dec(LeftCol);
  144.     SetRightCol;
  145.     SetLeftCol;
  146.     if OldLeftCol <= RightCol then
  147.       Scroll(RIGHT, Pred(ColStart[Succ(OldLeftCol - LeftCol)] - LEFTMARGIN),
  148.              Succ(LEFTMARGIN), 3, 80, ScreenRows + 2, WHITE);
  149.     ClearLastCol;
  150.     for Col := LeftCol to Pred(OldLeftCol) do
  151.       DisplayCol(Col, NOUPDATE);
  152.   end;
  153. end; { MoveColLeft }
  154.  
  155. procedure MoveColRight;
  156. var
  157.   Col, OldLeftCol, OldRightCol : Word;
  158.   OldColStart : array[1..SCREENCOLS] of Byte;
  159. begin
  160.   OldLeftCol := LeftCol;
  161.   Move(ColStart, OldColStart, Sizeof(ColStart));
  162.   OldRightCol := RightCol;
  163.   DisplayCell(CurCol, CurRow, NOHIGHLIGHT, NOUPDATE);
  164.   if CurCol < RightCol then
  165.     Inc(CurCol)
  166.   else if RightCol < MAXCOLS then
  167.   begin
  168.     Inc(CurCol);
  169.     Inc(RightCol);
  170.     SetLeftCol;
  171.     SetRightCol;
  172.     if OldRightCol >= LeftCol then
  173.       Scroll(LEFT, Pred(OldColStart[Succ(LeftCol - OldLeftCol)] - LEFTMARGIN),
  174.              Succ(LEFTMARGIN), 3, 80, ScreenRows + 2, WHITE);
  175.     ClearLastCol;
  176.     for Col := Succ(OldRightCol) to RightCol do
  177.       DisplayCol(Col, NOUPDATE);
  178.   end;
  179. end; { MoveColRight }
  180.  
  181. procedure EditCell;
  182. var
  183.   S : IString;
  184. begin
  185.   if ECell = nil then
  186.     Exit;
  187.   case ECell^.Attrib of
  188.     TXT : S := ECell^.T;
  189.     VALUE : Str(ECell^.Value:1:MAXPLACES, S);
  190.     FORMULA : S := ECell^.Formula;
  191.   end; { case }
  192.   if (not EditString(S, '', MAXINPUT)) or (S = '') then
  193.     Exit;
  194.   Act(S);
  195.   Changed := True;
  196. end; { EditCell }
  197.  
  198. procedure ClearSheet;
  199. var
  200.   Col, Row : Word;
  201. begin
  202.   for Row := 1 to LastRow do
  203.   begin
  204.     for Col := 1 to LastCol do
  205.       DeleteCell(Col, Row, NOUPDATE);
  206.   end;
  207.   InitVars;
  208.   SetRightCol;
  209.   SetBottomRow;
  210.   DisplayScreen(NOUPDATE);
  211.   PrintFreeMem;
  212.   Changed := False;
  213. end; { ClearSheet }
  214.  
  215. procedure LoadSheet;
  216. var
  217.   Dummy, Size, RealLastCol, RealLastRow : Word;
  218.   F : File;
  219.   Check : String[80];
  220.   Allocated : Boolean;
  221.   Blocks : Word;
  222.   RealSize : Byte;
  223. begin
  224.   RealLastCol := 1;
  225.   RealLastRow := 1;
  226.   if FileName = '' then
  227.   begin
  228.     WritePrompt(MSGFILENAME);
  229.     if not EditString(FileName, '', MAXINPUT) then
  230.       Exit;
  231.   end;
  232.   if not Exists(FileName) then
  233.   begin
  234.     ErrorMsg(MSGNOEXIST);
  235.     Exit;
  236.   end;
  237.   Assign(F, FileName);
  238.   Reset(F, 1);
  239.   if IOResult <> 0 then
  240.   begin
  241.     ErrorMsg(MSGNOOPEN);
  242.     Exit;
  243.   end;
  244.   BlockRead(F, Check[1], Length(Name), Blocks);
  245.   Check[0] := Chr(Length(Name));
  246.   if Check <> Name then
  247.   begin
  248.     ErrorMsg(MSGNOMICROCALC);
  249.     Close(F);
  250.     Exit;
  251.   end;
  252.   BlockRead(F, Size, 1, Blocks);
  253.   BlockRead(F, RealSize, 1, Blocks);
  254.   if RealSize <> SizeOf(Real) then
  255.   begin
  256.     ErrorMsg(MSGBADREALS);
  257.     Close(F);
  258.     Exit;
  259.   end;
  260.   SetColor(PROMPTCOLOR);
  261.   GotoXY(1, ScreenRows + 5);
  262.   Write(MSGLOADING);
  263.   GotoXY(Succ(Length(MSGLOADING)), ScreenRows + 5);
  264.   ClearSheet;
  265.   BlockRead(F, LastCol, SizeOf(LastCol), Blocks);
  266.   BlockRead(F, LastRow, SizeOf(LastRow), Blocks);
  267.   BlockRead(F, Size, SizeOf(Size), Blocks);
  268.   BlockRead(F, ColWidth, Sizeof(ColWidth), Blocks);
  269.   repeat
  270.     BlockRead(F, CurCol, SizeOf(CurCol), Blocks);
  271.     BlockRead(F, CurRow, SizeOf(CurRow), Blocks);
  272.     BlockRead(F, Format[CurCol, CurRow], 1, Blocks);
  273.     BlockRead(F, Size, SizeOf(Size), Blocks);
  274.     BlockRead(F, Rec, Size, Blocks);
  275.     case Rec.Attrib of
  276.       TXT : begin
  277.         Allocated := AllocText(CurCol, CurRow, Rec.T);
  278.         if Allocated then
  279.           Dummy := SetOFlags(CurCol, CurRow, NOUPDATE);
  280.       end;
  281.       VALUE : Allocated := AllocValue(CurCol, CurRow, Rec.Value);
  282.       FORMULA : Allocated := AllocFormula(CurCol, CurRow, Rec.Formula,
  283.                                           Rec.Fvalue);
  284.     end; { case }
  285.     if not Allocated then
  286.     begin
  287.       ErrorMsg(MSGFILELOMEM);
  288.       LastRow := RealLastRow;
  289.       LastCol := RealLastCol;
  290.       Format[CurCol, CurRow] := DEFAULTFORMAT;
  291.     end
  292.     else begin
  293.       Cell[CurCol, CurRow]^.Error := Rec.Error;
  294.       if CurCol > RealLastCol then
  295.         RealLastCol := CurCol;
  296.       if CurRow > RealLastRow then
  297.         RealLastRow := CurRow;
  298.     end;
  299.   until (not Allocated) or (EOF(F));
  300.   PrintFreeMem;
  301.   Close(F);
  302.   CurCol := 1;
  303.   CurRow := 1;
  304.   SetRightCol;
  305.   DisplayScreen(NOUPDATE);
  306.   SetColor(White);
  307.   GotoXY(1, ScreenRows + 5);
  308.   ClrEol;
  309.   Changed := False;
  310. end; { LoadSheet }
  311.  
  312. procedure SaveSheet;
  313. var
  314.   FileName : IString;
  315.   EndOfFile, Overwrite : Char;
  316.   Size, Col, Row : Word;
  317.   F : File;
  318.   CPtr : CellPtr;
  319.   Blocks : Word;
  320.   RealSize : Byte;
  321. begin
  322.   EndOfFile := #26;
  323.   FileName := '';
  324.   RealSize := SizeOf(Real);
  325.   WritePrompt(MSGFILENAME);
  326.   if not EditString(FileName, '', MAXINPUT) then
  327.     Exit;
  328.   Assign(F, FileName);
  329.   if Exists(FileName) then
  330.   begin
  331.     if (not GetYesNo(Overwrite, MSGOVERWRITE)) or (Overwrite = 'N') then
  332.       Exit;
  333.     Reset(F, 1);
  334.   end
  335.   else
  336.     Rewrite(F, 1);
  337.   if IOResult <> 0 then
  338.   begin
  339.     ErrorMsg(MSGNOOPEN);
  340.     Exit;
  341.   end;
  342.   SetColor(PROMPTCOLOR);
  343.   GotoXY(1, ScreenRows + 5);
  344.   Write(MSGSAVING);
  345.   GotoXY(Length(MSGSAVING) + 1, ScreenRows + 5);
  346.   BlockWrite(F, Name[1], Length(Name), Blocks);
  347.   BlockWrite(F, EndOfFile, 1, Blocks);
  348.   BlockWrite(F, RealSize, 1, Blocks);
  349.   BlockWrite(F, LastCol, SizeOf(LastCol), Blocks);
  350.   BlockWrite(F, LastRow, SizeOf(LastRow), Blocks);
  351.   Size := MAXCOLS;
  352.   BlockWrite(F, Size, SizeOf(Size), Blocks);
  353.   BlockWrite(F, ColWidth, Sizeof(ColWidth), Blocks);
  354.   for Row := 1 to LastRow do
  355.   begin
  356.     for Col := LastCol downto 1 do
  357.     begin
  358.       if Cell[Col, Row] <> nil then
  359.       begin
  360.         CPtr := Cell[Col, Row];
  361.         case CPtr^.Attrib of
  362.           TXT : Size := Length(CPtr^.T) + 3;
  363.           VALUE : Size := Sizeof(Real) + 2;
  364.           FORMULA : Size := Length(CPtr^.Formula) + Sizeof(Real) + 3;
  365.         end; { case }
  366.         BlockWrite(F, Col, SizeOf(Col), Blocks);
  367.         BlockWrite(F, Row, SizeOf(Row), Blocks);
  368.         BlockWrite(F, Format[Col, Row], 1, Blocks);
  369.         BlockWrite(F, Size, SizeOf(Size), Blocks);
  370.         BlockWrite(F, CPtr^, Size, Blocks);
  371.       end;
  372.     end;
  373.   end;
  374.   Close(F);
  375.   SetColor(White);
  376.   GotoXY(1, ScreenRows + 5);
  377.   ClrEol;
  378.   Changed := False;
  379. end; { SaveSheet }
  380.  
  381. function PageRows;
  382. var
  383.   Rows : Word;
  384. begin
  385.   if TopPage then
  386.     Rows := 66 - TOPMARGIN
  387.   else
  388.     Rows := 66;
  389.   if Border then
  390.     Dec(Rows);
  391.   if Pred(Row + Rows) > LastRow then
  392.     PageRows := Succ(LastRow - Row)
  393.   else
  394.     PageRows := Rows;
  395. end; { PageRows }
  396.  
  397. function PageCols;
  398. var
  399.   Len : Integer;
  400.   FirstCol : Word;
  401. begin
  402.   if (Col = 1) and Border then
  403.     Len := Columns - LEFTMARGIN
  404.   else
  405.     Len := Columns;
  406.   FirstCol := Col;
  407.   while (Len > 0) and (Col <= LastCol) do
  408.   begin
  409.     Dec(Len, ColWidth[Col]);
  410.     Inc(Col);
  411.   end;
  412.   if Len < 0 then
  413.     Dec(Col);
  414.   PageCols := Col - FirstCol;
  415. end; { PageCols }
  416.  
  417. procedure PrintSheet;
  418. var
  419.   FileName : IString;
  420.   S : String[132];
  421.   ColStr : String[MAXCOLWIDTH];
  422.   F : Text;
  423.   Columns, Counter1, Counter2, Counter3, Col, Row, LCol, LRow, Dummy,
  424.     Printed, OldLastCol : Word;
  425.   Answer : Char;
  426.   Border, TopPage : Boolean;
  427. begin
  428.   Col := 1;
  429.   WritePrompt(MSGPRINT);
  430.   FileName := '';
  431.   if not EditString(FileName, '', MAXINPUT) then
  432.     Exit;
  433.   if FileName = '' then
  434.     FileName := 'PRN';
  435.   Assign(F, FileName);
  436. {$I-}
  437.   Rewrite(F);
  438.   if IOResult <> 0 then
  439.   begin
  440.     ErrorMsg(MSGNOOPEN);
  441.     Exit;
  442.   end;
  443. {$I+}
  444.   OldLastCol := LastCol;
  445.   for Counter1 := 1 to LastRow do
  446.   begin
  447.     for Counter2 := LastCol to MAXCOLS do
  448.     begin
  449.       if Format[Counter2, Counter1] >= OVERWRITE then
  450.         LastCol := Counter2;
  451.     end;
  452.   end;
  453.   if not GetYesNo(Answer, MSGCOLUMNS) then
  454.     Exit;
  455.   if Answer = 'Y' then
  456.     Columns := 132
  457.   else
  458.     Columns := 80;
  459.   if not GetYesNo(Answer, MSGBORDER) then
  460.     Exit;
  461.   Border := Answer = 'Y';
  462.   while Col <= LastCol do
  463.   begin
  464.     Row := 1;
  465.     TopPage := True;
  466.     LCol := PageCols(Col, Columns, Border) + Col;
  467.     while Row <= LastRow do
  468.     begin
  469.       LRow := PageRows(Row, TopPage, Border) + Row;
  470.       Printed := 0;
  471.       if TopPage then
  472.       begin
  473.         for Counter1 := 1 to TOPMARGIN do
  474.         begin
  475.           Writeln(F);
  476.           Inc(Printed);
  477.         end;
  478.       end;
  479.       for Counter1 := Row to Pred(LRow) do
  480.       begin
  481.         if Border and (Counter1 = Row) and (TopPage) then
  482.         begin
  483.           if (Col = 1) and Border then
  484.           begin
  485.             S[0] := Chr(LEFTMARGIN);
  486.             FillChar(S[1], LEFTMARGIN, ' ');
  487.           end
  488.           else
  489.             S := '';
  490.           for Counter3 := Col to Pred(LCol) do
  491.           begin
  492.             ColStr := CenterColString(Counter3);
  493.             S := S + ColStr;
  494.           end;
  495.           Writeln(F, S);
  496.           Printed := Succ(Printed);
  497.         end;
  498.         if (Col = 1) and Border then
  499.           S := Pad(WordToString(Counter1, 1), LEFTMARGIN)
  500.         else
  501.           S := '';
  502.         for Counter2 := Col to Pred(LCol) do
  503.           S := S + CellString(Counter2, Counter1, Dummy, DOFORMAT);
  504.         Writeln(F, S);
  505.         Inc(Printed);
  506.       end;
  507.       Row := LRow;
  508.       TopPage := False;
  509.       if Printed < 66 then
  510.         Write(F, FORMFEED);
  511.     end;
  512.     Col := LCol;
  513.   end;
  514.   Close(F);
  515.   LastCol := OldLastCol;
  516. end; { PrintSheet }
  517.  
  518. procedure SetColWidth;
  519. var
  520.   Width, Row : Word;
  521. begin
  522.   WritePrompt(MSGCOLWIDTH);
  523.   if not GetWord(Width, MINCOLWIDTH, MAXCOLWIDTH) then
  524.     Exit;
  525.   ColWidth[Col] := Width;
  526.   SetRightCol;
  527.   if RightCol < Col then
  528.   begin
  529.     RightCol := Col;
  530.     SetLeftCol;
  531.     SetRightCol;
  532.   end;
  533.   for Row := 1 to LastRow do
  534.   begin
  535.     if (Cell[Col, Row] <> nil) and (Cell[Col, Row]^.Attrib = TXT) then
  536.       ClearOFlags(Succ(Col), Row, NOUPDATE)
  537.     else
  538.       ClearOFlags(Col, Row, NOUPDATE);
  539.     UpdateOFlags(Col, Row, NOUPDATE);
  540.   end;
  541.   DisplayScreen(NOUPDATE);
  542.   Changed := True;
  543. end; { SetColWidth }
  544.  
  545. procedure GotoCell;
  546. begin
  547.   WritePrompt(MSGGOTO);
  548.   if not GetCell(CurCol, CurRow) then
  549.     Exit;
  550.   LeftCol := CurCol;
  551.   TopRow := CurRow;
  552.   SetBottomRow;
  553.   SetRightCol;
  554.   SetLeftCol;
  555.   DisplayScreen(NOUPDATE);
  556. end; { GotoCell }
  557.  
  558. procedure FormatCells;
  559. var
  560.   Col, Row, Col1, Col2, Row1, Row2, NewFormat, ITemp : Word;
  561.   Temp : Char;
  562. begin
  563.   NewFormat := 0;
  564.   WritePrompt(MSGCELL1);
  565.   if not GetCell(Col1, Row1) then
  566.     Exit;
  567.   WritePrompt(MSGCELL2);
  568.   if not GetCell(Col2, Row2) then
  569.     Exit;
  570.   if (Col1 <> Col2) and (Row1 <> Row2) then
  571.     ErrorMsg(MSGDIFFCOLROW)
  572.   else begin
  573.     if Col1 > Col2 then
  574.       Switch(Col1, Col2);
  575.     if Row1 > Row2 then
  576.       Switch(Row1, Row2);
  577.     if not GetYesNo(Temp, MSGRIGHTJUST) then
  578.       Exit;
  579.     NewFormat := NewFormat + (Ord(Temp = 'Y') * RJUSTIFY);
  580.     if not GetYesNo(Temp, MSGDOLLAR) then
  581.       Exit;
  582.     NewFormat := NewFormat + (Ord(Temp = 'Y') * DOLLAR);
  583.     if not GetYesNo(Temp, MSGCOMMAS) then
  584.       Exit;
  585.     NewFormat := NewFormat + (Ord(Temp = 'Y') * COMMAS);
  586.     if (NewFormat and DOLLAR) <> 0 then
  587.       NewFormat := NewFormat + 2
  588.     else begin
  589.       WritePrompt(MSGPLACES);
  590.       if not GetWord(ITemp, 0, MAXPLACES) then
  591.         Exit;
  592.       NewFormat := NewFormat + ITemp;
  593.     end;
  594.     for Col := Col1 to Col2 do
  595.     begin
  596.       for Row := Row1 to Row2 do
  597.       begin
  598.         Format[Col, Row] := (Format[Col, Row] and OVERWRITE) or NewFormat;
  599.         if (Col >= LeftCol) and (Col <= RightCol) and
  600.            (Row >= TopRow) and (Row <= BottomRow) then
  601.         DisplayCell(Col, Row, NOHIGHLIGHT, NOUPDATE);
  602.       end;
  603.     end;
  604.   end;
  605.   Changed := True;
  606. end; { FormatCells }
  607.  
  608. procedure DeleteCol;
  609. var
  610.   OldLastCol, Counter, Row : Word;
  611. begin
  612.   if Col > LastCol then
  613.     Exit;
  614.   OldLastCol := LastCol;
  615.   for Counter := 1 to LastRow do
  616.     DeleteCell(Col, Counter, NOUPDATE);
  617.   PrintFreeMem;
  618.   if Col <> OldLastCol then
  619.   begin
  620.     Move(Cell[Succ(Col), 1], Cell[Col, 1], MAXROWS * Sizeof(CellPtr) *
  621.          (OldLastCol - Col));
  622.     Move(Format[Succ(Col), 1], Format[Col, 1], MAXROWS * (OldLastCol - Col));
  623.     Move(ColWidth[Succ(Col)], ColWidth[Col], OldLastCol - Col);
  624.   end;
  625.   FillChar(Cell[OldLastCol, 1], MAXROWS * Sizeof(CellPtr), 0);
  626.   FillChar(Format[OldLastCol, 1], MAXROWS, DEFAULTFORMAT);
  627.   ColWidth[OldLastCol] := DEFAULTWIDTH;
  628.   SetRightCol;
  629.   if CurCol > RightCol then
  630.   begin
  631.     Inc(RightCol);
  632.     SetLeftCol;
  633.   end;
  634.   ClearLastCol;
  635.   if OldLastCol = LastCol then
  636.     Dec(LastCol);
  637.   for Counter := 1 to LastCol do
  638.   begin
  639.     for Row := 1 to LastRow do
  640.     begin
  641.       if (Cell[Counter, Row] <> nil) and
  642.          (Cell[Counter, Row]^.Attrib = FORMULA) then
  643.         FixFormula(Counter, Row, COLDEL, Col);
  644.       UpdateOFlags(Col, Row, NOUPDATE);
  645.     end;
  646.   end;
  647.   for Counter := Col to RightCol do
  648.     DisplayCol(Counter, NOUPDATE);
  649.   LastCol := MAXCOLS;
  650.   SetLastCol;
  651.   Changed := True;
  652.   Recalc;
  653. end; { DeleteCol }
  654.  
  655. procedure InsertCol;
  656. var
  657.   Counter, Row : Word;
  658. begin
  659.   if (LastCol = MAXCOLS) or (Col > LastCol) then
  660.     Exit;
  661.   if Col <> LastCol then
  662.   begin
  663.     Move(Cell[Col, 1], Cell[Col + 1, 1], MAXROWS * Sizeof(CellPtr) *
  664.            Succ(LastCol - Col));
  665.     Move(Format[Col, 1], Format[Col + 1, 1], MAXROWS * Succ(LastCol - Col));
  666.     Move(ColWidth[Col], ColWidth[Col + 1], Succ(LastCol - Col));
  667.   end;
  668.   if LastCol < MAXCOLS then
  669.     Inc(LastCol);
  670.   FillChar(Cell[Col, 1], MAXROWS * Sizeof(CellPtr), 0);
  671.   FillChar(Format[Col, 1], MAXROWS, DEFAULTFORMAT);
  672.   ColWidth[Col] := DEFAULTWIDTH;
  673.   SetRightCol;
  674.   if CurCol > RightCol then
  675.   begin
  676.     Inc(RightCol);
  677.     SetLeftCol;
  678.   end;
  679.   for Counter := 1 to LastCol do
  680.   begin
  681.     for Row := 1 to LastRow do
  682.     begin
  683.       if (Cell[Counter, Row] <> nil) and
  684.          (Cell[Counter, Row]^.Attrib = FORMULA) then
  685.         FixFormula(Counter, Row, COLADD, Col);
  686.       UpdateOFlags(Col, Row, NOUPDATE);
  687.     end;
  688.   end;
  689.   for Counter := Col to RightCol do
  690.     DisplayCol(Counter, NOUPDATE);
  691.   LastCol := MAXCOLS;
  692.   SetLastCol;
  693.   Changed := True;
  694.   Recalc;
  695. end; { InsertCol }
  696.  
  697. procedure DeleteRow;
  698. var
  699.   OldLastRow, Counter, RowC : Word;
  700. begin
  701.   if Row > LastRow then
  702.     Exit;
  703.   OldLastRow := LastRow;
  704.   for Counter := 1 to LastCol do
  705.     DeleteCell(Counter, Row, NOUPDATE);
  706.   PrintFreeMem;
  707.   if Row <> OldLastRow then
  708.   begin
  709.     for Counter := 1 to MAXCOLS do
  710.     begin
  711.       Move(Cell[Counter, Succ(Row)], Cell[Counter, Row],
  712.            Sizeof(CellPtr) * (OldLastRow - Row));
  713.       Move(Format[Counter, Succ(Row)], Format[Counter, Row],
  714.            OldLastRow - Row);
  715.     end;
  716.   end;
  717.   for Counter := 1 to LastCol do
  718.   begin
  719.     Cell[Counter, OldLastRow] := nil;
  720.     Format[Counter, OldLastRow] := DEFAULTFORMAT;
  721.   end;
  722.   if OldLastRow = LastRow then
  723.     Dec(LastRow);
  724.   for Counter := 1 to LastCol do
  725.   begin
  726.     for RowC := 1 to LastRow do
  727.     begin
  728.       if (Cell[Counter, RowC] <> nil) and
  729.          (Cell[Counter, RowC]^.Attrib = FORMULA) then
  730.         FixFormula(Counter, RowC, ROWDEL, Row);
  731.     end;
  732.   end;
  733.   for Counter := Row to BottomRow do
  734.     DisplayRow(Counter, NOUPDATE);
  735.   LastRow := MAXROWS;
  736.   SetLastRow;
  737.   Changed := True;
  738.   Recalc;
  739. end; { DeleteRow }
  740.  
  741. procedure InsertRow;
  742. var
  743.   Counter, RowC : Word;
  744. begin
  745.   if (LastRow = MAXROWS) or (Row > LastRow) then
  746.     Exit;
  747.   if Row <> LastRow then
  748.   begin
  749.     for Counter := 1 to MAXCOLS do
  750.     begin
  751.       Move(Cell[Counter, Row], Cell[Counter, Succ(Row)],
  752.            Sizeof(CellPtr) * Succ(LastRow - Row));
  753.       Move(Format[Counter, Row], Format[Counter, Succ(Row)],
  754.            Succ(LastRow - Row));
  755.     end;
  756.   end;
  757.   Inc(LastRow);
  758.   for Counter := 1 to LastCol do
  759.   begin
  760.     Cell[Counter, Row] := nil;
  761.     Format[Counter, Row] := DEFAULTFORMAT;
  762.   end;
  763.   for Counter := 1 to LastCol do
  764.   begin
  765.     for RowC := 1 to LastRow do
  766.     begin
  767.       if (Cell[Counter, RowC] <> nil) and
  768.          (Cell[Counter, RowC]^.Attrib = FORMULA) then
  769.         FixFormula(Counter, RowC, ROWADD, Row);
  770.     end;
  771.   end;
  772.   for Counter := Row to BottomRow do
  773.     DisplayRow(Counter, NOUPDATE);
  774.   LastRow := MAXROWS;
  775.   SetLastRow;
  776.   Changed := True;
  777.   Recalc;
  778. end; { InsertRow }
  779.  
  780. procedure SMenu;
  781. var
  782.   FileName : IString;
  783.   X : Word;
  784. begin
  785.   FileName := '';
  786.   case GetCommand(SMNU, SCOMMAND) of
  787.     1 : begin
  788.       CheckForSave;
  789.       LoadSheet(FileName);
  790.     end;
  791.     2 : SaveSheet;
  792.     3 : PrintSheet;
  793.     4 : begin
  794.       CheckForSave;
  795.       ClearSheet;
  796.     end;
  797.   end; { case }
  798. end; { SMenu }
  799.  
  800. procedure CMenu;
  801. begin
  802.   case GetCommand(CMNU, CCOMMAND) of
  803.     1 : InsertCol(CurCol);
  804.     2 : DeleteCol(CurCol);
  805.     3 : SetColWidth(CurCol);
  806.   end; { case }
  807. end; { CMenu }
  808.  
  809. procedure RMenu;
  810. begin
  811.   case GetCommand(RMNU, RCOMMAND) of
  812.     1 : InsertRow(CurRow);
  813.     2 : DeleteRow(CurRow);
  814.   end; { case }
  815. end; { CMenu }
  816.  
  817. procedure UMenu;
  818. begin
  819.   case GetCommand(UMenuString, UCommandString) of
  820.     1 : Recalc;
  821.     2 : begin
  822.       ChangeFormDisplay(not FormDisplay);
  823.       DisplayScreen(UPDATE);
  824.     end;
  825.     3 : begin
  826.       if ScreenRows = 38 then
  827.       begin
  828.         ScreenRows := 20;
  829.         TextMode(Lo(LastMode));
  830.         SetCursor(NoCursor);
  831.         RedrawScreen;
  832.       end
  833.       else begin
  834.         TextMode(Lo(LastMode) + Font8x8);
  835.         if (LastMode and Font8x8) <> 0 then
  836.         begin
  837.           ScreenRows := 38;
  838.           SetCursor(NoCursor);
  839.           RedrawScreen;
  840.         end;
  841.       end;
  842.     end;
  843.   end; { case }
  844. end; { UMenu }
  845.  
  846. procedure MainMenu;
  847. begin
  848.   case GetCommand(MNU, COMMAND) of
  849.     1 : SMenu;
  850.     2 : FormatCells;
  851.     3 : begin
  852.       DeleteCell(CurCol, CurRow, UPDATE);
  853.       PrintFreeMem;
  854.       if AutoCalc then
  855.         Recalc;
  856.     end;
  857.     4 : GotoCell;
  858.     5 : CMenu;
  859.     6 : RMenu;
  860.     7 : EditCell(CurCell);
  861.     8 : UMenu;
  862.     9 : ChangeAutoCalc(not AutoCalc);
  863.     10 : begin
  864.       CheckForSave;
  865.       Stop := True;
  866.     end;
  867.   end; { case }
  868.   GotoXY(1, ScreenRows + 4);
  869.   ClrEol;
  870. end; { MainMenu }
  871.  
  872. end.
  873.