RVTable.pas
上传用户:daoqigc
上传日期:2021-04-20
资源大小:2795k
文件大小:372k
源码类别:

RichEdit

开发平台:

Delphi

  1.        end
  2.     else begin
  3.       Cell.Clear;
  4.       Cell.AddNL('',0,0);
  5.     end;
  6.   end;
  7. end;
  8. {------------------------------------------------------------------------------}
  9. procedure TRVTableRows.Do_UnClearCells(CellsList: TList;RowList, ColList: TRVIntegerList);
  10. var i: Integer;
  11.     ChosenCell: TCustomRVData;
  12. begin
  13.   if (FMainRVData is TCustomRVFormattedData) and (TCustomRVFormattedData(FMainRVData).GetChosenRVData<>nil) then
  14.     ChosenCell := TCustomRVFormattedData(FMainRVData).GetChosenRVData.GetSourceRVData
  15.   else
  16.     ChosenCell := nil;
  17.   for i := 0 to RowList.Count-1 do begin
  18.     if ChosenCell=Items[RowList[i]][ColList[i]] then
  19.       TCustomRVFormattedData(FMainRVData).SilentReplaceChosenRVData(TRVTableCellData(CellsList.Items[i]));
  20.     Items[RowList[i]][ColList[i]].Free;
  21.     Items[RowList[i]][ColList[i]] := TRVTableCellData(CellsList.Items[i]);
  22.     TRVTableCellData(CellsList.Items[i]).MovingFromUndoList;    
  23.   end;
  24.   CellsList.Clear;
  25. end;
  26. {------------------------------------------------------------------------------}
  27. function TRVTableRows.Do_BeforeMergeCells(ItemNo, Row, Col, ColSpan, RowSpan: Integer):TRVUndoInfo;
  28. var ui: TRVUndoMerge;
  29.     r,c: Integer;
  30. begin
  31.   ui := nil;
  32.   if (rvtsInserted in FTable.FState) and FTable.IsInEditor then begin
  33.     ui := TRVUndoMerge(AddTableUndoInfo(TRVEditRVData(FMainRVData), TRVUndoMerge,
  34.                                ItemNo, True, True));
  35.     if ui<>nil then begin
  36.       ui.Row          := Row;
  37.       ui.Col          := Col;
  38.       ui.OldColSpan   := Items[Row][Col].ColSpan;
  39.       ui.OldRowSpan   := Items[Row][Col].RowSpan;
  40.       ui.NewColSpan   := ColSpan;
  41.       ui.NewRowSpan   := RowSpan;
  42.       ui.OldBestWidth := Items[Row][Col].BestWidth;
  43.       ui.MergedItemsList := TRVList.Create;
  44.       for r := Row to Row+RowSpan-1 do
  45.         for c := Col to Col+ColSpan-1 do
  46.           if (Items[r][c]<>nil) and
  47.              (Items[r][c]<>Items[Row][Col]) then
  48.           ui.MergedItemsList.Add(TRVUndoMergeItem.Create(FTable,r,c,Row,Col));
  49.     end;
  50.   end;
  51.   Result := ui;
  52. end;
  53. {------------------------------------------------------------------------------}
  54. procedure TRVTableRows.Do_MergeCells(ItemNo, Row, Col, ColSpan, RowSpan: Integer;
  55.                                      ui: TRVUndoInfo; ChangeBestWidth: Boolean);
  56. var r,c: Integer;
  57.     Vampire, Victim: TRVTableCellData;
  58. begin
  59.   Vampire := Items[Row][Col];
  60.   if ChangeBestWidth then
  61.     Vampire.FBestWidth := GetBestWidth(Row, Col, ColSpan, RowSpan);
  62.   for r := Row to Row+RowSpan-1 do
  63.     for c := Col to Col+ColSpan-1 do begin
  64.       Victim := Items[r].Items[c];
  65.       if (Victim<>Vampire) and (Victim<>nil) then begin
  66.         if Victim.HasData(False) then
  67.           Vampire.DrainFrom(Victim);
  68.         if ItemNo=-1 then
  69.           Victim.Free
  70.         else begin
  71.           Victim.MovingToUndoList(ui);
  72.           Victim.State := Victim.State - [rvstCompletelySelected];
  73.         end;
  74.         Items[r][c] := nil;
  75.       end;
  76.     end;
  77.   Vampire.FColSpan := ColSpan;
  78.   Vampire.FRowSpan := RowSpan;
  79. end;
  80. {------------------------------------------------------------------------------}
  81. procedure TRVTableRows.Do_UndoMergeCells(ItemNo, Row, Col, OldColSpan, OldRowSpan: Integer;
  82.                                          MergedItemsList: TRVList;
  83.                                          OldBestWidth: TRVHTMLLength);
  84. var i,j,ItemIndex: Integer;
  85.     Vampire: TRVTableCellData;
  86.     UnmergeData: TRVUndoMergeItem;
  87. begin
  88.   Vampire := Items[Row][Col];
  89.   Vampire.FBestWidth := OldBestWidth;
  90.   ItemIndex := Vampire.Items.Count;
  91.   for i := MergedItemsList.Count-1 downto 0 do begin
  92.     UnmergeData := TRVUndoMergeItem(MergedItemsList.Items[i]);
  93.     UnmergeData.Cell.MovingFromUndoList;
  94.     Items[UnmergeData.Row][UnmergeData.Col] := UnmergeData.Cell;
  95.     UnmergeData.Cell.FList := Items[UnmergeData.Row];
  96.     dec(ItemIndex,UnmergeData.ItemCount);
  97.     for j := ItemIndex to ItemIndex+UnmergeData.ItemCount-1 do
  98.       UnmergeData.Cell.AddItemAsIs(Vampire.Items[j], TCustomRVItemInfo(Vampire.Items.Objects[j]));
  99.   end;
  100.   while Vampire.Items.Count>ItemIndex do
  101.     Vampire.Items.Delete(Vampire.Items.Count-1);
  102.   Vampire.FColSpan := OldColSpan;
  103.   Vampire.FRowSpan := OldRowSpan;
  104.   MergedItemsList.Clear;
  105. end;
  106. {------------------------------------------------------------------------------}
  107. procedure TRVTableRows.Do_BeforeUnmergeCell(ItemNo, Row, Col: Integer;
  108.   UnmergeRows, UnmergeCols: Boolean);
  109. var ui: TRVUndoUnmerge;
  110. begin
  111.   if (rvtsInserted in FTable.FState) and FTable.IsInEditor then begin
  112.     ui := TRVUndoUnmerge(AddTableUndoInfo(TRVEditRVData(FMainRVData), TRVUndoUnmerge,
  113.                                ItemNo, True, True));
  114.     if ui<>nil then begin
  115.       ui.Row          := Row;
  116.       ui.Col          := Col;
  117.       ui.OldColSpan   := Items[Row][Col].ColSpan;
  118.       ui.OldRowSpan   := Items[Row][Col].RowSpan;
  119.       ui.UnmergeCols   := UnmergeCols;
  120.       ui.UnmergeRows   := UnmergeRows;
  121.       ui.OldBestWidth := Items[Row][Col].BestWidth;
  122.       ui.OldBestHeight := Items[Row][Col].BestHeight;
  123.     end;
  124.   end;
  125. end;
  126. {------------------------------------------------------------------------------}
  127. procedure TRVTableRows.Do_UnmergeCell(ItemNo, Row, Col: Integer;
  128.   UnmergeRows, UnmergeCols: Boolean);
  129. var r,w,h, RowSpan: Integer;
  130.     MainCell: TRVTableCellData;
  131.     {.................................................}
  132.     procedure DoUnmergeCols(Row, RowSpan: Integer);
  133.     var c: Integer;
  134.         MainCell: TRVTableCellData;
  135.     begin
  136.       MainCell := Items[Row][Col];
  137.       for c := Col+1 to Col+MainCell.ColSpan-1 do begin
  138.         Items[Row][c] := TRVTableCellData.Create(Items[Row]);
  139.         Items[Row][c].BestWidth := w;
  140.         Items[Row][c].FRowSpan := RowSpan;
  141.         Items[Row][c].AssignAttributesFrom(MainCell,False,0,0);
  142.     end;
  143.     MainCell.FColSpan := 1;
  144.     MainCell.BestWidth := w;
  145.     end;
  146.     {.................................................}
  147. begin
  148.   MainCell := Items[Row][Col];
  149.   if UnmergeCols then begin
  150.     w := MainCell.BestWidth div MainCell.ColSpan;
  151.     if w=0 then
  152.       if MainCell.BestWidth>0 then
  153.         w := 1
  154.       else if MainCell.BestWidth<0 then
  155.         w := -1;
  156.     end
  157.   else
  158.     w := MainCell.BestWidth;
  159.   if UnmergeRows then begin
  160.     h := MainCell.BestHeight div MainCell.RowSpan;
  161.     RowSpan := MainCell.RowSpan;
  162.     for r := Row+1 to Row+RowSpan-1 do begin
  163.       Items[r][Col] := TRVTableCellData.Create(Items[r]);
  164.       Items[r][Col].AssignAttributesFrom( MainCell,True,1,MainCell.RowSpan);
  165.       Items[r][Col].FColSpan := MainCell.ColSpan;
  166.     end;
  167.     MainCell.FRowSpan := 1;
  168.     MainCell.BestHeight := h;
  169.     if UnmergeCols then
  170.       for r := Row to Row+RowSpan-1 do
  171.         DoUnmergeCols(r, 1);
  172.     end
  173.   else if UnmergeCols then
  174.     DoUnmergeCols(Row, MainCell.RowSpan);
  175. end;
  176. {------------------------------------------------------------------------------}
  177. procedure TRVTableRows.Do_UndoUnmergeCell(ItemNo, Row, Col: Integer;
  178.                                           OldColSpan, OldRowSpan: Integer;
  179.                                           OldBestWidth: TRVHTMLLength;
  180.                                           OldBestHeight: Integer);
  181. var r,c: Integer;
  182.     MainCell: TRVTableCellData;
  183. begin
  184.   MainCell := Items[Row][Col];
  185.   if OldRowSpan<>MainCell.RowSpan then
  186.     for r := Row+1 to Row+OldRowSpan-1 do
  187.       for c := Col to Col+OldColSpan-1 do begin
  188.         Items[r][c].Free;
  189.         Items[r][c] := nil;
  190.       end;
  191.   if OldColSpan<>MainCell.ColSpan then
  192.     for c := Col+1 to Col+OldColSpan-1 do begin
  193.       Items[Row][c].Free;
  194.       Items[Row][c] := nil;
  195.     end;
  196.   MainCell.FColSpan := OldColSpan;
  197.   MainCell.FRowSpan := OldRowSpan;
  198.   MainCell.FBestWidth  := OldBestWidth;
  199.   MainCell.FBestHeight := OldBestHeight;  
  200. end;
  201. {------------------------------------------------------------------------------}
  202. procedure TRVTableRows.InsertCols(Index, Count, CopyIndex: Integer;
  203.                                   DivideWidths: Boolean);
  204. var r,c,mr,mc: Integer;
  205.     ItemNo: Integer;
  206.     cell: TRVTableCellData;
  207.     ForbiddenRows: TRVIntegerList;
  208. begin
  209.   if (Index<0) or (Index>Items[0].Count) or
  210.      (CopyIndex<-1) or (CopyIndex>=Items[0].Count) then
  211.     raise ERichViewError.Create(errInvalidIndex);
  212.   ItemNo := FTable.GetEditorItemNoForUndo;
  213.   if ItemNo<>-1 then
  214.     TRVEditRVData(FMainRVData).Do_ItemModifyTerminator(ItemNo, True);
  215.   ForbiddenRows := TRVIntegerList.CreateEx(Self.Count,0);
  216.   try
  217.     if Index<>Items[0].Count then begin
  218.       r := Self.Count-1;
  219.       while r>=0 do begin
  220.         cell := GetMainCell(r,Index,mr,mc);
  221.         if (mc<Index) and (mc+cell.ColSpan-1>=Index) then begin
  222.           for c := mr to mr+cell.RowSpan-1 do
  223.             ForbiddenRows[c] := 1;
  224.           Do_SetSpan(ItemNo, mr, mc, cell.FColSpan+Count, True);
  225.         end;
  226.         r := mr-1;
  227.       end;
  228.     end;
  229.     r := 0;
  230.     while r<Self.Count do begin
  231.       if ForbiddenRows[r]=0 then begin
  232.         if CopyIndex<>-1 then
  233.           cell := Items[r][CopyIndex]
  234.         else
  235.           cell := nil;
  236.         if (cell<>nil) and DivideWidths then
  237.           FTable.SetCellBestWidth_(ItemNo, cell.BestWidth * cell.ColSpan div (cell.ColSpan+Count),r,CopyIndex);
  238.         for c := 0 to Count-1 do begin
  239.           Do_BeforeInsertCell(ItemNo,r,Index);
  240.           Items[r].Insert(Index);
  241.           if cell<>nil then begin
  242.             FTable.AssignCellAttributes(ItemNo, r, Index, cell, True, Cell.ColSpan,1);
  243.             Do_SetSpan(ItemNo, r, Index, cell.RowSpan, False);
  244.           end;
  245.         end;
  246.         if cell=nil then
  247.           inc(r)
  248.         else begin
  249.           Do_BeforeInsertEmptyCells(ItemNo,r+1,Index,Count,Cell.RowSpan-1);
  250.           Do_InsertEmptyCells(r+1,Index,Count,Cell.RowSpan-1);
  251.           inc(r,cell.RowSpan);
  252.         end;
  253.         end
  254.       else begin
  255.         Do_BeforeInsertEmptyCells(ItemNo,r,Index,Count,1);
  256.         Do_InsertEmptyCells(r,Index,Count,1);
  257.         inc(r);
  258.       end;
  259.     end;
  260.   finally
  261.     ForbiddenRows.Free;
  262.     if ItemNo<>-1 then
  263.       TRVEditRVData(FMainRVData).Do_ItemModifyTerminator(ItemNo, False);    
  264.   end;
  265. end;
  266. {------------------------------------------------------------------------------}
  267. procedure TRVTableRows.InsertRows(Index, Count, CopyIndex: Integer;
  268.                                   DivideHeights: Boolean);
  269. var r,c,mr,mc: Integer;
  270.     cell: TRVTableCellData;
  271.     ForbiddenCols: TRVIntegerList;
  272.     ItemNo: Integer;
  273.     ColCount: Integer;
  274. begin
  275.   if (Index<0) or (Index>Self.Count) or
  276.      (CopyIndex<-1) or (CopyIndex>=Self.Count) then
  277.     raise ERichViewError.Create(errInvalidIndex);
  278.   ItemNo := FTable.GetEditorItemNoForUndo;
  279.   if ItemNo<>-1 then
  280.     TRVEditRVData(FMainRVData).Do_ItemModifyTerminator(ItemNo, True);
  281.   ColCount := GetColCount;
  282.   ForbiddenCols := TRVIntegerList.CreateEx(ColCount,0);
  283.   try
  284.     if Index<>Self.Count then begin
  285.       c := ColCount-1;
  286.       while c>=0 do begin
  287.         cell := GetMainCell(Index,c, mr,mc);
  288.         if (mr<Index) and (mr+cell.RowSpan-1>=Index) then begin
  289.           for r := mc to mc+cell.ColSpan-1 do
  290.             ForbiddenCols[r] := 1;
  291.           Do_SetSpan(ItemNo, mr, mc, cell.FRowSpan+Count, False);
  292.         end;
  293.         c := mc-1;
  294.       end;
  295.     end;
  296.     if CopyIndex>=Index then
  297.       inc(CopyIndex,Count);
  298.     Do_BeforeInsertRows(ItemNo, Index,Count);
  299.     Do_InsertRows(Index,Count);
  300.     c := 0;
  301.     while c<ColCount do
  302.       if ForbiddenCols[c]=0 then begin
  303.         if CopyIndex<>-1 then
  304.           cell := Items[CopyIndex][c]
  305.         else
  306.           cell := nil;
  307.         if cell<>nil then begin
  308.           if DivideHeights then
  309.             FTable.SetCellBestHeight_(ItemNo, cell.BestHeight * cell.RowSpan div (cell.RowSpan+Count), CopyIndex,c);
  310.           for r := 0 to Count-1 do begin
  311.             FTable.AssignCellAttributes(ItemNo, Index+r, c, cell, True, 1, cell.RowSpan);
  312.             Do_BeforeSpreadOverEmptyCells(ItemNo, Index+r, c, cell.ColSpan);
  313.             Do_SpreadOverEmptyCells(Index+r, c, cell.ColSpan);
  314.           end;
  315.           inc(c,cell.ColSpan);
  316.           end
  317.         else
  318.           inc(c);
  319.         end
  320.       else begin
  321.         Do_BeforeFreeEmptyCells(ItemNo, Index, c, 1, Count);
  322.         Do_FreeEmptyCells(Index, c, 1, Count);
  323.         inc(c);
  324.       end;
  325.   finally
  326.     ForbiddenCols.Free;
  327.     if ItemNo<>-1 then
  328.       TRVEditRVData(FMainRVData).Do_ItemModifyTerminator(ItemNo, False);
  329.   end;
  330. end;
  331. {------------------------------------------------------------------------------}
  332. procedure TRVTableRows.DeleteRows(Index, Count: Integer; DecreaseHeight: Boolean);
  333. var c,mr,mc,span: Integer;
  334.     cell: TRVTableCellData;
  335.     ItemNo: Integer;
  336.     ui: TRVUndoInfo;
  337. begin
  338.   if (Index<0) or (Index>=Self.Count) or (Count<=0) or
  339.      ((Index=0) and (Count>Self.Count)) then
  340.     raise ERichViewError.Create(errInvalidIndex);
  341.   if Count+Index>Self.Count then
  342.     Count := Self.Count-Index;
  343.   ItemNo := FTable.GetEditorItemNoForUndo;
  344.   if ItemNo<>-1 then
  345.     TRVEditRVData(FMainRVData).Do_ItemModifyTerminator(ItemNo, True);
  346.   try
  347.     c := Items[0].Count-1;
  348.     while c>=0 do begin
  349.       cell := GetMainCell(Index+Count-1,c,mr,mc);
  350.       if mr+cell.RowSpan-1>Index+Count-1 then
  351.         if mr>=Index then begin
  352.           Do_BeforeSplitCellHorz(ItemNo,mr,mc,Index+Count,DecreaseHeight);
  353.           Do_SplitCellHorz(mr,mc,Index+Count,DecreaseHeight);
  354.         end;
  355.       c := mc-1;
  356.     end;
  357.     c := Items[0].Count-1;
  358.     while c>=0 do begin
  359.       cell := GetMainCell(Index,c,mr,mc);
  360.       if mr<Index then begin
  361.         if mr+cell.RowSpan-1<=Index+Count-1 then
  362.           span := (Index-mr)
  363.         else
  364.           span := cell.RowSpan-Count;
  365.         if DecreaseHeight then
  366.           FTable.SetCellBestHeight_(ItemNo, cell.BestHeight * span div cell.RowSpan, mr, mc);
  367.         Do_SetSpan(ItemNo,mr,mc,span,False);
  368.       end;
  369.       c := mc-1;
  370.     end;
  371.     ui := Do_BeforeDeleteRows(ItemNo,Index,Count);
  372.     Do_DeleteRows(ItemNo,Index,Count, ui);
  373.   finally
  374.     if ItemNo<>-1 then
  375.       TRVEditRVData(FMainRVData).Do_ItemModifyTerminator(ItemNo, False);
  376.   end;
  377. end;
  378. {------------------------------------------------------------------------------}
  379. procedure TRVTableRows.DeleteCols(Index, Count: Integer; DecreaseWidth: Boolean);
  380. var r,mr,mc,span: Integer;
  381.     cell: TRVTableCellData;
  382.     ItemNo: Integer;
  383.     ui: TRVUndoInfo;
  384. begin
  385.   if (Index<0) or (Index>=Items[0].Count) or (Count<=0) or
  386.      ((Index=0) and (Count>Items[0].Count)) then
  387.     raise ERichViewError.Create(errInvalidIndex);
  388.   if Count+Index>Items[0].Count then
  389.     Count := Items[0].Count-Index;
  390.   ItemNo := FTable.GetEditorItemNoForUndo;
  391.   if ItemNo<>-1 then
  392.     TRVEditRVData(FMainRVData).Do_ItemModifyTerminator(ItemNo, True);
  393.   try
  394.     r := Self.Count-1;
  395.     while r>=0 do begin
  396.       cell := GetMainCell(r,Index+Count-1,mr,mc);
  397.       if mc+cell.ColSpan-1>Index+Count-1 then
  398.         if mc>=Index then begin
  399.           Do_BeforeSplitCellVert(ItemNo,mr,mc,Index+Count,DecreaseWidth);
  400.           Do_SplitCellVert(mr,mc,Index+Count,DecreaseWidth);
  401.         end;
  402.       r := mr-1;
  403.     end;
  404.     r := Self.Count-1;
  405.     while r>=0 do begin
  406.       cell := GetMainCell(r,Index,mr,mc);
  407.       if mc<Index then begin
  408.         if mc+cell.ColSpan-1<=Index+Count-1 then
  409.           span := (Index-mc)
  410.         else
  411.           span := cell.ColSpan-Count;
  412.         if DecreaseWidth then
  413.           FTable.SetCellBestWidth_(ItemNo, cell.BestWidth * span div cell.ColSpan, mr, mc);
  414.         Do_SetSpan(ItemNo,mr,mc,span,True);
  415.       end;
  416.       r := mr-1;
  417.     end;
  418.     ui := Do_BeforeDeleteCols(ItemNo,Index,Count);
  419.     Do_DeleteCols(ItemNo,Index,Count, ui);
  420.   finally
  421.     if ItemNo<>-1 then
  422.       TRVEditRVData(FMainRVData).Do_ItemModifyTerminator(ItemNo, False);
  423.   end;
  424. end;
  425. {------------------------------------------------------------------------------}
  426. function TRVTableRows.SplitCellVertically(Row, Col, ColCount: Integer): Integer;
  427. var OldColSpan, r, c,mr,mc,mr2,mc2,
  428.     NewColCount, NewColSpan: Integer;
  429.     MainCell,Cell: TRVTableCellData;
  430. begin
  431.   Result := 0;
  432.   if ColCount<=1 then
  433.     exit;
  434.   MainCell := Items[Row][Col];
  435.   if MainCell=nil then
  436.     exit;
  437.   OldColSpan := MainCell.ColSpan;
  438.   if OldColSpan>1 then
  439.     UnmergeCell(Row,Col, False, True);
  440.   if OldColSpan<ColCount then begin
  441.     Result := ColCount-OldColSpan;
  442.     for c := Col+OldColSpan-1 downto Col do begin
  443.       if (ColCount=0) or (OldColSpan=0) then
  444.         exit;
  445.       NewColCount := ColCount div OldColSpan;
  446.       InsertCols(c, NewColCount-1,c, True);
  447.       r := Count-1;
  448.       while r>=0 do begin
  449.         GetMainCell(r,c,mr,mc);
  450.         if (mr<>Row) then begin
  451.           Cell := GetMainCell(mr,c+NewColCount-1,mr2,mc2);
  452.           inc(mc2,Cell.ColSpan);
  453.           MergeCells(mr,mc, mc2-mc,Cell.RowSpan, True, True);
  454.         end;
  455.         r := mr-1;
  456.       end;
  457.       dec(ColCount,NewColCount);
  458.       dec(OldColSpan);
  459.     end;
  460.     end
  461.   else if OldColSpan>ColCount then begin
  462.     c := Col+OldColSpan-1;
  463.     while c>=Col do begin
  464.       if (ColCount=0) or (OldColSpan=0) then
  465.         exit;
  466.       NewColSpan := OldColSpan div ColCount;
  467.       dec(c,NewColSpan-1);
  468.       MergeCells(Row, c, NewColSpan, Items[Row][c].RowSpan, True, True);
  469.       dec(OldColSpan, NewColSpan);
  470.       dec(ColCount);
  471.       dec(c);
  472.     end;
  473.     //Assert(ColCount=0);
  474.   end;
  475. end;
  476. {------------------------------------------------------------------------------}
  477. function TRVTableRows.SplitCellHorizontally(Row, Col, RowCount: Integer): Integer;
  478. var OldRowSpan, r, c,mr,mc,mr2,mc2,
  479.     NewRowCount, NewRowSpan: Integer;
  480.     MainCell,Cell: TRVTableCellData;
  481. begin
  482.   Result := 0;
  483.   if RowCount<=1 then
  484.     exit;
  485.   MainCell := Items[Row][Col];
  486.   if MainCell=nil then
  487.     exit;
  488.   OldRowSpan := MainCell.RowSpan;
  489.   if OldRowSpan>1 then
  490.     UnmergeCell(Row,Col, True, False);
  491.   if OldRowSpan<RowCount then begin
  492.     Result := RowCount-OldRowSpan;
  493.     for r := Row+OldRowSpan-1 downto Row do begin
  494.       if (RowCount=0) or (OldRowSpan=0) then
  495.         exit;
  496.       NewRowCount := RowCount div OldRowSpan;
  497.       InsertRows(r, NewRowCount-1,r, True);
  498.       c := Items[0].Count-1;
  499.       while c>=0 do begin
  500.         GetMainCell(r,c,mr,mc);
  501.         if (mc<>Col) then begin
  502.           Cell := GetMainCell(r+NewRowCount-1,mc,mr2,mc2);
  503.           inc(mr2,Cell.RowSpan);
  504.           MergeCells(mr,mc, Cell.ColSpan,mr2-mr, True, True);
  505.         end;
  506.         c := mc-1;
  507.       end;
  508.       dec(RowCount,NewRowCount);
  509.       dec(OldRowSpan);
  510.     end;
  511.     end
  512.   else if OldRowSpan>RowCount then begin
  513.     r := Row+OldRowSpan-1;
  514.     while r>=Row do begin
  515.       if (RowCount=0) or (OldRowSpan=0) then
  516.         exit;
  517.       NewRowSpan := OldRowSpan div RowCount;
  518.       dec(r,NewRowSpan-1);
  519.       MergeCells(r, Col, Items[r][Col].ColSpan, NewRowSpan,True, True);
  520.       dec(OldRowSpan, NewRowSpan);
  521.       dec(RowCount);
  522.       dec(r);
  523.     end;
  524.     //Assert(RowCount=0);
  525.   end;
  526. end;
  527. {------------------------------------------------------------------------------}
  528. function TRVTableRows.SplitCellsHorizontally(TopRow, LeftCol, ColSpan,
  529.   RowSpan, RowCount: Integer): Integer;
  530. var r,c,r2,rowadded,Span: Integer;
  531. begin
  532.   Result := 0;
  533.   for r := TopRow+RowSpan-1 downto TopRow do begin
  534.     rowadded := 0;
  535.     for c := LeftCol to LeftCol+ColSpan-1 do
  536.       if Items[r][c]<>nil then begin
  537.         if rowadded>0 then begin
  538.           Span := 0;
  539.           for r2 := r+1 to r+rowadded do
  540.             if Items[r2][c]<>nil then
  541.               inc(Span);
  542.           if (Span>0) then begin
  543.             MergeCells(r,c, Items[r][c].ColSpan,Items[r][c].RowSpan+Span,True,True);
  544.           end;
  545.         end;
  546.         inc(rowadded, SplitCellHorizontally(r,c,RowCount));
  547.       end;
  548.     inc(Result,rowadded);
  549.   end;
  550. end;
  551. {------------------------------------------------------------------------------}
  552. function TRVTableRows.SplitCellsVertically(TopRow, LeftCol, ColSpan,
  553.   RowSpan, ColCount: Integer): Integer;
  554. var r,c,c2,coladded,Span: Integer;
  555. begin
  556.   Result := 0;
  557.   for c := LeftCol+ColSpan-1 downto LeftCol do begin
  558.     coladded := 0;
  559.     for r := TopRow to TopRow+RowSpan-1 do
  560.       if Items[r][c]<>nil then begin
  561.         if coladded>0 then begin
  562.           Span := 0;
  563.           for c2 := c+1 to c+coladded do
  564.             if Items[r][c2]<>nil then
  565.               inc(Span);
  566.           if (Span>0) then begin
  567.             MergeCells(r,c, Items[r][c].ColSpan+Span,Items[r][c].RowSpan,True,True);
  568.           end;
  569.         end;
  570.         inc(coladded, SplitCellVertically(r,c,ColCount));
  571.       end;
  572.     inc(Result,coladded);
  573.   end;
  574. end;
  575. {========================= TRVTableItemFormattingInfo =========================}
  576. constructor TRVTableItemFormattingInfo.Create(CreateRows:Boolean);
  577. begin
  578.   inherited Create;
  579.   ColWidths  := TRVIntegerList.Create;
  580.   ColStarts  := TRVIntegerList.Create;
  581.   RowHeights := TRVIntegerList.Create;
  582.   RowStarts  := TRVIntegerList.Create;
  583.   if CreateRows then
  584.     Rows := TRVList.Create;
  585. end;
  586. {------------------------------------------------------------------------------}
  587. destructor TRVTableItemFormattingInfo.Destroy;
  588. begin
  589.   ColWidths.Free;
  590.   ColStarts.Free;
  591.   RowHeights.Free;
  592.   RowStarts.Free;
  593.   Rows.Free;
  594.   inherited Destroy;
  595. end;
  596. {------------------------------------------------------------------------------}
  597. procedure TRVTableItemFormattingInfo.Clear;
  598. begin
  599.   ColWidths.Clear;
  600.   ColStarts.Clear;
  601.   RowHeights.Clear;
  602.   RowStarts.Clear;
  603. end;
  604. {------------------------------------------------------------------------------}
  605. procedure TRVTableItemFormattingInfo.QuickClear;
  606. begin
  607.   ColWidths.Count := 0;
  608.   ColStarts.Count := 0;
  609.   RowHeights.Count := 0;
  610.   RowStarts.Count := 0;
  611. end;
  612. {========================== TRVTableItemInfo ==================================}
  613. constructor TRVTableItemInfo.Create(RVData: TPersistent);
  614. begin
  615.   inherited Create(RVData);
  616.   Init(1,1, TCustomRVData(RVData));
  617.   Include(FState, rvtsJustCreated);
  618. end;
  619. {------------------------------------------------------------------------------}
  620. constructor TRVTableItemInfo.CreateEx(nRows, nCols: Integer; AMainRVData: TCustomRVData);
  621. begin
  622.   inherited Create(AMainRVData);
  623.   Init(nRows,nCols, AMainRVData);
  624.   Include(FState, rvtsJustCreated);
  625. end;
  626. {------------------------------------------------------------------------------}
  627. procedure TRVTableItemInfo.Init(nRows, nCols: Integer; AMainRVData: TCustomRVData);
  628. begin
  629.   Fmt := TRVTableItemFormattingInfo.Create(False);
  630.   StyleNo := rvsTable;
  631.   FRows := TRVTableRows.Create(nRows, nCols, TCustomRVFormattedData(AMainRVData), Self);
  632.   FBorderWidth     := 0;
  633.   FCellBorderWidth := 0;
  634.   FBorderStyle     := rvtbRaised;
  635.   FCellBorderStyle := rvtbLowered;
  636.   FHRuleColor      := clWindowText;
  637.   FVRuleColor      := clWindowText;
  638.   FBorderColor     := clWindowText;
  639.   FCellBorderColor := clWindowText;
  640.   FCellBorderLightColor := clBtnHighlight;
  641.   FBorderLightColor := clBtnHighlight;
  642.   FCellVSpacing    := 2;
  643.   FCellHSpacing    := 2;
  644.   FBorderVSpacing  := 2;
  645.   FBorderHSpacing  := 2;
  646.   FCellPadding     := 1;
  647.   FHRuleWidth      := 0;
  648.   FVRuleWidth      := 0;
  649.   FColor       := clWindow;
  650.   FSelStartCol := -1;
  651.   FSelStartRow := -1;
  652.   FSelColOffs := 0;
  653.   FSelRowOffs := 0;
  654.   FOptions    := RVTABLEDEFAULTOPTIONS;
  655.   FPrintOptions := RVTABLEDEFAULTPRINTOPTIONS;
  656.   Screen.Cursors[crRVSelectCol] := LoadCursor(hInstance, 'RV_SELECTCOL_CURSOR');
  657.   Screen.Cursors[crRVSelectRow] := LoadCursor(hInstance, 'RV_SELECTROW_CURSOR');
  658.   TextRowSeparator := #13#10;
  659.   TextColSeparator := #13#10;
  660.   FocusedCellRow := -1;
  661.   FocusedCellCol := -1;
  662.   ChosenCellRow := -1;
  663.   ChosenCellCol := -1;
  664.   FVisibleBorders := TRVBooleanRect.Create(True);
  665. end;
  666. {------------------------------------------------------------------------------}
  667. destructor TRVTableItemInfo.Destroy;
  668. begin
  669.   ClearTemporal;
  670.   FRows.Free;
  671.   Fmt.Free;
  672.   FBackground.Free;
  673.   FVisibleBorders.Free;
  674.   inherited Destroy;
  675. end;
  676. {------------------------------------------------------------------------------}
  677. procedure TRVTableItemInfo.ClearTemporal;
  678. begin
  679.   if FRows.FMainRVData<>nil then begin
  680.     DestroyInplace(False);
  681.     if FRows.FMainRVData is TCustomRVFormattedData then
  682.       with TCustomRVFormattedData(FRows.FMainRVData) do begin
  683.         UnAssignXorDrawing(Self.XorDrawing);
  684.         ReleaseMouseCapture(Self);
  685.       end;
  686.   end;
  687.   Fmt.Clear;
  688. end;
  689. {------------------------------------------------------------------------------}
  690. function TRVTableItemInfo.GetHeight: Integer;
  691. begin
  692.   Result := Fmt.FHeight;
  693. end;
  694. {------------------------------------------------------------------------------}
  695. function TRVTableItemInfo.GetWidth: Integer;
  696. begin
  697.   Result := Fmt.FWidth;
  698. end;
  699. {------------------------------------------------------------------------------}
  700. function TRVTableItemInfo.GetCells(Row, Col: Integer): TRVTableCellData;
  701. begin
  702.   Result := FRows.Items[Row].Items[Col];
  703. end;
  704. {------------------------------------------------------------------------------}
  705. procedure TRVTableItemInfo.SetCells(Row, Col: Integer;
  706.   const Value: TRVTableCellData);
  707. begin
  708.   if FRows.Items[Row].Items[Col]<>nil then
  709.     FRows.Items[Row].Items[Col].Assign(Value);
  710. end;
  711. {------------------------------------------------------------------------------}
  712. procedure TRVTableItemInfo.PaintFullWidth(Left, Right, Top: Integer;
  713.   Canvas: TCanvas; State: TRVItemDrawStates; Style: TRVStyle; const ClipRect: TRect;
  714.   dli: TRVDrawLineInfo);
  715. begin
  716.   PaintTo(Left, Right, Top, 0, Rows.Count, Canvas, State, Style, Fmt, False,
  717.     ClipRect, rvcmColor, nil)
  718. end;
  719. {------------------------------------------------------------------------------}
  720. procedure TRVTableItemInfo.PaintTo(Left, Right, Top, FromRow, RowCount: Integer; Canvas: TCanvas;
  721.   State: TRVItemDrawStates; Style: TRVStyle; Fmt: TRVTableItemFormattingInfo;
  722.   UseHeadingRowCount: Boolean; const ClipRect: TRect; ColorMode: TRVColorMode;
  723.   RVData: TCustomPrintableRVData);
  724. var r,c,l,t,h: Integer;
  725.     VRules, HRules, Editing: Boolean;
  726.     DH, DV, DHHalf, DVHalf: Integer;
  727.     CBOffs,ROffs: Integer;
  728.     SelColor: TColor;
  729.     {...............................................}
  730.     procedure DrawVLine(X,Y1,Y2,Width: Integer);
  731.     begin
  732.       dec(X, Width div 2);
  733.       while Width>0 do begin
  734.         Canvas.MoveTo(X,Y1);
  735.         Canvas.LineTo(X,Y2);
  736.         inc(X);
  737.         dec(Width);
  738.       end;
  739.     end;
  740.     {...............................................}
  741.     procedure DrawVLine2(X,Y1,Y2,Width: Integer);
  742.     begin
  743.       if Y1<ClipRect.Top-1 then
  744.         Y1 := ClipRect.Top-1;
  745.       if Y2>ClipRect.Bottom+1 then
  746.         Y2 := ClipRect.Bottom+1;
  747.       dec(X, Width div 2);
  748.       while Width>0 do begin
  749.         Canvas.MoveTo(X,Y1);
  750.         Canvas.LineTo(X,Y2);
  751.         inc(X);
  752.         dec(Width);
  753.       end;
  754.     end;
  755.     {...............................................}
  756.     procedure DrawHLine(Y,X1,X2,Width: Integer);
  757.     begin
  758.       dec(Y, Width div 2);
  759.       while Width>0 do begin
  760.         Canvas.MoveTo(X1,Y);
  761.         Canvas.LineTo(X2,Y);
  762.         inc(Y);
  763.         dec(Width);
  764.       end;
  765.     end;
  766.     {...............................................}
  767.     function GetExtraPrnVOffs(CellHeight,RowHeight: Integer; VAlign: TRVCellVAlign): Integer;
  768.     begin
  769.       case VAlign of
  770.         rvcMiddle:
  771.           Result := (RowHeight-CellHeight) div 2;
  772.         rvcBottom:
  773.           Result := (RowHeight-CellHeight);
  774.         else
  775.           Result := 0;
  776.       end;
  777.     end;
  778.     {...............................................}
  779.     procedure DrawCell(r,c,h, DV, DH, l,t: Integer;
  780.                        Canvas: TCanvas;
  781.                        const ClipRect, BorderRect: TRect);
  782.     var cw,ch, i,idx: Integer;
  783.         Cell: TRVTableCellData;
  784.         CanDrawBitmappedBack,WasSelected: Boolean;
  785.         CellColor: TColor;
  786.         CPD: TCellPtblRVData;
  787.         BColor, BLColor: TColor;
  788.         CellRect, CellRect2: TRect;
  789.         {$IFNDEF RICHVIEWCBDEF3}
  790.         pt: TPoint;
  791.         {$ENDIF}
  792.         rgn: HRGN;
  793.         rgnres: Integer;
  794.     begin
  795.       rgnres := 0;
  796.       rgn := 0;
  797.       Cell := Cells[r,c];
  798.       if Fmt.Rows=nil then begin
  799.         idx := 0;
  800.         ch  := Cell.FHeight;
  801.         cw  := Cell.FWidth;
  802.         end
  803.       else begin
  804.         idx := r*Rows[0].Count+c;
  805.         if Fmt.Rows[idx]<>nil then begin
  806.           ch := TCellPtblRVData(Fmt.Rows[idx]).Height+GetDevY(CellPadding*2);
  807.           cw := TCellPtblRVData(Fmt.Rows[idx]).Width+GetDevX(CellPadding*2);
  808.           end
  809.         else begin
  810.           ch := h + GetDevY(CellPadding*2);
  811.           for i := 1 to Cell.RowSpan-1 do
  812.             inc(ch, Fmt.RowHeights[r+i]+DV);
  813.           cw := Fmt.ColWidths[c] + GetDevX(CellPadding*2);
  814.           for i := 1 to Cell.ColSpan-1 do
  815.             inc(cw, Fmt.ColWidths[c+i]+DH);
  816.         end;
  817.       end;
  818.       CellColor := clNone;
  819.       if rvidsSelected in State then begin
  820.         WasSelected := rvstCompletelySelected in Cells[r,c].State;
  821.         CellColor := SelColor;
  822.         Include(Cells[r,c].State, rvstCompletelySelected);
  823.         CanDrawBitmappedBack := False;
  824.         end
  825.       else begin
  826.         CanDrawBitmappedBack := not ((Fmt.Rows=nil) and IsCellSelected(r,c));
  827.         if not CanDrawBitmappedBack then
  828.           CellColor := SelColor;
  829.         WasSelected := True;
  830.       end;
  831.       if not CanDrawBitmappedBack then
  832.         CanDrawBitmappedBack := SelColor=clNone;
  833.       if CellColor=clNone then
  834.         CellColor := Cells[r,c].Color;
  835.       if (Fmt.Rows=nil) and (CellColor=clNone) and (FInplaceEditor<>nil) and
  836.          (TRVTableInplaceEdit(FInplaceEditor).FCell=Cell) and
  837.          TRVTableInplaceEdit(FInplaceEditor).NormalScrolling then
  838.         CellColor := clWindow;
  839.       if (CellColor<>clNone) or (Cell.FBackground<>nil) then begin
  840.         if (Fmt.Rows<>nil) and (rvtoWhiteBackground in PrintOptions) then
  841.           CellColor := clWhite;
  842.         CellColor := RV_GetBackColor(CellColor, ColorMode);
  843.         Canvas.Brush.Color := CellColor;
  844.         Canvas.Pen.Color   := CellColor;
  845.         CellRect := Bounds(l, t, cw, ch);
  846.         if rvtoCellBelowBorders in Options then
  847.           InflateRect(CellRect,GetDevX(CellBorderWidth),GetDevY(CellBorderWidth));
  848.         if (Fmt.Rows=nil) and (FInplaceEditor<>nil) and
  849.            (TRVTableInplaceEdit(FInplaceEditor).FCell=Cell) and
  850.            TRVTableInplaceEdit(FInplaceEditor).NormalScrolling then begin
  851.           SetBkColor(Canvas.Handle, ColorToRGB(CellColor));
  852.           Canvas.Brush.Style := bsFDiagonal;
  853.           Canvas.Brush.Color := CellBorderColor;
  854.           SetBrushOrgEx(Canvas.Handle, l,t,
  855.           {$IFNDEF RICHVIEWCBDEF3}pt{$ELSE}nil{$ENDIF});
  856.           SetBkMode(Canvas.Handle, OPAQUE);
  857.           SetBkColor(Canvas.Handle, ColorToRGB(CellColor));
  858.           CanDrawBitmappedBack := False;
  859.         end;
  860.         if CanDrawBitmappedBack and (Cell.FBackground<>nil) then begin
  861.           if Fmt.Rows=nil then
  862.             Cell.FBackground.Draw(Canvas, CellRect, 0, 0, CellRect.Left, CellRect.Top,
  863.               CellRect.Right-CellRect.Left, CellRect.Bottom-CellRect.Top, CellColor, True)
  864.           else begin
  865.             CellRect2 := CellRect;
  866.             OffsetRect(CellRect2,-CellRect2.Left,-CellRect2.Top);
  867.             OffsetRect(CellRect2,BorderRect.Left,BorderRect.Top);
  868.             Cell.FBackground.Print(Canvas, CellRect, CellRect2, cursad^, CellColor,
  869.               rvidsPreview in State, FRows.FMainRVData.GetRVLogPalette, RVData, 1);
  870.           end;
  871.           end
  872.         else if CellColor<>clNone then
  873.           Canvas.FillRect(CellRect);
  874.         Canvas.Brush.Style := bsSolid;
  875.       end;
  876.       if Fmt.Rows=nil then begin
  877.         if (rvtoIgnoreContentWidth in Options) or
  878.            (rvtoIgnoreContentHeight in Options) then begin
  879.           rgn := CreateRectRgn(0,0,1,1);
  880.           rgnres := GetClipRgn(Canvas.Handle, rgn);
  881.           IntersectClipRect(Canvas.Handle, l, t, l+cw, t+ch);
  882.         end;
  883.         try
  884.           Cell.PaintTo(Canvas, ClipRect);
  885.         finally
  886.           if (rvtoIgnoreContentWidth in Options) or
  887.              (rvtoIgnoreContentHeight in Options) then begin
  888.             if rgnres=1 then
  889.               SelectClipRgn(Canvas.Handle, rgn)
  890.             else
  891.               SelectClipRgn(Canvas.Handle, 0);            
  892.             DeleteObject(rgn);
  893.           end;
  894.         end;
  895.         {$IFDEF RVDEBUGTABLE}
  896.         if Cell.BestWidth>0 then begin
  897.           Canvas.Pen.Color := clRed;
  898.           Canvas.MoveTo(l+CellPadding,t);
  899.           Canvas.LineTo(l+CellPadding+Cell.BestWidth,t);
  900.         end;
  901.         if Cell.BestHeight>0 then begin
  902.           Canvas.Pen.Color := clGreen;
  903.           Canvas.MoveTo(l,t+CellPadding);
  904.           Canvas.LineTo(l,t+CellPadding+Cell.BestHeight);
  905.         end;
  906.         Canvas.Font.Color := clBlack;
  907.         Canvas.Font.Name := 'Small Fonts';
  908.         Canvas.Font.Size := 6;
  909.         Canvas.TextOut(l,t, IntToStr(Cells[r,c].BestWidth)+','+IntToStr(Cells[r,c].BestHeight));
  910.         {$ENDIF}
  911.         end
  912.       else begin
  913.         if Fmt.Rows[idx]<>nil then begin
  914.           CPD := TCellPtblRVData(Fmt.Rows[idx]);
  915.           CPD.Left := Left;
  916.           CPD.Top  := Top+GetExtraPrnVOffs(CPD.DocumentHeight, CPD.Height, Cells[r,c].GetRealVAlign);
  917.           FPrintCell := Cell;
  918.           if (rvtoIgnoreContentWidth in Options) or
  919.              (rvtoIgnoreContentHeight in Options)  then begin
  920.             rgn := CreateRectRgn(0,0,1,1);
  921.             rgnres := GetClipRgn(Canvas.Handle, rgn);
  922.             IntersectClipRect(Canvas.Handle, l, t, l+cw, t+ch);
  923.           end;
  924.           try
  925.             FPrintCellRect := Bounds(l,t,cw,ch);
  926.             OffsetRect(FPrintCellRect,-BorderRect.Left,-BorderRect.Top);
  927.             RV_RectToScreen(FPrintCellRect, cursad^);
  928.             CPD.AssignItemsFrom(Cells[r,c].GetRVData);
  929.             if (FInplaceEditor<>nil) and (TRVTableInplaceEdit(FInplaceEditor).FCell=Cells[r,c]) then begin
  930.               CPD.FSourceDataForPrinting := TRVTableInplaceEdit(FInplaceEditor).FCell;
  931.               CPD.DrawPage(1, Canvas, rvidsPreview in State, rvidsPreviewCorrection in State);
  932.               CPD.FSourceDataForPrinting := Cells[r,c];
  933.               end
  934.             else begin
  935.               CPD.DrawPage(1, Canvas, rvidsPreview in State, rvidsPreviewCorrection in State);
  936.             end;
  937.             FPrintCell := nil;
  938.           finally
  939.             if (rvtoIgnoreContentWidth in Options) or
  940.                (rvtoIgnoreContentHeight in Options) then begin
  941.               if rgnres=1 then
  942.                 SelectClipRgn(Canvas.Handle, rgn)
  943.               else
  944.                 SelectClipRgn(Canvas.Handle, 0);
  945.               DeleteObject(rgn);
  946.             end;
  947.           end;
  948.         end;
  949.       end;
  950.       if Cell.BorderColor <> clNone then
  951.         BColor := Cell.BorderColor
  952.       else
  953.         BColor := CellBorderColor;
  954.       if Cell.BorderLightColor <> clNone then
  955.         BLColor := Cell.BorderLightColor
  956.       else
  957.         BLColor := CellBorderLightColor;
  958.       DrawBorder(Canvas, l-CBOffs,t-CBOffs,l+cw+CBOffs,t+ch+CBOffs,
  959.         FCellBorderWidth, BLColor, BColor, Color, CellBorderStyle,
  960.         not (rvtoHideGridLines in Options), Editing,
  961.         rvidsPrinting in State, ClipRect, Cell.VisibleBorders, r, c, ColorMode);
  962.       if not WasSelected then
  963.         Exclude(Cell.State, rvstCompletelySelected);
  964.     end;
  965.     {...............................................}
  966. var StartRow, LastRow, StartCol,RuleWidth:Integer;
  967.     mr,mc, hrc: Integer;
  968.     Clr: TColor;
  969.     BorderRect, BorderRect2: TRect;
  970. begin
  971.   if TRVScroller(Rows.FMainRVData.GetRootData.GetParentControl).FocusedEx then
  972.     SelColor := Rows.FMainRVData.GetRVStyle.SelColor
  973.   else
  974.     SelColor := Rows.FMainRVData.GetRVStyle.InactiveSelColor;
  975.   Editing := rvtsEditMode in FState;
  976.   if Editing then
  977.     Editing := (FRows.FMainRVData is TRVEditRVData) and
  978.       not TCustomRichViewEdit(TRVEditRVData(FRows.FMainRVData).RichView).ReadOnly;
  979.   MyClientLeft := Left;
  980.   MyClientTop  := Top;
  981.   VRules := (FVRuleWidth<>0) and (FVRuleColor<>clNone);
  982.   HRules := (FHRuleWidth<>0) and (FHRuleColor<>clNone);
  983.   DH := GetDevX(CellPadding+CellHSpacing+CellPadding+FCellBorderWidth*2);
  984.   DV := GetDevY(CellPadding+CellVSpacing+CellPadding+FCellBorderWidth*2);
  985.   CBOffs  := GetDevY(FCellBorderWidth);
  986.   if Fmt.Rows=nil then begin
  987.     StartRow := GetCrossed(ClipRect.Top-Top-GetDevY(BorderWidth),Fmt.RowStarts);
  988.     LastRow  := Rows.Count-1;
  989.     BorderRect := Bounds(Left,Top,Fmt.FWidth,Fmt.FHeight);
  990.     hrc := 0;
  991.     end
  992.   else begin
  993.     if UseHeadingRowCount then begin
  994.       hrc := HeadingRowCount;
  995.       if hrc>FromRow then
  996.         hrc := FromRow;
  997.       end
  998.     else
  999.       hrc := 0;
  1000.     StartRow := FromRow;
  1001.     LastRow  := FromRow+RowCount-1;
  1002.     BorderRect := Bounds(Left,Top,Fmt.FWidth,
  1003.                   Fmt.RowStarts[0]+Fmt.FHeight-Fmt.RowStarts[Rows.Count-1]-Fmt.RowHeights[Rows.Count-1]);
  1004.     if LastRow>=StartRow then
  1005.       inc(BorderRect.Bottom, Fmt.RowStarts[LastRow]+Fmt.RowHeights[LastRow]-Fmt.RowStarts[StartRow]);
  1006.     if hrc>0 then begin
  1007.       inc(BorderRect.Bottom, Fmt.RowStarts[hrc-1]+Fmt.RowHeights[hrc-1]-Fmt.RowStarts[0]);
  1008.       if LastRow>=FromRow then
  1009.         inc(BorderRect.Bottom, Fmt.RowStarts[hrc]-(Fmt.RowStarts[hrc-1]+Fmt.RowHeights[hrc-1]));
  1010.     end;
  1011.     //dec(Top, Fmt.RowStarts[FromRow]-Fmt.RowStarts[0]);
  1012.   end;
  1013.   if FBackground<>nil then begin
  1014.     if FColor=clNone then
  1015.       Clr := clNone
  1016.     else if (Fmt.Rows<>nil) and (rvtoWhiteBackground in PrintOptions) then
  1017.       Clr := clWhite
  1018.     else
  1019.       Clr := RV_GetBackColor(FColor, ColorMode);
  1020.     IntersectRect(BorderRect2, BorderRect, ClipRect);
  1021.     if Fmt.Rows=nil then
  1022.       FBackground.Draw(Canvas, BorderRect2, 0, 0, Left, Top, Fmt.FWidth, Fmt.FHeight, Clr, True)
  1023.     else
  1024.       FBackground.Print(Canvas, BorderRect2, BorderRect, cursad^, Clr, rvidsPreview in State,
  1025.         FRows.FMainRVData.GetRVLogPalette, RVData, 0);
  1026.     end
  1027.   else if FColor<>clNone then begin
  1028.     if (Fmt.Rows<>nil) and (rvtoWhiteBackground in PrintOptions) then
  1029.       Canvas.Brush.Color := clWhite
  1030.     else
  1031.       Canvas.Brush.Color := RV_GetBackColor(FColor, ColorMode);
  1032.     IntersectRect(BorderRect2, BorderRect, ClipRect);
  1033.     Canvas.FillRect(BorderRect2);
  1034.   end;
  1035.   Canvas.Pen.Width := 1;
  1036.   Canvas.Pen.Style := psSolid;
  1037.   if VRules then begin
  1038.     RuleWidth := GetDevX(FVRuleWidth);
  1039.     DHHalf := (GetDevX(CellHSpacing+FCellBorderWidth*2)+1) div 2;
  1040.     StartCol := GetCrossed(ClipRect.Left-Left-GetDevX(BorderWidth+CellHSpacing+BorderHSpacing),Fmt.ColStarts);
  1041.     if HRules and FHOutermostRule then
  1042.       ROffs := GetDevX(BorderWidth+(BorderVSpacing{-FHRuleWidth}) div 2)
  1043.     else
  1044.       ROffs := 0;
  1045.     Canvas.Pen.Color := FVRuleColor;
  1046.     if FVOutermostRule and (StartCol=0) then begin
  1047.       l := Left+GetDevX(BorderWidth+BorderHSpacing div 2);
  1048.       DrawVLine2(l, BorderRect.Top+ROffs, BorderRect.Bottom-ROffs, RuleWidth);
  1049.     end;
  1050.     for c := StartCol to Rows[0].Count-2 do begin
  1051.       l := Left+Fmt.ColStarts[c+1]-DHHalf;
  1052.       if l-RuleWidth>ClipRect.Right then
  1053.         break;
  1054.       DrawVLine2(l, BorderRect.Top+ROffs, BorderRect.Bottom-ROffs, RuleWidth);
  1055.     end;
  1056.     if FVOutermostRule then begin
  1057.       l := Left+Fmt.FWidth-GetDevX(BorderWidth+BorderHSpacing div 2)-1;
  1058.       if GetDevX(FVRuleWidth) mod 2 = 0 then
  1059.         inc(l);
  1060.       DrawVLine2(l, BorderRect.Top+ROffs, BorderRect.Bottom-ROffs, RuleWidth);
  1061.     end;
  1062.   end;
  1063.   if HRules then begin
  1064.     RuleWidth := GetDevY(FHRuleWidth);
  1065.     DVHalf := (GetDevY(CellVSpacing+FCellBorderWidth*2)+1) div 2;
  1066.     if VRules and FVOutermostRule then
  1067.       ROffs := GetDevY(BorderWidth+(BorderHSpacing{-FVRuleWidth}) div 2)
  1068.     else
  1069.       ROffs := 0;
  1070.     Canvas.Pen.Color := FHRuleColor;
  1071.     if FHOutermostRule and ((StartRow<2) or (Fmt.Rows<>nil)) then begin
  1072.       t := BorderRect.Top+GetDevY(BorderWidth+BorderVSpacing div 2);
  1073.       DrawHLine(t, Left+ROffs, Left+Fmt.FWidth-ROffs, RuleWidth);
  1074.     end;
  1075.     if hrc>0 then
  1076.       for r := 0 to hrc-2 do begin
  1077.         t := Top+Fmt.RowStarts[r+1]-DVHalf;
  1078.         if t-RuleWidth>ClipRect.Bottom then
  1079.           break;
  1080.         DrawHLine(t, Left+ROffs, Left+Fmt.FWidth-ROffs, RuleWidth);
  1081.       end;
  1082.     if LastRow>=StartRow then begin
  1083.       if Fmt.Rows<>nil then
  1084.         dec(Top, Fmt.RowStarts[FromRow]-Fmt.RowStarts[hrc]);
  1085.       StartCol := StartRow-1;
  1086.       if StartCol<0 then
  1087.         StartCol := 0;
  1088.       for r := StartCol to LastRow-1 do begin
  1089.         t := Top+Fmt.RowStarts[r+1]-DVHalf;
  1090.         if t-RuleWidth>ClipRect.Bottom then
  1091.           break;
  1092.         DrawHLine(t, Left+ROffs, Left+Fmt.FWidth-ROffs, RuleWidth);
  1093.       end;
  1094.       if Fmt.Rows<>nil then
  1095.         inc(Top, Fmt.RowStarts[FromRow]-Fmt.RowStarts[hrc]);
  1096.     end;
  1097.     if FHOutermostRule then begin
  1098.       t := BorderRect.Bottom-GetDevY(BorderWidth+BorderVSpacing div 2)-1;
  1099.       if GetDevY(FHRuleWidth) mod 2 = 0 then
  1100.         inc(t);
  1101.       DrawHLine(t, Left+ROffs, Left+Fmt.FWidth-ROffs, RuleWidth);
  1102.     end;
  1103.   end;
  1104.   DrawBorder(Canvas, BorderRect.Left,BorderRect.Top,
  1105.     BorderRect.Right,BorderRect.Bottom, BorderWidth, BorderLightColor, BorderColor,
  1106.     TCustomRVFormattedData(Rows.FMainRVData).GetColor, BorderStyle,
  1107.     not (rvtoHideGridLines in Options), Editing,
  1108.     rvidsPrinting in State,  ClipRect, VisibleBorders, -1, -1, ColorMode);
  1109.   if (StartRow>0) and (StartRow<Rows.Count) then begin
  1110.     c := Rows[StartRow].Count-1;
  1111.     while c>=0 do begin
  1112.       Rows.GetMainCell(StartRow,c,mr,mc);
  1113.       if mr<StartRow then
  1114.         DrawCell(mr, mc, Fmt.RowHeights[mr], DV, DH,
  1115.                  Fmt.ColStarts[mc]+Left,Fmt.RowStarts[mr]+Top,
  1116.                  Canvas, ClipRect, BorderRect);
  1117.       c := mc-1;
  1118.     end;
  1119.   end;
  1120.   if hrc>0 then
  1121.     for r := 0 to hrc-1 do begin
  1122.       t := Fmt.RowStarts[r]+Top;
  1123.       if t-CBOffs>ClipRect.Bottom then
  1124.         break;
  1125.       h := Fmt.RowHeights[r];
  1126.       for c := 0 to Rows[r].Count-1 do begin
  1127.         l := Fmt.ColStarts[c]+Left;
  1128.         if l-CBOffs>ClipRect.Right then break;
  1129.         if Cells[r,c]<>nil then
  1130.           DrawCell(r,c,h, DV, DH, l,t, Canvas, ClipRect, BorderRect);
  1131.       end;
  1132.     end;
  1133.   if LastRow>=StartRow then begin
  1134.     if Fmt.Rows<>nil then
  1135.       dec(Top, Fmt.RowStarts[FromRow]-Fmt.RowStarts[hrc]);
  1136.     for r := StartRow to LastRow do begin
  1137.       t := Fmt.RowStarts[r]+Top;
  1138.       if t-CBOffs>ClipRect.Bottom then
  1139.         break;
  1140.       h := Fmt.RowHeights[r];
  1141.       for c := 0 to Rows[r].Count-1 do begin
  1142.         l := Fmt.ColStarts[c]+Left;
  1143.         if l-CBOffs>ClipRect.Right then break;
  1144.         if Cells[r,c]<>nil then
  1145.           DrawCell(r,c,h, DV, DH, l,t, Canvas, ClipRect, BorderRect);
  1146.       end;
  1147.     end;
  1148.   end;
  1149.   Canvas.Pen.Width := 1;
  1150. end;
  1151. {------------------------------------------------------------------------------}
  1152. procedure TRVTableItemInfo.DrawBackgroundUnderCell(Canvas: TCanvas;
  1153.   Cell: TRVTableCellData; const Rect: TRect);
  1154. var r: TRect;
  1155.     Clr: TColor;
  1156. begin
  1157.   Clr := GetTableColor(False);
  1158.   if FBackground<>nil then
  1159.     FBackground.Draw(Canvas, Rect, 0, 0,
  1160.       -Cell.Left, -Cell.Top-Cell.GetExtraVOffs, Width, Height, Clr, False)
  1161.   else if Clr<>clNone then begin
  1162.     Canvas.Brush.Style := bsSolid;
  1163.     Canvas.Brush.Color := Clr;
  1164.     r := Rect;
  1165.     OffsetRect(r, -r.Left, -r.Top);
  1166.     Canvas.FillRect(r);
  1167.   end;
  1168. end;
  1169. {------------------------------------------------------------------------------}
  1170. function TRVTableItemInfo.IsSemiTransparentBackground: Boolean;
  1171. begin
  1172.   Result := (FColor=clNone) and (FBackground<>nil) and FBackground.IsSemitransparent; 
  1173. end;
  1174. {------------------------------------------------------------------------------}
  1175. function TRVTableItemInfo.GetHorzExtra: Integer;
  1176. begin
  1177.   Result := GetDevX(((BorderWidth+BorderHSpacing)*2+(CellHSpacing*(Rows[0].Count-1)))+
  1178.             Rows[0].Count*CellBorderWidth*2);
  1179. end;
  1180. {------------------------------------------------------------------------------}
  1181. function TRVTableItemInfo.GetMinWidth(sad: PRVScreenAndDevice; Canvas: TCanvas; RVData: TPersistent): Integer;
  1182. var ColWidths: TRVIntegerList;
  1183.     MinColsWidth: Integer;
  1184.     {.................................................}
  1185.     procedure CalcMinWidths;
  1186.     var c,w,w2: Integer;
  1187.     begin
  1188.       MinColsWidth := 0;
  1189.       for c := 0 to Rows[0].Count-1 do begin
  1190.         if rvtoIgnoreContentWidth in Options then
  1191.           w := 0
  1192.         else
  1193.           w := Rows.GetMinColWidth(c,sad,Canvas);
  1194.         if BestWidth=0 then begin
  1195.           w2 := GetDevX(Rows.GetPixelColWidth(c));
  1196.           if w2>w then
  1197.             w := w2;
  1198.         end;
  1199.         inc(MinColsWidth, w);
  1200.         ColWidths.Add(w);
  1201.       end;
  1202.     end;
  1203.     {.................................................}
  1204.     procedure ExpandCols(Row,Col, Width, Depth: Integer);
  1205.     var c, oldw, neww, savedw, pureoldw, DH, UnsizedCount: Integer;
  1206.         Cell: TRVTableCellData;
  1207.         AddProportionally: Boolean;
  1208.     const MAXDEPTH = 30;
  1209.     begin
  1210.       if Width<=0 then
  1211.         exit;
  1212.       AddProportionally := Depth>MAXDEPTH;
  1213.       savedw := Width;
  1214.       inc(Width, GetDevX(CellPadding*2));
  1215.       Cell := Cells[Row,Col];
  1216.       DH := GetDevX(CellPadding+CellHSpacing+CellPadding+FCellBorderWidth*2);
  1217.       oldw := GetDevX(-CellHSpacing-FCellBorderWidth*2);
  1218.       pureoldw := 0;
  1219.       UnsizedCount := 0;
  1220.       for c := Col to Col+Cell.ColSpan-1 do begin
  1221.         inc(oldw, ColWidths[c]+DH);
  1222.         if AddProportionally and (ColWidths[c]+GetDevX(CellPadding*2)=0) then
  1223.           inc(pureoldw, 1)
  1224.         else
  1225.           inc(pureoldw, ColWidths[c]+GetDevX(CellPadding*2));
  1226.         inc(UnsizedCount);
  1227.       end;
  1228.       if AddProportionally then begin
  1229.         for c := Col to Col+Cell.ColSpan-1 do begin
  1230.           oldw := ColWidths[c]+GetDevX(CellPadding*2);
  1231.           if oldw=0 then
  1232.             inc(oldw);
  1233.           Width := MulDiv(oldw,DH,pureoldw);
  1234.           ColWidths[c] := Width-GetDevX(CellPadding*2);
  1235.           dec(pureoldw, oldw);
  1236.           dec(DH,Width);
  1237.           inc(MinColsWidth, Width-oldw);
  1238.         end;
  1239.         exit;
  1240.       end;
  1241.       if (oldw<Width) and (UnsizedCount<>0) then begin
  1242.         DH := Width-oldw;
  1243.         inc(DH, pureoldw);
  1244.         for c := Col to Col+Cell.ColSpan-1 do begin
  1245.           if (UnsizedCount=0) or (DH<=0) then
  1246.             break;
  1247.           oldw := ColWidths[c]+GetDevX(CellPadding*2);
  1248.           neww := Round(DH/UnsizedCount);
  1249.           if oldw>=neww then begin
  1250.             dec(DH, oldw);
  1251.             dec(UnsizedCount);
  1252.           end;
  1253.         end;
  1254.         for c := Col to Col+Cell.ColSpan-1 do begin
  1255.           if (UnsizedCount=0) or (DH<=0) then
  1256.             break;
  1257.           oldw := ColWidths[c]+GetDevX(CellPadding*2);
  1258.           neww := Round(DH/UnsizedCount);
  1259.           if oldw<neww then begin
  1260.             ColWidths[c] := neww-GetDevX(CellPadding*2);
  1261.             inc(MinColsWidth, neww-oldw);
  1262.             dec(DH, neww);
  1263.             dec(UnsizedCount);
  1264.           end;
  1265.         end;
  1266.         ExpandCols(Row,Col, savedw, Depth+1);
  1267.       end;
  1268.     end;
  1269.     {.................................................}
  1270.     procedure CalcMinWidthsSpan;
  1271.     var r,c,w,w2: Integer;
  1272.     begin
  1273.       for r := 0 to Rows.Count-1 do
  1274.         with Rows[r] do
  1275.           for c := 0 to Rows[r].Count-1 do
  1276.             if (Items[c]<>nil) and (Items[c].ColSpan>1) then begin
  1277.               if rvtoIgnoreContentWidth in Options then
  1278.                 w := 0
  1279.               else
  1280.                 w := Items[c].GetMinWidth(sad,Canvas);
  1281.               if BestWidth=0 then begin
  1282.                 w2 := GetDevX(Items[c].BestWidth);
  1283.                 if w2>w then
  1284.                   w := w2;
  1285.               end;
  1286.               ExpandCols(r,c, w, 0);
  1287.             end;
  1288.     end;
  1289.     {.................................................}
  1290. var oldsad: PRVScreenAndDevice;
  1291. begin
  1292.   oldsad := cursad;
  1293.   cursad := sad;
  1294.   try
  1295.     if Rows.Empty then begin
  1296.       Result := GetDevX((BorderWidth+BorderHSpacing)*2);
  1297.       cursad := oldsad;
  1298.       exit;
  1299.     end;
  1300.     Result := GetHorzExtra+GetDevX(CellPadding*Rows[0].Count*2);
  1301.     MinColsWidth := 0;
  1302.     ColWidths := TRVIntegerList.Create;
  1303.     try
  1304.       CalcMinWidths;
  1305.       CalcMinWidthsSpan;
  1306.     finally
  1307.       ColWidths.Free;
  1308.     end;
  1309.     inc(Result, MinColsWidth);
  1310.     if GetDevX(BestWidth)>Result then
  1311.       Result := GetDevX(BestWidth);
  1312.   finally
  1313.     cursad := oldsad;
  1314.   end;
  1315. end;
  1316. {------------------------------------------------------------------------------}
  1317. function TRVTableItemInfo.IsFixedWidthTable: Boolean;
  1318. var r,c,mr,mc: Integer;
  1319.     cell: TRVTableCellData;
  1320.     definedwidth: Boolean;
  1321. begin
  1322.   Result := False;
  1323.   if Rows.IsEmptyRows(0,0,Rows[0].Count,Rows.Count,0,0) then
  1324.     exit;
  1325.   for c := 0 to Rows[0].Count-1 do begin
  1326.     definedwidth := False;
  1327.     for r := 0 to Rows.Count-1 do begin
  1328.       cell := Rows.GetMainCell(r,c,mr,mc);
  1329.       if cell.BestWidth<0 then
  1330.         exit;
  1331.       if (mc+cell.ColSpan-1=c) and (cell.BestWidth>0) then
  1332.         definedwidth := True;
  1333.     end;
  1334.     if not definedwidth then
  1335.       exit;
  1336.   end;
  1337.   Result := True;
  1338. end;
  1339. {------------------------------------------------------------------------------}
  1340. procedure TRVTableItemInfo.OnDocWidthChange(DocWidth: Integer; dli: TRVDrawLineInfo;
  1341.   Printing: Boolean; Canvas: TCanvas; RVData: TPersistent; sad: PRVScreenAndDevice;
  1342.   var HShift, Desc: Integer; NoCaching, Reformatting: Boolean);
  1343. begin
  1344.   HShift := 0;
  1345.   Desc   := 0;
  1346.   if not Printing then begin
  1347.     if (rvtsModified in FState) then begin
  1348.       Exclude(FState, rvtsModified);
  1349.       Fmt.FWidth := 0;
  1350.     end;
  1351.     InternalOnDocWidthChange(DocWidth, Fmt, Canvas, NoCaching, Reformatting)
  1352.     end
  1353.   else
  1354.     try
  1355.       cursad := @(TRVTablePrintInfo(dli).sad);
  1356.       InternalOnDocWidthChange(DocWidth, (dli as TRVTablePrintInfo).Fmt, Canvas, False, False);
  1357.       dli.Width := TRVTablePrintInfo(dli).Fmt.FWidth;
  1358.       dli.Height := TRVTablePrintInfo(dli).Fmt.FHeight;
  1359.     finally
  1360.       cursad := nil;
  1361.     end;
  1362. end;
  1363. {------------------------------------------------------------------------------}
  1364. procedure TRVTableItemInfo.InternalOnDocWidthChange(DocWidth: Integer;
  1365.                                                     Fmt: TRVTableItemFormattingInfo;
  1366.                                                     Canvas: TCanvas;
  1367.                                                     NoCaching, Reformatting: Boolean);
  1368. var r,c,w,w2,w3, PureWidth, SumColWidth, MinColsWidth, ExtraWidth: Integer;
  1369.     ColsWithAssignedWidths: TRVIntegerList;
  1370.     FixedWidthCount,AssignedCount: Integer;
  1371.     FixedWidth: Boolean;
  1372.     {.................................................}
  1373.     procedure CalcMinWidths;
  1374.     var c,w: Integer;
  1375.     begin
  1376.       MinColsWidth := 0;
  1377.       for c := 0 to Rows[0].Count-1 do begin
  1378.         if (rvtoIgnoreContentWidth in Options) then
  1379.           w := 0
  1380.         else
  1381.           w := Rows.GetMinColWidth(c,cursad,Canvas);
  1382.         inc(MinColsWidth, w);
  1383.         Fmt.ColWidths.Add(w);
  1384.       end;
  1385.     end;
  1386.     {.................................................}
  1387.     procedure ExpandCols(Row,Col, Width, CWALim: Integer; ChangeMins: Boolean;
  1388.       Depth: Integer);
  1389.     var c, oldw, pureoldw, DH, UnsizedCount, neww, savedw: Integer;
  1390.         Cell: TRVTableCellData;
  1391.         Lim: Integer;
  1392.         AddProportionally: Boolean;
  1393.     const MAXDEPTH = 30;
  1394.     begin
  1395.       if Width=0 then
  1396.         exit;
  1397.       AddProportionally := not ChangeMins or (Depth>MAXDEPTH);
  1398.       savedw := Width;
  1399.       inc(Width, GetDevX(CellPadding*2));
  1400.       Cell := Cells[Row,Col];
  1401.       DH := GetDevX(CellPadding+CellHSpacing+CellPadding+FCellBorderWidth*2);
  1402.       Lim := 0;
  1403.       repeat
  1404.         oldw := GetDevX(-CellHSpacing-FCellBorderWidth*2);
  1405.         UnsizedCount := 0;
  1406.         pureoldw := 0;
  1407.         for c := Col to Col+Cell.ColSpan-1 do begin
  1408.           inc(oldw, Fmt.ColWidths[c]+DH);
  1409.           if ChangeMins or (ColsWithAssignedWidths[c]<=Lim) then begin
  1410.             if AddProportionally and (Fmt.ColWidths[c]+GetDevX(CellPadding*2)=0) then
  1411.               inc(pureoldw, 1)
  1412.             else
  1413.               inc(pureoldw, Fmt.ColWidths[c]+GetDevX(CellPadding*2));
  1414.             inc(UnsizedCount);
  1415.           end;
  1416.         end;
  1417.         inc(Lim);
  1418.       until ChangeMins or (Lim>CWALim) or (UnsizedCount>0);
  1419.       dec(Lim);
  1420.       if (oldw<Width) and (UnsizedCount<>0) then begin
  1421.         DH := Width-oldw;
  1422.         if not ChangeMins and not FixedWidth then begin
  1423.           if DH>ExtraWidth then
  1424.             DH := ExtraWidth;
  1425.           if AddProportionally then
  1426.             dec(ExtraWidth, DH);
  1427.         end;
  1428.         inc(DH, pureoldw);
  1429.         if AddProportionally then begin
  1430.           for c := Col to Col+Cell.ColSpan-1 do
  1431.             if ChangeMins or (ColsWithAssignedWidths[c]<=Lim) then begin
  1432.               oldw := Fmt.ColWidths[c]+GetDevX(CellPadding*2);
  1433.               if oldw=0 then
  1434.                 inc(oldw);
  1435.               Width := MulDiv(oldw,DH,pureoldw);
  1436.               Fmt.ColWidths[c] := Width-GetDevX(CellPadding*2);
  1437.               dec(pureoldw, oldw);
  1438.               dec(DH,Width);
  1439.               if ChangeMins then begin
  1440.                 inc(MinColsWidth, Width-oldw);
  1441.               end;
  1442.             end;
  1443.           end
  1444.         else begin
  1445.           for c := Col to Col+Cell.ColSpan-1 do begin
  1446.             if (UnsizedCount=0) or (DH<=0) then
  1447.               break;
  1448.             if ChangeMins or (ColsWithAssignedWidths[c]<=Lim) then begin
  1449.               oldw := Fmt.ColWidths[c]+GetDevX(CellPadding*2);
  1450.               neww := Round(DH/UnsizedCount);
  1451.               if oldw>=neww then begin
  1452.                 dec(DH, oldw);
  1453.                 dec(UnsizedCount);
  1454.               end;
  1455.             end;
  1456.           end;
  1457.           for c := Col to Col+Cell.ColSpan-1 do begin
  1458.             if (UnsizedCount=0) or (DH<=0) then
  1459.               break;
  1460.             if ChangeMins or (ColsWithAssignedWidths[c]<=Lim) then begin
  1461.               oldw := Fmt.ColWidths[c]+GetDevX(CellPadding*2);
  1462.               neww := Round(DH/UnsizedCount);
  1463.               if oldw<neww then begin
  1464.                 Fmt.ColWidths[c] := neww-GetDevX(CellPadding*2);
  1465.                 if ChangeMins then
  1466.                   inc(MinColsWidth, neww-oldw);
  1467.                 dec(DH, neww);
  1468.                 if not ChangeMins and not FixedWidth then
  1469.                   dec(ExtraWidth, neww-oldw);
  1470.                 dec(UnsizedCount);
  1471.               end;
  1472.             end;
  1473.           end;
  1474.           if ChangeMins or FixedWidth or (ExtraWidth>0) then
  1475.             ExpandCols(Row,Col, savedw, CWALim, ChangeMins, Depth+1);
  1476.         end;
  1477.       end;
  1478.     end;
  1479.     {.................................................}
  1480.     procedure CalcMinWidthsSpan;
  1481.     var r,c: Integer;
  1482.     begin
  1483.       for r := 0 to Rows.Count-1 do
  1484.         with Rows[r] do
  1485.           for c := 0 to Rows[r].Count-1 do
  1486.             if (Items[c]<>nil) and (Items[c].ColSpan>1) then
  1487.               ExpandCols(r,c, Items[c].GetMinWidth(cursad,Canvas), 2,True,0);
  1488.     end;
  1489.     {.................................................}
  1490.     procedure CalcPercentWidths;
  1491.     var c,w,pw,NonDistribWidth: Integer;
  1492.         Widths: TRVIntegerList;
  1493.     begin
  1494.       ExtraWidth := PureWidth-MinColsWidth;
  1495.       NonDistribWidth := 0;
  1496.       Widths := TRVIntegerList.CreateEx(Rows[0].Count,0);
  1497.       try
  1498.         pw := 0;
  1499.         for c := 0 to Rows[0].Count-1 do begin
  1500.           w := Rows.GetPercentColWidth(c, SumColWidth)-GetDevX(CellPadding*2);
  1501.           if w<0 then
  1502.             w := 0;
  1503.           Widths[c] := w;
  1504.           if w>Fmt.ColWidths[c] then begin
  1505.             inc(pw,w);
  1506.             inc(NonDistribWidth, Fmt.ColWidths[c]);
  1507.             inc(ExtraWidth, Fmt.ColWidths[c]);
  1508.           end;
  1509.         end;
  1510.         if pw=0 then
  1511.           exit;
  1512.         if pw<ExtraWidth then
  1513.           pw := ExtraWidth;
  1514.         for c := 0 to Rows[0].Count-1 do begin
  1515.           if Widths[c]=0 then
  1516.             continue;
  1517.           if Widths[c]<=Fmt.ColWidths[c] then begin
  1518.             ColsWithAssignedWidths[c] := 2;
  1519.             inc(AssignedCount);
  1520.             continue;          
  1521.           end;
  1522.           dec(NonDistribWidth, Fmt.ColWidths[c]);
  1523.           w := MulDiv(Widths[c], ExtraWidth,pw);
  1524.           dec(pw, Widths[c]);
  1525.           if w>0 then begin
  1526.             ColsWithAssignedWidths[c] := 2;
  1527.             inc(AssignedCount);
  1528.           end;
  1529.           if w>ExtraWidth-NonDistribWidth then
  1530.             w := ExtraWidth-NonDistribWidth;
  1531.           if w>Fmt.ColWidths[c] then
  1532.             Fmt.ColWidths[c] := w;
  1533.           dec(ExtraWidth, Fmt.ColWidths[c]);
  1534.           if (ExtraWidth=0) and (NonDistribWidth=0) then
  1535.             break;
  1536.         end;
  1537.     finally
  1538.       Widths.Free;
  1539.     end;
  1540.       {
  1541.       ExtraWidth := PureWidth-MinColsWidth;
  1542.       for c := 0 to Rows[0].Count-1 do begin
  1543.         w := Rows.GetPercentColWidth(c, SumColWidth)-GetDevX(CellPadding*2);
  1544.         if w>0 then begin
  1545.           ColsWithAssignedWidths[c] := 2;
  1546.           inc(AssignedCount);
  1547.         end;
  1548.         if w>Fmt.ColWidths[c] then begin
  1549.           inc(ExtraWidth, Fmt.ColWidths[c]);
  1550.           if w>ExtraWidth then
  1551.             w := ExtraWidth;
  1552.           Fmt.ColWidths[c] := w;
  1553.           dec(ExtraWidth,w);
  1554.           if ExtraWidth=0 then break;
  1555.         end;
  1556.       end;
  1557.       }
  1558.     end;
  1559.     {.................................................}
  1560.     procedure CalcPercentWidthsSpan;
  1561.     var r,c,w,i: Integer;
  1562.     begin
  1563.       if ExtraWidth<=0 then exit;
  1564.       for r := 0 to Rows.Count-1 do
  1565.         with Rows[r] do
  1566.           for c := 0 to Rows[r].Count-1 do
  1567.             if (Items[c]<>nil) and (Items[c].ColSpan>1) and
  1568.                (Items[c].BestWidth<0) then begin
  1569.               w := MulDiv(-Items[c].BestWidth, SumColWidth, 100)-GetDevX(CellPadding*2);
  1570.               ExpandCols(r,c,w, 2, False, 0);
  1571.             end;
  1572.       for r := 0 to Rows.Count-1 do
  1573.         with Rows[r] do
  1574.           for c := 0 to Rows[r].Count-1 do
  1575.             if (Items[c]<>nil) and (Items[c].ColSpan>1) and
  1576.                (Items[c].BestWidth<0) then begin
  1577.               for i := 0 to Items[c].ColSpan-1 do
  1578.                 if ColsWithAssignedWidths[c+i]=0 then begin
  1579.                   ColsWithAssignedWidths[c+i] := 2;
  1580.                   inc(AssignedCount);
  1581.                 end;
  1582.             end;
  1583.     end;
  1584.     {.................................................}
  1585.     { Calculates widths of pixel-width columns in tables having
  1586.       width=sum of column widths }
  1587.     procedure CalcFixedWidths;
  1588.     var c,w: Integer;
  1589.     begin
  1590.       if not FixedWidth then
  1591.         exit;
  1592.       for c := 0 to Rows[0].Count-1 do
  1593.         if ColsWithAssignedWidths[c]=0 then begin
  1594.           w := GetDevX(Rows.GetPixelColWidth(c));
  1595.           if w>0 then begin
  1596.             ColsWithAssignedWidths[c] := 1;
  1597.             inc(AssignedCount);
  1598.             inc(FixedWidthCount);
  1599.           end;
  1600.           if w>Fmt.ColWidths[c] then
  1601.             Fmt.ColWidths[c] := w;
  1602.         end;
  1603.     end;
  1604.     {.................................................}
  1605.     { Calculates widths of pixel-width columns in tables having
  1606.       width<>sum of column widths. This function does not distribute extra width
  1607.       larger than necessary. If extra width is less than necessary, it distributes
  1608.       lack of width between affected columns proportionally }
  1609.     procedure CalcFixedWidths2;
  1610.     var c,w, aw, fw: Integer;
  1611.         Widths: TRVIntegerList;
  1612.     begin
  1613.       if FixedWidth or (ExtraWidth<=0) then
  1614.         exit;
  1615.       Widths := TRVIntegerList.CreateEx(Rows[0].Count,0);
  1616.       try
  1617.         aw := 0;
  1618.         for c := 0 to Rows[0].Count-1 do
  1619.           if ColsWithAssignedWidths[c]=0 then begin
  1620.             w := GetDevX(Rows.GetPixelColWidth(c));
  1621.             if w>0 then begin
  1622.               ColsWithAssignedWidths[c] := 1;
  1623.               inc(AssignedCount);
  1624.               inc(FixedWidthCount);
  1625.             end;
  1626.             if w>Fmt.ColWidths[c] then begin
  1627.               Widths[c] := w;
  1628.               inc(aw, w);
  1629.               inc(ExtraWidth, Fmt.ColWidths[c]);
  1630.             end;
  1631.           end;
  1632.         fw := aw;
  1633.         if aw>ExtraWidth then
  1634.           aw := ExtraWidth;
  1635.         if fw>0 then
  1636.           for c := 0 to Rows[0].Count-1 do
  1637.             if (ColsWithAssignedWidths[c]=1) and (Widths[c]>0) then begin
  1638.               w := MulDiv(Widths[c], aw, fw);
  1639.               if w>ExtraWidth then
  1640.                 w := ExtraWidth;
  1641.               if w<Fmt.ColWidths[c] then
  1642.                 w := Fmt.ColWidths[c];
  1643.               dec(ExtraWidth,w);
  1644.               Fmt.ColWidths[c] := w;
  1645.               dec(fw, Widths[c]);
  1646.               dec(aw, w);
  1647.             end;
  1648.       finally
  1649.         Widths.Free;
  1650.       end;
  1651.     end;
  1652.     {.................................................}
  1653.     procedure CalcFixedWidthsSpan;
  1654.     var r,c,w,i: Integer;
  1655.     begin
  1656.       if not FixedWidth and (ExtraWidth<=0) then exit;
  1657.       for r := 0 to Rows.Count-1 do
  1658.         with Rows[r] do
  1659.           for c := 0 to Rows[r].Count-1 do
  1660.             if //(ColsWithAssignedWidths[c]<>2) and
  1661.                (Items[c]<>nil) and (Items[c].ColSpan>1) and
  1662.                (Items[c].BestWidth>0) then begin
  1663.               w := GetDevX(Items[c].BestWidth);
  1664.               ExpandCols(r,c,w, 1, False, 0);
  1665.             end;
  1666.       for r := 0 to Rows.Count-1 do
  1667.         with Rows[r] do
  1668.           for c := 0 to Rows[r].Count-1 do
  1669.             if (Items[c]<>nil) and (Items[c].ColSpan>1) and
  1670.                (Items[c].BestWidth>0) then begin
  1671.               for i := 0 to Items[c].ColSpan-1 do
  1672.                 if ColsWithAssignedWidths[c+i]=0 then begin
  1673.                   ColsWithAssignedWidths[c+i] := 1;
  1674.                   inc(AssignedCount);
  1675.                   inc(FixedWidthCount);
  1676.                 end;
  1677.             end;
  1678.     end;
  1679.     {.................................................}
  1680.     procedure ExpandRows(Row,Col: Integer);
  1681.     var r,h,h2,oldh, pureoldh, pureoldh2, DV: Integer;
  1682.         EmptyRows: Boolean;
  1683.         Cell: TRVTableCellData;
  1684.     begin
  1685.       Cell := Cells[Row,Col];
  1686.       DV := GetDevY(CellPadding+CellVSpacing+CellPadding+FCellBorderWidth*2);
  1687.       if Fmt.Rows=nil then
  1688.         h := GetDevY(Cell.GetCellHeight(rvtoIgnoreContentHeight in Options)+CellPadding*2)
  1689.       else begin
  1690.         h := GetDevY(Cell.BestHeight);
  1691.         if ((h=0) or not (rvtoIgnoreContentHeight in Options)) and
  1692.            (Fmt.Rows[Row*Rows[0].Count+Col]<>nil) then begin
  1693.           h2 := TCellPtblRVData(Fmt.Rows[Row*Rows[0].Count+Col]).DocumentHeight;
  1694.           if h2>h then
  1695.             h := h2;
  1696.         end;
  1697.         inc(h, GetDevY(CellPadding*2));
  1698.       end;
  1699.       oldh := GetDevY(-CellVSpacing-FCellBorderWidth*2);
  1700.       pureoldh := 0;
  1701.       pureoldh2 := 0;
  1702.       EmptyRows := False;
  1703.       for r := Row to Row+Cell.RowSpan-1 do begin
  1704.         inc(oldh, Fmt.RowHeights[r]+DV);
  1705.         inc(pureoldh, Fmt.RowHeights[r]);
  1706.         if not Rows[r].HasCellsInRange(r, Row, Cell.RowSpan) then begin
  1707.           inc(pureoldh2, Fmt.RowHeights[r]);
  1708.           EmptyRows := True;
  1709.         end;
  1710.       end;
  1711.       if EmptyRows then
  1712.         pureoldh := pureoldh2;
  1713.       if oldh<h then begin
  1714.         DV := h-oldh;
  1715.         inc(Fmt.FHeight, DV);
  1716.         for r := Row to Row+Cell.RowSpan-1 do
  1717.           if not (EmptyRows and Rows[r].HasCellsInRange(r, Row, Cell.RowSpan)) then begin
  1718.             oldh := Fmt.RowHeights[r];
  1719.             h := MulDiv(oldh,DV,pureoldh);
  1720.             Fmt.RowHeights[r] := Integer(Fmt.RowHeights.Items[r])+h;
  1721.             dec(pureoldh, oldh);
  1722.             dec(DV,h);
  1723.           end;
  1724.       end;
  1725.     end;
  1726.     {.................................................}
  1727. var NewWidth, HorExtra: Integer;
  1728. begin
  1729.   if Rows.Empty then begin
  1730.     Fmt.FWidth := GetDevX((BorderWidth+BorderHSpacing)*2);
  1731.     Fmt.FHeight := GetDevY((BorderWidth+BorderVSpacing)*2);
  1732.     exit;
  1733.   end;
  1734.   HorExtra := GetHorzExtra;
  1735.   FixedWidth := False;
  1736.   if BestWidth>0 then
  1737.     NewWidth := GetDevX(BestWidth)
  1738.   else if BestWidth<0 then
  1739.     NewWidth := -BestWidth*DocWidth div 100
  1740.   else begin
  1741.     FixedWidth := IsFixedWidthTable;
  1742.     if not FixedWidth then begin //  temporary
  1743.       NewWidth := GetMinWidth(cursad, Canvas, nil);
  1744.       if DocWidth>NewWidth then
  1745.         NewWidth := DocWidth;
  1746.       end
  1747.     else
  1748.       NewWidth := 0; //CalcPixelWidth;
  1749.       //inc(NewWidth, HorExtra+GetDevX(CellPadding*Rows[0].Count*2));
  1750.   end;
  1751.   if (NewWidth<>0) and (NewWidth=Fmt.FWidth) and not NoCaching then
  1752.     exit;
  1753.   Fmt.FWidth := NewWidth;
  1754.   if Rows.Empty then
  1755.     exit;
  1756.   ColsWithAssignedWidths := nil;
  1757.   if not FixedWidth then begin
  1758.     SumColWidth := Fmt.FWidth - HorExtra;
  1759.     PureWidth := SumColWidth - GetDevX(CellPadding*Rows[0].Count*2);
  1760.     end
  1761.   else begin
  1762.     SumColWidth := 0;
  1763.     PureWidth   := 0;
  1764.     ExtraWidth  := 0;
  1765.   end;
  1766.   Fmt.QuickClear;
  1767.   // Calculating minimal widths
  1768.   CalcMinWidths;
  1769.   if not (rvtoIgnoreContentWidth in Options) then
  1770.     CalcMinWidthsSpan;
  1771.   if not FixedWidth and (MinColsWidth>=PureWidth) then begin
  1772.     // Table is too narrow. Setting all width to minimums
  1773.     Fmt.FWidth := Fmt.FWidth-PureWidth+MinColsWidth;
  1774.     end
  1775.   else begin
  1776.     ColsWithAssignedWidths := TRVIntegerList.Create;
  1777.     try
  1778.       AssignedCount := 0;
  1779.       FixedWidthCount := 0;
  1780.       ColsWithAssignedWidths.Capacity := Fmt.ColWidths.Count;
  1781.       for c := 0 to Fmt.ColWidths.Count-1 do
  1782.         ColsWithAssignedWidths.Add(0);
  1783.       // Setting widths for autosizing cols...
  1784.       if not FixedWidth then begin
  1785.         CalcPercentWidths;
  1786.         CalcPercentWidthsSpan;
  1787.       end;
  1788.       // Setting widths for fixed cols...
  1789.       CalcFixedWidths;
  1790.       CalcFixedWidths2;
  1791.       CalcFixedWidthsSpan;
  1792.       if FixedWidth then begin
  1793.         Fmt.FWidth := HorExtra+GetDevX(CellPadding*Rows[0].Count*2);
  1794.         for c := 0 to Rows[0].Count-1 do
  1795.           inc(Fmt.FWidth, Fmt.ColWidths[c]);
  1796.         end
  1797.       else if ExtraWidth>0 then
  1798.         if AssignedCount<ColsWithAssignedWidths.Count then begin
  1799.           // Setting widths for other cols...
  1800.           for c := 0 to Rows[0].Count-1 do
  1801.             if ColsWithAssignedWidths[c]=0 then begin
  1802.               w := ExtraWidth div (ColsWithAssignedWidths.Count-AssignedCount);
  1803.               Fmt.ColWidths[c] := Fmt.ColWidths[c]+w;
  1804.               dec(ExtraWidth,w);
  1805.               inc(AssignedCount);
  1806.               if ExtraWidth<=0 then break;
  1807.             end;
  1808.           end
  1809.         else if FixedWidthCount>0 then begin
  1810.           // Expanding fixed width cols.
  1811.           w2 := 0;
  1812.           for c := 0 to Rows[0].Count-1 do
  1813.             if not Rows.IsPercentWidthColumn(c) then begin
  1814.               w := Rows.GetPixelColWidth(c);
  1815.               if w=0 then
  1816.                 w := 1;
  1817.               ColsWithAssignedWidths[c] := w;
  1818.               inc(w2,w);
  1819.               end
  1820.             else
  1821.               ColsWithAssignedWidths[c] := 0;
  1822.           for c := 0 to Rows[0].Count-1 do begin
  1823.             w3 := ColsWithAssignedWidths[c];
  1824.             if w3<>0 then begin
  1825.               w := MulDiv(ExtraWidth, w3, w2);
  1826.               Fmt.ColWidths[c] := Fmt.ColWidths[c]+w;
  1827.               dec(ExtraWidth,w);
  1828.               dec(w2, w3);
  1829.               if ExtraWidth<=0 then break;
  1830.             end;
  1831.           end
  1832.           end
  1833.         else begin
  1834.           // Expanding all cols
  1835.          w2 := 0;
  1836.          for c := 0 to Rows[0].Count-1 do
  1837.           if Rows.IsPercentWidthColumn(c) then begin
  1838.             w := Rows.GetPercentColWidth(c, SumColWidth)-GetDevX(CellPadding*2);
  1839.             if w<=0 then
  1840.               w := 1;
  1841.             ColsWithAssignedWidths[c] := w;
  1842.             inc(w2,w);
  1843.           end;
  1844.           for c := 0 to Rows[0].Count-1 do begin
  1845.             if Rows.IsPercentWidthColumn(c) then begin
  1846.               w3 := ColsWithAssignedWidths[c];
  1847.               w := MulDiv(ExtraWidth, w3, w2);
  1848.               if w>ExtraWidth then
  1849.                 w := ExtraWidth;
  1850.               Fmt.ColWidths[c] := Fmt.ColWidths[c]+w;
  1851.               dec(ExtraWidth,w);
  1852.               dec(w2, w3);
  1853.               if ExtraWidth<=0 then break;
  1854.             end;
  1855.           end;
  1856.         end;
  1857.     finally
  1858.       ColsWithAssignedWidths.Free;
  1859.     end;
  1860.   end;
  1861.   // Note: for table with undefined width algorithm must be completely different...
  1862.   UpdateCellXCoords(Fmt, NoCaching, Reformatting);
  1863.   Fmt.FHeight := GetDevY((CellPadding*Rows.Count+BorderWidth+BorderVSpacing)*2+(CellVSpacing*(Rows.Count-1))+
  1864.              Rows.Count*CellBorderWidth*2);
  1865.   Fmt.RowHeights.Capacity := Rows.Count;
  1866.   Fmt.RowStarts.Count := Rows.Count;
  1867.   // pass 1...
  1868.   if Fmt.Rows=nil then
  1869.     for r := 0 to Rows.Count-1 do begin
  1870.       w := GetDevY(Rows[r].GetHeight(rvtoIgnoreContentHeight in Options));
  1871.       Fmt.RowHeights.Add(w);
  1872.       inc(Fmt.FHeight, w);
  1873.     end
  1874.   else
  1875.     for r := 0 to Rows.Count-1 do begin
  1876.       with Rows[r] do begin
  1877.         w := GetDevY(GetBestHeight);
  1878.         if (w=0) or not (rvtoIgnoreContentHeight in Options) then
  1879.           for c := 0 to Count-1 do
  1880.             if (Items[c]<>nil) and (Items[c].RowSpan=1) and
  1881.                ((Items[c].BestHeight=0) or
  1882.                  not (rvtoIgnoreContentHeight in Options)) then begin 
  1883.               if Fmt.Rows[r*Count+c]<>nil then
  1884.                 w2 := TCellPtblRVData(Fmt.Rows[r*Count+c]).DocumentHeight
  1885.               else begin
  1886.                 w2 := GetDevY(Items[c].DocumentHeight);
  1887.                 if w2=0 then begin
  1888.                   if (Items[c].GetRVData.ItemCount>0) and (Items[c].GetRVData.GetItemStyle(0)>=0) then begin
  1889.                     FRows.FMainRVData.GetRVStyle.ApplyStyle(Canvas, Items[c].GetRVData.GetItemStyle(0),
  1890.                       rvbdUnspecified, False);
  1891.                     w2 := Canvas.TextHeight(' ');
  1892.                     with FRows.FMainRVData.GetRVStyle.ParaStyles[Items[c].GetRVData.GetItemPara(0)] do
  1893.                     inc(w2, GetDevY(SpaceBefore+SpaceAfter));
  1894.                   end;
  1895.                 end;
  1896.               end;
  1897.               if w2>w then
  1898.                 w := w2;
  1899.             end;
  1900.       end;
  1901.       if w=0 then
  1902.         w := 10; // temporal
  1903.       Fmt.RowHeights.Add(w);
  1904.       inc(Fmt.FHeight, w);
  1905.     end;
  1906.   // pass 2...
  1907.   for r := 0 to Rows.Count-1 do
  1908.     with Rows[r] do
  1909.       for c := 0 to Count-1 do
  1910.         if (Items[c]<>nil) and (Items[c].RowSpan>1) then
  1911.           ExpandRows(r,c);
  1912.   UpdateCellYCoords(Fmt);
  1913. end;
  1914. {------------------------------------------------------------------------------}
  1915. procedure TRVTableItemInfo.DrawBorder(Canvas: TCanvas;
  1916.   Left,Top,Right,Bottom, Width: Integer; LightColor, Color, BackgroundColor: TColor;
  1917.   Style: TRVTableBorderStyle; DrawEvenEmptyBorder, Editing, Printing: Boolean;
  1918.   const ClipRect: TRect; VisibleBorders: TRVBooleanRect;
  1919.   r,c: Integer; ColorMode: TRVColorMode);
  1920. var i,y1,y2,incr: Integer;
  1921.     par: array [0..2] of TPoint;
  1922.     DrawGridLines: Boolean;
  1923.     {..........................................}
  1924.     procedure ClipY(var y1,y2: Integer; const ClipRect: TRect);
  1925.     begin
  1926.       if y1<ClipRect.Top-1 then
  1927.         y1 := ClipRect.Top-1;
  1928.       if y2>ClipRect.Bottom+1 then
  1929.         y2 := ClipRect.Bottom+1;
  1930.     end;
  1931.     {..........................................}
  1932.     function HasTopLine: Boolean;
  1933.     var r2,c2: Integer;
  1934.     begin
  1935.       if r<0 then
  1936.         Result := False
  1937.       else if r=0 then
  1938.         Result := (BorderVSpacing<0) and (BorderWidth>0) and VisibleBorders.Top
  1939.       else
  1940.         Result := (CellVSpacing<0) and Rows.GetMainCell(r-1,c,r2,c2).VisibleBorders.Bottom;
  1941.     end;
  1942.     {..........................................}
  1943.     function HasBottomLine: Boolean;
  1944.     var r2,c2: Integer;
  1945.     begin
  1946.       if r<0 then
  1947.         Result := False
  1948.       else begin
  1949.         r2 := r+Cells[r,c].RowSpan-1;
  1950.         if r2=Rows.Count-1 then
  1951.           Result := (BorderVSpacing<0) and (BorderWidth>0) and VisibleBorders.Bottom
  1952.         else
  1953.           Result := (CellVSpacing<0) and Rows.GetMainCell(r2+1,c,r2,c2).VisibleBorders.Top;
  1954.       end;
  1955.     end;
  1956.     {..........................................}
  1957.     function HasLeftLine: Boolean;
  1958.     var r2,c2: Integer;
  1959.     begin
  1960.       if c<0 then
  1961.         Result := False
  1962.       else if c=0 then
  1963.         Result := (BorderHSpacing<0) and (BorderWidth>0) and VisibleBorders.Left
  1964.       else
  1965.         Result := (CellHSpacing<0) and Rows.GetMainCell(r,c-1,r2,c2).VisibleBorders.Right;
  1966.     end;
  1967.     {..........................................}
  1968.     function HasRightLine: Boolean;
  1969.     var r2,c2: Integer;
  1970.     begin
  1971.       if c<0 then
  1972.         Result := False
  1973.       else begin
  1974.         c2 := c+Cells[r,c].ColSpan-1;
  1975.         if c2=Rows[r].Count-1 then
  1976.           Result := (BorderHSpacing<0) and (BorderWidth>0) and VisibleBorders.Right
  1977.         else
  1978.           Result := (CellHSpacing<0) and Rows.GetMainCell(r,c2+1,r2,c2).VisibleBorders.Left;
  1979.       end;
  1980.     end;
  1981.     {..........................................}
  1982. var DoDefault: Boolean;
  1983.     GridStyle: TPenStyle;
  1984. begin
  1985.   if (ClipRect.Left>Right) or
  1986.      (ClipRect.Right<Left) or
  1987.      (ClipRect.Top>Bottom) or
  1988.      (ClipRect.Bottom<Top) then
  1989.     exit;
  1990.   if Assigned(FOnDrawBorder) then begin
  1991.     DoDefault := True;
  1992.     FOnDrawBorder(Self, Canvas, Left, Top, Right, Bottom, Width, LightColor, Color,
  1993.     BackgroundColor, Style, Printing, VisibleBorders, r, c, DoDefault);
  1994.     if not DoDefault then
  1995.       exit;
  1996.   end;
  1997.   if Editing then
  1998.     GridStyle := RichViewTableGridStyle
  1999.   else
  2000.     GridStyle := RichViewTableGridStyle2;
  2001.   DrawGridLines := DrawEvenEmptyBorder and not Printing and (GridStyle<>psClear);
  2002.   if Width=0 then begin
  2003.     if not DrawGridLines then
  2004.       exit;
  2005.     Canvas.Pen.Width := 1;
  2006.     Canvas.Brush.Color := clNone;
  2007.     Canvas.Brush.Style := bsClear;
  2008.     Canvas.Pen.Style := GridStyle;
  2009.     Canvas.Pen.Color := RichViewTableGridColor;
  2010.     Canvas.Rectangle(Left,Top,Right,Bottom);
  2011.     Canvas.Pen.Mode := pmCopy;
  2012.     Canvas.Pen.Style := psSolid;
  2013.     exit;
  2014.   end;
  2015.   if DrawGridLines and (VisibleBorders<>nil) and not VisibleBorders.IsAllEqual(True) then begin
  2016.     Canvas.Pen.Width := 1;
  2017.     Canvas.Brush.Color := clNone;
  2018.     Canvas.Brush.Style := bsClear;
  2019.     Canvas.Pen.Style := GridStyle;
  2020.     Canvas.Pen.Color := RichViewTableGridColor;
  2021.     if not VisibleBorders.Top and not HasTopLine then begin
  2022.       Canvas.MoveTo(Left,Top);
  2023.       Canvas.LineTo(Right,Top);
  2024.     end;
  2025.     if not VisibleBorders.Bottom and not HasBottomLine then begin
  2026.       Canvas.MoveTo(Left,Bottom);
  2027.       Canvas.LineTo(Right,Bottom);
  2028.     end;
  2029.     if not VisibleBorders.Left and not HasLeftLine then begin
  2030.       y1 := Top;
  2031.       y2 := Bottom;
  2032.       ClipY(y1,y2,ClipRect);
  2033.       Canvas.MoveTo(Left,y1);
  2034.       Canvas.LineTo(Left,y2);
  2035.     end;
  2036.     if not VisibleBorders.Right and not HasRightLine then begin
  2037.       y1 := Top;
  2038.       y2 := Bottom;
  2039.       ClipY(y1,y2,ClipRect);
  2040.       Canvas.MoveTo(Right,y1);
  2041.       Canvas.LineTo(Right,y2);
  2042.     end;
  2043.     Canvas.Pen.Mode := pmCopy;
  2044.     Canvas.Pen.Style := psSolid;
  2045.   end;
  2046.   Canvas.Brush.Style := bsClear;
  2047.   if Style in [rvtbRaised, rvtbLowered, rvtbRaisedColor, rvtbLoweredColor] then begin
  2048.     dec(Right);
  2049.     dec(Bottom);
  2050.     Width := GetDevY(Width);
  2051.     // 3d frame
  2052.     case Style of
  2053.       rvtbRaised:
  2054.         begin
  2055.           if ColorToRGB(BackgroundColor)=ColorToRGB(clBtnHighlight) then
  2056.             Canvas.Pen.Color := RV_GetColor(clBtnFace, ColorMode)
  2057.           else
  2058.             Canvas.Pen.Color := RV_GetColor(clBtnHighlight, ColorMode)
  2059.         end;
  2060.       rvtbRaisedColor:
  2061.         Canvas.Pen.Color := RV_GetColor(LightColor, ColorMode);
  2062.       rvtbLoweredColor:
  2063.         Canvas.Pen.Color := RV_GetColor(Color, ColorMode);
  2064.       else {rvtbLowered}
  2065.         Canvas.Pen.Color := RV_GetColor(clBtnShadow, ColorMode);
  2066.     end;
  2067.     if Printing and (rvtoHalftoneBorders in PrintOptions) then begin
  2068.       if (cursad<>nil) and (cursad.ppiyScreen<cursad.ppiyDevice) then begin
  2069.         Canvas.Pen.Width := Width+1;
  2070.         dec(Left);
  2071.         dec(Top);
  2072.       end;
  2073.       Canvas.Pen.Style := psInsideFrame;
  2074.       Width := Width div 2;
  2075.       inc(Left,Width);
  2076.       inc(Top,Width);
  2077.       dec(Right,Width);
  2078.       dec(Bottom,Width);
  2079.       Width := 1;
  2080.       incr := 0;
  2081.       end
  2082.     else begin
  2083.       Canvas.Pen.Width := 1;
  2084.       Canvas.Pen.Style := psSolid;
  2085.       incr := 1;
  2086.     end;
  2087.     with par[0] do begin x := Left;  y := Bottom; end;
  2088.     with par[1] do begin x := Left;  y := Top;    end;
  2089.     with par[2] do begin x := Right; y := Top;    end;
  2090.     for i := 0 to Width-1 do begin
  2091.       //Canvas.Polyline(par);  <- does not work for looooong tables
  2092.       if (VisibleBorders=nil) or (VisibleBorders.Top) then begin
  2093.         with par[1] do Canvas.MoveTo(x,y);
  2094.         with par[2] do Canvas.LineTo(x+incr,y);
  2095.       end;
  2096.       if (VisibleBorders=nil) or (VisibleBorders.Left) then begin
  2097.         y1 := par[1].y;
  2098.         y2 := par[0].y;
  2099.         ClipY(y1,y2,ClipRect);
  2100.         Canvas.MoveTo(par[1].x,y1);
  2101.         Canvas.LineTo(par[0].x,y2+incr);
  2102.       end;
  2103.       with par[0] do begin inc(x); dec(y); end;
  2104.       with par[1] do begin inc(x); inc(y); end;
  2105.       with par[2] do begin dec(x); inc(y); end;
  2106.     end;
  2107.     case Style of
  2108.       rvtbRaised:
  2109.         Canvas.Pen.Color := RV_GetColor(clBtnShadow, ColorMode);
  2110.       rvtbRaisedColor:
  2111.         Canvas.Pen.Color := RV_GetColor(Color, ColorMode);
  2112.       rvtbLoweredColor:
  2113.         Canvas.Pen.Color := RV_GetColor(LightColor, ColorMode);
  2114.       else {rvtbLowered}
  2115.         begin
  2116.           if ColorToRGB(BackgroundColor)=ColorToRGB(clBtnHighlight) then
  2117.             Canvas.Pen.Color := RV_GetColor(clBtnFace, ColorMode)
  2118.           else
  2119.             Canvas.Pen.Color := RV_GetColor(clBtnHighlight, ColorMode);
  2120.         end;
  2121.     end;
  2122.     with par[0] do begin x := Right; y := Top;    end;
  2123.     with par[1] do begin x := Right; y := Bottom; end;
  2124.     with par[2] do begin x := Left;  y := Bottom; end;
  2125.     for i := 0 to Width-1 do begin
  2126.       //Canvas.Polyline(par);  <- does not work for looooong tables
  2127.       if (VisibleBorders=nil) or (VisibleBorders.Bottom) then begin
  2128.         with par[2] do Canvas.MoveTo(x,y);
  2129.         with par[1] do Canvas.LineTo(x+incr,y);
  2130.       end;
  2131.       if (VisibleBorders=nil) or (VisibleBorders.Right) then begin
  2132.         y1 := par[0].y;
  2133.         y2 := par[1].y;
  2134.         ClipY(y1,y2,ClipRect);
  2135.         Canvas.MoveTo(par[0].x,y1);
  2136.         Canvas.LineTo(par[1].x,y2+incr);
  2137.       end;
  2138.       with par[0] do begin dec(x); inc(y); end;
  2139.       with par[1] do begin dec(x); dec(y); end;
  2140.       with par[2] do begin inc(x); dec(y); end;
  2141.     end;
  2142.     end
  2143.   else begin
  2144.     // Single frame
  2145.     if Color=clNone then exit;
  2146.     Canvas.Pen.Color := RV_GetColor(Color, ColorMode);
  2147.     if (RVNT or (Bottom-Top<32000)) and
  2148.        ((VisibleBorders=nil) or
  2149.        (VisibleBorders.Left and VisibleBorders.Right and
  2150.         VisibleBorders.Top and VisibleBorders.Bottom)) then begin
  2151.       Canvas.Pen.Width := GetDevY(Width);
  2152.       if Printing and (cursad<>nil) and (cursad.ppiyScreen<cursad.ppiyDevice) then begin
  2153.         Canvas.Pen.Width := Canvas.Pen.Width+1;
  2154.         dec(Left);
  2155.         dec(Top);
  2156.       end;
  2157.       Canvas.Pen.Style := psInsideFrame;
  2158.       Canvas.Rectangle(Left, Top, Right, Bottom);
  2159.       Canvas.Pen.Width := 1;
  2160.       Canvas.Pen.Style := psSolid;
  2161.       end
  2162.     else begin
  2163.       Width := GetDevY(Width);
  2164.       if Printing and (cursad<>nil) and (cursad.ppiyScreen<cursad.ppiyDevice) then begin
  2165.         inc(Width);
  2166.         dec(Top);
  2167.         dec(Left);
  2168.       end;
  2169.       if Printing and (rvtoHalftoneBorders in PrintOptions) then begin
  2170.         Canvas.Pen.Width := Width;
  2171.         Canvas.Pen.Style := psInsideFrame;
  2172.         Width := Width div 2;
  2173.         inc(Left,Width);
  2174.         inc(Top,Width);
  2175.         dec(Right,Width);
  2176.         dec(Bottom,Width);
  2177.         Width := 1;
  2178.         end
  2179.       else begin
  2180.         Canvas.Pen.Width := 1;
  2181.         Canvas.Pen.Style := psSolid;
  2182.       end;
  2183.       dec(Right);
  2184.       dec(Bottom);
  2185.       if rvtoOverlappingCorners in Options then begin
  2186.         for i := 0 to Width-1 do begin // idea of Harley Pebley
  2187.           y1 := Top;
  2188.           y2 := Bottom+1;
  2189.           ClipY(y1,y2,ClipRect);
  2190.           if (VisibleBorders=nil) or VisibleBorders.Left then begin
  2191.             Canvas.MoveTo(Left+i,y1);
  2192.             Canvas.LineTo(Left+i,y2);
  2193.           end;
  2194.           if (VisibleBorders=nil) or VisibleBorders.Right then begin
  2195.             Canvas.MoveTo(Right-i,y1);
  2196.             Canvas.LineTo(Right-i,y2);
  2197.           end;
  2198.           if (VisibleBorders=nil) or VisibleBorders.Top then begin
  2199.             Canvas.MoveTo(Left,Top+i);
  2200.             Canvas.LineTo(Right+1,Top+i);
  2201.           end;
  2202.           if (VisibleBorders=nil) or VisibleBorders.Bottom then begin
  2203.             Canvas.MoveTo(Left,Bottom-i);
  2204.             Canvas.LineTo(Right+1,Bottom-i);
  2205.           end;
  2206.         end
  2207.         end
  2208.       else
  2209.         for i := 0 to Width-1 do begin
  2210.           if (VisibleBorders=nil) or VisibleBorders.Left then begin
  2211.             y1 := Top;
  2212.             y2 := Bottom+1;
  2213.             ClipY(y1,y2,ClipRect);
  2214.             Canvas.MoveTo(Left,y1);
  2215.             Canvas.LineTo(Left,y2);
  2216.           end;
  2217.           if (VisibleBorders=nil) or VisibleBorders.Right then begin
  2218.             y1 := Top;
  2219.             y2 := Bottom+1;
  2220.             ClipY(y1,y2,ClipRect);
  2221.             Canvas.MoveTo(Right,y1);
  2222.             Canvas.LineTo(Right,y2);
  2223.           end;
  2224.           if (VisibleBorders=nil) or VisibleBorders.Top then begin
  2225.             Canvas.MoveTo(Left,Top);
  2226.             Canvas.LineTo(Right+1,Top);
  2227.           end;
  2228.           if (VisibleBorders=nil) or VisibleBorders.Bottom then begin
  2229.             Canvas.MoveTo(Left,Bottom);
  2230.             Canvas.LineTo(Right+1,Bottom);
  2231.           end;
  2232.           inc(Left);
  2233.           inc(Top);
  2234.           dec(Right);
  2235.           dec(Bottom);
  2236.         end;
  2237.     end;
  2238.   end;
  2239.   Canvas.Pen.Style := psSolid;
  2240. end;
  2241. {------------------------------------------------------------------------------}
  2242. function TRVTableItemInfo.GetVerticalRuleNo(X: Integer; var MinX, ZeroChangeX: Integer): Integer;
  2243. var i, DH,l: Integer;
  2244.  {..................................}
  2245.  function InEps(v, delta: Integer): Boolean;
  2246.  begin
  2247.    delta := delta div 2;
  2248.    if delta<2 then delta := 2;
  2249.    Result := abs(v-X)<=delta;
  2250.  end;
  2251.  {..................................}
  2252. begin
  2253.  Result := -1;
  2254.  if (X<0) or (X>Fmt.FWidth) then exit;
  2255.  DH := CellHSpacing+FCellBorderWidth*2;
  2256.  l := BorderWidth+BorderHSpacing+CellBorderWidth;
  2257.  if InEps(l div 2, l) then begin
  2258.    Result := 0;
  2259.    MinX := -1;
  2260.    ZeroChangeX := l div 2;
  2261.    exit;
  2262.  end;
  2263.  if InEps(Fmt.FWidth - l div 2, l) then begin
  2264.    Result := Rows[0].Count;
  2265.    MinX := Fmt.ColStarts[Result-1];
  2266.    ZeroChangeX := Fmt.FWidth - l div 2;
  2267.    exit;
  2268.  end;
  2269.  for i := 0 to Rows[0].Count-2 do begin
  2270.    l := Fmt.ColStarts[i+1];
  2271.    if InEps(l-DH div 2, DH) then begin
  2272.      Result := i+1;
  2273.      MinX := Fmt.ColStarts[Result-1];
  2274.      ZeroChangeX := l-(DH+1) div 2;
  2275.      exit;
  2276.    end;
  2277.  end;
  2278. end;
  2279. {------------------------------------------------------------------------------}
  2280. function TRVTableItemInfo.GetHorizontalRuleNo(Y: Integer; var MinY, ZeroChangeY: Integer): Integer;
  2281. var i, DV,t: Integer;
  2282.  {..................................}
  2283.  function InEps(v, delta: Integer): Boolean;
  2284.  begin
  2285.    delta := delta div 2;
  2286.    if delta<2 then delta := 2;
  2287.    Result := abs(v-Y)<=delta;
  2288.  end;
  2289.  {..................................}
  2290. begin
  2291.  Result := -1;
  2292.  if (Y<0) or (Y>Fmt.FHeight) then exit;
  2293.  DV := CellVSpacing+FCellBorderWidth*2;
  2294.  t := BorderWidth+BorderVSpacing+CellBorderWidth;
  2295.  if InEps(t div 2, t) then begin
  2296.    Result := 0;
  2297.    MinY := -1;
  2298.    ZeroChangeY := t div 2;
  2299.    exit;
  2300.  end;
  2301.  if InEps(Fmt.FHeight - t div 2, t) then begin
  2302.    Result := Rows.Count;
  2303.    MinY := Fmt.RowStarts[Result-1];
  2304.    ZeroChangeY := Fmt.FHeight - t div 2;
  2305.    exit;
  2306.  end;
  2307.  for i := 0 to Rows.Count-2 do begin
  2308.    t := Fmt.RowStarts[i+1];
  2309.    if InEps(t-DV div 2, DV) then begin
  2310.      Result := i+1;
  2311.      MinY := Fmt.RowStarts[Result-1];
  2312.      ZeroChangeY := t-(DV+1) div 2;
  2313.      exit;
  2314.    end;
  2315.  end;
  2316. end;
  2317. {------------------------------------------------------------------------------}
  2318. function TRVTableItemInfo.GetColNo(X: Integer): Integer;
  2319. var c:Integer;
  2320. begin
  2321.   Result := -1;
  2322.   for c := 0 to Rows[0].Count-1 do begin
  2323.     if X<Fmt.ColStarts[c] then
  2324.       exit;
  2325.     if X<=Fmt.ColStarts[c]+Fmt.ColWidths[c] then begin
  2326.       Result := c;
  2327.       exit;
  2328.     end;
  2329.   end;
  2330. end;
  2331. {------------------------------------------------------------------------------}
  2332. function TRVTableItemInfo.GetRowNo(Y: Integer): Integer;
  2333. var r:Integer;
  2334. begin
  2335.   Result := -1;
  2336.   for r := 0 to Rows.Count-1 do begin
  2337.     if Y<Fmt.RowStarts[r] then
  2338.       exit;
  2339.     if Y<=Fmt.RowStarts[r]+Fmt.RowHeights[r] then begin
  2340.       Result := r;
  2341.       exit;
  2342.     end;
  2343.   end;
  2344. end;
  2345. {------------------------------------------------------------------------------}
  2346. function TRVTableItemInfo.GetCrossed(Coord: Integer;List: TRVIntegerList): Integer;
  2347. var a,b:Integer;
  2348. begin
  2349.   if List.Count<2 then begin
  2350.     Result := 0;
  2351.     exit;
  2352.   end;
  2353.   if Coord>=List[List.Count-1] then begin
  2354.     Result := List.Count-1;
  2355.     exit;
  2356.   end;
  2357.   a := 0;
  2358.   b := List.Count-1;
  2359.   while b-a>1 do begin
  2360.     Result := (b+a) div 2;
  2361.     if List[Result]<Coord then
  2362.       a := Result
  2363.     else
  2364.       b := Result;
  2365.   end;
  2366.   Result := a;
  2367. end;
  2368. {------------------------------------------------------------------------------}
  2369. function TRVTableItemInfo.MouseMove(Shift: TShiftState; X, Y,ItemNo: Integer; RVData: TObject): Boolean;
  2370. var Row,Col, RuleNo,a,b: Integer;
  2371.     NewSelColOffs, NewSelRowOffs: Integer;
  2372.     Redraw: Boolean;
  2373. begin
  2374.   if Rows.Empty or TCustomRVFormattedData(Rows.FMainRVData).UsingThisXorDrawing(XORDrawing) then begin
  2375.     Result := False;
  2376.     exit;
  2377.   end;
  2378.   MyClientTop := 0;
  2379.   MyClientLeft := 0;
  2380.   Result := True;
  2381.   if BusyCount>0 then exit;
  2382.   if GetCellAt(X, Y, Row, Col) then begin
  2383.     if FMakingSelection and (ssLeft in Shift) then begin
  2384.       NewSelColOffs := Col-FSelStartCol;
  2385.       NewSelRowOffs := Row-FSelStartRow;
  2386.       Redraw :=  (FSelColOffs<>NewSelColOffs) or
  2387.                  (FSelRowOffs<>NewSelRowOffs);
  2388.       FSelColOffs := NewSelColOffs;
  2389.       FSelRowOffs := NewSelRowOffs;
  2390.       if (FSelColOffs<>0) or (FSelRowOffs<>0) then
  2391.         Include(FState, rvtsSelExists)
  2392.       else
  2393.         Exclude(FState, rvtsSelExists);      
  2394.       if Redraw then begin
  2395.         UpdateCellSel;
  2396.         TCustomRVFormattedData(Rows.FMainRVData).Invalidate;
  2397.         if FInplaceEditor<>nil then
  2398.           TRVTableInplaceEdit(FInplaceEditor).SelectCompletely(rvtsSelExists in FState);
  2399.       end;
  2400.     end;
  2401.     if not FMakingSelection or not (rvtsSelExists in FState) then
  2402.       with Cells[Row,Col] do begin
  2403.         if RV_PointInRect(X, Y, Left+CellPadding, Top+CellPadding,
  2404.                           Width-CellPadding*2, Height-CellPadding*2) then begin
  2405.           MouseMove(Shift, X{-Left-CellPadding}, Y{-Top-CellPadding});
  2406.           Result := True;
  2407.           exit;
  2408.         end;
  2409.     end
  2410.     end
  2411.   else begin
  2412.     RuleNo := GetVerticalRuleNo(X,a,b);
  2413.     if (rvtoRowSelect in Options) and (RuleNo=0) and
  2414.        (rvoAllowSelection in TCustomRVFormattedData(RVData).Options) then begin
  2415.       TCustomRVFormattedData(RVData).SetCursor(crRVSelectRow);
  2416.       exit;
  2417.     end;
  2418.     if CanChange and (rvtoColSizing in Options) and (RuleNo>0) then begin
  2419.       TCustomRVFormattedData(RVData).SetCursor(crHSplit);
  2420.       exit;
  2421.     end;
  2422.     RuleNo := GetHorizontalRuleNo(Y,a,b);
  2423.     if (rvtoColSelect in Options) and (RuleNo=0) and
  2424.        (rvoAllowSelection in TCustomRVFormattedData(RVData).Options) then begin
  2425.       TCustomRVFormattedData(RVData).SetCursor(crRVSelectCol);
  2426.       exit;
  2427.     end;
  2428.     if CanChange and (rvtoRowSizing in Options) and (RuleNo>0) then begin
  2429.       TCustomRVFormattedData(RVData).SetCursor(crVSplit);
  2430.       exit;
  2431.     end;
  2432.   end;
  2433.   TCustomRVFormattedData(RVData).SetCursor(crArrow);
  2434. end;
  2435. {------------------------------------------------------------------------------}
  2436. procedure TRVTableItemInfo.XorDrawing(Sender: TObject; Shift: TShiftState;
  2437.   X, Y: Integer);
  2438. var Offs: Integer;
  2439.     Canvas: TCanvas;
  2440. begin
  2441.   Offs := 0;
  2442.   Canvas := TCustomRVFormattedData(Sender).GetCanvas;
  2443.   with Canvas do begin
  2444.     Pen.Mode := pmNot;
  2445.     Pen.Width := 1;
  2446.     Brush.Style := bsClear;
  2447.     Pen.Style := psSolid;
  2448.     if not (rvtsVerticalDraggedRule in FState) then begin
  2449.       if (DRMin<>-1) or (DRMax<>-1) then
  2450.         Offs := MyTop-TCustomRVFormattedData(Rows.FMainRVData).GetVOffs;
  2451.       if (DRMin<>-1) and (Y<DRMin+Offs) then
  2452.         Y := DRMin+Offs;
  2453.       if (DRMax<>-1) and (Y<DRMax+Offs) then
  2454.         Y := DRMax+Offs;
  2455.       DrawFancyHLine(Canvas, 0, TCustomRVFormattedData(Sender).GetWidth, Y);
  2456.       end
  2457.     else begin
  2458.       if (DRMin<>-1) or (DRMax<>-1) then
  2459.         Offs := MyLeft-TCustomRVFormattedData(Rows.FMainRVData).GetHOffs;
  2460.       if (DRMin<>-1) and (X<DRMin+Offs) then
  2461.         X := DRMin+Offs;
  2462.       if (DRMax<>-1) and (X<DRMax+Offs) then
  2463.         X := DRMax+Offs;
  2464.       DrawFancyVLine(Canvas, X, 0, TCustomRVFormattedData(Sender).GetHeight);
  2465.     end;
  2466.     Pen.Mode := pmCopy;
  2467.   end;
  2468. end;
  2469. {------------------------------------------------------------------------------}
  2470. function TRVTableItemInfo.DoOnCellEditing(Row,Col: Integer; Automatic: Boolean): Boolean;
  2471. begin
  2472.   Result := True;
  2473.   if Assigned(FOnCellEditing) then
  2474.     FOnCellEditing(Self, Row, Col, Automatic, Result);
  2475. end;
  2476. {------------------------------------------------------------------------------}
  2477. procedure TRVTableItemInfo.CreateInplace(ItemNo, Row, Col: Integer;
  2478.                                          BuildJumps, CaretAtStart, CaretAtEnd, SetTime,
  2479.                                          Unquestioning: Boolean);
  2480. var RVData: TCustomRVFormattedData;
  2481.     tie: TRVTableInplaceEdit;
  2482.     Idx, Offs: Integer;
  2483. begin
  2484.   if not (rvtsInserted in FState) or not IsInEditor or
  2485.   (not Unquestioning and not DoOnCellEditing(Row,Col, False)) then
  2486.     exit;
  2487.   if ItemNo=-1 then
  2488.     ItemNo := GetMyItemNo;
  2489.   DestroyInplace(True);
  2490.   DeselectPartial;
  2491.   TCustomRVFormattedData(FRows.FMainRVData).PartialSelectedItem := nil;
  2492.   TCustomRVFormattedData(FRows.FMainRVData).FActiveItem := nil;
  2493.   TCustomRVFormattedData(FRows.FMainRVData).RestoreSelBounds(ItemNo, ItemNo, 1, 1);
  2494.   TCustomRVFormattedData(FRows.FMainRVData).DoOnSelection(False);
  2495.   Deselect;
  2496.   RVData := TCustomRVFormattedData(FRows.FMainRVData);
  2497.   if IsInEditor and TCustomRichViewEdit(TRichViewRVData(RVData).RichView).ReadOnly then
  2498.     BuildJumps := True;
  2499.   FMinWidthPlus := RVData.CalculateMinItemWidthPlusEx(ItemNo);
  2500.   tie := TRVTableInplaceEdit.Create(nil);
  2501.   FInplaceEditor := tie;
  2502.   tie.Options := TRichViewRVData(RVData).GetOptions;
  2503.   tie.OnChangeEx := InplaceEditorChange;
  2504.   tie.OnCaretGetOut := InplaceEditorCaretGetout;
  2505.   if RVData is TRichViewRVData then begin
  2506.     tie.BiDiMode := TCustomRichView(TRichViewRVData(RVData).RichView).BiDiMode;
  2507.     tie.Cursor := TCustomRichView(TRichViewRVData(RVData).RichView).Cursor;
  2508.     tie.Delimiters := TCustomRichView(TRichViewRVData(RVData).RichView).Delimiters;
  2509.     tie.AssignEvents(TCustomRichView(TRichViewRVData(RVData).RichView));
  2510.     tie.RVFTextStylesReadMode := TCustomRichView(TRichViewRVData(RVData).RichView).RVFTextStylesReadMode;
  2511.     tie.RVFParaStylesReadMode := TCustomRichView(TRichViewRVData(RVData).RichView).RVFParaStylesReadMode;
  2512.     tie.OnRVMouseDown := InplaceEditorMouseDown;
  2513.     tie.OnRVMouseUp   := InplaceEditorMouseUp;
  2514.     tie.OnControlAction   := InplaceEditorControlAction;
  2515.     tie.OnMouseMove   := InplaceEditorMouseMove;
  2516.     tie.OnDragOver    := InplaceEditorDragOver;
  2517.     tie.OnDragDrop    := InplaceEditorDragDrop;
  2518.     if RVData is TRVEditRVData then
  2519.       with TCustomRichViewEdit(TRVEditRVData(RVData).RichView) do begin
  2520.         tie.EditorOptions := EditorOptions + [rvoWantTabs];
  2521.         if UndoLimit<>0 then
  2522.           tie.UndoLimit := -1 // temporal solution
  2523.         else
  2524.           tie.UndoLimit := 0;
  2525.       end;
  2526.   end;
  2527.   tie.Color := GetCellColor(Cells[Row,Col]);
  2528.   tie.Transparent := CanSeeBackgroundThroughCell(Cells[Row,Col]);
  2529.   tie.Parent := TCustomRVData(RVData).GetParentControl;
  2530.   tie.VScrollVisible := False;
  2531.   tie.HScrollVisible := False;
  2532.   RVData.GetItemClientCoords(ItemNo, MyLeft, MyTop);
  2533.   with Cells[Row,Col] do
  2534.     SetInplaceBounds(MyLeft+Left, MyTop+Top+GetExtraVOffs, Width, Height-GetExtraVOffs);
  2535.   tie.SetParentRVData(RVData);
  2536.   tie.FCell := Cells[Row,Col];
  2537.   tie.RVData.DrainFrom(Cells[Row,Col]);
  2538.   tie.SetCell(Row,Col,Self,CellPadding);
  2539.   tie.Format;
  2540.   if tie.ClientHeight<tie.RVData.DocumentHeight then
  2541.     tie.NormalScrolling := True;
  2542.   if SetTime then
  2543.    tie.FClickTime := GetMessageTime;
  2544.   //tie.FirstJumpNo := Cells[Row,Col].FirstJumpNo;
  2545.   if BuildJumps then
  2546.     TRVTableInplaceRVData(tie.RVData).BuildJumpsCoords(True);
  2547.   tie.Visible := True;
  2548.   RVData.AssignChosenRVData(Cells[Row,Col], Self);
  2549.   ChosenCellRow := Row;
  2550.   ChosenCellCol := Col;
  2551.   FInplaceMinWidthPlus := tie.RVData.CalculateMinDocWidthPlus(nil,nil);
  2552.   if CaretAtEnd then begin
  2553.     Idx :=  tie.ItemCount-1;
  2554.     Offs := tie.GetOffsAfterItem(Idx);
  2555.     tie.SetSelectionBounds(Idx,Offs,Idx,Offs);
  2556.   end;
  2557.   if CaretAtStart then begin
  2558.     Idx :=  0;
  2559.     Offs := tie.GetOffsBeforeItem(Idx);
  2560.     tie.SetSelectionBounds(Idx,Offs,Idx,Offs);
  2561.   end;
  2562.   tie.CurTextStyleChange;
  2563.   tie.CurParaStyleChange;
  2564.   RVData.GetAbsoluteRootData.State := RVData.GetAbsoluteRootData.State+[rvstNoKillFocusEvents];
  2565.   try
  2566.     tie.SetFocusSilent;
  2567.   finally
  2568.     RVData.GetAbsoluteRootData.State := RVData.GetAbsoluteRootData.State-[rvstNoKillFocusEvents];
  2569.   end;
  2570. end;
  2571. {------------------------------------------------------------------------------}
  2572. function TRVTableItemInfo.MouseDown(Button: TMouseButton;
  2573.   Shift: TShiftState; X, Y,ItemNo: Integer; RVData: TObject): Boolean;
  2574. var Row,Col, ERow, ECol: Integer;
  2575.     VDRNo,HDRNo:Integer;
  2576. begin
  2577.   Result  := False;
  2578.   if Rows.Empty then
  2579.     exit;
  2580.   if (BusyCount>0) or
  2581.      (rvstIgnoreNextMouseDown in TCustomRVFormattedData(Rows.FMainRVData).State) then exit;
  2582.   if (Button in [mbLeft, mbRight]) and
  2583.      CanChange and (rvtoEditing in Options) and
  2584.      GetCellAt(X, Y, Row, Col) then begin
  2585.     if (Button=mbRight) and (IsCellSelected(Row,Col) or CompletelySelected) then
  2586.       exit;
  2587.     CreateInplace(ItemNo, Row, Col, ssCtrl in Shift, False, False, Button=mbLeft, False);
  2588.     if (GetEditedCell(ERow,ECol)<>nil) and (ERow=Row) and (ECol=Col) then begin
  2589.       SetCaptureControl(FInplaceEditor);
  2590.       with Cells[Row,Col] do
  2591.         FInplaceEditor.MouseDown(Button, Shift, X-Left, Y-Top-GetExtraVOffs);
  2592.       exit;
  2593.     end;
  2594.   end;
  2595.   MyClientTop := 0;
  2596.   MyClientLeft := 0;
  2597.   if GetCellAt(X, Y, Row, Col) then begin
  2598.     DestroyInplace(True);
  2599.     if Rows.FMainRVData is TRVEditRVData then
  2600.       Rows.FMainRVData.GetParentControl.SetFocus;
  2601.     if Button=mbLeft then begin
  2602.       {
  2603.       TCustomRVFormattedData(Rows.FMainRVData).State := TCustomRVFormattedData(Rows.FMainRVData).State+[rvstNoScroll];
  2604.       try
  2605.         TCustomRVFormattedData(Rows.FMainRVData).SetSelectionBounds(ItemNo, 1, ItemNo, 1);
  2606.       finally
  2607.         TCustomRVFormattedData(Rows.FMainRVData).State := TCustomRVFormattedData(Rows.FMainRVData).State-[rvstNoScroll];
  2608.       end;
  2609.       }
  2610.       MyClientTop := 0;
  2611.       MyClientLeft := 0;
  2612.     end;
  2613.     if Button in [mbLeft, mbRight] then begin
  2614.       TCustomRVFormattedData(Rows.FMainRVData).AssignChosenRVData(Cells[Row,Col], Self);
  2615.       ChosenCellRow := Row;
  2616.       ChosenCellCol := Col;
  2617.     end;
  2618.     with Cells[Row,Col] do begin
  2619.       if RV_PointInRect(X, Y, Left+CellPadding, Top+CellPadding,
  2620.                         Width-CellPadding*2, Height-CellPadding*2) then begin
  2621.         MouseDown(Button, Shift, X, Y);
  2622.       end;
  2623.       if (Button=mbLeft) and not (rvstStartingDragDrop in Rows.FMainRVData.GetAbsoluteRootData.State) and
  2624.         StartSelecting(Row,Col) then begin
  2625.         TCustomRVFormattedData(RVData).SetMouseCapture(Self,MyLeft,MyTop);
  2626.         TCustomRVFormattedData(Rows.FMainRVData).Invalidate;
  2627.       end;
  2628.       exit;
  2629.     end;
  2630.   end;
  2631.   if (Button<>mbLeft) or
  2632.      not ((rvtoRowSizing in Options) or (rvtoColSizing in Options) or
  2633.           (rvtoColSelect in Options) or (rvtoRowSelect in Options)) then begin
  2634.     DestroyInplace(True);
  2635.     Rows.FMainRVData.GetParentControl.SetFocus;
  2636.     exit;
  2637.   end;
  2638.   if (CanChange and (rvtoColSizing in Options)) or (rvtoRowSelect in Options) then begin
  2639.     VDRNo := GetVerticalRuleNo(X, DRMin, DRDelta);
  2640.     DRCoord := X;
  2641.     end
  2642.   else
  2643.     VDRNo := -1;
  2644.   if (VDRNo>0) and CanChange and (rvtoColSizing in Options) then begin
  2645.     DRNo := VDRNo;
  2646.     dec(DRDelta,X);
  2647.     TCustomRVFormattedData(RVData).AssignXorDrawing(XorDrawing);
  2648.     TCustomRVFormattedData(RVData).SetMouseCapture(Self,MyLeft,MyTop);
  2649.     DRMax := -1;
  2650.     if ssShift in Shift then
  2651.       Include(FState, rvtsDRChangeTableWidth)
  2652.     else
  2653.       Exclude(FState, rvtsDRChangeTableWidth);
  2654.     Include(FState, rvtsVerticalDraggedRule);
  2655.     SaveInplace;
  2656.     end
  2657.   else begin
  2658.     if (CanChange and (rvtoRowSizing in Options)) or (rvtoColSelect in Options) then begin
  2659.       HDRNo := GetHorizontalRuleNo(Y,DRMin,DRDelta);
  2660.       DRCoord := Y;
  2661.       end
  2662.     else
  2663.       HDRNo := -1;
  2664.     if (HDRNo>0) and CanChange and (rvtoRowSizing in Options) then begin
  2665.       DRNo := HDRNo;
  2666.       dec(DRDelta,Y);
  2667.       TCustomRVFormattedData(RVData).AssignXorDrawing(XorDrawing);
  2668.       TCustomRVFormattedData(RVData).SetMouseCapture(Self,MyLeft,MyTop);
  2669.       DRMax := -1;
  2670.       Exclude(FState, rvtsVerticalDraggedRule);
  2671.       SaveInplace;
  2672.       end
  2673.     else if (HDRNo=0) and (rvtoColSelect in Options) then begin
  2674.       Col := GetColNo(X);
  2675.       if Col>=0 then begin
  2676.         SelectCols(Col,1);
  2677.         TCustomRVFormattedData(RVData).SetMouseCapture(Self,MyLeft,MyTop);
  2678.       end;
  2679.       end
  2680.     else if (VDRNo=0) and (rvtoRowSelect in Options) then begin
  2681.       Row := GetRowNo(Y);
  2682.       if Row>=0 then begin
  2683.         SelectRows(Row,1);
  2684.         TCustomRVFormattedData(RVData).SetMouseCapture(Self,MyLeft,MyTop);
  2685.       end;
  2686.       end
  2687. //    else
  2688. //      DestroyInplace(True);
  2689.   end;
  2690. end;
  2691. {------------------------------------------------------------------------------}
  2692. procedure TRVTableItemInfo.ResizeRow(Index, Height: Integer);
  2693.   {...........................................}
  2694.   procedure SetHeight(r,h,y: Integer);
  2695.   var c,a,b,a1,b1: Integer;
  2696.       Changed: Boolean;
  2697.       Cell: TRVTableCellData;
  2698.   begin
  2699.     a := h;
  2700.     dec(h, CellPadding*2);
  2701.     if r<Rows.Count-1 then
  2702.       dec(h, CellVSpacing div 2 + CellBorderWidth)
  2703.     else
  2704.       dec(h, (BorderWidth+BorderVSpacing+CellBorderWidth+1) div 2);
  2705.     inc(y, h-a);
  2706.     if h<0 then h := 0;
  2707.     Changed := False;
  2708.     with Rows[r] do begin
  2709.       for c := 0 to Count-1 do
  2710.         if (Items[c]<>nil) and (Items[c].RowSpan=1) then begin
  2711.           SetCellBestHeight(h,r,c);
  2712.           Changed := True;
  2713.         end;
  2714.       for c := 0 to Count-1 do
  2715.         if (Items[c]=nil) then begin
  2716.           Cell := Rows.GetMainCell(r,c,a,b);
  2717.           if a=r then continue;
  2718.           if (r=Rows.Count-1) or
  2719.              (Cells[r+1,c]<>nil) or
  2720.              (Cell<>Rows.GetMainCell(r+1,c,a1,b1)) then begin
  2721.             if Changed then
  2722.               h := 0
  2723.             else begin
  2724.               h := y-Cell.Top;
  2725.               if h<0 then
  2726.                 h := 0;
  2727.             end;
  2728.             SetCellBestHeight(h,a,b);
  2729.           end;
  2730.         end;
  2731.     end;
  2732.   end;
  2733.   {........................................}
  2734. begin
  2735.   InitUndo;
  2736.   try
  2737.     SetHeight(Index, Height, Fmt.RowStarts[Index]+Height);
  2738.   finally
  2739.     DoneUndo;
  2740.   end;
  2741.   Fmt.FWidth := 0;
  2742.   if (Rows.FMainRVData is TRVEditRVData) then begin
  2743.     TRVEditRVData(Rows.FMainRVData).Reformat(False, False, False, GetMyItemNo, False);
  2744.     TCustomRVFormattedData(Rows.FMainRVData).Invalidate;
  2745.     Change;
  2746.   end;
  2747. end;
  2748. {------------------------------------------------------------------------------}
  2749. procedure TRVTableItemInfo.ResizeCol(Index, Width: Integer; Shift: Boolean);
  2750.   {...........................................}
  2751.   procedure SetWidth(c,w,x: Integer; Decrement: Boolean);
  2752.   var r,a,b,a1,b1,oldw: Integer;
  2753.       Changed: Boolean;
  2754.       Cell: TRVTableCellData;
  2755.   begin
  2756.     oldw := w-CellPadding*2;
  2757.     if Decrement then begin
  2758.       if c<Rows[0].Count-1 then
  2759.         x := Fmt.ColStarts[c+1] - (CellBorderWidth+(CellHSpacing+1) div 2)
  2760.       else
  2761.         x := Fmt.FWidth-(BorderWidth+BorderHSpacing+CellBorderWidth{+1}) div 2;
  2762.       x  := x + (Fmt.ColStarts[c]-Fmt.ColStarts[c-1] - (CellHSpacing+1) div 2)-w-CellBorderWidth;
  2763.       w := x - Fmt.ColStarts[c];
  2764.     end;
  2765.     a := w;
  2766.     dec(w, CellPadding*2);
  2767.     if c<Rows[0].Count-1 then begin
  2768.       dec(w,CellBorderWidth);
  2769.       dec(w, CellHSpacing div 2);
  2770.       end
  2771.     else
  2772.       dec(w, (BorderWidth+BorderHSpacing+CellBorderWidth+1) div 2);
  2773.     //inc(x, w-a);
  2774.     if w<=0 then w := 1;
  2775.     Changed := False;
  2776.     for r := 0 to Rows.Count-1 do
  2777.       if (Cells[r,c]<>nil) and (Cells[r,c].ColSpan=1) then begin
  2778.         SetCellBestWidth(w,r,c);
  2779.         Changed := True;
  2780.       end;
  2781.     for r := 0 to Rows.Count-1 do
  2782.       if (Cells[r,c]=nil) then begin
  2783.         Cell := Rows.GetMainCell(r,c,a,b);
  2784.         if (b=c) or Decrement then continue;
  2785.         if (c=Rows[r].Count-1) or
  2786.            (Cells[r,c+1]<>nil) or
  2787.            (Cell<>Rows.GetMainCell(r,c+1,a1,b1)) then begin
  2788.           if Changed then
  2789.             w := 0
  2790.           else begin
  2791.            // w := x-Cell.Left;
  2792.             w := Cell.Width - Fmt.ColWidths[c]+oldw;
  2793.             if w<=0 then
  2794.               w := 1;
  2795.           end;
  2796.           SetCellBestWidth(w,a,b)
  2797.         end;
  2798.       end;
  2799.   end;
  2800.   {...........................................}
  2801.   procedure SetPercentWidth(c,w,x: Integer; Decrement: Boolean);
  2802.   var r,a,b,a1,b1, he: Integer;
  2803.       Changed: Boolean;
  2804.       Cell: TRVTableCellData;
  2805.   begin
  2806.     he := GetHorzExtra;
  2807.     a := w;
  2808.     if c<Rows[0].Count-1 then begin
  2809.       dec(w,CellBorderWidth);
  2810.       dec(w, CellHSpacing div 2);
  2811.       end
  2812.     else
  2813.       dec(w, (BorderWidth+BorderHSpacing+CellBorderWidth) div 2);
  2814.     inc(x, w-a);
  2815.     w := - w*100 div (Fmt.FWidth-he);
  2816.     if w>=0 then w := -1;
  2817.     Changed := False;
  2818.     for r := 0 to Rows.Count-1 do
  2819.       if (Cells[r,c]<>nil) and (Cells[r,c].ColSpan=1) then begin
  2820.         SetCellBestWidth(w,r,c);
  2821.         Changed := True;
  2822.       end;
  2823.     for r := 0 to Rows.Count-1 do
  2824.       if (Cells[r,c]=nil) then begin
  2825.         Cell := Rows.GetMainCell(r,c,a,b);
  2826.         if b=c then continue;
  2827.         if (c=Rows[r].Count-1) or
  2828.            (Cells[r,c+1]<>nil) or
  2829.            (Cell<>Rows.GetMainCell(r,c+1,a1,b1)) then begin
  2830.           if Changed then
  2831.             w := 0
  2832.           else begin
  2833.             w := -(x-Cell.Left)*100 div (Fmt.FWidth-he);
  2834.             if w>=0 then
  2835.               w := -1;
  2836.           end;
  2837.           SetCellBestWidth(w,a,b);
  2838.         end;
  2839.       end;
  2840.   end;
  2841.   {...........................................}
  2842. var pc: Boolean;
  2843.     data: Integer;
  2844. begin
  2845.   data := BeginModify(GetMyItemNo);
  2846.   pc := Rows.IsPercentWidthColumn(Index);
  2847.   InitUndo;
  2848.   try
  2849.     if pc then begin
  2850.       SetPercentWidth(Index, Width, Fmt.ColStarts[Index]+Width, False);
  2851.       end
  2852.     else begin
  2853.       SetWidth(Index, Width, Fmt.ColStarts[Index]+Width, False);
  2854.       if not Shift and (Index+1<>Rows[0].Count) and
  2855.          not Rows.IsPercentWidthColumn(Index+1) then
  2856.         SetWidth(Index+1, Width, Fmt.ColStarts[Index]+Width, True);
  2857.     end;
  2858.   finally
  2859.     DoneUndo;
  2860.   end;
  2861.   Fmt.FWidth := 0;
  2862.   EndModify(GetMyItemNo, Data);
  2863.   Change;
  2864. end;
  2865. {------------------------------------------------------------------------------}
  2866. function TRVTableItemInfo.MouseUp(Button: TMouseButton; Shift: TShiftState;
  2867.   X, Y,ItemNo: Integer; RVData: TObject): Boolean;
  2868. var Row,Col: Integer;
  2869. begin
  2870.   Result := False;
  2871.   if Rows.Empty then
  2872.     exit;
  2873.   if BusyCount>0 then exit;
  2874.   MyClientTop := 0;
  2875.   MyClientLeft := 0;
  2876.   if (Button=mbLeft) then begin
  2877.     if TCustomRVFormattedData(RVData).UsingThisXorDrawing(XORDrawing) then begin
  2878.       TCustomRVFormattedData(RVData).UnAssignXorDrawing(XorDrawing);
  2879.       if BeforeChange then
  2880.         if rvtsVerticalDraggedRule in FState then begin
  2881.           if DRCoord<>X then
  2882.             ResizeCol(DRNo-1, X-DRMin+DRDelta, rvtsDRChangeTableWidth in FState);
  2883.           end
  2884.         else begin
  2885.           if DRCoord<>Y then
  2886.             ResizeRow(DRNo-1, Y-DRMin+DRDelta);
  2887.         end;
  2888.       TCustomRVFormattedData(RVData).ReleaseMouseCapture(Self);
  2889.       RestoreInplace;
  2890.       exit;
  2891.     end;
  2892.     //TCustomRVFormattedData(RVData).GetItemClientCoords(ItemNo, MyClientTop,MyC
  2893.     MyClientTop := 0;
  2894.     MyClientLeft := 0;
  2895.     if FMakingSelection then begin
  2896.       if FInplaceEditor=nil then begin
  2897.         with Cells[FSelStartRow,FSelStartCol] do begin
  2898.           MouseUp(Button, Shift, X, Y);
  2899.         end;
  2900.         if (TCustomRVFormattedData(FRows.FMainRVData).GetChosenRVData<>nil) and
  2901.            (rvstCompletelySelected in TCustomRVFormattedData(FRows.FMainRVData).GetChosenRVData.State) then
  2902.           TCustomRVFormattedData(FRows.FMainRVData).UnassignChosenRVData(TCustomRVFormattedData(FRows.FMainRVData).GetChosenRVData);
  2903.       end
  2904.       end
  2905.     else
  2906.       if FInplaceEditor=nil then begin
  2907.         if GetCellAt(X, Y, Row, Col) then
  2908.           with Cells[Row,Col] do
  2909.             if RV_PointInRect(X, Y, Left+CellPadding, Top+CellPadding,
  2910.                               Width-CellPadding*2, Height-CellPadding*2) then
  2911.               MouseUp(Button, Shift, X, Y);
  2912.       end;
  2913.     TCustomRVFormattedData(RVData).ReleaseMouseCapture(Self);
  2914.     FMakingSelection := False;
  2915.     end
  2916.   else if FInplaceEditor=nil then begin
  2917.     if GetCellAt(X, Y, Row, Col) then begin
  2918.       with Cells[Row,Col] do
  2919.         if RV_PointInRect(X, Y, Left+CellPadding, Top+CellPadding,
  2920.                           Width-CellPadding*2, Height-CellPadding*2) then begin
  2921.           MouseUp(Button, Shift, X, Y);
  2922.           if (Button=mbRight) and (rvoRClickDeselects in Rows.FMainRVData.Options) and
  2923.              not IsCellSelected(Row,Col) and not CompletelySelected
  2924.              and not ((ChosenCellRow=Row) and (ChosenCellCol=Col) and CellIsChosen)
  2925.              then begin
  2926.             TCustomRVFormattedData(Rows.FMainRVData).SetSelectionBounds(ItemNo, 1, ItemNo, 1);
  2927.           end;
  2928.         end;
  2929.     end;
  2930.   end;
  2931. end;
  2932. {------------------------------------------------------------------------------}
  2933. procedure TRVTableItemInfo.UpdateCellXCoords(Fmt: TRVTableItemFormattingInfo;
  2934.   NoCaching, Reformatting: Boolean);
  2935. var r,c,l,w,i, cw: Integer;
  2936.     AllDH, StartAllDH, CurDH, CP, Cnt, iew: Integer;
  2937. begin
  2938.   Cnt := Rows[0].Count;
  2939.   Fmt.ColStarts.Count := Cnt;
  2940.   AllDH := GetDevX((CellHSpacing+(CellPadding+FCellBorderWidth)*2)*Cnt);
  2941.   StartAllDH := AllDH;
  2942.   l := GetDevX(BorderWidth+BorderHSpacing+CellBorderWidth);
  2943.   CP := GetDevX(CellPadding);
  2944.   for c := 0 to Rows[0].Count-1 do begin
  2945.     Fmt.ColStarts[c] := l;
  2946.     CurDH := AllDH div Cnt;
  2947.     dec(AllDH,CurDH);
  2948.     inc(l, Fmt.ColWidths[c]+CurDH);
  2949.     dec(Cnt);
  2950.   end;
  2951.   for r := 0 to Rows.Count-1 do begin
  2952.     for c := 0 to Rows[r].Count-1 do begin
  2953.       l := Fmt.ColStarts[c];
  2954.       w := Fmt.ColWidths[c];
  2955.       if Cells[r,c]<>nil then begin
  2956.         cw := w + GetDevX(CellPadding*2);
  2957.         for i := 1 to Cells[r,c].ColSpan-1 do
  2958.           inc(cw, Fmt.ColWidths[c+i]);
  2959.         inc(cw, MulDiv(StartAllDH,Cells[r,c].ColSpan-1,Rows[r].Count));
  2960.         if Fmt.Rows=nil then
  2961.           with Cells[r,c] do begin
  2962.             FLeft := l;
  2963.             FWidth  := cw;
  2964.           end
  2965.         else
  2966.           if Fmt.Rows[r*Rows[0].Count+c]<>nil then
  2967.             with TCellPtblRVData(Fmt.Rows[r*Rows[0].Count+c]) do begin
  2968.               DX := l+CP;
  2969.               Width := cw-CP*2;
  2970.             end;
  2971.       end;
  2972.     end;
  2973.   end;
  2974.   if Fmt.Rows=nil then begin
  2975.     for r := 0 to Rows.Count-1 do
  2976.       with Rows[r] do
  2977.         for c := 0 to Count-1 do
  2978.           if (Items[c]<>nil) then begin
  2979.             Items[c].State := Items[c].State+[rvstDoNotMoveChildren];
  2980.             try
  2981.              Items[c].Format(NoCaching);
  2982.             finally
  2983.               Items[c].State := Items[c].State-[rvstDoNotMoveChildren];
  2984.             end;
  2985.           end;
  2986.     if (FInplaceEditor<>nil) and
  2987.        (TRVTableInplaceEdit(FInplaceEditor).FCell<>nil)  then begin
  2988.         iew := FInplaceEditor.Width;
  2989.         FInplaceEditor.Width := TRVTableInplaceEdit(FInplaceEditor).FCell.Width;
  2990.         if (iew=FInplaceEditor.Width) and Reformatting then
  2991.           FInplaceEditor.Reformat;
  2992.     end;
  2993.     end
  2994.   else begin
  2995.     for r := 0 to Fmt.Rows.Count-1 do
  2996.       if Fmt.Rows[r]<>nil then
  2997.         TCellPtblRVData(Fmt.Rows[r]).Format(NoCaching);
  2998.   end;
  2999. end;
  3000. {------------------------------------------------------------------------------}
  3001. procedure TRVTableItemInfo.UpdateCellYCoords(Fmt: TRVTableItemFormattingInfo);
  3002. var r,c,t,h, i, ch: Integer;
  3003.     StartAllDV,AllDV,CurDV,CP,Cnt: Integer;
  3004. begin
  3005.   AllDV := GetDevY((CellVSpacing+(CellPadding+FCellBorderWidth)*2)*Rows.Count);
  3006.   StartAllDV := AllDV;
  3007.   CP := GetDevY(CellPadding);
  3008.   t := GetDevY(BorderWidth+BorderVSpacing+CellBorderWidth);
  3009.   Cnt := Rows.Count;
  3010.   for r := 0 to Rows.Count-1 do begin
  3011.     h := Fmt.RowHeights[r];
  3012.     Fmt.RowStarts[r] := t;
  3013.     for c := 0 to Rows[r].Count-1 do begin
  3014.       if Cells[r,c]<>nil then begin
  3015.         ch := h + GetDevY(CellPadding*2);
  3016.         for i := 1 to Cells[r,c].RowSpan-1 do
  3017.           inc(ch, Fmt.RowHeights[r+i]);
  3018.         inc(ch, MulDiv(StartAllDV,Cells[r,c].RowSpan-1,Rows.Count));
  3019.         if Fmt.Rows=nil then
  3020.           with Cells[r,c] do begin
  3021.             FTop  := t;
  3022.             FHeight := ch;
  3023.           end
  3024.         else
  3025.           if Fmt.Rows[r*Rows[0].Count+c]<>nil then
  3026.             with TCellPtblRVData(Fmt.Rows[r*Rows[0].Count+c]) do begin
  3027.               DY  := t+CP;
  3028.               Height := ch-CP*2;
  3029.             end;
  3030.       end;
  3031.     end;
  3032.     CurDV := AllDV div Cnt;
  3033.     dec(AllDV,CurDV);
  3034.     inc(t, h+CurDV);
  3035.     dec(Cnt);
  3036.   end;
  3037. end;
  3038. {------------------------------------------------------------------------------}
  3039. function TRVTableItemInfo.GetCellAt_(X, Y: Integer; var Row,Col: Integer): Boolean;
  3040. var r,c,dx,dy: Integer;
  3041. begin
  3042.   Result := False;
  3043.   dx := Cells[0,0].Left;
  3044.   dy := Cells[0,0].Top;
  3045.   if not RV_PointInRect(X,Y,dx+1,dy+1,Fmt.FWidth-dx*2-2,Fmt.FHeight-dy*2-2) then exit;
  3046.   row := Rows.Count-1; // to change to bsearch !
  3047.   for r := 0 to Rows.Count-2 do
  3048.     if Fmt.RowStarts[r+1]>Y then begin
  3049.       row := r;
  3050.       break;
  3051.     end;
  3052.   with Rows[row] do begin
  3053.     col := Count-1;
  3054.     for c := 0 to Count-2 do // to change to bsearch !
  3055.       if (Fmt.ColStarts[c+1]>X) then begin
  3056.         col := c;
  3057.         break;
  3058.       end;
  3059.   end;
  3060.   Rows.GetMainCell(row, col, row, col);
  3061.   with Cells[row,col]  do
  3062.     Result := RV_PointInRect(X,Y, Left+1,Top+1,Width-2,Height-2);
  3063. end;
  3064. {------------------------------------------------------------------------------}
  3065. function TRVTableItemInfo.GetCellAt(X, Y: Integer; var Row, Col: Integer): Boolean;
  3066. begin
  3067.   if (MouseRow>=0) and (MouseRow<Rows.Count) and
  3068.      (MouseCol>=0) and (MouseCol<Rows[0].Count) and
  3069.      (Cells[MouseRow, MouseCol]<>nil) then
  3070.     with Cells[MouseRow, MouseCol] do
  3071.       if RV_PointInRect(X,Y, Left+1, Top+1, Width-2, Height-2) then begin
  3072.         Row := MouseRow;
  3073.         Col := MouseCol;
  3074.         Result := True;
  3075.         exit;
  3076.       end;
  3077.   Result := GetCellAt_(X,Y, Row, Col);
  3078.   if Result then begin
  3079.     MouseRow := Row;
  3080.     MouseCol := Col;
  3081.   end;
  3082. end;
  3083. {------------------------------------------------------------------------------}
  3084. function TRVTableItemInfo.IsCellSelected(Row, Col: Integer): Boolean;
  3085. var l,t,w,h: Integer;
  3086.     Cell: TRVTableCellData;
  3087. begin
  3088.   Result := False;
  3089.   if not (rvtsSelExists in FState) then
  3090.     exit;
  3091.   Cell := FRows.GetMainCell(Row,Col,Row,Col);
  3092.   GetNormalizedSelectionBounds(False, t,l,w,h);
  3093.   if not (rvtsSelExists in FState) then
  3094.     exit;  
  3095.   Result := (Col+Cell.ColSpan>l) and (Col<l+w) and
  3096.             (Row+Cell.RowSpan>t) and (Row<t+h);
  3097. end;
  3098. {------------------------------------------------------------------------------}
  3099. procedure TRVTableItemInfo.InsertCols(Index, Count, CopyIndex: Integer
  3100.                                       {$IFDEF RICHVIEWDEF4};Select:Boolean=True{$ENDIF});
  3101. begin
  3102.   if (Index<0) or (Index>Rows[0].Count) or
  3103.      (CopyIndex<-1) or (CopyIndex>=Rows[0].Count) then
  3104.     raise ERichViewError.Create(errInvalidIndex);
  3105.   DestroyInplace(True);
  3106.   InitUndo;
  3107.   try
  3108.     Rows.InsertCols(Index, Count, CopyIndex, False);
  3109.   finally
  3110.     DoneUndo;
  3111.   end;
  3112.   {$IFDEF RICHVIEWDEF4}
  3113.   if Select then
  3114.     SelectCols(Index, Count);
  3115.   {$ENDIF}
  3116.   ResetLiveSpell;  
  3117.   Changed;
  3118. end;
  3119. {------------------------------------------------------------------------------}
  3120. procedure TRVTableItemInfo.InsertRows(Index, Count, CopyIndex: Integer
  3121.                                       {$IFDEF RICHVIEWDEF4};Select:Boolean=True{$ENDIF});
  3122. begin
  3123.   if (Index<0) or (Index>Rows.Count) or
  3124.      (CopyIndex<-1) or (CopyIndex>=Rows.Count) then
  3125.     raise ERichViewError.Create(errInvalidIndex);
  3126.   DestroyInplace(True);
  3127.   InitUndo;
  3128.   try
  3129.     Rows.InsertRows(Index, Count, CopyIndex, False);
  3130.   finally
  3131.     DoneUndo;
  3132.   end;
  3133.   {$IFDEF RICHVIEWDEF4}
  3134.   if Select then
  3135.     SelectRows(Index, Count);
  3136.   {$ENDIF}
  3137.   ResetLiveSpell;  
  3138.   Changed;
  3139. end;
  3140. {------------------------------------------------------------------------------}
  3141. procedure TRVTableItemInfo.InsertColsLeft(Count: Integer);
  3142. var r,c,cs,rs: Integer;
  3143. begin
  3144.   if not GetNormalizedSelectionBounds(True, r,c,cs,rs) then begin
  3145.     Rows.FMainRVData.Beep;
  3146.     exit;
  3147.   end;
  3148.   InsertCols(c, Count, c);
  3149. end;
  3150. {------------------------------------------------------------------------------}
  3151. procedure TRVTableItemInfo.InsertColsRight(Count: Integer);
  3152. var r,c,cs,rs: Integer;
  3153. begin
  3154.   if not GetNormalizedSelectionBounds(True, r,c,cs,rs) then begin
  3155.     Rows.FMainRVData.Beep;
  3156.     exit;
  3157.   end;
  3158.   InsertCols(c+cs, Count, c+cs-1);
  3159. end;
  3160. {------------------------------------------------------------------------------}
  3161. procedure TRVTableItemInfo.InsertRowsAbove(Count: Integer);
  3162. var r,c,cs,rs: Integer;
  3163. begin
  3164.   if not GetNormalizedSelectionBounds(True, r,c,cs,rs) then begin
  3165.     Rows.FMainRVData.Beep;
  3166.     exit;
  3167.   end;
  3168.   InsertRows(r, Count, r);
  3169. end;
  3170. {------------------------------------------------------------------------------}
  3171. procedure TRVTableItemInfo.InsertRowsBelow(Count: Integer);
  3172. var r,c,cs,rs: Integer;
  3173. begin
  3174.   if not GetNormalizedSelectionBounds(True, r,c,cs,rs) then begin
  3175.     Rows.FMainRVData.Beep;
  3176.     exit;
  3177.   end;
  3178.   InsertRows(r+rs, Count, r+rs-1);
  3179. end;
  3180. {------------------------------------------------------------------------------}
  3181. procedure TRVTableItemInfo.DeleteRows(Index, Count: Integer;
  3182.                                       DecreaseHeight: Boolean);
  3183. var er,ec,mr,mc: Integer;
  3184. begin
  3185.   if Rows.Empty then
  3186.     exit;
  3187.   if (Index<0) or (Index>=Rows.Count) or (Count<=0) or
  3188.      ((Index=0) and (Count>Rows.Count)) then
  3189.     raise ERichViewError.Create(errInvalidIndex);
  3190.   if GetEditedCell(er,ec)<>nil then begin
  3191.     if er>=Index+Count then
  3192.       dec(er, Count)
  3193.   end;
  3194.   DestroyInplace(True);
  3195.   Deselect;
  3196.   InitUndo;
  3197.   try
  3198.     Rows.DeleteRows(Index,Count,DecreaseHeight);
  3199.   finally
  3200.     DoneUndo;
  3201.   end;
  3202.   if (Rows.Count>0)  and (rvtoEditing in Options) then begin
  3203.     if er<0 then begin
  3204.       ec := 0;
  3205.       er := Index;
  3206.     end;
  3207.     if er>=Rows.Count then
  3208.       er := Rows.Count-1;
  3209.     Rows.GetMainCell(er,ec,mr,mc);
  3210.     CreateInplace(-1, mr,mc, False, True, False, False, False);
  3211.   end;
  3212.   ResetLiveSpell;  
  3213.   Changed;
  3214. end;
  3215. {------------------------------------------------------------------------------}
  3216. procedure TRVTableItemInfo.DeleteCols(Index, Count: Integer; DecreaseWidth: Boolean);
  3217. var er,ec,mr,mc: Integer;
  3218. begin
  3219.   if Rows.Empty then
  3220.     exit;
  3221.   if (Index<0) or (Index>=Rows[0].Count) or (Count<=0) or
  3222.      ((Index=0) and (Count>Rows[0].Count)) then
  3223.     raise ERichViewError.Create(errInvalidIndex);
  3224.   if GetEditedCell(er,ec)<>nil then begin
  3225.     if ec>=Index+Count then
  3226.       dec(ec, Count)
  3227.   end;
  3228.   DestroyInplace(True);
  3229.   Deselect;
  3230.     InitUndo;
  3231.   try
  3232.     Rows.DeleteCols(Index,Count,DecreaseWidth);
  3233.   finally
  3234.     DoneUndo;
  3235.   end;
  3236.   if (Rows.Count>0) and (Rows[0].Count>0) and CanChange and (rvtoEditing in Options) then begin
  3237.     if er<0 then begin
  3238.       er := 0;
  3239.       ec := Index;
  3240.     end;
  3241.     if ec>=Rows[er].Count then
  3242.       ec := Rows[er].Count-1;
  3243.     Rows.GetMainCell(er,ec,mr,mc);
  3244.     CreateInplace(-1, mr,mc, False, True, False, False, False);
  3245.   end;
  3246.   ResetLiveSpell;  
  3247.   Changed;
  3248. end;
  3249. {------------------------------------------------------------------------------}
  3250. procedure TRVTableItemInfo.DeleteSelectedRows;
  3251. var r,c,cs,rs: Integer;
  3252. begin
  3253.   if not GetNormalizedSelectionBounds(True, r,c,cs,rs) then begin
  3254.     Rows.FMainRVData.Beep;
  3255.     exit;
  3256.   end;
  3257.   DeleteRows(r, rs, True);
  3258. end;
  3259. {------------------------------------------------------------------------------}
  3260. procedure TRVTableItemInfo.DeleteSelectedCols;
  3261. var r,c,cs,rs: Integer;
  3262. begin
  3263.   if not GetNormalizedSelectionBounds(True, r,c,cs,rs) then begin
  3264.     Rows.FMainRVData.Beep;
  3265.     exit;
  3266.   end;
  3267.   DeleteCols(c, cs, True);
  3268. end;
  3269. {------------------------------------------------------------------------------}
  3270. procedure TRVTableItemInfo.DeleteEmptyCols;
  3271. var r,c: Integer;
  3272.     empty: Boolean;
  3273. begin
  3274.   if Rows.Empty then
  3275.     exit;
  3276.   for c := Rows[0].Count-1 downto 0 do begin
  3277.     empty := True;
  3278.     for r := 0 to Rows.Count-1 do
  3279.       if Cells[r,c]<>nil then begin
  3280.         empty := False;
  3281.         break;
  3282.       end;
  3283.     if empty then
  3284.       DeleteCols(c,1,False);
  3285.   end;
  3286. end;
  3287. {------------------------------------------------------------------------------}
  3288. procedure TRVTableItemInfo.DeleteEmptyRows;
  3289. var r,c: Integer;
  3290.     empty: Boolean;
  3291. begin
  3292.   for r := Rows.Count-1 downto 0 do begin
  3293.     empty := True;
  3294.     for c := 0 to Rows[r].Count-1 do
  3295.       if Cells[r,c]<>nil then begin
  3296.         empty := False;
  3297.         break;
  3298.       end;
  3299.     if empty then
  3300.       DeleteRows(r,1,False);
  3301.   end;
  3302. end;
  3303. {------------------------------------------------------------------------------}
  3304. procedure TRVTableItemInfo.Deselect;
  3305. begin
  3306.   {
  3307.   if FInplaceEditor<>nil then begin
  3308.     FInplaceEditor.Deselect;
  3309.     FInplaceEditor.Invalidate;
  3310.     exit;
  3311.   end;
  3312.   }
  3313.   DestroyInplace(True);
  3314.   Exclude(FState, rvtsSelExists);
  3315.   FSelStartCol := -1;
  3316.   FSelStartRow := -1;
  3317.   FSelColOffs  := 0;
  3318.   FSelRowOffs  := 0;
  3319.   UpdateCellSel;
  3320.   UnAssignActiveCell;
  3321.   if Rows.FMainRVData is TCustomRVFormattedData then begin
  3322.     TCustomRVFormattedData(Rows.FMainRVData).Invalidate;
  3323.     TCustomRVFormattedData(Rows.FMainRVData).DoSelect;
  3324.   end;
  3325. end;
  3326. {------------------------------------------------------------------------------}
  3327. procedure TRVTableItemInfo.Select(StartRow, StartCol, RowOffs, ColOffs: Integer);
  3328. begin
  3329.   if not (rvtsInserted in FState) then
  3330.     exit;
  3331.   DestroyInplace(True);
  3332.   if not (Rows.FMainRVData is TCustomRVFormattedData) then
  3333.     exit;
  3334.   if not (rvoAllowSelection in Rows.FMainRVData.Options) then
  3335.     exit;
  3336.   TCustomRVFormattedData(Rows.FMainRVData).PartialSelectedItem := Self;
  3337.   Include(FState, rvtsSelExists);
  3338.   FSelStartCol := StartCol;
  3339.   FSelStartRow := StartRow;
  3340.   FSelColOffs  := ColOffs;
  3341.   FSelRowOffs  := RowOffs;
  3342.   UpdateCellSel;
  3343.   if Rows.FMainRVData is TCustomRVFormattedData then begin
  3344.     TCustomRVFormattedData(Rows.FMainRVData).Invalidate;
  3345.     TCustomRVFormattedData(Rows.FMainRVData).DoSelect;
  3346.   end;
  3347. end;
  3348. {------------------------------------------------------------------------------}
  3349. procedure TRVTableItemInfo.SelectCols(StartCol, Count: Integer);
  3350. begin
  3351.   Select(0, StartCol, Rows.Count-1, Count-1);
  3352. end;
  3353. {------------------------------------------------------------------------------}
  3354. procedure TRVTableItemInfo.SelectRows(StartRow, Count: Integer);
  3355. begin
  3356.   Select(StartRow, 0, Count-1, Rows[StartRow].Count-1);
  3357. end;
  3358. {------------------------------------------------------------------------------}
  3359. function TRVTableItemInfo.GetSelectionBounds(var StartRow, StartCol,
  3360.                                                  RowOffs, ColOffs: Integer): Boolean;
  3361. begin
  3362.   StartCol := FSelStartCol;
  3363.   StartRow := FSelStartRow;
  3364.   ColOffs  := FSelColOffs;
  3365.   RowOffs  := FSelRowOffs;
  3366.   Result := rvtsSelExists in FState;
  3367. end;
  3368. {------------------------------------------------------------------------------}
  3369. function TRVTableItemInfo.GetNormalizedSelectionBounds(IncludeEditedCell: Boolean;
  3370.      var TopRow, LeftCol, ColSpan, RowSpan: Integer): Boolean;
  3371. var r,c: Integer;
  3372.     Cell: TRVTableCellData;