Hi! I want to get the current sentence, but I do not have any idea about how to achieve it.
Thanks.
How to get the current sentence?
-
- Site Admin
- Posts: 17559
- Joined: Sat Aug 27, 2005 10:28 am
- Contact:
For simple functions returning the current word, line, etc. see the unit RVGetText (or RVGetTextW for Unicode versions).
As for the sentence, it's more complicated, and the result depends on the definition of "sentence".
Recently I was asked to create a procedure expanding the current selection to a sentence.
A sentence is delimited either with '.', '?', '!' characters followed by a space or end of line or end of doc (for example, sentences can be finished with '!? ' or '... '), or any non-text item (picture), or a line break.
Not extensively tested, but I hope it's ok.
After calling this procedure, use GetSelText to get the selected text.
As for the sentence, it's more complicated, and the result depends on the definition of "sentence".
Recently I was asked to create a procedure expanding the current selection to a sentence.
A sentence is delimited either with '.', '?', '!' characters followed by a space or end of line or end of doc (for example, sentences can be finished with '!? ' or '... '), or any non-text item (picture), or a line break.
Not extensively tested, but I hope it's ok.
Code: Select all
procedure ExpandToSentence(rve: TCustomRichViewEdit);
var ItemNo1, ItemNo2, Offs1, Offs2: Integer;
Found: Boolean;
s: String;
// Returns True is the specified position contains punctuation followed by
// a space, of line end, or doc end.
function HasSpaceAfter(ItemNo, Offs: Integer): Boolean;
var s: String;
begin
Result := True;
while ItemNo<rve.ItemCount do begin
s := rve.GetItemText(ItemNo);
while (Offs<=Length(s)) and (s[Offs] in ['.','!','?']) do
inc(Offs);
if Offs<Length(s) then begin
Result := s[Offs]=' ';
exit;
end;
inc(ItemNo);
if (ItemNo<rve.ItemCount) then begin
if (rve.GetItemStyle(ItemNo)<0) or rve.IsFromNewLine(ItemNo) then
exit;
Offs := rve.GetOffsBeforeItem(ItemNo);
end;
end;
end;
// Moves the position to the right, skipping punctuation
procedure SkipPunct(var AItemNo, AOffs: Integer);
var s: String;
ItemNo, Offs: Integer;
begin
ItemNo := AItemNo;
Offs := AOffs;
while ItemNo<rve.ItemCount do begin
s := rve.GetItemText(ItemNo);
while (Offs<=Length(s)) and (s[Offs] in ['.','!','?']) do
inc(Offs);
AItemNo := ItemNo;
AOffs := Offs;
if Offs<Length(s) then
exit;
inc(ItemNo);
if (ItemNo<rve.ItemCount) and
((rve.GetItemStyle(ItemNo)<0) or rve.IsFromNewLine(ItemNo)) then
exit;
end;
end;
begin
rve := rve.TopLevelEditor;
// assigning the selection bounds to ItemNo1, Offs1, ItemNo2, Offs2
if rve.SelectionExists then
rve.GetSelectionBounds(ItemNo1, Offs1, ItemNo2, Offs2, True)
else begin
ItemNo1 := rve.CurItemNo;
ItemNo2 := ItemNo1;
Offs1 := rve.OffsetInCurItem;
Offs2 := Offs1;
end;
// expanding the top bound (Item1, Offs1)
while True do begin
if Offs1>=rve.GetOffsBeforeItem(ItemNo1) then begin
if rve.GetItemStyle(ItemNo1)<0 then
break;
s := rve.GetItemText(ItemNo1);
Found := False;
while Offs1>1 do begin
if (s[Offs1-1] in ['.','!','?']) and HasSpaceAfter(ItemNo1, Offs1) then begin
Found := True;
break;
end;
dec(Offs1);
end;
if Found then
break;
end;
if rve.IsFromNewLine(ItemNo1) then
break;
dec(ItemNo1);
Offs1 := rve.GetOffsAfterItem(ItemNo1)
end;
// expanding the bottom bound (Item2, Offs2)
while ItemNo2<rve.ItemCount do begin
if Offs2<=rve.GetOffsAfterItem(ItemNo2) then begin
if rve.GetItemStyle(ItemNo2)<0 then
break;
s := rve.GetItemText(ItemNo2);
Found := False;
while Offs2<=Length(s) do begin
if (s[Offs2] in ['.','!','?']) and HasSpaceAfter(ItemNo2, Offs2) then begin
Found := True;
SkipPunct(ItemNo2, Offs2);
break;
end;
inc(Offs2);
end;
if Found then
break;
end;
if (ItemNo2+1=rve.ItemCount) or rve.IsFromNewLine(ItemNo2+1) then
break;
inc(ItemNo2);
Offs2 := rve.GetOffsBeforeItem(ItemNo2)
end;
rve.SetSelectionBounds(ItemNo1, Offs1, ItemNo2, Offs2);
rve.Invalidate;
end;
-
- Posts: 8
- Joined: Sat Sep 13, 2008 1:36 am
Thanks.
Thanks a lot. Your code works well.