Page 1 of 1
Access violation on undo in table
Posted: Wed Jan 13, 2010 1:45 am
by Marsianin
There is a problem with Access Violation when making undo inside table in RVE 12.0.4
Just create a table, enter something and press Alt+Backspace several times.
Sometimes access violation fires on pressing Backspace only or changing cell background color.
The problem appears here:
Code: Select all
function TRVEditRVData.GetCurItemNo: Integer;
{........................................}
function IndexOf(obj: TCustomRVItemInfo): Integer;
var ItemNo: Integer;
begin
Result := -1;
if (CaretDrawItemNo>=0) and (CaretDrawItemNo<DrawItems.Count) then begin
ItemNo := DrawItems[CaretDrawItemNo].ItemNo;
...
Posted: Wed Jan 13, 2010 5:05 pm
by Sergey Tkachenko
I cannot reproduce this error in the ActionTest demo.
Please give me exact steps to do to reproduce it.
Posted: Wed Jan 13, 2010 5:49 pm
by Marsianin
Will try to find the problem but I didn't change anything in my code before migrating to v.12.
Posted: Wed Jan 13, 2010 9:43 pm
by Marsianin
It happens when undo action moves cursor from one cell to another.
I have this OnCaretMove implementation:
Code: Select all
procedure TMainForm.RichViewEdit1CaretMove(Sender: TObject);
var line,linescount,col:Integer;
begin
UpdateEditorUI;
RichViewEdit1.GetCurrentLineCol(line,col);
with RichViewEdit1 do
try
linescount:=GetLineNo(ItemCount-1,GetOffsAfterItem(ItemCount-1));
except
end;
SpTBXLabelItem1.Caption:=WideFormat(TXT_Line[lang],[line,linescount]);
SpTBXLabelItem2.Caption:=TXT_Column[lang]+' '+IntToStr(col);
end;
When undo moves caret from one cell to another this event fires more that 10 times and after that I'm gettin access violation. But without this event handler (just put Exit; at the beginning) it works fine.
Before 12.0 this code worked fine.
UpdateEditorUI just updates toolbars with the current item information.
Also if there is no undo and you press Alt+Backspace (Ctrl+Z) in editor - Windows sound beeps but in table it does not.
Posted: Wed Jan 13, 2010 9:48 pm
by Marsianin
Commented UpdateEditorUI and got just one AccessViolation here (not infinite access violation loop as in the first case):
Code: Select all
procedure TCustomRVFormattedData.Item2DrawItem(ItemNo, ItemOffs: Integer;
var DrawItemNo, DrawItemOffs: Integer);
var item: TCustomRVItemInfo;
i: Integer;
begin
DrawItemNo := -1;
if ItemNo = -1 then
exit;
item := GetItem(ItemNo);
DrawItemNo := item.DrawItemNo;
if item.StyleNo<0 then begin
DrawItemOffs := ItemOffs-DrawItems[DrawItemNo].Offs;
Here is my UpdateEditorUI:
Code: Select all
procedure TMainForm.UpdateEditorUI;
var boo,selexist:Boolean;
item :TCustomRVItemInfo;
begin
if not RichViewEdit1.Visible then Exit;
boo:=SendMessage(RichViewEdit1.Handle,EM_CANUNDO,0,0)<>0;
if ReadOnly then boo:=False;
TBXItem24.Enabled:=boo;
TBXItem67.Enabled:=boo;
boo:=SendMessage(RichViewEdit1.Handle,WM_USER+85,0,0)<>0;
TBXItem25.Enabled:=boo;
TBXItem66.Enabled:=boo;
selexist:=RichViewEdit1.RVData.SelectionExists(False,True);
boo:=selexist;
TBXItem21.Enabled:=boo;
TBXItem64.Enabled:=boo;
TBXItem141.Enabled:=boo;
If ReadOnly then boo:=False;
TBXItem142.Enabled:=boo;
TBXItem20.Enabled:=boo;
TBXItem65.Enabled:=boo;
boo:=(Clipboard.FormatCount>0)and(not ReadOnly);
SpTBXSubMenuItem1.Enabled:=boo;
SpTBXSubMenuItem2.Enabled:=boo;
TBXItem22.Enabled:=boo;
TBXItem63.Enabled:=boo;
TBXItem140.Enabled:=boo;
TBXItem189.Enabled:=RichViewEdit1.PageBreaksBeforeItems[RichViewEdit1.CurItemNo];
item:=RichViewEdit1.GetCurrentItem;
boo:=(item is TRVGraphicItemInfo)or(item is TRVBreakItemInfo)or(item is TRVTableItemInfo);
if ReadOnly then boo:=False;
TBXItem163.Enabled:=boo;
TBXItem164.Enabled:=boo;
SpTBXItem64.Visible:=(item is TRVGraphicItemInfo);
SpTBXSeparatorItem75.Visible:=SpTBXItem64.Visible;
end;
Posted: Thu Jan 14, 2010 10:02 am
by Sergey Tkachenko
Document may be unformatted in OnCaretMove.
In this event, you can use functions returning caret position (like GetCurrentLineCol), but you cannot use any other methods requiring formatted document.
This includes all functions related to selection.
I recommend to move UpdateEditorUI from this event (leave only procedures depending on the caret position but not on selection).
This is not a new limitation in version 12. It was so from the beginning. If something worked before, it was accidentally.
Posted: Thu Jan 14, 2010 6:11 pm
by Marsianin
It worked before like a charm. Never got any errors.
So where I should move it? Where is better?
Posted: Thu Jan 14, 2010 8:46 pm
by Sergey Tkachenko
For operations depending on selection - in OnSelect.
Posted: Sun Jan 17, 2010 7:27 pm
by Marsianin
Ok, thanks. It's working now.
Had to put some other checks to avoid selection bounds errors but now it works.
I have the similar problem
Posted: Wed Feb 24, 2010 3:33 am
by cychia
I have a context panel in my form which will display properties of the current item. I found there is not OnItemChanged(ItemStyle) event, so I've handled the OnCaretMoved and check curItemStyle to update my UI context panel accordingly. I got an AV too and from your explanation the AV is caused by GetCurrentItemEx where it tries to access an unformatted doc.
Code: Select all
procedure OnCaretMoved;
var
nLine, nColumn, nListIndex, nItemStyle: Integer;
rveTemp: TCustomRichViewEdit;
function IsCaretInTableCell: Boolean;
var
rveTable: TCustomRichViewEdit;
rveTableItemInfo: TCustomRVItemInfo;
begin
Result := RichViewEdit1.GetCurrentItemEx(TRVTableItemInfo, rveTable, rveTableItemInfo);
end;
begin
rveTemp := RichViewEdit1.TopLevelEditor;
with rveTemp do
begin
nItemStyle := rveTemp.GetItemStyle(rveTemp.CurItemNo);
if nItemStyle < 0 then
begin
case nItemStyle of
rvsPicture, rvsHotPicture: Caption := 'Now Picture';
else
begin
if IsCaretInTableCell then
Caption := 'Now Table'
else
Caption := 'Now Normal';
end;
end;
end
else
begin
if IsCaretInTableCell then
Caption := 'Now Table'
else
Caption := 'Now Normal';
end;
end;
end;
Then from your suggestion, I have move this part of code to OnSelect, it works fine, but there is a case where this event will not be triggered which is, use your mouse to click a picture in the content, then press -> in your keyboard, then start typing, this event is not triggered so I have no way of knowing current the caret is no longer in a picture so that I can hide my picture context panel.
For this type of context showing, any better event to handle? Thanks.
Posted: Wed Feb 24, 2010 4:36 am
by cychia
another doubt is why i get the itemstyle as 0 when the caret is in a table cell?
Posted: Wed Feb 24, 2010 6:44 pm
by Sergey Tkachenko
I tried to place your procedure (OnCaretMoved) in OnCaretMove event.
It works fine for me.
But for any case, I suggest to add
Code: Select all
if RichViewEdit1.ItemCount=0 then
exit;
at the beginning.
Posted: Wed Feb 24, 2010 7:11 pm
by Sergey Tkachenko
Each table cell initially has one empty text item of the 0th text and the 0th paragraph style.
If you need another style, you can replace it before inserting table.
For example:
Code: Select all
table := TRVTableItemInfo.CreateEx(..., RichViewEdit1.RVData);
for r := 0 to table.RowCount-1 do
for c := 0 to table.ColCount-1 do begin
table.Cells[r,c].Clear;
table.Cells[r,c].Add('', RichViewEdit1.CurTextStyleNo, RichViewEdit1.CurParaStyleNo);
end;
RichViewEdit1.InsertItem('', table);
Posted: Thu Feb 25, 2010 1:19 am
by cychia
Sergey Tkachenko wrote:I tried to place your procedure (OnCaretMoved) in OnCaretMove event.
It works fine for me.
But for any case, I suggest to add
Code: Select all
if RichViewEdit1.ItemCount=0 then
exit;
at the beginning.
after inserted a table, click one of the cell, start typing, u will get AV
Posted: Thu Feb 25, 2010 11:19 am
by Sergey Tkachenko
Add this code instead:
Code: Select all
if (RichViewEdit1.ItemCount=0) or
(rvstFormattingPart in RichViewEdit1.RVData.State) then
exit;
By the way, your procedure IsCaretInTableCell has a wrong name.
It returns True if
- the caret is table cell or
- table has multicell selection or
- the caret is to the right or to the left of table.
If you really need to know if the caret is inside table cell, the test is simple:
Code: Select all
InTableCell := RichViewEdit1.InplaceEditor<>nil