Here is the function it starts in readerpaste and ends in WMAfterPaste and it all seems to work fine until I click on a different reader....
Code: Select all
var
MuteReaderPasteDelegate: Boolean = False;
TextStyleBeforePaste, ParaStyleBeforePaste: Integer;
procedure TfmBookView.readerPaste(Sender: TCustomRichViewEdit;
var DoDefault: Boolean);
var
sItemNo, sItemOffs, eItemno, eItemOffs: Integer;
CurItem: Integer;
InsertWS: String;
begin
//So Reader paste doesn't take over edtTopics.
{ if edtTopics.Focused then begin
//edtTopics.PasteFromClipboard;
exit;
end else if edtVol.Focused then begin
//edtVol.PasteFromClipboard;
exit;
end;}
// Early validation
if not Assigned(reader) then begin
DoDefault := True;
Exit;
end;
// Ensure document is formatted before accessing properties
//reader.ReFormat; //keeps the caret and selection
// Safe bounds checking
if reader.ItemCount = 0 then begin
DoDefault := True;
Exit;
end;
try
CurItem := reader.CurItemNo;
// Validate CurItem is within bounds
if (CurItem < 0) or (CurItem >= reader.ItemCount) then begin
CurItem := 0;
end;
// Safe access to style properties
TextStyleBeforePaste := 0;
ParaStyleBeforePaste := 0;
if (reader.CurTextStyleNo >= 0) and (reader.CurTextStyleNo < reader.Style.TextStyles.Count) then
TextStyleBeforePaste := reader.CurTextStyleNo;
if (reader.CurParaStyleNo >= 0) and (reader.CurParaStyleNo < reader.Style.ParaStyles.Count) then
ParaStyleBeforePaste := reader.CurParaStyleNo;
//If Called from Paste To Editor but only from inside of Bookview this boolean helps with that.
if FVerseLinkPasteToEditor and
(TextStyleBeforePaste < reader.Style.TextStyles.Count) and
reader.Style.TextStyles[TextStyleBeforePaste].Jump then begin
//Check if the item is a jump link should be since that is where this came from.
reader.SetSelectionBounds(CurItem,reader.GetOffsAfterItem(CurItem),CurItem,reader.GetOffsAfterItem(CurItem));
InsertWS := _getGlobalIni.ReadString('general','default.bkv.paste.to.editor.str', ' ');
InsertWS := GlobalUtils.StringReplaceU(InsertWS,'#9', #9);
InsertWS := GlobalUtils.StringReplaceU(InsertWS,'#13', #13);
InsertWS := GlobalUtils.StringReplaceU(InsertWS,'#10', #10);
reader.InsertTextW(InsertWS); //Now insert a space, enter something the user desires.
end;
FVerseLinkPasteToEditor := False; //Unfortunately this should be done immeditately after the popup closes but I can't get it to trigger OnClose
//This problem can cause a user to paste in a link and could cause a problem but will work the second time because this will be set.
reader.GetSelectionBounds(sItemNo, sItemOffs, eItemno, eItemOffs, True);
if (sItemNo = eItemNo) and (sItemOffs = eItemOffs) and (sItemOffs = 1) then
Dec(CurItem);
// Validate CurItem again after potential decrement
if CurItem < 0 then CurItem := 0;
//call the WMAfterPaste in 300ms...
//need to use a timer because there is a Application.ProcessMessages; call in
//the uFrmCopyVerses that would 'eat' the PostMessage below
//FAfterPaste_Handle := Handle;
FAfterPaste_CurItem := CurItem;
FAfterPaste_ItemCount := reader.ItemCount;
// Only set timer if window handle is valid
{if IsWindow(Handle) then
SetTimer(Handle, 1, 300, @TimerProc_AfterPaste);}
// Use timer instead of Windows callback
FAfterPasteTimer.Enabled := False; // Stop any existing timer
FAfterPasteTimer.Enabled := True; // Start new timer
// Post message directly instead of using timer
//PostMessage(Handle, WM_AFTERPASTE, FAfterPaste_CurItem, FAfterPaste_ItemCount);
//This handler is called with CTRL+V. In that case, the Paste method of RVE
//is called which does NOT handle the HTML format. To handle HTML, we need
//to calle the RichViewActions.OnPaste action. So, if the clipboard contains
//HTML, with call the rvActionPaste2 action and set DoDefault to false, to not
//alow the RVE to handle the Paste itself.
if IsClipboardFormatAvailable(CFRV_HTML) and
(not IsClipboardFormatAvailable(CFRV_RVF)) and
(not IsClipboardFormatAvailable(CFRV_RTF)) and
(not MuteReaderPasteDelegate)then begin
try
MuteReaderPasteDelegate := True;
MainReaderForm.rvActionPaste2.Execute;
DoDefault := False;
finally
MuteReaderPasteDelegate := False;
end
end
else begin
DoDefault := True;
end;
except
on E: Exception do begin
debugOnScreen(PChar('readerPaste error: ' + E.Message));
DoDefault := True;
end;
end;
end;
Code: Select all
var
FixEswordLinksOnPasteRE: TRegExx = ();
{ This code tries to remove dead hyperlinks on paste... I am not sure at all
about it. Commented out above
Need to do ApplyStyleConversion here!!! }
procedure TFmBookView.WMAfterPaste(var msg: TMessage);
var
i, CurItem, ItemCount, c, p, minIndex, maxIndex: Integer;
RVTag: TRVTag;
cpd: TCheckpointData;
s: string;
name: TRVUnicodeString;
re: Boolean;
readerName: String;
begin
// Validate we're still in the correct context
if not (Self.Focused or Self.ContainsControl(Screen.ActiveControl)) then begin
debugOnScreen('WMAfterPaste: BookView no longer active, ignoring');
Exit;
end;
// Validate that the reader is still valid and assigned
if not Assigned(reader) then begin
debugOnScreen('WMAfterPaste: Reader not assigned, ignoring message');
Exit;
end;
// Check if reader handle is valid
if not reader.HandleAllocated then begin
debugOnScreen('WMAfterPaste: Reader handle not allocated, ignoring message');
Exit;
end;
// Validate that we're not in a destroying state
if (csDestroying in ComponentState) or (csLoading in ComponentState) then begin
debugOnScreen('WMAfterPaste: Component destroying/loading, ignoring message');
Exit;
end;
//RvBookUtil.ConvertToUnicodeAndMisc(reader.RVData, FCurModule, False, 0);
if (reader.BiDiMode = rvbdUnspecified) then
if RVShouldUserComplexRendering(reader) then
reader.BiDiMode := rvbdLeftToRight;
//remove possible protections from everything pasted
//with reader.Style do
if Assigned(FCurModule) then begin
//user module: remove protection
if FCurModule.IsUserModule then begin
for i:=0 to reader.Style.TextStyles.Count-1 do
reader.Style.TextStyles[i].Protection := [];
for i:=0 to reader.Style.ParaStyles.Count-1 do
reader.Style.ParaStyles[i].Options := reader.Style.ParaStyles[i].Options - [rvpaoReadOnly, rvpaoNoWrap,
rvpaoDoNotWantReturns];
end
end;
CurItem := msg.WParam;
ItemCount := msg.LParam;
// Validate parameters and get current item count
if (CurItem < 0) or (reader.ItemCount = 0) then Exit;
// Ensure CurItem is within valid range
if CurItem >= reader.ItemCount then
CurItem := reader.ItemCount - 1;
//Check if CurItem is a TBitmap if it is convert it to PNG
BitmapToPNG(CurItem);
// Calculate safe range for the loop
maxIndex := Min(CurItem + reader.ItemCount - ItemCount + 1, reader.ItemCount - 1);
// Additional safety check
if maxIndex < CurItem + 1 then
maxIndex := reader.ItemCount - 1;
minIndex := CurItem+1;
if minIndex > maxIndex then Exit; // Nothing to process
for i:=maxIndex downto minIndex do begin //JGK was CurItem+reader.ItemCount-ItemCount+1 do begin
// Double-check bounds before accessing
if (i < 0) or (i >= reader.ItemCount) then //just to be sure...
Break;
//SHIFT not pressed (UP)
if GetKeyState(VK_SHIFT) and $ff00 = 0 then begin
try
s := reader.GetItemTag(i);
p := Pos(':', s);
if (p>0) and(p<6) then continue;
//JGK ERROR THIS IS A PROBLEM
//IT needs used otherwise we have tags users don't need
//But it is causing a TRVItemList error cascade.
reader.SetItemTag(i, '');
except
on E: Exception do begin
debugOnScreen(PChar('WMAfterPaste GetItemTag error: ' + E.Message));
Continue;
end;
end;
end;
try
// Validate style index before accessing
if (reader.GetItemStyle(i) >= 0) and (reader.GetItemStyle(i) < reader.Style.TextStyles.Count) then begin
if reader.Style.TextStyles[reader.GetItemStyle(i)].Jump then begin
if reader.GetItemTag(i) = '' then
reader.Style.TextStyles[reader.GetItemStyle(i)].Jump := False;
end
end;
except
on E: Exception do begin
debugOnScreen(PChar('WMAfterPaste TextStyles error: ' + E.Message));
Continue;
end;
end;
//if pasting tables, add the rvtoEditing (see http://www.trichview.com/forums/viewtopic.php?p=10747#10747)
//bug when pasting from compare view to book view
try
if reader.GetItemStyle(i) = rvsTable then
with TRVTableItemInfo(reader.GetItem(i)) do
Options := Options + [rvtoEditing];
except
on E: Exception do begin
debugOnScreen(PChar('WMAfterPaste Table error: ' + E.Message));
Continue;
end;
end;
//remove checkpoint when pasting from bible view
try
cpd := reader.GetItemCheckpoint(i);
if ( cpd<>nil ) then begin
reader.GetCheckpointInfo(cpd, RVTag, name, re);
if GlobalUtils.StrSameStartU('_TW_VLIDX', RVTag) then
reader.RemoveCheckpointEd(i);
end;
except
on E: Exception do begin
debugOnScreen(PChar('WMAfterPaste Checkpoint error: ' + E.Message));
Continue;
end;
end;
end;
//if SHIFT is down, fix e-Sword style links: for pasting from eSword
if GetKeyState(VK_SHIFT) and $ff00 <> 0 then begin
c := reader.ItemCount-ItemCount;
if c>0 then begin
if not FixEswordLinksOnPasteRE.IsInit then FixEswordLinksOnPasteRE.Create(gc_AutoRefRegex, [roCompiled]);
// Safer bounds for RVIterateAllItems
maxIndex := Math.Min(CurItem+c+1, reader.ItemCount-1);
if maxIndex >= minIndex then begin
RVIterateAllItems(reader.RVData, [], DetectVRefsOnPasteCB, 'WMAfterPaste minIndex to maxIndex', minIndex,
maxIndex);
end else begin
// Fallback: use full range if calculation fails
maxIndex := reader.ItemCount - 1;
if maxIndex >= minIndex then begin
RVIterateAllItems(reader.RVData, [], DetectVRefsOnPasteCB, 'WMAfterPaste minIndex to maxIndex', minIndex, maxIndex);
end;
{$IFDEF DEBUG}
debugOnScreen(PChar('WMAfterPaste: Used fallback maxIndex ' + IntToStr(maxIndex)));
{$ENDIF}
end;
cmdAutoDetectVREFsClick(nil);
end;
end;
end;
if I comment out:
in WMAfterPaste it works fine but off course there are tags that we don't want.