@@ -175,6 +175,16 @@ TActiveTextAttrNames = record
175
175
// / <summary>Appends elements from another given active text object to the
176
176
// / current object.</summary>
177
177
procedure Append (const ActiveText: IActiveText);
178
+ // / <summary>Returns a new IActiveText instance containing just the first
179
+ // / block of the current object.</summary>
180
+ // / <remarks>
181
+ // / <para>The first block is the content of the block level tag that starts
182
+ // / the active text. If this block has child blocks (for e.g. an unordered
183
+ // / list) then they are included.</para>
184
+ // / <para>If the current object is empty then an empty object is returned.
185
+ // / </para>
186
+ // / </remarks>
187
+ function FirstBlock : IActiveText;
178
188
// / <summary>Checks if the active text object contains any elements.
179
189
// / </summary>
180
190
function IsEmpty : Boolean;
@@ -474,6 +484,17 @@ TActiveText = class(TInterfacedObject,
474
484
// / </summary>
475
485
// / <remarks>Method of IActiveText.</remarks>
476
486
procedure Append (const ActiveText: IActiveText);
487
+ // / <summary>Returns a new IActiveText instance containing just the first
488
+ // / block of the current object.</summary>
489
+ // / <remarks>
490
+ // / <para>The first block is the content of the block level tag that starts
491
+ // / the active text. If this block has child blocks (for e.g. an unordered
492
+ // / list) then they are included.</para>
493
+ // / <para>If the current object is empty then an empty object is returned.
494
+ // / </para>
495
+ // / <para>Method of IActiveText.</para>
496
+ // / </remarks>
497
+ function FirstBlock : IActiveText;
477
498
// / <summary>Checks if the element list is empty.</summary>
478
499
// / <remarks>Method of IActiveText.</remarks>
479
500
function IsEmpty : Boolean;
@@ -719,6 +740,67 @@ destructor TActiveText.Destroy;
719
740
inherited ;
720
741
end ;
721
742
743
+ function TActiveText.FirstBlock : IActiveText;
744
+
745
+ function IsBlockWithState (Elem: IActiveTextElem; State: TActiveTextElemState):
746
+ Boolean;
747
+ var
748
+ ActionElem: IActiveTextActionElem;
749
+ begin
750
+ Result := False;
751
+ if not Supports(Elem, IActiveTextActionElem, ActionElem) then
752
+ Exit;
753
+ if TActiveTextElemCaps.DisplayStyleOf(ActionElem.Kind) <> dsBlock then
754
+ Exit;
755
+ if ActionElem.State <> State then
756
+ Exit;
757
+ Result := True;
758
+ end ;
759
+
760
+ function IsBlockOpener (Elem: IActiveTextElem): Boolean; inline;
761
+ begin
762
+ Result := IsBlockWithState(Elem, fsOpen);
763
+ end ;
764
+
765
+ function IsBlockCloser (Elem: IActiveTextElem): Boolean; inline;
766
+ begin
767
+ Result := IsBlockWithState(Elem, fsClose);
768
+ end ;
769
+
770
+ var
771
+ Depth: Cardinal;
772
+ Elem: IActiveTextElem;
773
+ Idx: Integer;
774
+ begin
775
+ Result := TActiveText.Create;
776
+ if IsEmpty then
777
+ Exit;
778
+
779
+ Elem := GetElem(0 );
780
+
781
+ if not IsBlockOpener(Elem) then
782
+ begin
783
+ Result.Append(Self);
784
+ Exit;
785
+ end ;
786
+
787
+ Depth := 1 ;
788
+ Result.AddElem(Elem);
789
+ for Idx := 1 to Pred(GetCount) do
790
+ begin
791
+ Elem := GetElem(Idx);
792
+ Result.AddElem(Elem);
793
+ // NOTE: we're not checking for matching openers and closers
794
+ if IsBlockOpener(Elem) then
795
+ Inc(Depth);
796
+ if IsBlockCloser(Elem) then
797
+ Dec(Depth);
798
+ if Depth = 0 then
799
+ Break;
800
+ end ;
801
+ // We're not checking for balancing block closer here either:
802
+ end ;
803
+
722
804
function TActiveText.GetCount : Integer;
723
805
begin
724
806
Result := fElems.Count;
0 commit comments