AddStyle( [afsIsInsertPoint] ), and "DropMarkers&quot

  • afsIsInsert point appears to have been removed from TOneWrtStyle with WPTools 5. How would a line such as:

    WPRichText1.CurrAttr.AddStyle( [ afsIsInsertPoint ] );

    be migrated to WPTools 5?

    Similarly, what about

    WPRichText1.CurrAttr.AddStyle( [ afsAutomatic ] );

    • Offizieller Beitrag

    Hi,

    afsIsInsertPoint does not exist anymore since merge fields are always marked by an opening and closing mergefield text objects.

    So you need to use the

    function InputMergeField(
    const FieldName: string;
    const DisplayText: string = '';
    Command: string = '';
    Format: Integer = 0;
    DisplayChar: Char = #0 //<-- obsolete parameter!
    ): TWPTextObj;

    to create such a field.

    When and why would you need to set the char style? It didn't make much sense in V4 since the style without a 'tag' would not be helpful.

    Julian

  • The code in question that used

    WPRichText1.CurrAttr.AddStyle( [ afsIsInsertPoint ] );

    was actually from Version 3 - I'm leapfrogging from Version 3 to Version 5!

    The code takes text entered into a <shudder> non-TWPRichText component, moving it into a TWPRichText component. It parsed the user-entered text, and, if it encounters a special symbol reserved for a merge code, the code replaces the special symbol with a merge character, assigning it the afsIsInsertPoint attribute.

    • Offizieller Beitrag

    There is a function in WPCtrMemo which is probably a good example to perform this task. The function ReplaceTokens replcaed text between certain character combinations, such as << and >> with a field. The text within the tokens is expected to be the fiueld name.

    I copy the complete code here:

    Code
    function TWPCustomRtfEdit.ReplaceTokens(const opening, closing: string): Integer;var  s, r: string;  StartID, SelStartID, SelEndID: Integer;  RestoreSel: Boolean;begin  StartID := 0;  RestoreSel := FALSE;  SelEndID := 0;  SelStartID := 0;  Result := 0;  with TextCursor do  try    s := opening + '*' + closing;    StartID := DropMarker;    SelStartID := DropMarkerAtSelStart;    SelEndID := DropMarkerAtSelEnd;    RestoreSel := HideSelection;    with Finder do    begin      ToStart;      while Next(s) do      begin        r := FoundText;        CPPosition := FoundPosition + FoundLength - Length(closing);        DeleteChar(Length(closing));        CPPosition := FoundPosition;        DeleteChar(Length(opening));        SetSelPosLen(FoundPosition, FoundLength -             Length(opening) - Length(closing));        r := Copy(r, Length(opening) + 1,          Length(r) - Length(opening) - Length(closing));// We use InputCode to create a field wrapping the selected text!        InputCode(wpobjMergeField, r, '', [wpinpWrapSelectedText]);        FoundPosition := FoundPosition + Length(r) + 2;        inc(Result);      end;    end;  finally    HideSelection;    if RestoreSel then    begin      TextCursor.SelectMarker(SelEndID, SelStartID);    end    else TextCursor.GotoMarker(StartID);    Refresh;  end;end;

    This code uses the new DropMarkers which are maintained by the TextCursor class. These markers behave like bookmarks, only that they are not invasive - meaning that if you are dropping such a marker this does not chage the text. The markers are also not saved with the text. But - the markers will be moved automatically when text is inserted. (Within limits, insert from stream is not supported)
    This makes the markers ideal to first locate certain spots in the text and then replace the text.

    I suggest you copy the text into the destination TWPRichText and make the required updates there, using code like the above.

    This are the functions which are used for markers:

    Code
    function DropMarker: Integer;
        function DropMarkerAt(par: TParagraph; PosInPar: Integer): Integer;
        function DropMarkerAtSelStart: Integer;
        function DropMarkerAtSelEnd: Integer;
        function GotoMarker(Collect: Boolean = TRUE; 
            DroppMarkerID: Integer = -1): Boolean; overload;
        function GotoMarker(DroppMarkerID: Integer): Boolean; overload;
        function SelectMarker(FromMarker, ToMarker: Integer): Boolean;
        procedure CollectAllMarker;
        procedure CollectMarker(DroppMarkerID: Integer);
  • Thank you for this. I'll spend some time looking at and familiarizing myself with the code you show here.

    Question: When you indicate the markers are not saved with the text, you mean that next time I bring the document up, the markers will not be in there?

    If that's the case, the usefulness of markers within text is diminished, perhaps entirely. A document in my application, by its very nature, needs to be saved between sessions, so that the next time the user works with the document, all their edits, changes, and effects (such as, previously, InsertPoints), will still be there.

    Is there a more "sticky" (i.e., permanent, saved-with-the-document) solution you suggest I use, or did I misunderstand what you meant by markers not being saved with the document?

  • Zitat

    Question: When you indicate the markers are not saved with the text, you mean that next time I bring the document up, the markers will not be in there?

    The markers created with 'DropMarkers' only live as long as the document is loaded. They are not saved.

    >>If that's the case, the usefulness of markers within text is diminished, perhaps entirely. <<

    You misunderstood - this markers are not a replacement for bookmarks or mailmerge fields. They are a useful tool to be used during the modfication of a document, such as in the mentioned methods. The markers work similar as a
    pos := CPPosition;
    .. do something A ...
    CPPosition := pos;
    .. do something B ...
    only that the above code would not work correctly if "do something A" inserted or deleted code in a way that 'pos' is pointing to a different place in the document.

    Think of the use in ReplaceTokens - If you have the text <<NAME>> and convert the signs '<<' and '>>' both into a one char TWPTextObject the total length has been reduced by 2. The markers make sure that this does not matter.

    From your explanation I understand that you do somethign similar, so ReplaceTokens is a good example for a solution to your problem.

    A document in my application, by its very nature, needs to be saved between sessions, so that the next time the user works with the document, all their edits, changes, and effects (such as, previously, InsertPoints), will still be there.

    As I said - the markers are a tool, not a replacement for insert points or bookmarks. They can be used to INSERT the new InsertPoints which are TWPTextObjects, created by InputCode(wpobjMergeField, r, '', [wpinpWrapSelectedText]) in this example.

    Julian