RVERVData.pas
上传用户:daoqigc
上传日期:2021-04-20
资源大小:2795k
文件大小:247k
- {*******************************************************}
- { }
- { RichView }
- { TRichViewRVData represents RichViewEdit }
- { document. }
- { This is a type of TRichViewEdit.RVData. }
- { }
- { Copyright (c) Sergey Tkachenko }
- { svt@trichview.com }
- { http://www.trichview.com }
- { }
- {*******************************************************}
- unit RVERVData;
- {$I RV_Defs.inc}
- interface
- uses SysUtils, Windows, Graphics, Classes, Controls, Forms,
- CRVData, CRVFData, RVRVData, RVItem, RVUndo, RVBack,
- DLines, RVFuncs, RVEdit, RVUni,
- RVScroll, RichView, RVStyle, ComCtrls, TypInfo, RVClasses,
- RVRTFProps, RVResize,
- {$IFNDEF RVDONOTUSEDRAGDROP}
- ActiveX, RVDragDrop,
- {$ENDIF}
- RVRTFErr;
- type
- TRVCharPos = class (TCollectionItem)
- public
- X, DrawItemNo, Offset, MoveRightTo: Integer;
- constructor Create(Owner: TCollection); override;
- procedure Assign(Source: TPersistent); override;
- end;
- TRVCharPosCollection = class (TCollection)
- private
- function GetItem(Index: Integer): TRVCharPos;
- procedure SetItem(Index: Integer; const Value: TRVCharPos);
- public
- property Items[Index: Integer]: TRVCharPos read GetItem write SetItem;
- end;
- TRVParaListOperation = (rvplopChange, rvplopRemove, rvplopLevel);
- TRVUndoDest = (udNone, udUndo, udRedo);
- TRVEditRVData = class (TRichViewRVData)
- private
- FPrevTextStyleNo: Integer;
- FCurTag: Integer;
- FResizer: TRVItemResizer;
- ResizingControl: TControl;
- FRVFInserted: Boolean;
- function InsSomething(var info: TCustomRVItemInfo; var s: String;
- AutoTag: Boolean; var InsertPoint, ItemsAdded: Integer;
- var FullReformat: Boolean; var NewListNo: Integer): Boolean;
- function InsEmptyString(Index, Tag, ParaStyle, FontStyle: Integer;
- SameAsPrev, BR: Boolean):TCustomRVItemInfo;
- function InsString(s: String; Index, Tag, ParaStyle, FontStyle: Integer;
- SameAsPrev, BR: Boolean; var FullReformat: Boolean): TCustomRVItemInfo;
- function InsString2(s: String; Index, Tag: Integer;
- Source: TCustomRVItemInfo; SameAsPrev, BR: Boolean;
- var FullReformat: Boolean): TCustomRVItemInfo;
- function CreateTextItem(Tag, ParaStyle, FontStyle: Integer;
- SameAsPrev, BR: Boolean): TCustomRVItemInfo;
- function CreateTextItem2(Tag: Integer; Source: TCustomRVItemInfo;
- SameAsPrev, BR: Boolean): TCustomRVItemInfo;
- procedure InsertString(var s: String; StyleNo: Integer; AutoTag,
- CaretBefore: Boolean);
- procedure DoResizeControl(ItemNo, OldWidth, OldHeight,
- NewWidth, NewHeight: Integer);
- function GetParaEndItemNo(ItemNo: Integer): Integer;
- function SetParaStyle(StartItemNo,EndItemNo, ParaNo: Integer;
- var FullReformat: Boolean): Boolean;
- procedure AfterAddingText(StartItemNo,EndItemNo, ItemsAdded,
- DIStartNo, DIEndNo: Integer; FullReformat, CaretBefore: Boolean);
- function ItemHasPersistentCheckpoint(ItemNo: Integer): Boolean;
- function ParaHasPersistentCheckpoint(ItemNo: Integer): Boolean;
- function MovePersistentCheckpoint(ItemNo: Integer; OnlyToPrev: Boolean): Boolean;
- procedure ClearCurTag;
- function GetOneSelectedItemNo: Integer;
- function InsertItemFromTextFile(var s: String; item: TCustomRVItemInfo;
- AutoTag, BR: Boolean; var FirstIP, InsertPoint, ItemsAdded, MarkerItemNo: Integer;
- var FirstItem, PageBreak, FromNewLine, FullReformat: Boolean): Boolean;
- protected
- CaretHeight: Integer;
- CharEnds: TRVCharPosCollection;
- procedure DeselectPartiallySelectedItem(NewPartiallySelected: TCustomRVItemInfo); override;
- procedure SetPartialSelectedItem(Item: TCustomRVItemInfo); override;
- procedure AfterDeleteStyles(Data: TRVDeleteUnusedStylesData); override;
- {$IFNDEF RVDONOTUSELISTS}
- function ReplicateMarker(ReferenceItemNo, InsertItemNo: Integer;
- var FullReformat: Boolean; EditFlag: Boolean): Boolean;
- procedure AdjustMarkerCaret(Right: Boolean; var Offs: Integer);
- procedure AdjustMarkerPos(var ItemNo, Offs: Integer; DefRight: Boolean);
- {$ENDIF}
- function CaretAtTheBeginningOfParaSection: Boolean;
- function CaretAtTheEndOfParaSection: Boolean;
- function CaretInTheLastLine: Boolean;
- function CaretAtTheBeginningOfLine: Boolean;
- function CaretAtTheEndOfLine: Boolean;
- procedure PostPaintTo(Canvas: TCanvas;
- XShift, YShift, FirstDrawItemNo, LastDrawItemNo: Integer); override;
- function GetResizeHandleAt(X, Y: Integer; var Index: TRVResizeHandleIndex): Boolean;
- {$IFNDEF RVDONOTUSEDRAGDROP}
- { Drag & drop: drop from }
- function InitDragging(var DropSource: TRVDropSource;
- var OKEffect: Integer): Boolean; override;
- procedure DoneDragging(FDeleteSelection: Boolean); override;
- {$ENDIF}
- {$IFNDEF RVDONOTUSELIVESPELL}
- procedure LiveSpellingCheckCurrentItem; override;
- {$ENDIF}
- public
- {$IFNDEF RVDONOTUSEDRAGDROP}
- FDragDropCaretInfo: TRVDragDropCaretInfo; // info about drag&drop caret location
- {$ENDIF}
- FCurTextStyleNo, FCurParaStyleNo: Integer;
- UndoList, RedoList: TRVUndoList;
- UndoDest: TRVUndoDest;
- CaretDrawItemNo: Integer;
- CaretOffs: Integer;
- {$IFNDEF RVDONOTUSELIVESPELL}
- procedure LaterSetBackLiveSpellingTo(ItemNo, Offs: Integer; ClearPainters: Boolean);
- {$ENDIF}
- {$IFNDEF RVDONOTUSEDRAGDROP}
- procedure CreateDragDropCaretInfo;
- procedure ReleaseDragDropCaretInfo;
- function GetDragDropCaretInfo: TRVDragDropCaretInfo; override;
- {$ENDIF}
- procedure AssignCurTag;
- function GetActualCurStyleNo: Integer;
- procedure MouseMove(Shift: TShiftState; X, Y: Integer); override;
- procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);override;
- procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);override;
- function CancelResize: Boolean;
- procedure AdjustMouseUpSelection; override;
- procedure ResizeItem(ItemNo, Width, Height: Integer);
- procedure XorDrawing; override;
- procedure MarkStylesInUse(Data: TRVDeleteUnusedStylesData); override;
- function InsertFirstRVFItem(var Index: Integer; var s: String;
- var li: TCustomRVItemInfo; EditFlag: Boolean; var FullReformat: Boolean;
- var NewListNo: Integer): Boolean; override;
- function GetUndoList: TRVUndoList;
- procedure Change;
- procedure ChangeEx(ClearRedo: Boolean);
- procedure DoOnSelection(AllowScrolling: Boolean); override;
- procedure CreateResizer;
- procedure UpdateResizer;
- procedure DoCurrentTextStyleConversion(var StyleNo: Integer;
- ParaStyleNo, ItemNo, UserData: Integer; ToWholeParagraphs: Boolean); override;
- procedure Do_ReformateRange(StartNo, EndNo: Integer; SuperReformat: Boolean);
- procedure Do_DeleteItem(ItemNo: Integer; var FullReformat: Boolean);
- procedure Do_InsertItem(ItemNo: Integer; var s: String; item: TCustomRVItemInfo; FromUndo: Boolean;
- var FullReformat: Boolean);
- procedure Do_ReplaceItem(ItemNo: Integer; item: TCustomRVItemInfo);
- procedure Do_DeleteItems(StartItemNo, EndItemNo: Integer; var FullReformat: Boolean);
- procedure Do_InsertItems(ItemNo: Integer; sl: TStringList; FromUndo: Boolean;
- var FullReformat: Boolean);
- procedure Do_ModifyItem(ItemNo: Integer; const s: String; Item: TCustomRVItemInfo);
- function Do_InsertItems_1(ItemNo,Count: Integer): TRVUndoInsertItemsInfo;
- procedure Do_InsertItems_2(ItemNo,Count: Integer; ui: TRVUndoInsertItemsInfo;
- var FullReformat: Boolean);
- procedure Do_DeleteSubstring(ItemNo, Index, ALength: Integer);
- procedure Do_InsertSubstring(ItemNo, Index: Integer; const s: String);
- procedure Do_NewLine(ItemNo: Integer; SameAsPrev: Boolean; ParaNo: Integer;
- var FullReformat: Boolean);
- procedure Do_BR(ItemNo: Integer; BR: Boolean; var FullReformat: Boolean);
- procedure Do_PageBreak(ItemNo: Integer; PageBreak: Boolean);
- procedure Do_ExtraIntProperty(ItemNo: Integer; Prop: TRVExtraItemProperty;
- Value: Integer);
- procedure Do_ExtraStrProperty(ItemNo: Integer; Prop: TRVExtraItemStrProperty;
- const Value: String);
- procedure Do_Concate(FirstItemNo: Integer);
- procedure Do_MoveCP(SrcItemNo, DestItemNo: Integer);
- function Do_Para(FirstItemNo, EndItemNo, ParaNo: Integer;
- var FullReformat: Boolean): Boolean;
- function Do_ParaList(FirstItemNo: Integer; ParaList: TRVIntegerList;
- var FullReformat: Boolean): Boolean;
- procedure Do_StyleNo(ItemNo, StyleNo: Integer);
- procedure Do_AssociatedTextStyleNo(ItemNo, TextStyleNo: Integer);
- procedure Do_Tag(ItemNo, Tag: Integer; AssignAsIs: Boolean);
- procedure Do_AddCP(ItemNo: Integer; Checkpoint: TRVCPInfo);
- procedure Do_DeleteCP(ItemNo: Integer);
- procedure Do_ChangeText(ItemNo: Integer; const s: String);
- procedure Do_ChangeVAlign(ItemNo: Integer; VAlign: TRVVAlign);
- procedure Do_Resize(ItemNo: Integer; Width, Height: Integer;Reformat: Boolean);
- procedure Do_ItemModifyTerminator(ItemNo: Integer; Opening: Boolean);
- function Do_ModifyItemIntProperty(ItemNo: Integer;
- SubObject: TObject;
- const PropertyName: String;
- Value: LongInt;
- AffectSize, AffectWidth: Boolean;
- UndoInfoClass: TRVUndoInfoClass):TRVUndoModifyItemProps;
- function Do_ModifyItemIntProperties(ItemNo: Integer;
- SubObject: TObject;
- PropList: TStringList;
- AffectSize, AffectWidth: Boolean;
- UndoInfoClass: TRVUndoInfoClass):TRVUndoModifyItemProps;
- procedure BeginUndoSequence(UndoType: TRVUndoType; AllowFinalize: Boolean);
- procedure SetUndoGroupMode(GroupUndo: Boolean);
- procedure FinalizeUndoGroup;
- procedure BeginNamedUndoSequence(UndoType: TRVUndoType; const Caption: String;
- AllowFinalize: Boolean);
- procedure EndUndoSequence;
- procedure BeginRedoSequence(UndoType: TRVUndoType; const Caption: String);
- procedure GetSelectionBoundsEx(var StartItemNo, StartItemOffs, EndItemNo,
- EndItemOffs: Integer; Normalize: Boolean); override;
- procedure GetSelBounds(var StartNo, EndNo, StartOffs, EndOffs: Integer;
- Normalize: Boolean); override;
- procedure Clear; override;
- procedure PrepareForEdit;
- function DeleteSelection_: Boolean;
- function CanDelete: Boolean;
- procedure InsertTextTyping(text: String; Key: Char);
- procedure InsertText_(const text: String; AutoTag, CaretBefore: Boolean);
- procedure InsertTextW_(const text: String; AutoTag, CaretBefore: Boolean);
- function OnEnterPress_(Shift: Boolean; Recursive: Boolean): Boolean;
- procedure OnDeletePress_(Ctrl: Boolean; MovedFromLineEnd: Boolean);
- procedure OnBackSpacePress_(Ctrl: Boolean; MultiDelete, FromNextLine: Boolean);
- procedure SetCurTextStyleNo(Value: Integer);
- procedure SetCurParaStyleNo(Value: Integer);
- procedure ClearTemporal; override;
- procedure ApplyParaStyle(ParaStyleNo: Integer; ConvType: TRVEStyleConversionType);
- function OnHomePress(Ctrl: Boolean): Boolean;
- function OnDownPress(Shift, Ctrl: Boolean): Boolean;
- function OnEndPress(Ctrl: Boolean): Boolean;
- function OnLeftPress(Shift, Ctrl: Boolean): Boolean;
- function OnPgDownPress: Boolean;
- function OnPgUpPress: Boolean;
- function OnRightPress(Shift, Ctrl: Boolean): Boolean;
- function OnUpPress(Shift,Ctrl: Boolean): Boolean;
- procedure MoveCaretToTheBeginningOfThePrevParagraph;
- procedure MoveCaretToTheEndOfTheNextParagraph;
- procedure ChangeCaret(ForceCreate, ScrollToCaret, DontChangeStyle, RefreshBefore: Boolean);
- function BuildJumpsCoords(IgnoreReadOnly: Boolean): Integer; dynamic;
- procedure ClearJumpsCoords; dynamic;
- procedure Format_(OnlyResized,ForceFormat,NoScroll: Boolean; depth: Integer;
- Canvas: TCanvas; OnlyTail, NoCaching, Reformatting: Boolean); override;
- procedure GetSelStart(var DINo, DIOffs: Integer);override;
- procedure SrchSelectIt(strt, offs, len: Integer; Invert: Boolean);override;
- procedure SrchStart(Down: Boolean; var strt, offs: Integer);override;
- function GetCurItemNo: Integer;
- function GetOffsetInCurItem: Integer;
- function InsertSomething(info: TCustomRVItemInfo; var s: String;
- AutoTag, CaretBefore: Boolean): Boolean;
- function NotFormatted: Boolean;
- procedure StartShiftMoving;
- procedure EndShiftMoving;
- procedure ApplyStyleConversion_(UserData: Integer;
- ConvType: TRVEStyleConversionType; ApplyToWholeParas: Boolean);
- function InsertRVFFromStreamEd_(Stream: TStream): Boolean;
- procedure OnChangeCaretLine(DLOffs: Integer);
- procedure ConcateAfterAdding(var InsertPoint, LastInserted, ItemsAdded, Offs: Integer);
- {$IFNDEF RVDONOTUSERTFIMPORT}
- function InsertRTFFromStreamEd_(Stream: TStream): Boolean;
- {$ENDIF}
- {$IFNDEF RVDONOTUSERTF}
- function SaveRTFToStream(Stream: TStream; const Path: String; SelectionOnly: Boolean;
- Level: Integer; Color: TColor; Background: TRVBackground; ColorList: TRVColorList;
- StyleToFont, ListOverrideOffsetsList1, ListOverrideOffsetsList2: TRVIntegerList;
- FontTable: TRVRTFFontTable; tpp: Double):Boolean; override;
- {$ENDIF}
- function InsertTextFromStream(Stream: TStream; OEM, AutoTag: Boolean): Boolean;
- function InsertTextFromStreamW(Stream: TStream; AutoTag: Boolean): Boolean;
- function InsertTextFromFile(const FileName: String; OEM, AutoTag: Boolean): Boolean;
- function InsertTextFromFileW(const FileName: String; AutoTag: Boolean): Boolean;
- procedure KeyPress(var Key: Char);
- procedure AdjustControlPlacement(ItemNo: Integer);
- procedure ResizeControl(ItemNo, NewWidth, NewHeight: Integer; Reformat: Boolean);
- procedure Reformat(FullFormat,ForceFormat, NoScroll: Boolean; ItemNo: Integer; UpdateView: Boolean);
- procedure Reformat_(FullFormat: Boolean; StartDrawItem, EndDrawItem, ItemsAdded: Integer);
- procedure BeginItemModify(ItemNo: Integer; var ModifyData: Integer);
- procedure EndItemModify(ItemNo: Integer; ModifyData: Integer);
- procedure SelectCurrentWord;
- procedure InsertPageBreak;
- {$IFNDEF RVDONOTUSEHTML}
- function SaveHTMLToStreamEx(Stream: TStream;
- const Path, Title, ImagesPrefix, ExtraStyles, ExternalCSS, CPPrefix: String;
- Options: TRVSaveOptions; Color: TColor; var CurrentFileColor: TColor;
- var imgSaveNo: Integer;
- LeftMargin, TopMargin, RightMargin, BottomMargin: Integer;
- Background: TRVBackground; Bullets: TRVList): Boolean; override;
- function SaveHTMLToStream(Stream: TStream; const Path, Title,
- ImagesPrefix: String; Options: TRVSaveOptions; Color: TColor;
- var imgSaveNo: Integer;
- LeftMargin, TopMargin, RightMargin, BottomMargin: Integer;
- Background: TRVBackground; Bullets: TRVList): Boolean; override;
- {$ENDIF}
- function GetIMEWinCoord: TPoint;
- {$IFNDEF RVDONOTUSELISTS}
- procedure UpdateAfterMarkers(FirstItemNo, LastMarkerIndex: Integer;
- ListNos: TRVIntegerList; ListNo: Integer);
- procedure PrepareForUpdateRangeAfterMarkers(StartNo, EndNo: Integer;
- ForDeletion: Boolean;
- var FirstItemNo, LastMarkerIndex: Integer; var ListNos: TRVIntegerList);
- procedure UpdateRangeAfterMarkers(StartNo, EndNo: Integer);
- procedure ApplyListStyle_(AListNo, AListLevel, AStartFrom: Integer;
- AUseStartFrom, ARecursive: Boolean; Operation: TRVParaListOperation;
- var ItemsAdded, StartNo, EndNo, SelStartNo, SelEndNo: Integer;
- ListNos: TRVIntegerList; var LastVWMarkerIndex: Integer);
- procedure ApplyListStyle(AListNo, AListLevel, AStartFrom: Integer;
- AUseStartFrom, ARecursive: Boolean; Operation: TRVParaListOperation);
- {$ENDIF}
- constructor Create(RichView: TRVScroller); override;
- destructor Destroy; override;
- end;
- const RichViewEditCaretWidth: Integer = 1;
- RichViewEditCaretHeightExtra: Integer = 0;
- RichViewEditMaxCaretHeight: Integer = 1000;
- RichViewEditDefaultProportionalResize: Boolean = True;
- RichViewEditEnterAllowsEmptyMarkeredLines: Boolean = False;
- implementation
- uses RVStr
- {$IFNDEF RVDONOTUSELISTS}
- , RVMarker, RVCtrlData
- {$ENDIF}
- ;
- {==============================================================================}
- function RV_CreateTextCopy(li: TRVTextItemInfo;
- RVData: TCustomRVData): TRVTextItemInfo;
- begin
- Result := RichViewTextItemClass.Create(RVData);
- with Result do begin
- Assign(li);
- ItemOptions := [];
- SameAsPrev := li.SameAsPrev;
- {$IFNDEF RVDONOTUSEUNICODE}
- if rvioUnicode in li.ItemOptions then
- Include(ItemOptions,rvioUnicode);
- {$ENDIF}
- Tag := RV_CopyTag(li.Tag, rvoTagsArePChars in RVData.Options);
- Checkpoint := nil;
- end;
- end;
- {================================== TRVCharPos ================================}
- constructor TRVCharPos.Create(Owner: TCollection);
- begin
- inherited Create(Owner);
- X := 0;
- DrawItemNo := -1;
- Offset := -1;
- end;
- {------------------------------------------------------------------------------}
- procedure TRVCharPos.Assign(Source: TPersistent);
- begin
- if Source is TRVCharPos then begin
- X := TRVCharPos(Source).X;
- DrawItemNo := TRVCharPos(Source).DrawItemNo;
- Offset := TRVCharPos(Source).Offset;
- end;
- end;
- {============================= TRVCharPosCollection ===========================}
- function TRVCharPosCollection.GetItem(Index: Integer): TRVCharPos;
- begin
- Result := TRVCharPos(inherited GetItem(Index));
- end;
- {------------------------------------------------------------------------------}
- procedure TRVCharPosCollection.SetItem(Index: Integer;
- const Value: TRVCharPos);
- begin
- inherited SetItem(Index, Value);
- end;
- {================================= TRVEditRVData ==============================}
- constructor TRVEditRVData.Create(RichView: TRVScroller);
- begin
- inherited Create(RichView);
- CharEnds := TRVCharPosCollection.Create(TRVCharPos);
- CaretDrawItemNo := -1;
- CaretOffs := -1;
- CaretHeight := 0;
- FCurTextStyleNo := 0;
- FCurParaStyleNo := 0;
- FPrevTextStyleNo := 0;
- UndoList := TRVUndoList.Create(TCustomRVFormattedData(Self.GetAbsoluteRootData));
- RedoList := TRVUndoList.Create(TCustomRVFormattedData(Self.GetAbsoluteRootData));
- TabNavigation := rvtnNone;
- end;
- {------------------------------------------------------------------------------}
- destructor TRVEditRVData.Destroy;
- begin
- CharEnds.Free;
- UndoList.Free;
- RedoList.Free;
- CharEnds := nil;
- UndoList := nil;
- RedoList := nil;
- inherited Destroy;
- end;
- {------------------------------------------------------------------------------}
- procedure TRVEditRVData.ClearTemporal;
- begin
- if CharEnds<>nil then
- CharEnds.Clear;
- CaretDrawItemNo := -1;
- CaretOffs := -1;
- FResizer.Free;
- FResizer := nil;
- ClearCurTag;
- Exclude(State, rvstDoNotClearCurTag);
- inherited ClearTemporal;
- end;
- {------------------------------------------------------------------------------}
- procedure TRVEditRVData.Clear;
- begin
- inherited Clear;
- if RichView<>nil then
- TCustomRichViewEdit(RichView).Modified := False;
- if UndoList<>nil then
- UndoList.Clear;
- if RedoList<>nil then
- RedoList.Clear;
- FPrevTextStyleNo := 0;
- SetCurTextStyleNo(0);
- SetCurParaStyleNo(0);
- Include(State, rvstEditorUnformatted);
- end;
- {------------------------------------------------------------------------------}
- function TRVEditRVData.GetUndoList: TRVUndoList;
- begin
- case UndoDest of
- udUndo:
- begin
- if UndoList.Limit<>0 then
- Result := UndoList
- else
- Result := nil;
- end;
- udRedo:
- Result := RedoList;
- else
- Result := nil;
- end;
- end;
- {------------------------------------------------------------------------------}
- procedure TRVEditRVData.BeginRedoSequence(UndoType: TRVUndoType; const Caption: String);
- begin
- if RedoList.BeginItem(UndoType, Caption, GetCurItemNo, GetOffsetInCurItem) then
- UndoDest := udRedo
- else
- UndoDest := udNone;
- end;
- {------------------------------------------------------------------------------}
- procedure TRVEditRVData.FinalizeUndoGroup;
- begin
- if not (rvstFinalizingUndo in State) then begin
- State := State + [rvstFinalizingUndo];
- try
- if FPartialSelectedItem<>nil then
- FPartialSelectedItem.FinalizeUndoGroup
- else if GetChosenItem<>nil then
- GetChosenItem.FinalizeUndoGroup;
- finally
- State := State - [rvstFinalizingUndo];
- end;
- end;
- end;
- {------------------------------------------------------------------------------}
- procedure TRVEditRVData.BeginUndoSequence(UndoType: TRVUndoType; AllowFinalize: Boolean);
- begin
- if AllowFinalize then
- FinalizeUndoGroup;
- if UndoList.BeginItem(UndoType, '', GetCurItemNo, GetOffsetInCurItem) then
- UndoDest := udUndo
- else
- UndoDest := udNone;
- end;
- {------------------------------------------------------------------------------}
- procedure TRVEditRVData.BeginNamedUndoSequence(UndoType: TRVUndoType; const Caption: String;
- AllowFinalize: Boolean);
- begin
- if AllowFinalize then
- FinalizeUndoGroup;
- if UndoList.BeginItem(UndoType, Caption, GetCurItemNo, GetOffsetInCurItem) then
- UndoDest := udUndo
- else
- UndoDest := udNone;
- end;
- {------------------------------------------------------------------------------}
- procedure TRVEditRVData.SetUndoGroupMode(GroupUndo: Boolean);
- begin
- if GroupUndo then
- inc(UndoList.GroupModeCount)
- else
- dec(UndoList.GroupModeCount);
- end;
- {------------------------------------------------------------------------------}
- procedure TRVEditRVData.EndUndoSequence;
- begin
- UndoList.EndItem;
- end;
- {------------------------------------------------------------------------------}
- function TRVEditRVData.GetParaEndItemNo(ItemNo: Integer): Integer;
- begin
- Result := ItemNo+1;
- while Result<Items.Count do begin
- if GetItem(Result).CanBeBorderStart then break;
- inc(Result)
- end;
- dec(Result);
- end;
- {------------------------------------------------------------------------------}
- function TRVEditRVData.SetParaStyle(StartItemNo, EndItemNo, ParaNo: Integer;
- var FullReformat: Boolean): Boolean;
- var i: Integer;
- NewWidth, OldWidth: Integer;
- item : TCustomRVItemInfo;
- begin
- Result := False;
- OldWidth := CalculateParaSectionsMinWidthDef(StartItemNo, EndItemNo);
- for i := StartItemNo to EndItemNo do begin
- item := GetItem(i);
- if (item.ParaNo<>ParaNo) and
- (not (rvpaoStyleProtect in GetRVStyle.ParaStyles[item.ParaNo].Options) or
- ((i>0) and (item.SameAsPrev or item.BR) and (GetItemPara(i-1)=ParaNo)))
- then begin
- item.ParaNo := ParaNo;
- Result := True;
- end;
- end;
- if Result then begin
- NewWidth := CalculateParaSectionsMinWidthDef(StartItemNo, EndItemNo);
- FullReformat := {(OldWidth<>NewWidth) and}
- ((NewWidth>DocumentWidth) or
- (OldWidth>=DocumentWidth));
- end
- else
- FullReformat := False;
- end;
- {------------------------------------------------------------------------------}
- procedure TRVEditRVData.Do_ItemModifyTerminator(ItemNo: Integer; Opening: Boolean);
- var ui: TRVUndoModifyItemTerminator;
- List: TRVUndoList;
- begin
- List := GetUndoList;
- if List<>nil then begin
- ui := TRVUndoModifyItemTerminator.Create;
- ui.ItemNo := ItemNo;
- ui.Opening := Opening;
- List.AddInfo(ui);
- end;
- end;
- {------------------------------------------------------------------------------}
- procedure TRVEditRVData.Do_ReformateRange(StartNo, EndNo: Integer;
- SuperReformat: Boolean);
- var ui: TRVUndoReformateRange;
- List: TRVUndoList;
- begin
- List := GetUndoList;
- if List<>nil then begin
- ui := TRVUndoReformateRange.Create;
- ui.Action := rvuMisc;
- ui.ItemNo := StartNo;
- ui.LastAffectedItemNo := EndNo;
- ui.SuperReformat := SuperReformat;
- List.AddInfo(ui);
- end;
- end;
- {------------------------------------------------------------------------------}
- procedure TRVEditRVData.Do_DeleteItem(ItemNo: Integer; var FullReformat: Boolean);
- var ui: TRVUndoDeleteItemInfo;
- item: TCustomRVItemInfo;
- List: TRVUndoList;
- LastAffectedItemNo: Integer;
- FR: Boolean;
- begin
- item := GetItem(ItemNo);
- FullReformat := CalculateMinItemWidthPlusEx(ItemNo)=DocumentWidth;
- if item.Checkpoint<>nil then
- Do_DeleteCP(ItemNo);
- if False and (ItemNo>0) and item.CanBeBorderStart then
- LastAffectedItemNo := GetParaEndItemNo(ItemNo)
- else
- LastAffectedItemNo := -1;
- List := GetUndoList;
- if List<>nil then begin
- ui := TRVUndoDeleteItemInfo.Create;
- ui.Action := rvuDeleteItem;
- ui.Item := item;
- //!!ui.RVData := Self;
- ui.ItemNo := ItemNo;
- ui.LastAffectedItemNo := LastAffectedItemNo;
- ui.s := Items[ItemNo];
- List.AddInfo(ui);
- item.MovingToUndoList(ItemNo, Self, ui);
- end
- else begin
- FreeItem(ItemNo, False);
- end;
- Items.Delete(ItemNo);
- if (LastAffectedItemNo<>-1) then begin
- Do_Para(ItemNo, LastAffectedItemNo-1,
- GetItem(ItemNo-1).ParaNo, FR);
- FullReformat := FR or FullReformat;
- end;
- end;
- {------------------------------------------------------------------------------}
- procedure TRVEditRVData.Do_ModifyItem(ItemNo: Integer; const s: String;
- Item: TCustomRVItemInfo);
- var ui: TRVUndoModifyItemInfo;
- OldItem: TCustomRVItemInfo;
- List: TRVUndoList;
- begin
- OldItem := GetItem(ItemNo);
- Item.Checkpoint := OldItem.Checkpoint;
- if Item.Checkpoint<>nil then
- Item.Checkpoint.ItemInfo := Item;
- OldItem.Checkpoint := nil;
- if (rvoTagsArePChars in Options) and (Item.Tag=OldItem.Tag) then
- Item.Tag := RV_CopyTag(OldItem.Tag,rvoTagsArePChars in Options);
- Item.ParaNo := OldItem.ParaNo;
- Item.ItemOptions := OldItem.ItemOptions;
- Item.JumpID := OldItem.JumpID;
- Item.DrawItemNo := OldItem.DrawItemNo;
- Item.TransferProperties(OldItem, Self);
- if FActiveItem=OldItem then
- FActiveItem := Item;
- if FPartialSelectedItem=OldItem then
- FPartialSelectedItem := Item;
- List := GetUndoList;
- if List<>nil then begin
- ui := TRVUndoModifyItemInfo.Create;
- ui.Action := rvuModifyItem;
- ui.Item := OldItem;
- //!!ui.RVData := Self;
- ui.ItemNo := ItemNo;
- ui.s := Items[ItemNo];
- //OldItem.MovingToUndoList;
- List.AddInfo(ui);
- end
- else begin
- InternalFreeItem(OldItem, False); // never called for controls
- end;
- Items[ItemNo] := s;
- Items.Objects[ItemNo] := Item;
- end;
- {------------------------------------------------------------------------------}
- procedure TRVEditRVData.Do_DeleteItems(StartItemNo, EndItemNo: Integer; var FullReformat: Boolean);
- var i: Integer;
- item: TCustomRVItemInfo;
- List: TRVUndoList;
- ui: TRVUndoDeleteItemsInfo;
- LastAffectedItemNo: Integer;
- FR: Boolean;
- begin
- FullReformat := False;
- if StartItemNo>EndItemNo then exit;
- FullReformat := CalculateMinItemsWidthPlusEx(StartItemNo, EndItemNo)=DocumentWidth;
- for i := EndItemNo downto StartItemNo do begin
- item := GetItem(i);
- if item.Checkpoint<>nil then
- Do_DeleteCP(i);
- end;
- if False and (StartItemNo>0) then
- LastAffectedItemNo := GetParaEndItemNo(EndItemNo)
- else
- LastAffectedItemNo := -1;
- List := GetUndoList;
- if List<>nil then begin
- ui := TRVUndoDeleteItemsInfo.Create;
- ui.Action := rvuDeleteItems;
- ui.StartItemNo := StartItemNo;
- ui.LastAffectedItemNo := LastAffectedItemNo;
- List.AddInfo(ui);
- for i := EndItemNo downto StartItemNo do begin
- item := GetItem(i);
- ui.List.AddObject(Items[i],item);
- item.MovingToUndoList(i, Self, ui);
- Items.Delete(i);
- end;
- end
- else begin
- for i := EndItemNo downto StartItemNo do begin
- FreeItem(i, False);
- Items.Delete(i);
- end;
- end;
- if (LastAffectedItemNo<>-1) then begin
- Do_Para(StartItemNo,LastAffectedItemNo-(EndItemNo-StartItemNo+1),
- GetItemPara(StartItemNo-1), FR);
- FullReformat := FullReformat or FR;
- end;
- end;
- {------------------------------------------------------------------------------}
- procedure TRVEditRVData.Do_DeleteSubstring(ItemNo, Index,ALength: Integer);
- var s: String;
- List: TRVUndoList;
- ui: TRVUndoDeleteSubstringInfo;
- begin
- s := Items[ItemNo];
- if ALength=-1 then
- ALength := RVU_Length(s,GetItemOptions(ItemNo))-Index+1;
- if ALength=0 then exit;
- List := GetUndoList;
- if List<>nil then begin
- ui := TRVUndoDeleteSubstringInfo.Create;
- ui.Action := rvuDeleteSubstring;
- ui.ItemNo := ItemNo;
- ui.Index := Index;
- ui.s := RVU_Copy(Items[ItemNo],Index, ALength, GetItemOptions(ItemNo));
- List.AddInfo(ui);
- end;
- RVU_Delete(s, Index, ALength, GetItemOptions(ItemNo));
- ItemAction(rviaTextModifying, GetItem(ItemNo), s, Self);
- Items[ItemNo] := s;
- end;
- {------------------------------------------------------------------------------}
- function TRVEditRVData.Do_Para(FirstItemNo, EndItemNo, ParaNo: Integer;
- var FullReformat: Boolean): Boolean;
- var List: TRVUndoList;
- ui: TRVUndoParaListInfo;
- i: Integer;
- begin
- Result := False;
- FullReformat := False;
- if EndItemNo<FirstItemNo then
- exit;
- List := GetUndoList;
- if List<>nil then begin
- ui := TRVUndoParaListInfo.Create;
- ui.Action := rvuPara;
- ui.StartItemNo := FirstItemNo;
- for i := FirstItemNo to EndItemNo do
- ui.List.Add(GetItemPara(i));
- List.AddInfo(ui);
- end;
- Result := SetParaStyle(FirstItemNo, EndItemNo, ParaNo, FullReformat);
- end;
- {------------------------------------------------------------------------------}
- function TRVEditRVData.Do_ParaList(FirstItemNo: Integer; ParaList: TRVIntegerList;
- var FullReformat: Boolean): Boolean;
- var List: TRVUndoList;
- ui: TRVUndoParaInfo;
- i: Integer;
- NewWidth, OldWidth: Integer;
- begin
- Result := False;
- FullReformat := False;
- if ParaList.Count=0 then
- exit;
- List := GetUndoList;
- if List<>nil then begin
- ui := TRVUndoParaInfo.Create;
- ui.Action := rvuPara;
- ui.ItemNo := FirstItemNo;
- ui.Count := ParaList.Count;
- ui.ParaNo := GetItemPara(FirstItemNo);
- for i := 0 to ParaList.Count-1 do
- if not GetItem(FirstItemNo+i).GetBoolValue(rvbpFullWidth) then begin
- ui.ParaNo := GetItemPara(FirstItemNo+i);
- break;
- end;
- List.AddInfo(ui);
- end;
- OldWidth := CalculateMinItemsWidthPlusEx(FirstItemNo, FirstItemNo+ParaList.Count-1);
- for i := 0 to ParaList.Count-1 do
- if GetItem(FirstItemNo+i).ParaNo<>ParaList[i] then begin
- GetItem(FirstItemNo+i).ParaNo := ParaList[i];
- Result := True;
- end;
- NewWidth := CalculateMinItemsWidthPlusEx(FirstItemNo, FirstItemNo+ParaList.Count-1);
- FullReformat := (OldWidth<>NewWidth) and
- ((NewWidth>DocumentWidth) or
- (OldWidth>=DocumentWidth));
- end;
- {------------------------------------------------------------------------------}
- procedure TRVEditRVData.Do_StyleNo(ItemNo, StyleNo: Integer);
- var List: TRVUndoList;
- ui: TRVUndoStyleNoInfo;
- item :TCustomRVItemInfo;
- begin
- item := GetItem(ItemNo);
- if (item.StyleNo<0) or (item.StyleNo=StyleNo) then
- exit;
- List := GetUndoList;
- if List<>nil then begin
- ui := TRVUndoStyleNoInfo.Create;
- ui.Action := rvuStyleNo;
- ui.ItemNo := ItemNo;
- ui.WasStyleNo := item.StyleNo;
- List.AddInfo(ui);
- end;
- {$IFNDEF RVDONOTUSEUNICODE}
- if GetRVStyle.TextStyles[GetActualStyle(item)].Unicode then begin
- if not GetRVStyle.TextStyles[GetActualStyle2(StyleNo, item.ParaNo)].Unicode then
- Exclude(item.ItemOptions, rvioUnicode)
- end
- else begin
- if GetRVStyle.TextStyles[GetActualStyle2(StyleNo,item.ParaNo)].Unicode then
- Include(item.ItemOptions, rvioUnicode)
- end;
- {$ENDIF}
- item.StyleNo := StyleNo;
- end;
- {------------------------------------------------------------------------------}
- procedure TRVEditRVData.Do_AssociatedTextStyleNo(ItemNo, TextStyleNo: Integer);
- var List: TRVUndoList;
- ui: TRVUndoAssociatedTextStyleNoInfo;
- item :TCustomRVItemInfo;
- begin
- item := GetItem(ItemNo);
- if item.AssociatedTextStyleNo=TextStyleNo then
- exit;
- List := GetUndoList;
- if List<>nil then begin
- ui := TRVUndoAssociatedTextStyleNoInfo.Create;
- ui.Action := rvuStyleNo;
- ui.ItemNo := ItemNo;
- ui.WasStyleNo := item.AssociatedTextStyleNo;
- List.AddInfo(ui);
- end;
- item.AssociatedTextStyleNo := TextStyleNo;
- end;
- {------------------------------------------------------------------------------}
- procedure TRVEditRVData.Do_InsertItem(ItemNo: Integer; var s: String;
- item: TCustomRVItemInfo; FromUndo: Boolean;
- var FullReformat: Boolean);
- var List: TRVUndoList;
- ui: TRVUndoInsertItemInfo;
- LastAffectedItemNo: Integer;
- Checkpoint: TRVCPInfo;
- begin
- FullReformat := False;
- if item.CanBeBorderStart and (ItemNo<Items.Count) and
- not GetItem(ItemNo).CanBeBorderStart then
- LastAffectedItemNo := GetParaEndItemNo(ItemNo)
- else
- LastAffectedItemNo := -1;
- Checkpoint := item.Checkpoint;
- item.Checkpoint := nil;
- List := GetUndoList;
- if List<>nil then begin
- ui := TRVUndoInsertItemInfo.Create;
- ui.Action := rvuInsertItem;
- ui.ItemNo := ItemNo;
- ui.LastAffectedItemNo := LastAffectedItemNo;
- List.AddInfo(ui);
- end;
- item.Inserting(Self, s, False);
- Items.InsertObject(ItemNo,s,item);
- item.Inserted(Self, ItemNo);
- {$IFNDEF RVDONOTUSELISTS}
- AddMarkerInList(ItemNo);
- {$ENDIF}
- if FromUndo then
- item.MovingFromUndoList(ItemNo, Self);
- item.UpdatePaletteInfo(GetDoInPaletteMode, False, GetRVPalette, GetRVLogPalette);
- if LastAffectedItemNo<>-1 then
- Do_Para(ItemNo+1,LastAffectedItemNo+1,item.ParaNo,FullReformat);
- //SetParaStyle(ItemNo+1,LastAffectedItemNo+1,item.ParaNo);
- if Checkpoint<>nil then
- Do_AddCP(ItemNo, Checkpoint);
- end;
- {------------------------------------------------------------------------------}
- procedure TRVEditRVData.Do_ReplaceItem(ItemNo: Integer; item: TCustomRVItemInfo);
- var List: TRVUndoList;
- ui: TRVUndoReplaceItemInfo;
- olditem :TCustomRVItemInfo;
- s: String;
- StyleNo: Integer;
- begin
- s := Items[ItemNo];
- olditem := GetItem(ItemNo);
- StyleNo := item.StyleNo;
- item.Assign(olditem);
- item.StyleNo := StyleNo;
- item.DrawItemNo := olditem.DrawItemNo;
- item.Tag := olditem.Tag;
- item.ItemOptions:= olditem.ItemOptions;
- item.JumpID := olditem.JumpID;
- item.Checkpoint := olditem.Checkpoint;
- if item.Checkpoint<>nil then
- item.Checkpoint.ItemInfo := item;
- olditem.Checkpoint := nil;
- olditem.Tag := 0;
- if olditem=CaptureMouseItem then
- ReleaseMouseCapture(olditem);
- if olditem=FActiveItem then
- FActiveItem := item;
- List := GetUndoList;
- if List<>nil then begin
- ui := TRVUndoReplaceItemInfo.Create;
- ui.Action := rvuModifyItem;
- ui.ItemNo := ItemNo;
- ui.item := olditem;
- olditem.MovingToUndoList(ItemNo, Self, ui);
- List.AddInfo(ui);
- end
- else
- FreeItem(ItemNo, False);
- item.Inserting(Self, s, False);
- Items.Objects[ItemNo] := item;
- item.Inserted(Self, ItemNo);
- end;
- {------------------------------------------------------------------------------}
- function TRVEditRVData.Do_InsertItems_1(ItemNo,Count: Integer):TRVUndoInsertItemsInfo;
- var List: TRVUndoList;
- ui: TRVUndoInsertItemsInfo;
- begin
- Result := nil;
- if Count=0 then
- exit;
- List := GetUndoList;
- if List<>nil then begin
- ui := TRVUndoInsertItemsInfo.Create;
- ui.Action := rvuInsertItems;
- ui.ItemNo := ItemNo;
- ui.Count := Count;
- List.AddInfo(ui);
- end
- else
- ui := nil;
- Result := ui;
- end;
- {------------------------------------------------------------------------------}
- procedure TRVEditRVData.Do_InsertItems_2(ItemNo,Count: Integer; ui: TRVUndoInsertItemsInfo;
- var FullReformat: Boolean);
- var i: Integer;
- Checkpoint: TRVCPInfo;
- item: TCustomRVItemInfo;
- LastAffectedItemNo: Integer;
- begin
- FullReformat := False;
- if Count=0 then exit;
- if (ItemNo+Count<Items.Count) and
- not GetItem(ItemNo+Count).CanBeBorderStart then
- LastAffectedItemNo := GetParaEndItemNo(ItemNo+Count-1)
- else
- LastAffectedItemNo := -1;
- if ui<>nil then begin
- ui.LastAffectedItemNo := LastAffectedItemNo;
- end;
- if LastAffectedItemNo<>-1 then
- Do_Para(ItemNo+Count-1,LastAffectedItemNo,
- GetItemPara(ItemNo+Count-1), FullReformat);
- for i := ItemNo to ItemNo+Count-1 do begin
- item := GetItem(i);
- if item.Checkpoint<>nil then begin
- Checkpoint := item.Checkpoint;
- item.Checkpoint := nil;
- Do_AddCP(i, Checkpoint);
- end;
- end;
- end;
- {------------------------------------------------------------------------------}
- // in rev. order
- procedure TRVEditRVData.Do_InsertItems(ItemNo: Integer; sl: TStringList; FromUndo: Boolean;
- var FullReformat: Boolean);
- var i: Integer;
- item: TCustomRVItemInfo;
- ui: TRVUndoInsertItemsInfo;
- s: String;
- begin
- FullReformat := False;
- if sl.Count=0 then exit;
- ui := Do_InsertItems_1(ItemNo, sl.Count);
- for i := 0 to sl.Count-1 do begin
- item := TCustomRVItemInfo(sl.Objects[i]);
- s := sl[i];
- item.Inserting(Self, s, False);
- Items.InsertObject(ItemNo, s, item);
- item.Inserted(Self, ItemNo);
- {$IFNDEF RVDONOTUSELISTS}
- AddMarkerInList(ItemNo);
- {$ENDIF}
- if FromUndo then
- item.MovingFromUndoList(ItemNo, Self);
- item.UpdatePaletteInfo(GetDoInPaletteMode, False, GetRVPalette, GetRVLogPalette);
- end;
- Do_InsertItems_2(ItemNo, sl.Count, ui, FullReformat);
- end;
- {------------------------------------------------------------------------------}
- procedure TRVEditRVData.Do_InsertSubstring(ItemNo, Index: Integer; const s: String);
- var str: String;
- List: TRVUndoList;
- ui: TRVUndoInsertSubstringInfo;
- begin
- if (Length(s)=0) then exit;
- if (ItemNo<0) or (ItemNo>=Items.Count) or
- (GetItemStyle(ItemNo)<0) then
- raise Exception.Create(errRVUndo);
- List := GetUndoList;
- if List<>nil then begin
- ui := TRVUndoInsertSubstringInfo.Create;
- ui.Action := rvuInsertSubstring;
- ui.ItemNo := ItemNo;
- ui.Index := Index;
- ui.Length := RVU_Length(s, GetItemOptions(ItemNo));
- List.AddInfo(ui);
- end;
- str := Items[ItemNo];
- RVU_Insert(s, str, Index, GetItemOptions(ItemNo));
- ItemAction(rviaTextModifying, GetItem(ItemNo), str, Self);
- Items[ItemNo] := str;
- end;
- {------------------------------------------------------------------------------}
- procedure TRVEditRVData.Do_ChangeText(ItemNo: Integer; const s: String);
- var List: TRVUndoList;
- ui: TRVUndoChangeTextInfo;
- str: String;
- begin
- if Items[ItemNo]=s then exit;
- List := GetUndoList;
- if List<>nil then begin
- ui := TRVUndoChangeTextInfo.Create;
- ui.Action := rvuChangeText;
- ui.ItemNo := ItemNo;
- ui.s := Items[ItemNo];
- List.AddInfo(ui);
- end;
- str := s;
- ItemAction(rviaTextModifying, GetItem(ItemNo), str, Self);
- Items[ItemNo] := str;
- end;
- {------------------------------------------------------------------------------}
- procedure TRVEditRVData.Do_ChangeVAlign(ItemNo: Integer; VAlign: TRVVAlign);
- var List: TRVUndoList;
- ui: TRVUndoChangeVAlignInfo;
- item: TCustomRVItemInfo;
- begin
- item := GetItem(ItemNo);
- if (item as TRVRectItemInfo).VAlign = VAlign then exit;
- List := GetUndoList;
- if List<>nil then begin
- ui := TRVUndoChangeVAlignInfo.Create;
- ui.Action := rvuChangeText;
- ui.ItemNo := ItemNo;
- ui.VAlign := TRVRectItemInfo(item).VAlign;
- List.AddInfo(ui);
- end;
- TRVRectItemInfo(item).Valign := VAlign;
- end;
- {------------------------------------------------------------------------------}
- procedure TRVEditRVData.Do_Resize(ItemNo, Width, Height: Integer;Reformat: Boolean);
- var List: TRVUndoList;
- ui: TRVUndoResizeInfo;
- item: TRVControlItemInfo;
- begin
- // for controls only
- item := TRVControlItemInfo(GetItem(ItemNo));
- if (item.Control.Width = Width) and
- (item.Control.Height = Height) then exit;
- List := GetUndoList;
- if List<>nil then begin
- ui := TRVUndoResizeInfo.Create;
- ui.Action := rvuModifyItem;
- ui.ItemNo := ItemNo;
- ui.Width := item.Control.Width;
- ui.Height := item.Control.Height;
- List.AddInfo(ui);
- end;
- ResizeControl(ItemNo, Width, Height, Reformat);
- end;
- {------------------------------------------------------------------------------}
- function TRVEditRVData.Do_ModifyItemIntProperty(ItemNo: Integer;
- SubObject: TObject;
- const PropertyName: String;
- Value: LongInt;
- AffectSize, AffectWidth: Boolean;
- UndoInfoClass: TRVUndoInfoClass):TRVUndoModifyItemProps;
- var List: TRVUndoList;
- ui: TRVUndoModifyItemIntProperty;
- item: TCustomRVItemInfo;
- propinfo: PPropInfo;
- OldValue:LongInt;
- begin
- Result := nil;
- item := GetItem(ItemNo);
- if SubObject=nil then
- SubObject := item;
- propinfo := GetPropInfo(SubObject.ClassInfo, PropertyName);
- OldValue := GetOrdProp(SubObject, propinfo);
- if OldValue=Value then exit;
- List := GetUndoList;
- if List<>nil then begin
- ui := TRVUndoModifyItemIntProperty(UndoInfoClass.Create);
- ui.Action := rvuModifyItem;
- ui.ItemNo := ItemNo;
- ui.PropertyName := PropertyName;
- ui.Value := OldValue;
- ui.AffectSize := AffectSize;
- ui.AffectWidth := AffectWidth;
- ui.SubObject := SubObject;
- List.AddInfo(ui);
- end
- else
- ui := nil;
- item.BeforeUndoChangeProperty;
- try
- SetOrdProp(SubObject, propinfo,Value);
- finally
- item.AfterUndoChangeProperty;
- end;
- Result := ui;
- end;
- {------------------------------------------------------------------------------}
- function TRVEditRVData.Do_ModifyItemIntProperties(ItemNo: Integer;
- SubObject: TObject; PropList: TStringList; AffectSize,
- AffectWidth: Boolean;
- UndoInfoClass: TRVUndoInfoClass):TRVUndoModifyItemProps;
- var List: TRVUndoList;
- ui: TRVUndoModifyItemIntProperties;
- item: TCustomRVItemInfo;
- propinfo: PPropInfo;
- i: Integer;
- OldValue, NewValue: LongInt;
- begin
- item := GetItem(ItemNo);
- if SubObject=nil then
- SubObject := item;
- List := GetUndoList;
- if List<>nil then begin
- ui := TRVUndoModifyItemIntProperties(UndoInfoClass.Create);
- ui.Action := rvuModifyItem;
- ui.ItemNo := ItemNo;
- ui.AffectSize := AffectSize;
- ui.AffectWidth := AffectWidth;
- ui.SubObject := SubObject;
- end
- else
- ui := nil;
- item.BeforeUndoChangeProperty;
- try
- for i := PropList.Count-1 downto 0 do begin
- propinfo := GetPropInfo(SubObject.ClassInfo, PropList[i]);
- OldValue := GetOrdProp(SubObject, propinfo);
- NewValue := LongInt(PropList.Objects[i]);
- if OldValue<>NewValue then begin
- if ui<>nil then
- ui.PropList.AddObject(PropList[i], TObject(OldValue));
- SetOrdProp(SubObject, propinfo, NewValue);
- end;
- end;
- finally
- item.AfterUndoChangeProperty;
- end;
- if ui<>nil then begin
- if ui.PropList.Count=0 then begin
- ui.Free;
- ui := nil;
- end
- else
- List.AddInfo(ui);
- end;
- Result := ui;
- end;
- {------------------------------------------------------------------------------}
- procedure TRVEditRVData.Do_NewLine(ItemNo: Integer; SameAsPrev: Boolean;
- ParaNo: Integer;
- var FullReformat: Boolean);
- var item: TCustomRVItemInfo;
- List: TRVUndoList;
- ui: TRVUndoNewLineInfo;
- LastAffectedItemNo: Integer;
- FR: Boolean;
- begin
- FullReformat := False;
- item := GetItem(ItemNo);
- if Item.GetBoolValue(rvbpFullWidth) then
- exit;
- if not SameAsPrev and (item.SameAsPrev = SameAsPrev) then exit;
- if SameAsPrev then begin
- Do_BR(ItemNo, False, FR);
- FullReformat := FullReformat or FR;
- Do_PageBreak(ItemNo, False);
- end;
- if (ItemNo<Items.Count-1) and
- not GetItem(ItemNo+1).CanBeBorderStart then
- LastAffectedItemNo := GetParaEndItemNo(ItemNo+1)
- else
- LastAffectedItemNo := -1;
- List := GetUndoList;
- if List<>nil then begin
- ui := TRVUndoNewLineInfo.Create;
- ui.Action := rvuNewLine;
- ui.ItemNo := ItemNo;
- ui.WasSameAsPrev := item.SameAsPrev;
- ui.WasParaNo := item.ParaNo;
- ui.LastAffectedItemNo := LastAffectedItemNo;
- List.AddInfo(ui);
- end;
- if LastAffectedItemNo=-1 then
- LastAffectedItemNo := ItemNo;
- if SameAsPrev then begin
- if ItemNo>0 then begin
- Do_Para(ItemNo,LastAffectedItemNo,
- GetItemPara(ItemNo-1), FR);
- FullReformat := FullReformat or FR;
- end
- end
- else begin
- if ParaNo<>-1 then begin
- Do_Para(ItemNo,LastAffectedItemNo, ParaNo, FR);
- FullReformat := FullReformat or FR;
- end;
- end;
- item.SameAsPrev := SameAsPrev;
- end;
- {------------------------------------------------------------------------------}
- procedure TRVEditRVData.Do_BR(ItemNo: Integer; BR: Boolean; var FullReformat: Boolean);
- var item: TCustomRVItemInfo;
- List: TRVUndoList;
- ui: TRVUndoBRInfo;
- OldWidth, NewWidth: Integer;
- begin
- FullReformat := False;
- item := GetItem(ItemNo);
- if item.SameAsPrev or item.BR=BR then
- exit;
- OldWidth := CalculateMinItemWidthPlusEx(ItemNo);
- List := GetUndoList;
- if List<>nil then begin
- ui := TRVUndoBRInfo.Create;
- ui.Action := rvuBR;
- ui.ItemNo := ItemNo;
- ui.WasBR := item.BR;
- List.AddInfo(ui);
- end;
- item.BR := BR;
- NewWidth := CalculateMinItemWidthPlusEx(ItemNo);
- FullReformat := (OldWidth<>NewWidth) and
- ((NewWidth>DocumentWidth) or
- (OldWidth>=DocumentWidth));
- end;
- {------------------------------------------------------------------------------}
- procedure TRVEditRVData.Do_PageBreak(ItemNo: Integer; PageBreak: Boolean);
- var item: TCustomRVItemInfo;
- List: TRVUndoList;
- ui: TRVUndoPageBreakInfo;
- begin
- {$IFNDEF RVDONOTUSELISTS}
- if (ItemNo>0) and (GetItemStyle(ItemNo-1)=rvsListMarker) then
- dec(ItemNo);
- {$ENDIF}
- item := GetItem(ItemNo);
- if item.SameAsPrev or item.PageBreakBefore=PageBreak then
- exit;
- List := GetUndoList;
- if List<>nil then begin
- ui := TRVUndoPageBreakInfo.Create;
- ui.Action := rvuPageBreak;
- ui.ItemNo := ItemNo;
- ui.WasPageBreak := item.PageBreakBefore;
- List.AddInfo(ui);
- end;
- item.PageBreakBefore := PageBreak;
- end;
- {------------------------------------------------------------------------------}
- procedure TRVEditRVData.Do_ExtraIntProperty(ItemNo: Integer;
- Prop: TRVExtraItemProperty; Value: Integer);
- var item: TCustomRVItemInfo;
- List: TRVUndoList;
- ui: TRVUndoExtraIntProperty;
- OldValue: Integer;
- begin
- item := GetItem(ItemNo);
- if not item.GetExtraIntProperty(Prop,OldValue) or (OldValue=Value) then
- exit;
- List := GetUndoList;
- if List<>nil then begin
- ui := TRVUndoExtraIntProperty.Create;
- ui.Action := rvuModifyItem;
- ui.ItemNo := ItemNo;
- ui.OldValue := OldValue;
- ui.Prop := Prop;
- List.AddInfo(ui);
- end;
- item.SetExtraIntProperty(Prop, Value);
- {$IFNDEF RVDONOTUSEANIMATION}
- if (Prop in [rvepAnimationInterval, rvepImageWidth, rvepImageHeight]) then
- item.UpdateAnimator(Self);
- {$ENDIF}
- end;
- {------------------------------------------------------------------------------}
- procedure TRVEditRVData.Do_ExtraStrProperty(ItemNo: Integer;
- Prop: TRVExtraItemStrProperty; const Value: String);
- var item: TCustomRVItemInfo;
- List: TRVUndoList;
- ui: TRVUndoExtraStrProperty;
- OldValue: String;
- begin
- item := GetItem(ItemNo);
- if not item.GetExtraStrProperty(Prop, OldValue) or (OldValue=Value) then
- exit;
- List := GetUndoList;
- if List<>nil then begin
- ui := TRVUndoExtraStrProperty.Create;
- ui.Action := rvuModifyItem;
- ui.ItemNo := ItemNo;
- ui.OldValue := OldValue;
- ui.Prop := Prop;
- List.AddInfo(ui);
- end;
- item.SetExtraStrProperty(Prop, Value);
- end;
- {------------------------------------------------------------------------------}
- procedure TRVEditRVData.Do_Tag(ItemNo, Tag: Integer; AssignAsIs: Boolean);
- var item: TCustomRVItemInfo;
- List: TRVUndoList;
- ui: TRVUndoTagInfo;
- begin
- item := GetItem(ItemNo);
- if Tag=item.Tag then exit;
- List := GetUndoList;
- if List<>nil then begin
- ui := TRVUndoTagInfo.Create;
- ui.Action := rvuTag;
- ui.ItemNo := ItemNo;
- ui.WasTag := RV_CopyTag(item.Tag, rvoTagsArePChars in Options);
- ui.TagsArePChars := rvoTagsArePChars in Options;
- List.AddInfo(ui);
- end;
- if rvoTagsArePChars in Options then
- StrDispose(PChar(item.Tag));
- if AssignAsIs then
- item.Tag := Tag
- else
- item.Tag := RV_CopyTag(Tag, rvoTagsArePChars in Options);
- end;
- {------------------------------------------------------------------------------}
- procedure TRVEditRVData.Do_AddCP(ItemNo: Integer; Checkpoint: TRVCPInfo);
- var item: TCustomRVItemInfo;
- List: TRVUndoList;
- ui: TRVUndoAddCPInfo;
- begin
- if ItemNo<>-1 then begin
- item := GetItem(ItemNo);
- if item.Checkpoint<>nil then
- raise ERichViewError.Create(errRVCP);
- end
- else begin
- item := nil;
- if NotAddedCP<>nil then
- raise ERichViewError.Create(errRVCP);
- end;
- if Checkpoint=nil then exit;
- List := GetUndoList;
- if List<>nil then begin
- ui := TRVUndoAddCPInfo.Create;
- ui.Action := rvuCheckpoint;
- ui.ItemNo := ItemNo;
- List.AddInfo(ui);
- end;
- if item<>nil then begin
- item.Checkpoint := Checkpoint;
- Checkpoint.ItemInfo := item;
- end
- else begin
- NotAddedCP := Checkpoint;
- Checkpoint.ItemInfo := nil;
- end;
- inc(CPCount);
- UpdateCPPos(Checkpoint, ItemNo);
- end;
- {------------------------------------------------------------------------------}
- procedure TRVEditRVData.Do_DeleteCP(ItemNo: Integer);
- var item: TCustomRVItemInfo;
- List: TRVUndoList;
- ui: TRVUndoDeleteCPInfo;
- CP: TRVCPInfo;
- begin
- if ItemNo<>-1 then begin
- item := GetItem(ItemNo);
- CP := item.Checkpoint;
- end
- else begin
- item := nil;
- CP := NotAddedCP;
- end;
- if CP=nil then
- raise ERichViewError.Create(errRVCP);
- List := GetUndoList;
- if List<>nil then begin
- ui := TRVUndoDeleteCPInfo.Create;
- ui.Action := rvuCheckpoint;
- ui.ItemNo := ItemNo;
- ui.Checkpoint := CP;
- ui.TagsArePChars := rvoTagsArePChars in Options;
- List.AddInfo(ui);
- UnlinkCheckpoint(CP,True);
- end
- else
- FreeCheckpoint(CP,True,True);
- if item<>nil then
- item.Checkpoint := nil
- else
- NotAddedCP := nil;
- end;
- {------------------------------------------------------------------------------}
- { Moving checkpoint (by copying-deleting) from the SrcItemNo-th item to
- the DestItemNo-th item }
- procedure TRVEditRVData.Do_MoveCP(SrcItemNo, DestItemNo: Integer);
- var CP: TRVCPInfo;
- begin
- if GetItemCheckpoint(SrcItemNo)<>nil then begin
- if GetItemCheckpoint(DestItemNo)<>nil then
- Do_DeleteCP(DestItemNo);
- CP := TRVCPInfo.Create;
- CP.Assign(GetItemCheckpoint(SrcItemNo), rvoTagsArePChars in Options);
- Do_AddCP(DestItemNo, CP);
- Do_DeleteCP(SrcItemNo);
- end;
- end;
- {------------------------------------------------------------------------------}
- procedure TRVEditRVData.Do_Concate(FirstItemNo: Integer);
- var // FullReformat,
- FR: Boolean;
- StyleNo: Integer;
- SAP, BR: Boolean;
- item: TCustomRVItemInfo;
- CP: TRVCPInfo;
- begin
- // FullReformat := False;
- if ((rvioUnicode in GetItemOptions(FirstItemNo))<>
- (rvioUnicode in GetItemOptions(FirstItemNo+1))) and
- (Items[FirstItemNo+1]<>'') then begin
- item := GetItem(FirstItemNo);
- BR := item.BR;
- SAP := item.SameAsPrev;
- if not SAP then begin
- Do_NewLine(FirstItemNo+1, False, item.ParaNo, FR);
- // FullReformat := FullReformat or FR;
- end;
- if BR then begin
- Do_BR(FirstItemNo+1, True, FR);
- // FullReformat := FullReformat or FR;
- end;
- if (GetItemCheckpoint(FirstItemNo)<>nil) and
- (GetItemCheckpoint(FirstItemNo+1)=nil) then begin
- CP := TRVCPInfo.Create;
- CP.Assign(GetItemCheckpoint(FirstItemNo), rvoTagsArePChars in Options);
- Do_AddCP(FirstItemNo+1, CP);
- end;
- Do_DeleteItem(FirstItemNo,FR);
- // FullReformat := FullReformat or FR;
- end
- else begin
- if Items[FirstItemNo]='' then begin
- StyleNo := GetItem(FirstItemNo+1).StyleNo;
- Do_Tag(FirstItemNo, GetItemTag(FirstItemNo+1), False);
- end
- else begin
- StyleNo := -1;
- end;
- Do_InsertSubstring(FirstItemNo, ItemLength(FirstItemNo)+1,Items[FirstItemNo+1]);
- if (GetItemCheckpoint(FirstItemNo+1)<>nil) and
- (GetItemCheckpoint(FirstItemNo)=nil) then begin
- CP := TRVCPInfo.Create;
- CP.Assign(GetItemCheckpoint(FirstItemNo+1), rvoTagsArePChars in Options);
- Do_AddCP(FirstItemNo, CP);
- end;
- Do_DeleteItem(FirstItemNo+1, FR);
- // FullReformat := FullReformat or FR;
- if StyleNo<>-1 then
- Do_StyleNo(FirstItemNo, StyleNo);
- end;
- // assuming FullReformat=False for text
- end;
- {------------------------------------------------------------------------------}
- function TRVEditRVData.InsSomething(var info: TCustomRVItemInfo;
- var s: String; AutoTag: Boolean; var InsertPoint, ItemsAdded: Integer;
- var FullReformat: Boolean; var NewListNo: Integer): Boolean;
- {.............................................................}
- procedure AdjustTag(cur: TCustomRVItemInfo);
- begin
- if AutoTag and (info.Tag=0) and (info.StyleNo>=0) and (info.StyleNo=cur.StyleNo) then
- info.Tag := RV_CopyTag(cur.Tag, rvoTagsArePChars in Options)
- end;
- {.............................................................}
- procedure SetTagToCurTag;
- begin
- if AutoTag and (info.Tag=0) and (info.StyleNo>=0) and
- (info.StyleNo=FCurTextStyleNo) then
- info.Tag := RV_CopyTag(FCurTag, rvoTagsArePChars in Options)
- end;
- {.............................................................}
- // Inserting before or after non-text item.
- // If inserting a full-line item before the first item in bulleted paragraph,
- // inserting a empty string before, so result will look like
- // {bullet} {empty string (added)}
- // {new full-line item}
- // Special case: marker can be inserted only in place of empty line,
- // not here
- procedure IS_InsertNearNonText(CharPos: TRVCharPos; dli: TRVDrawLineInfo;
- var ItemParaNo: Integer; var InsertPoint: Integer; var ItemsAdded: Integer;
- var FullReformat: Boolean);
- var FR: Boolean;
- begin
- {$IFNDEF RVDONOTUSELISTS}
- if info.StyleNo=rvsListMarker then begin
- Result := True;
- info.Free;
- info := nil;
- exit;
- end;
- {$ENDIF}
- if CharPos.Offset=0 then begin // inserting before nontext
- InsertPoint := dli.ItemNo;
- if not GetItem(InsertPoint).SameAsPrev then begin
- info.SameAsPrev := False;
- info.BR := GetItem(InsertPoint).BR;
- if info.BR then
- ItemParaNo := -1;
- if GetItem(InsertPoint).PageBreakBefore then
- info.PageBreakBefore := True;
- Do_NewLine(InsertPoint, True, -1, FR);
- FullReformat := FullReformat or FR;
- end
- else begin
- ItemParaNo := -1;
- {$IFNDEF RVDONOTUSELISTS}
- if (InsertPoint>0) and (GetItemStyle(InsertPoint-1)=rvsListMarker) and
- (info.GetBoolValue(rvbpFullWidth) or
- ((info.Checkpoint<>nil) and info.Checkpoint.Persistent and
- ItemHasPersistentCheckpoint(InsertPoint-1))) then begin
- InsEmptyString(InsertPoint, 0, GetItemPara(InsertPoint),
- FCurTextStyleNo, True, False);
- inc(InsertPoint);
- inc(ItemsAdded);
- end;
- {$ENDIF}
- end;
- end
- else begin // inserting after nontext
- ItemParaNo := -1;
- InsertPoint := dli.ItemNo+1;
- if GetItem(dli.ItemNo).GetBoolValue(rvbpFullWidth) then
- info.SameAsPrev := False;
- end;
- end;
- {.............................................................}
- // Replacing an empty line with new item
- // Exception: If inserting a full-line item in bulleted paragraph,
- // we do not replace empty string, but add new item after,
- // so result will look like:
- // {bullet} {old empty string}
- // {new full-line item}
- // Special case: if inserting marker, it deletes empty string and
- // replaces a marker before it (if exists)
- function IS_ReplaceEmptyText(CharPos: TRVCharPos;
- dli: TRVDrawLineInfo;
- var ItemParaNo: Integer;
- var InsertPoint: Integer;
- var ItemsAdded: Integer;
- var FullReformat: Boolean): Boolean;
- var curitem: TCustomRVItemInfo;
- FR: Boolean;
- {$IFNDEF RVDONOTUSELISTS}
- PrevMarkerItemNo: Integer;
- {$ENDIF}
- begin
- Result := False;
- if IsSticking(dli.ItemNo-1, False) or
- IsSticking(dli.ItemNo, False) then begin
- info.Free;
- info := nil;
- exit;
- end;
- {$IFNDEF RVDONOTUSELISTS}
- if (dli.ItemNo>0) and (GetItemStyle(dli.ItemNo-1)=rvsListMarker) and
- (info.GetBoolValue(rvbpFullWidth) or
- ((info.Checkpoint<>nil) and info.Checkpoint.Persistent and
- ParaHasPersistentCheckpoint(dli.ItemNo)))
- then
- InsertPoint := dli.ItemNo+1
- else
- {$ENDIF}
- begin
- curitem := GetItem(dli.ItemNo);
- {$IFNDEF RVDONOTUSELISTS}
- if (info.StyleNo=rvsListMarker) and (TRVMarkerItemInfo(info).ListNo>=0) and
- GetRVStyle.ListStyles[TRVMarkerItemInfo(info).ListNo].HasNumbering then begin
- if dli.ItemNo=rvsListMarker then
- PrevMarkerItemNo := dli.ItemNo
- else begin
- PrevMarkerItemNo := dli.ItemNo-1;
- if PrevMarkerItemNo>=0 then begin
- PrevMarkerItemNo := GetFirstParaItem(PrevMarkerItemNo);
- if (GetItemStyle(PrevMarkerItemNo)<>rvsListMarker) then
- PrevMarkerItemNo := -1;
- end;
- end;
- if (PrevMarkerItemNo>=0) and (TRVMarkerItemInfo(GetItem(PrevMarkerItemNo)).ListNo>=0) and
- GetRVStyle.ListStyles[TRVMarkerItemInfo(GetItem(PrevMarkerItemNo)).ListNo].IsSimpleEqual(
- GetRVStyle.ListStyles[TRVMarkerItemInfo(info).ListNo], True, True) then begin
- NewListNo := TRVMarkerItemInfo(GetItem(PrevMarkerItemNo)).ListNo;
- TRVMarkerItemInfo(info).ListNo := NewListNo;
- end;
- end;
- {$ENDIF}
- if not curitem.SameAsPrev then begin
- info.SameAsPrev := False;
- {$IFNDEF RVDONOTUSELISTS}
- if info.StyleNo<>rvsListMarker then
- {$ENDIF}
- info.BR := curitem.BR;
- end;
- if info.BR then
- ItemParaNo := -1;
- if curitem.PageBreakBefore then
- info.ItemOptions := info.ItemOptions+[rvioPageBreakBefore];
- Do_DeleteItem(dli.ItemNo, FR);
- FullReformat := FullReformat or FR;
- InsertPoint := dli.ItemNo;
- dec(ItemsAdded);
- info.ParaNo := FCurParaStyleNo;
- {$IFNDEF RVDONOTUSELISTS}
- if (info.StyleNo=rvsListMarker) and (InsertPoint>0) and
- (GetItemStyle(InsertPoint-1)=rvsListMarker) then begin
- dec(InsertPoint);
- Do_DeleteItem(InsertPoint, FR);
- FullReformat := FullReformat or FR;
- dec(ItemsAdded);
- end;
- {$ENDIF}
- end;
- Result := True;
- end;
- {.............................................................}
- // Inserting in text (before, after, or between)
- // Special case: a full-line item is never inserted before the first text
- // item in bulleted paragraph. In this case, it splits this text item into
- // two parts, one of them is empty:
- // {bullet} {empty string (added) }
- // {new full-line item} { string } { rest of paragraph }
- // Another special case: marker can be inserted only in place of empty line,
- // not here
- function IS_InsertInText(CharPos: TRVCharPos;
- dli: TRVDrawLineInfo;
- var ItemParaNo: Integer;
- var InsertPoint: Integer;
- var ItemsAdded: Integer;
- var FullReformat: Boolean): Boolean;
- var s2: String;
- newsubstr: TCustomRVItemInfo;
- FR: Boolean;
- begin
- {$IFNDEF RVDONOTUSELISTS}
- if info.StyleNo=rvsListMarker then begin
- Result := True;
- info.Free;
- info := nil;
- exit;
- end;
- {$ENDIF}
- Result := False;
- if (dli.Offs+CharPos.Offset-1<=1)
- {$IFNDEF RVDONOTUSELISTS}
- and not
- (((dli.ItemNo>0) and (GetItemStyle(dli.ItemNo-1)=rvsListMarker)) and
- (info.GetBoolValue(rvbpFullWidth) or
- ((info.Checkpoint<>nil) and info.Checkpoint.Persistent and
- ItemHasPersistentCheckpoint(dli.ItemNo-1))))
- {$ENDIF} then begin // inserting before text
- InsertPoint := dli.ItemNo;
- if IsSticking(InsertPoint-1, False) then begin
- info.Free;
- info := nil;
- exit;
- end;
- if not info.GetBoolValue(rvbpFullWidth) and not GetItem(InsertPoint).SameAsPrev then begin
- info.SameAsPrev := False;
- info.BR := GetItem(InsertPoint).BR;
- if info.BR then
- ItemParaNo := -1;
- Do_NewLine(InsertPoint, True, -1, FR);
- FullReformat := FullReformat or FR;
- end
- else
- ItemParaNo := -1;
- AdjustTag(GetItem(InsertPoint));
- end
- else if dli.Offs+CharPos.Offset-1>ItemLength(dli.ItemNo) then begin // inserting after text
- ItemParaNo := -1;
- InsertPoint := dli.ItemNo+1;
- if IsSticking(InsertPoint-1, False) then begin
- info.Free;
- info := nil;
- exit;
- end;
- AdjustTag(GetItem(InsertPoint-1));
- end
- else begin // inserting in text
- if IsProtected(dli.ItemNo, rvprModifyProtect) then begin
- info.Free;
- info := nil;
- exit;
- end;
- ItemParaNo := -1;
- inc(ItemsAdded);
- {$IFNDEF RVDONOTUSELIVESPELL}
- LaterSetBackLiveSpellingTo(dli.ItemNo, dli.Offs+CharPos.Offset-1, True);
- {$ENDIF}
- InsertPoint := dli.ItemNo+1;
- s2 := RVU_Copy(Items[dli.ItemNo], dli.Offs+CharPos.Offset-1,
- RVU_Length(Items[dli.ItemNo], GetItemOptions(dli.ItemNo)),
- GetItemOptions(dli.ItemNo));
- Do_DeleteSubstring(dli.ItemNo, dli.Offs+CharPos.Offset-1, -1);
- newsubstr := RV_CreateTextCopy(TRVTextItemInfo(GetItem(dli.ItemNo)), Self);
- newsubstr.SameAsPrev := True;
- Do_InsertItem(InsertPoint,s2,newsubstr,False, FR);
- AdjustTag(GetItem(InsertPoint));
- FullReformat := FullReformat or FR;
- end;
- Result := True;
- end;
- {.............................................................}
- var dli: TRVDrawLineInfo;
- FR: Boolean;
- ItemParaNo: Integer;
- ItemNo1, ItemNo2: Integer;
- begin
- NewListNo := -1;
- FullReformat := False;
- Result := True;
- ItemsAdded := 1;
- ItemParaNo := info.ParaNo;
- if info.SameAsPrev or (ItemParaNo>=GetRVStyle.ParaStyles.Count) then
- ItemParaNo := -1;
- if (DrawItems.Count<>0) and not info.GetBoolValue(rvbpFullWidth) and
- ((info.Checkpoint=nil) or not info.Checkpoint.Persistent)
- {$IFNDEF RVDONOTUSELISTS}
- and (info.StyleNo<>rvsListMarker)
- {$ENDIF}
- then begin
- info.SameAsPrev := True;
- info.ParaNo := GetItemPara(DrawItems[CaretDrawItemNo].ItemNo);
- end
- else begin
- info.SameAsPrev := False;
- info.ParaNo := FCurParaStyleNo;
- end;
- if IsParaProtected(info.ParaNo,rvpaoReadOnly) then begin
- info.Free;
- info := nil;
- Result := False;
- exit;
- end;
- SetTagToCurTag;
- dli := DrawItems[CharEnds.Items[CaretOffs].DrawItemNo];
- if GetItemStyle(dli.ItemNo)<0 then
- IS_InsertNearNonText(CharEnds.Items[CaretOffs], dli, ItemParaNo, InsertPoint, ItemsAdded, FullReformat)
- else if (Items[dli.ItemNo]='') then
- Result := IS_ReplaceEmptyText(CharEnds.Items[CaretOffs], dli, ItemParaNo, InsertPoint, ItemsAdded, FullReformat)
- else
- Result := IS_InsertInText(CharEnds.Items[CaretOffs], dli, ItemParaNo, InsertPoint, ItemsAdded, FullReformat);
- if not Result or (info=nil) then
- exit;
- {$IFNDEF RVDONOTUSELISTS}
- if (InsertPoint-1>=0) and (GetItemStyle(InsertPoint-1)=rvsListMarker) then
- info.SameAsPrev := True;
- {$ENDIF}
- if info.GetBoolValue(rvbpFullWidth) then begin
- if InsertPoint<>Items.Count then begin
- Do_NewLine(InsertPoint, False, -1, FR);
- FullReformat := FullReformat or FR;
- Do_BR(InsertPoint, False, FR);
- FullReformat := FullReformat or FR;
- end;
- if info.StyleNo=rvsBreak then
- info.ParaNo := 0;
- end;
- FullReformat := FullReformat or FR;
- Do_InsertItem(InsertPoint, s, info, False, FR);
- if InsertPoint+1<Items.Count then
- MovePersistentCheckpoint(InsertPoint+1, True);
- if (ItemParaNo>=0) and (ItemParaNo<>info.ParaNo) and (info.StyleNo<>rvsBreak) then begin
- ExpandToPara(InsertPoint, InsertPoint, ItemNo1, ItemNo2);
- Do_Para(ItemNo1, ItemNo2, ItemParaNo, FR);
- FullReformat := FullReformat or FR;
- end;
- if (InsertPoint+1<Items.Count) and not IsParaStart(InsertPoint+1) and
- ItemHasPersistentCheckpoint(InsertPoint+1) then begin
- Do_NewLine(InsertPoint+1, False, -1, FR);
- FullReformat := FullReformat or FR;
- end;
- {$IFNDEF RVDONOTUSELIVESPELL}
- LaterSetBackLiveSpellingTo(InsertPoint, 0, True);
- {$ENDIF}
- end;
- {------------------------------------------------------------------------------}
- function TRVEditRVData.InsertSomething(info: TCustomRVItemInfo; var s: String;
- AutoTag, CaretBefore: Boolean): Boolean;
- var
- InsertPoint, Dummy : Integer;
- Offs, ItemsAdded: Integer;
- FullReformat : Boolean;
- begin
- if (info.StyleNo<>rvsBreak) and ((info.Checkpoint=nil) or not (info.Checkpoint.Persistent)) then
- info.ParaNo := FCurParaStyleNo;
- if (FPartialSelectedItem<>nil) or
- not InsSomething(info, s, AutoTag, InsertPoint, ItemsAdded, FullReformat, Dummy) then begin
- Beep;
- Result := False;
- exit;
- end;
- if info=nil then begin
- // only possible if info was a marker, and it was not inserted, but this is
- // not error
- Result := True;
- exit;
- end;
- if (FullReformat or (CalculateMinItemWidthPlusEx(InsertPoint)>DocumentWidth)) and
- (DocumentWidth<>CalculateMinDocWidthPlus(nil,nil)) then begin
- Format_(False,True,False,0,GetCanvas,False,False,False);
- Invalidate;
- ChangeCaret(False,True,True,False);
- end
- else
- FormatParas(CharEnds.Items[0].DrawItemNo, CharEnds.Items[CharEnds.Count-1].DrawItemNo,ItemsAdded);
- if CaretBefore then
- if info.StyleNo<0 then
- Offs := 0
- else
- Offs := 1
- else
- if info.StyleNo<0 then
- Offs := 1
- else
- Offs := RVU_Length(S, GetItemOptions(InsertPoint))+1;
- Item2DrawItem(InsertPoint, Offs, {->} CaretDrawItemNo, Offs);
- OnChangeCaretLine(Offs-2);
- ChangeCaret(False, True, False, False);
- Result := True;
- end;
- {------------------------------------------------------------------------------}
- function TRVEditRVData.CreateTextItem(Tag, ParaStyle, FontStyle: Integer;
- SameAsPrev, BR: Boolean): TCustomRVItemInfo;
- begin
- Result := RichViewTextItemClass.Create(Self);
- Result.StyleNo := FontStyle;
- Result.ParaNo := ParaStyle;
- {$IFNDEF RVDONOTUSEUNICODE}
- if GetRVStyle.TextStyles[GetActualStyle(Result)].Unicode then
- Include(Result.ItemOptions,rvioUnicode);
- {$ENDIF}
- Result.SameAsPrev := SameAsPrev;
- Result.BR := BR;
- Result.Tag := Tag;
- end;
- {------------------------------------------------------------------------------}
- function TRVEditRVData.CreateTextItem2(Tag: Integer; Source: TCustomRVItemInfo;
- SameAsPrev, BR: Boolean): TCustomRVItemInfo;
- begin
- Result := RichViewTextItemClass.Create(Self);
- Result.Assign(Source);
- Result.ItemOptions := [];
- {$IFNDEF RVDONOTUSEUNICODE}
- if GetRVStyle.TextStyles[Result.StyleNo].Unicode then
- Include(Result.ItemOptions,rvioUnicode);
- {$ENDIF}
- Result.SameAsPrev := SameAsPrev;
- Result.BR := BR;
- Result.Tag := Tag;
- end;
- {------------------------------------------------------------------------------}
- function TRVEditRVData.InsString(s: String;
- Index, Tag: Integer;
- ParaStyle, FontStyle: Integer;
- SameAsPrev, BR: Boolean;
- var FullReformat: Boolean): TCustomRVItemInfo;
- begin
- Result := CreateTextItem(Tag, ParaStyle, FontStyle, SameAsPrev, BR);
- Do_InsertItem(Index, s, Result, False, FullReformat);
- end;
- {------------------------------------------------------------------------------}
- function TRVEditRVData.InsString2(s: String; Index, Tag: Integer; Source: TCustomRVItemInfo; SameAsPrev, BR: Boolean;
- var FullReformat: Boolean): TCustomRVItemInfo;
- begin
- Result := CreateTextItem2(Tag, Source, SameAsPrev, BR);
- Do_InsertItem(Index, s, Result, False, FullReformat);
- end;
- {------------------------------------------------------------------------------}
- function TRVEditRVData.InsEmptyString(Index, Tag, ParaStyle, FontStyle: Integer; SameAsPrev, BR: Boolean): TCustomRVItemInfo;
- var FullReformat: Boolean;
- begin
- Result := InsString('', Index, Tag, ParaStyle, FontStyle, SameAsPrev, BR, FullReformat);
- end;
- {------------------------------------------------------------------------------}
- function TRVEditRVData.CanDelete: Boolean;
- var i, StyleNo: Integer;
- StartNo, EndNo, StartOffs, EndOffs: Integer;
- {................................................}
- function CompletelySelected(a,b, ItemNo: Integer): Boolean;
- begin
- Result := (a<=GetOffsBeforeItem(ItemNo)) and
- (b>=GetOffsAfterItem(ItemNo));
- end;
- {................................................}
- function NotSelected(a,b, ItemNo: Integer): Boolean;
- begin
- Result := (a=b) or (b<=GetOffsBeforeItem(ItemNo)) or
- (a>=GetOffsAfterItem(ItemNo));
- end;
- {................................................}
- function CD(a,b, ItemNo, StyleNo: Integer): Boolean;
- var Protection : TRVProtectOptions;
- begin
- if NotSelected(a, b, ItemNo) then
- Result := True
- else begin
- if StyleNo<0 then begin
- Result := not IsProtected(ItemNo, rvprDeleteProtect);
- end
- else begin
- Protection := GetRVStyle.TextStyles[StyleNo].Protection;
- Result := False;
- if (rvprDeleteProtect in Protection) and
- CompletelySelected(a,b, ItemNo) then exit;
- if (rvprModifyProtect in Protection) and
- not CompletelySelected(a,b, ItemNo) then exit;
- Result := True;
- end;
- end;
- end;
- {................................................}
- // Searching "persistent" checkpoints in the selected paragraphs
- // (not including the first one)
- function HasNonFirstPersistentCheckpoints: Boolean;
- var nonfirst: Boolean;
- i: Integer;
- begin
- Result := True;
- nonfirst := False;
- for i := StartNo+1 to EndNo do begin
- if not nonfirst and IsParaStart(i) then
- nonfirst := True;
- if nonfirst and ItemHasPersistentCheckpoint(i) then
- exit;
- end;
- if nonfirst then
- for i := EndNo+1 to ItemCount-1 do begin
- if IsParaStart(i) then
- break;
- if ItemHasPersistentCheckpoint(i) then
- exit;
- end;
- Result := False;
- end;
- {................................................}
- begin
- if not SelectionExists(True, False) then begin
- if FPartialSelectedItem<>nil then
- Result := FPartialSelectedItem.CanDeletePartiallySelected
- else
- Result := True;
- exit;
- end;
- {$IFNDEF RVDONOTUSEINPLACE}
- if (GetChosenRVData<>nil) then begin
- if (GetChosenRVData is TRVEditRVData) then
- Result := TRVEditRVData(GetChosenRVData).CanDelete
- else
- Result := False;
- exit;
- end;
- {$ENDIF}
- Result := False;
- StoreSelBounds(StartNo, EndNo, StartOffs, EndOffs, True);
- for i := StartNo+1 to EndNo-1 do begin
- if IsProtected(i, rvprDeleteProtect) then
- exit;
- end;
- if (StartNo<>EndNo) then begin
- StyleNo := GetItemStyle(StartNo);
- if not CD(StartOffs, GetOffsAfterItem(StartNo), StartNo, StyleNo) then exit;
- StyleNo := GetItemStyle(EndNo);
- if not CD(GetOffsBeforeItem(EndNo), EndOffs, EndNo, StyleNo) then exit;
- end
- else begin
- StyleNo := GetItemStyle(StartNo);
- if not CD(StartOffs, EndOffs, StartNo, StyleNo) then exit;
- end;
- if IsItemParaProtected(StartNo) and
- (not IsParaStart(StartNo) or
- (StartOffs>GetOffsBeforeItem(StartNo))) then
- exit;
- if IsItemParaProtected(EndNo) and
- ((EndOffs<GetOffsAfterItem(EndNo)) or
- ((EndNo<Items.Count-1) and
- not IsParaStart(EndNo+1))
- ) then
- exit;
- if IsItemParaProtected(StartNo) and (StartNo=EndNo) and (StartOffs=EndOffs) then
- exit;
- Result := not IsParaProtected(FCurParaStyleNo,rvpaoReadOnly) and
- not HasNonFirstPersistentCheckpoints;
- end;
- {------------------------------------------------------------------------------}
- procedure TRVEditRVData.Reformat_(FullFormat: Boolean; StartDrawItem, EndDrawItem,
- ItemsAdded: Integer);
- begin
- if FullFormat and (DocumentWidth<>CalculateMinDocWidthPlus(nil,nil)) then begin
- Format_(False, True, False, 0, GetCanvas, False, False,False);
- Invalidate;
- end
- else
- FormatParasExact(StartDrawItem, EndDrawItem, ItemsAdded, False);
- end;
- {------------------------------------------------------------------------------}
- function TRVEditRVData.DeleteSelection_: Boolean;
- var StartNo, EndNo, StartOffs, EndOffs, TagForEmptyItem: Integer;
- {$IFNDEF RVDONOTUSEDRAGDROP}
- DragDropCaretInfo: TRVDragDropCaretInfo;
- {$ENDIF}
- {........................................................}
- // Searching the checkpoint with "persistent" flag in the
- // first selected paragraph; if found, moving it to the
- // first selected item or (if this item is not the first
- // in paragraph and selected completely) to the item
- // before the first selected one
- procedure MovePersistentCP;
- var i: Integer;
- CPItemNo: Integer;
- MultiParagraphSelection: Boolean;
- begin
- CPItemNo := -1;
- MultiParagraphSelection := False;
- if ItemHasPersistentCheckpoint(StartNo) and
- (StartOffs<GetOffsAfterItem(StartNo)) then
- CPItemNo := StartNo
- else begin
- for i := StartNo+1 to EndNo-1 do begin
- if IsParaStart(i) then begin
- MultiParagraphSelection := True;
- break;
- end;
- if ItemHasPersistentCheckpoint(i) then begin
- CPItemNo := i;
- break
- end;
- end;
- if not MultiParagraphSelection and (EndNo>StartNo) and
- not IsParaStart(EndNo) and (EndOffs>=GetOffsAfterItem(EndNo)) and
- ItemHasPersistentCheckpoint(EndNo) then
- CPItemNo := EndNo;
- end;
- if CPItemNo>=0 then begin
- if (StartOffs<=GetOffsBeforeItem(StartNo)) and
- (StartNo>0) and not IsParaStart(StartNo) then
- i := StartNo-1
- else
- i := StartNo;
- if i<CPItemNo then
- Do_MoveCP(CPItemNo, i);
- end;
- end;
- {........................................................}
- // Deleting selection consisting of multiple items.
- // Step 1: Deleting from last item (which is selected completely or partially)
- procedure DelSel_DelFromLastItem(var FullReformat, ShouldAddEmpty,
- SubstringDeleted: Boolean; var ItemsDeleted, DeletedWidth: Integer);
- var FR: Boolean;
- begin
- DeletedWidth := CalculateMinItemWidthPlusEx(EndNo);
- SubstringDeleted := False;
- FR := False;
- if EndOffs>=GetOffsAfterItem(EndNo) then begin
- // last item is selected completely - deleting it
- ShouldAddEmpty := (EndNo=Items.Count-1) or
- not GetItem(EndNo+1).SameAsPrev;
- Do_DeleteItem(EndNo,FR);
- FullReformat := FullReformat or FR;
- inc(ItemsDeleted);
- {$IFNDEF RVDONOTUSEDRAGDROP}
- if (DragDropCaretInfo<>nil) then begin
- if DragDropCaretInfo.ItemNo=EndNo then
- DragDropCaretInfo.ItemOffs := GetOffsAfterItem(EndNo-1);
- dec(DragDropCaretInfo.ItemNo);
- end;
- {$ENDIF}
- end
- else begin
- // deleting substring from last item }
- if GetItemStyle(EndNo)>=0 then
- Do_DeleteSubstring(EndNo, 1, EndOffs-1);
- {$IFNDEF RVDONOTUSEDRAGDROP}
- if (DragDropCaretInfo<>nil) and (DragDropCaretInfo.ItemNo=EndNo) then
- dec(DragDropCaretInfo.ItemOffs, EndOffs-1);
- {$ENDIF}
- SubstringDeleted := True;
- ShouldAddEmpty := False;
- end;
- end;
- {........................................................}
- // Deleting selection consisting of multiple items.
- // Step 2: Deleting all items except from the first and the last one
- procedure DelSel_DelMiddleItems(var FullReformat: Boolean;
- var ItemsDeleted, DeletedWidth: Integer);
- var DeletedWidth1: Integer;
- FR: Boolean;
- begin
- FR := False;
- DeletedWidth1 := CalculateMinItemsWidthPlusEx(StartNo+1,EndNo-1);
- if DeletedWidth<DeletedWidth1 then
- DeletedWidth := DeletedWidth1;
- inc(ItemsDeleted,EndNo-StartNo-1);
- Do_DeleteItems(StartNo+1,EndNo-1,FR);
- {$IFNDEF RVDONOTUSEDRAGDROP}
- if (DragDropCaretInfo<>nil) then begin
- if (DragDropCaretInfo.ItemNo=EndNo-1) and (EndNo-StartNo-1>0) then
- DragDropCaretInfo.ItemOffs := GetOffsAfterItem(StartNo);
- dec(DragDropCaretInfo.ItemNo, EndNo-StartNo-1);
- end;
- {$ENDIF}
- FullReformat := FullReformat or FR;
- end;
- {........................................................}
- // Deleting selection consisting of multiple items.
- // Step 3: Deleting from the first item (which is selected completely or partially)
- // or
- // Deleting selection consisting of one item.
- procedure DelSel_DelFromFirstItem(StartOffs, EndOffs: Integer;
- var FullReformat, ShouldAddEmpty, SubstringDeleted: Boolean;
- var ItemsDeleted, DeletedWidth, ItemNo, ItemOffs: Integer);
- var item: TCustomRVItemInfo;
- FR, DeletedBR, DeletedSAP, NewPara: Boolean;
- DeletedWidth1, ParaNo: Integer;
- CPForEmptyString: TRVCPInfo;
- begin
- CPForEmptyString := nil;
- DeletedWidth1 := CalculateMinItemWidthPlusEx(StartNo);
- if DeletedWidth<DeletedWidth1 then
- DeletedWidth := DeletedWidth1;
- item := GetItem(StartNo);
- if (StartOffs<=GetOffsBeforeItem(StartNo)) and
- (EndOffs >=GetOffsAfterItem(StartNo)) then begin
- // first item is selected completely
- NewPara := not item.SameAsPrev;
- if ShouldAddEmpty then begin
- if not NewPara then
- ShouldAddEmpty := False;
- // if (ItemCount>1) and (GetRVStyle.SelectionMode=rvsmParagraph) then
- // ShouldAddEmpty := False;
- {$IFNDEF RVDONOTUSELISTS}
- if not ShouldAddEmpty and (StartNo>0) and (GetItemStyle(StartNo-1)=rvsListMarker) then
- ShouldAddEmpty := True;
- {$ENDIF}
- if ShouldAddEmpty and ItemHasPersistentCheckpoint(StartNo) then
- CPForEmptyString := item.Checkpoint.CreateCopy(rvoTagsArePChars in Options);
- end;
- DeletedBR := item.BR;
- DeletedSAP := item.SameAsPrev;
- ParaNo := item.ParaNo;
- if not ShouldAddEmpty then
- MovePersistentCheckpoint(StartNo, False);
- Do_DeleteItem(StartNo,FR);
- inc(ItemsDeleted);
- FullReformat := FullReformat or FR;
- if ShouldAddEmpty then begin
- InsEmptyString(StartNo, TagForEmptyItem, ParaNo, FCurTextStyleNo, DeletedSAP, DeletedBR);
- TagForEmptyItem := 0;
- if CPForEmptyString<>nil then
- Do_AddCP(StartNo, CPForEmptyString);
- dec(ItemsDeleted);
- ItemNo := StartNo;
- ItemOffs := 1;
- end
- else if NewPara and (StartNo<Items.Count) then begin
- if not ((StartNo>0) and IsProtected(StartNo, rvprParaStartProtect)) then begin
- Do_NewLine(StartNo,False,-1,FR);
- FullReformat := FullReformat or FR;
- if DeletedBR then begin
- Do_BR(StartNo, True, FR);
- FullReformat := FullReformat or FR;
- end;
- end;
- ItemNo := StartNo;
- ItemOffs := GetOffsBeforeItem(ItemNo);
- end
- else begin
- ItemNo := StartNo-1;
- ItemOffs := GetOffsAfterItem(ItemNo);
- if (StartNo<Items.Count) and SubstringDeleted then begin
- Do_NewLine(StartNo,True,-1,FR);
- FullReformat := FullReformat or FR;
- end;
- end;
- {$IFNDEF RVDONOTUSEDRAGDROP}
- if (DragDropCaretInfo<>nil) then begin
- if DragDropCaretInfo.ItemNo=StartNo then begin
- DragDropCaretInfo.ItemNo := ItemNo;
- DragDropCaretInfo.ItemOffs := ItemOffs;
- end
- else if not ShouldAddEmpty then
- dec(DragDropCaretInfo.ItemNo);
- end;
- {$ENDIF}
- end
- else begin
- // deleting substring from the first item
- if GetItemStyle(StartNo)>=0 then begin
- Do_DeleteSubstring(StartNo, StartOffs, EndOffs-StartOffs);
- {$IFNDEF RVDONOTUSEDRAGDROP}
- if (DragDropCaretInfo<>nil) then begin
- if DragDropCaretInfo.ItemNo=StartNo then
- dec(DragDropCaretInfo.ItemOffs, EndOffs-StartOffs);
- end;
- {$ENDIF}
- end;
- ItemNo := StartNo;
- ItemOffs := StartOffs;
- if (StartNo+1<Items.Count) and SubstringDeleted then begin
- Do_NewLine(StartNo+1,True,-1,FR);
- FullReformat := FullReformat or FR;
- end;
- end;
- end;
- {........................................................}
- var DIStartNo, DIEndNo, DIStartOffs, DIEndOffs: Integer;
- ItemsDeleted, DeletedWidth, ACaretItemNo, ACaretOffs: Integer;
- FullReformat, ShouldAddEmpty, SubstringDeleted: Boolean;
- {$IFNDEF RVDONOTUSELISTS}
- M_FirstItemNo, M_LastMarkerIndex: Integer;
- M_ListNos: TRVIntegerList;
- {$ENDIF}
- begin
- Result := True;
- if not SelectionExists(True, False) then begin
- if (FPartialSelectedItem<>nil) then begin
- Result := FPartialSelectedItem.CanDeletePartiallySelected;
- if Result then
- FPartialSelectedItem.DeletePartiallySelected
- else
- Beep;
- end
- else
- Result := True;
- exit;
- end;
- if not CanDelete or (GetChosenRVData<>nil) then begin
- Beep;
- Result := False;
- exit;
- end;
- {$IFNDEF RVDONOTUSEDRAGDROP}
- DragDropCaretInfo := GetDragDropCaretInfo;
- if DragDropCaretInfo<>nil then
- if DragDropCaretInfo.RVData<>Self then
- DragDropCaretInfo := nil
- else begin
- if Item_InsideSelection(DragDropCaretInfo.ItemNo, DragDropCaretInfo.ItemOffs) then begin
- Beep;
- Result := False;
- exit;
- end;
- end;
- {$ENDIF}
- BeginUndoSequence(rvutDelete, True);
- GetSelBounds(DIStartNo, DIEndNo, DIStartOffs, DIEndOffs, True);
- GetParaBounds(DIStartNo,DIEndNo,DIStartNo,DIEndNo);
- StoreSelBounds(StartNo, EndNo, StartOffs, EndOffs, False);
- if FCurTextStyleNo = GetItemStyle(EndNo) then
- TagForEmptyItem := RV_CopyTag(GetItemTag(EndNo), rvoTagsArePChars in Options)
- else
- TagForEmptyItem := 0;
- StoreSelBounds(StartNo, EndNo, StartOffs, EndOffs, True);
- {$IFNDEF RVDONOTUSEDRAGDROP}
- if (DragDropCaretInfo<>nil) and
- ((DragDropCaretInfo.ItemNo<EndNo) or
- ((DragDropCaretInfo.ItemNo=EndNo) and
- (DragDropCaretInfo.ItemOffs<=EndOffs))) then
- DragDropCaretInfo := nil;
- {$ENDIF}
- Deselect(nil, False);
- if (StartNo>0) and GetItem(StartNo).SameAsPrev and
- (StartOffs<=GetOffsBeforeItem(StartNo)) then begin
- dec(StartNo);
- StartOffs := GetOffsAfterItem(StartNo);
- end;
- {$IFNDEF RVDONOTUSELISTS}
- AdjustMarkerPos(StartNo, StartOffs, True);
- AdjustMarkerPos(EndNo, EndOffs, True);
- {$ENDIF}
- ItemsDeleted := 0;
- DeletedWidth := 0;
- ShouldAddEmpty := True;
- FullReformat := False;
- SubstringDeleted := False;
- {$IFNDEF RVDONOTUSELISTS}
- PrepareForUpdateRangeAfterMarkers(StartNo, EndNo, True, M_FirstItemNo, M_LastMarkerIndex, M_ListNos);
- {$ENDIF}
- MovePersistentCP;
- if StartNo=EndNo then begin
- // one item is selected
- ShouldAddEmpty := (EndNo+1>=Items.Count) or not GetItem(EndNo+1).SameAsPrev;
- DelSel_DelFromFirstItem(StartOffs, EndOffs, FullReformat, ShouldAddEmpty,
- SubstringDeleted, ItemsDeleted, DeletedWidth, ACaretItemNo, ACaretOffs)
- end
- else begin { delete selected itemS }
- DelSel_DelFromLastItem(FullReformat, ShouldAddEmpty, SubstringDeleted,
- ItemsDeleted, DeletedWidth);
- DelSel_DelMiddleItems(FullReformat, ItemsDeleted, DeletedWidth);
- DelSel_DelFromFirstItem(StartOffs, GetOffsAfterItem(StartNo), FullReformat,
- ShouldAddEmpty, SubstringDeleted, ItemsDeleted, DeletedWidth,
- ACaretItemNo, ACaretOffs);
- end;
- if (ACaretItemNo+1<Items.Count) and
- RV_CanConcateItems(ACaretItemNo, GetItem(ACaretItemNo), GetItem(ACaretItemNo+1), False) then begin
- {$IFNDEF RVDONOTUSEDRAGDROP}
- if (DragDropCaretInfo<>nil) then begin
- if DragDropCaretInfo.ItemNo=ACaretItemNo+1 then begin
- dec(DragDropCaretInfo.ItemNo);
- inc(DragDropCaretInfo.ItemOffs, ItemLength(ACaretItemNo));
- end
- else if DragDropCaretInfo.ItemNo>ACaretItemNo+1 then
- dec(DragDropCaretInfo.ItemNo);
- end;
- {$ENDIF}
- Do_Concate(ACaretItemNo);
- inc(ItemsDeleted);
- end;
- {$IFNDEF RVDONOTUSELIVESPELL}
- LaterSetBackLiveSpellingTo(ACaretItemNo, 0, True);
- {$ENDIF}
- Reformat_(FullReformat or (DeletedWidth>=DocumentWidth), DIStartNo, DIEndNo, -ItemsDeleted);
- Item2DrawItem(ACaretItemNo, ACaretOffs, CaretDrawItemNo, CaretOffs);
- {$IFNDEF RVDONOTUSELISTS}
- AdjustMarkerCaret(True, CaretOffs);
- {$ENDIF}
- OnChangeCaretLine(CaretOffs-2);
- ChangeCaret(False,True,True,False);
- ApplyParaStyle(GetItemPara(ACaretItemNo), rvscParaStyle);
- {$IFNDEF RVDONOTUSELISTS}
- if (M_ListNos<>nil) and (M_ListNos.Count>0) then
- UpdateAfterMarkers(GetFirstParaItem(StartNo), M_LastMarkerIndex, M_ListNos, -1);
- M_ListNos.Free;
- {$ENDIF}
- if (TagForEmptyItem<>0) and (rvoTagsArePChars in Options) then
- StrDispose(PChar(TagForEmptyItem));
- Change;
- DoSelect;
- end;
- {------------------------------------------------------------------------------}
- function TRVEditRVData.OnEnterPress_(Shift: Boolean; Recursive: Boolean): Boolean;
- {................................................................}
- procedure UpdateCaretAtTheBeginningOfLine;
- begin
- CaretOffs := GetOffsBeforeDrawItem(CaretDrawItemNo);
- {$IFNDEF RVDONOTUSELISTS}
- AdjustMarkerCaret(True, CaretOffs);
- {$ENDIF}
- OnChangeCaretLine(CaretOffs-2);
- ChangeCaret(False,True,False,False);
- end;
- {................................................................}
- // Adding an empty line before or after the current paragraph
- function AddEmptyLine(dli: TRVDrawLineInfo): Boolean;
- var li, srcli: TCustomRVItemInfo;
- ItemsAdded, InsertPoint, SrcItemNo, Last: Integer;
- //FullReformat,
- FR: Boolean;
- s: String;
- {$IFNDEF RVDONOTUSELISTS}
- AddedMarkerItemNo : Integer;
- {$ENDIF}
- begin
- Result := False;
- //FullReformat := False;
- if IsProtected(dli.ItemNo, rvprParaStartProtect) then begin
- Beep;
- exit;
- end;
- Result := True;
- ItemsAdded := 1;
- {$IFNDEF RVDONOTUSELISTS}
- AddedMarkerItemNo := -1;
- {$ENDIF}
- srcli := GetItem(dli.ItemNo);
- {$IFNDEF RVDONOTUSELISTS}
- if not Shift and not Recursive and (srcli.StyleNo>=0) and
- not RichViewEditEnterAllowsEmptyMarkeredLines and
- (GetItemText(dli.ItemNo)='') and (dli.ItemNo>0) and
- (GetItemStyle(dli.ItemNo-1)=rvsListMarker) then begin
- OnBackSpacePress_(False, False, False);
- OnEnterPress_(Shift, True);
- exit;
- end;
- {$ENDIF}
- li := RichViewTextItemClass.Create(Self);
- if (CaretOffs=CharEnds.Count-1) and
- (srcli.StyleNo=FCurTextStyleNo) and
- (GetRVStyle.TextStyles[GetActualCurStyleNo].NextStyleNo<>-1) then
- SetCurTextStyleNo(GetRVStyle.TextStyles[GetActualCurStyleNo].NextStyleNo);
- if not Shift and ((dli.ItemNo+1>=Items.Count) or not GetItem(dli.ItemNo+1).BR) then
- if IsParaProtected(srcli.ParaNo,rvpaoReadOnly) or
- ((CaretOffs=CharEnds.Count-1) and
- (GetRVStyle.ParaStyles[srcli.ParaNo].NextParaNo<>-1)) then
- if GetRVStyle.ParaStyles[srcli.ParaNo].NextParaNo>=0 then
- SetCurParaStyleNo(GetRVStyle.ParaStyles[srcli.ParaNo].NextParaNo)
- else
- SetCurParaStyleNo(0);
- if rvprModifyProtect in GetRVStyle.TextStyles[GetActualCurStyleNo].Protection then
- li.StyleNo := 0
- else
- li.StyleNo := FCurTextStyleNo;
- {$IFNDEF RVDONOTUSEUNICODE}
- if GetRVStyle.TextStyles[li.StyleNo].Unicode then
- Include(li.ItemOptions,rvioUnicode);
- {$ENDIF}
- li.ParaNo := FCurParaStyleNo;
- li.SameAsPrev := False;
- if Shift then begin
- li.ParaNo := GetItemPara(dli.ItemNo);
- if (CaretOffs>0) or (CharEnds.Count=1) then // inserting after...
- li.BR := True
- else begin// inserting before...
- li.BR := GetItem(dli.ItemNo).BR;
- Do_BR(dli.ItemNo,True,FR);
- //FullReformat := FullReformat or FR;
- end;
- end;
- if GetItemStyle(dli.ItemNo)=li.StyleNo then begin
- li.Tag := RV_CopyTag(GetItem(dli.ItemNo).Tag, rvoTagsArePChars in Options);
- {$IFNDEF RVDONOTUSEITEMHINTS}
- li.Hint := GetItem(dli.ItemNo).Hint;
- {$ENDIF}
- end;
- if CaretOffs=CharEnds.Count-1 then begin
- InsertPoint := dli.ItemNo+1;
- SrcItemNo := dli.ItemNo;
- {$IFNDEF RVDONOTUSELISTS}
- if not Shift and (li.ParaNo=srcli.ParaNo) and
- ReplicateMarker(dli.ItemNo, InsertPoint, FR,True) then begin
- //FullReformat := FullReformat or FR;
- AddedMarkerItemNo := InsertPoint;
- inc(ItemsAdded);
- inc(InsertPoint);
- li.SameAsPrev := True;
- end;
- {$ENDIF}
- Last := InsertPoint;
- end
- else begin
- InsertPoint := dli.ItemNo;
- Last := InsertPoint+1;
- {$IFNDEF RVDONOTUSELISTS}
- if Shift then begin
- if GetItemStyle(GetFirstParaSectionItem(dli.ItemNo))=rvsListMarker then begin
- li.SameAsPrev := True;
- Do_NewLine(dli.ItemNo,False,-1, FR);
- //FullReformat := FullReformat or FR;
- Do_BR(dli.ItemNo, True, FR);
- //FullReformat := FullReformat or FR;
- end;
- end
- else begin
- if GetItemStyle(GetFirstParaSectionItem(dli.ItemNo))=rvsListMarker then
- li.SameAsPrev := True;
- if ReplicateMarker(dli.ItemNo, dli.ItemNo, FR, True) then begin
- //FullReformat := FullReformat or FR;
- AddedMarkerItemNo := dli.ItemNo+1;
- Do_NewLine(dli.ItemNo+1,True,-1,FR);
- //FullReformat := FullReformat or FR;
- inc(ItemsAdded);
- inc(Last);
- end;
- end;
- {$ENDIF}
- SrcItemNo := Last;
- end;
- s := '';
- Do_InsertItem(InsertPoint, s, li, False, FR);
- if InsertPoint<SrcItemNo then
- Do_MoveCP(SrcItemNo, InsertPoint);
- {$IFNDEF RVDONOTUSELIVESPELL}
- LaterSetBackLiveSpellingTo(InsertPoint, 0, True);
- {$ENDIF}
- // FullReformat := FullReformat or FR;
- FormatParas(CharEnds.Items[0].DrawItemNo, CharEnds.Items[CharEnds.Count-1].DrawItemNo, ItemsAdded);
- Item2FirstDrawItem(Last, CaretDrawItemNo);
- UpdateCaretAtTheBeginningOfLine;
- {$IFNDEF RVDONOTUSELISTS}
- UpdateRangeAfterMarkers(AddedMarkerItemNo,AddedMarkerItemNo);
- {$ENDIF}
- end;
- {................................................................}
- // Moving the item to the right of caret to the new line
- // (or adding a marker instead)
- // This procedure is rarely executed, usually the item
- // to the right of the caret is not a current
- function WrapCurrentItem(dli: TRVDrawLineInfo; OldWidth: Integer;
- NoWrap: Boolean): Boolean;
- var PItem1, PItem2, Last, ItemsAdded: Integer;
- FullReformat, FR: Boolean;
- {$IFNDEF RVDONOTUSELISTS}
- AddedMarkerItemNo : Integer;
- {$ENDIF}
- begin
- Result := False;
- if IsProtected(dli.ItemNo, rvprParaStartProtect) then begin
- Beep;
- exit;
- end;
- Result := True;
- {$IFNDEF RVDONOTUSELISTS}
- AddedMarkerItemNo := -1;
- {$ENDIF}
- FullReformat := False;
- GetParaBounds(CharEnds.Items[0].DrawItemNo,
- CharEnds.Items[CharEnds.Count-1].DrawItemNo,
- PItem1, PItem2);
- ItemsAdded := 0;
- if Shift then begin
- Do_NewLine(dli.ItemNo,False,-1, FR);
- FullReformat := FullReformat or FR;
- Do_BR(dli.ItemNo,True, FR);
- FullReformat := FullReformat or FR;
- end
- else begin
- {$IFNDEF RVDONOTUSELISTS}
- if ReplicateMarker(dli.ItemNo-1, dli.ItemNo, FR, True) then begin
- {$IFNDEF RVDONOTUSELIVESPELL}
- LaterSetBackLiveSpellingTo(dli.ItemNo, 0, True);
- {$ENDIF}
- AddedMarkerItemNo := dli.ItemNo;
- FullReformat := FullReformat or FR;
- inc(ItemsAdded);
- end
- else
- {$ENDIF}
- begin
- Do_NewLine(dli.ItemNo,False,-1, FR);
- FullReformat := FullReformat or FR;
- end;
- end;
- Last := dli.ItemNo;
- Reformat_((NoWrap and (OldWidth>=DocumentWidth)) or FullReformat, PItem1, PItem2,ItemsAdded);
- Item2FirstDrawItem(Last, CaretDrawItemNo);
- UpdateCaretAtTheBeginningOfLine;
- {$IFNDEF RVDONOTUSELISTS}
- UpdateRangeAfterMarkers(AddedMarkerItemNo,AddedMarkerItemNo);
- {$ENDIF}
- end;
- {................................................................}
- // Moving the item to the right of caret to the new line
- // (or adding a marker instead)
- function WrapNextItem(dli: TRVDrawLineInfo; OldWidth: Integer;
- NoWrap: Boolean): Boolean;
- var PItem1, PItem2, Last, ItemsAdded: Integer;
- FullReformat, FR: Boolean;
- {$IFNDEF RVDONOTUSELISTS}
- AddedMarkerItemNo : Integer;
- {$ENDIF}
- begin
- Result := False;
- GetParaBounds(CharEnds.Items[0].DrawItemNo,
- CharEnds.Items[CharEnds.Count-1].DrawItemNo,
- PItem1, PItem2);
- if IsProtected(dli.ItemNo+1, rvprParaStartProtect) then begin
- Beep;
- exit;
- end;
- Result := True;
- {$IFNDEF RVDONOTUSELISTS}
- AddedMarkerItemNo := -1;
- {$ENDIF}
- FullReformat := False;
- Last := dli.ItemNo+1;
- ItemsAdded := 0;
- if Shift then begin
- Do_NewLine(Last,False,-1, FR);
- FullReformat := FullReformat or FR;
- Do_BR(Last,True,FR);
- FullReformat := FullReformat or FR;
- end
- else begin
- {$IFNDEF RVDONOTUSELISTS}
- if ReplicateMarker(Last-1, Last, FR, True) then begin
- {$IFNDEF RVDONOTUSELIVESPELL}
- LaterSetBackLiveSpellingTo(Last, 0, True);
- {$ENDIF}
- AddedMarkerItemNo := Last;
- FullReformat := FullReformat or FR;
- inc(ItemsAdded);
- end
- else
- {$ENDIF}
- begin
- Do_NewLine(Last,False,-1, FR);
- FullReformat := FullReformat or FR;
- end;
- end;
- inc(CaretDrawItemNo);
- if CaretDrawItemNo>PItem2 then
- PItem2 := CaretDrawItemNo;
- Reformat_((NoWrap and (OldWidth>=DocumentWidth)) or FullReformat, PItem1, PItem2,ItemsAdded);
- Item2FirstDrawItem(Last, CaretDrawItemNo);
- UpdateCaretAtTheBeginningOfLine;
- {$IFNDEF RVDONOTUSELISTS}
- UpdateRangeAfterMarkers(AddedMarkerItemNo,AddedMarkerItemNo);
- {$ENDIF}
- end;
- {................................................................}
- // Breaking a text line (removing part of text after caret,
- // adding it as a new item from new line; adding marker if needbe)
- function BreakTextItem(dli: TRVDrawLineInfo; OldWidth: Integer;
- NoWrap: Boolean): Boolean;
- var PItem1, PItem2, InsertPoint, ItemsAdded: Integer;
- li: TCustomRVItemInfo;
- FullReformat1, FullReformat2: Boolean;
- s: String;
- {$IFNDEF RVDONOTUSELISTS}
- AddedMarkerItemNo : Integer;
- {$ENDIF}
- begin
- Result := False;
- if IsProtected(dli.ItemNo, rvprParaStartProtect) then begin
- Beep;
- exit;
- end;
- {$IFNDEF RVDONOTUSELISTS}
- AddedMarkerItemNo := -1;
- {$ENDIF}
- with CharEnds.Items[CaretOffs] do begin
- if IsProtected(dli.ItemNo, rvprModifyProtect) then begin
- Beep;
- exit;
- end;
- Result := True;
- GetParaBounds(CharEnds.Items[0].DrawItemNo,
- CharEnds.Items[CharEnds.Count-1].DrawItemNo,
- PItem1, PItem2);
- InsertPoint := dli.ItemNo+1;
- s := RVU_Copy(Items[dli.ItemNo], dli.Offs+Offset-1,
- RVU_Length(Items[dli.ItemNo], GetItemOptions(dli.ItemNo)),
- GetItemOptions(dli.ItemNo));
- Do_DeleteSubstring(dli.ItemNo, dli.Offs+Offset-1,-1);
- ItemsAdded := 1;
- FullReformat1 := False;
- FullReformat2 := False;
- li := RV_CreateTextCopy(TRVTextItemInfo(Items.Objects[dli.ItemNo]), Self);
- li.SameAsPrev := False;
- if Shift then
- li.BR := True
- else begin
- {$IFNDEF RVDONOTUSELISTS}
- if ReplicateMarker(InsertPoint-1, InsertPoint, FullReformat1, True) then begin
- AddedMarkerItemNo := InsertPoint;
- inc(ItemsAdded);
- inc(InsertPoint);
- li.SameAsPrev := True
- end;
- {$ENDIF}
- end;
- Do_InsertItem(InsertPoint, s, li, False, FullReformat2);
- {$IFNDEF RVDONOTUSELIVESPELL}
- LaterSetBackLiveSpellingTo(InsertPoint, 0, True);
- {$ENDIF}
- Reformat_((NoWrap and (OldWidth>=DocumentWidth)) or FullReformat1 or FullReformat2, PItem1, PItem2,ItemsAdded);
- Item2FirstDrawItem(InsertPoint,CaretDrawItemNo);
- UpdateCaretAtTheBeginningOfLine;
- {$IFNDEF RVDONOTUSELISTS}
- UpdateRangeAfterMarkers(AddedMarkerItemNo,AddedMarkerItemNo);
- {$ENDIF}
- end;
- end;
- {................................................................}
- var dli: TRVDrawLineInfo;
- li: TCustomRVItemInfo;
- OldWidth: Integer;
- NoWrap: Boolean;
- begin
- Result := False;
- CaretDrawItemNo := CharEnds.Items[CaretOffs].DrawItemNo;
- dli := DrawItems[CaretDrawItemNo];
- li := GetItem(dli.ItemNo);
- if IsParaProtected(li.ParaNo,rvpaoDoNotWantReturns) then begin
- Beep;
- exit;
- end;
- BeginUndoSequence(rvutMiscTyping, True);
- if CaretAtTheBeginningOfParaSection or CaretAtTheEndOfParaSection then begin
- Result := AddEmptyLine(dli);
- exit;
- end;
- if IsParaProtected(li.ParaNo,rvpaoReadOnly) then begin
- Result := False;
- Beep;
- exit;
- end;
- { breaking line }
- OldWidth := CalculateParaSectionMinWidthDef(dli.ItemNo);
- NoWrap := rvpaoNoWrap in GetRVStyle.ParaStyles[li.ParaNo].Options;
- if ((li.StyleNo<0) and (CharEnds.Items[CaretOffs].Offset=0)) or
- ((li.StyleNo>=0) and (dli.Offs+CharEnds.Items[CaretOffs].Offset-1<=GetOffsBeforeItem(dli.ItemNo))) then begin
- Result := WrapCurrentItem(dli, OldWidth, NoWrap);
- exit;
- end;
- if (li.StyleNo<0) or
- (ItemLength(dli.ItemNo)<dli.Offs+CharEnds.Items[CaretOffs].Offset-1) then begin
- Result := WrapNextItem(dli, OldWidth, NoWrap);
- exit;
- end;
- Result := BreakTextItem(dli, OldWidth, NoWrap);
- end;
- {------------------------------------------------------------------------------}
- procedure TRVEditRVData.OnChangeCaretLine(DLOffs: Integer);
- var First,Last,i: Integer;
- Canvas: TCanvas;
- const
- VARGE_VALUE = 100000;
- {........................................................}
- procedure SimpleBuildCaretPositions(Canvas: TCanvas; i: Integer);
- var
- item: TCustomRVItemInfo;
- ditem: TRVDrawLineInfo;
- arr: PRVIntegerArray;
- j, max: Integer;
- s: String;
- BiDiMode: TRVBiDiMode;
- {$IFNDEF RVDONOTUSEUNICODE}
- PStart, PCur: Pointer;
- prevj: Integer;
- {$ENDIF}
- begin
- ditem := DrawItems[i];
- item := GetItem(ditem.ItemNo);
- BiDiMode := GetParaBiDiMode(item.ParaNo);
- if (i=First) and ((item.StyleNo<0) or (Items[ditem.ItemNo]<>'')) then
- with TRVCharPos(CharEnds.Add) do begin
- if item.StyleNo<0 then
- Offset := 0
- else
- Offset := 1;
- if (item.StyleNo<0) and (BiDiMode=rvbdRightToLeft) then begin
- MoveRightTo := 2;
- X := ditem.Left+ditem.Width;
- end
- else begin
- MoveRightTo := 1;
- X := ditem.Left;
- end;
- DrawItemNo := i;
- if (i=CaretDrawItemNo) and (DLOffs<0) then
- CaretOffs := CharEnds.Count-1;
- end;
- max := 0;
- if (item.StyleNo>=0) and (Items[ditem.ItemNo]<>'') then begin
- GetRVStyle.ApplyStyle(Canvas, item.StyleNo, GetParaBiDiMode(item.ParaNo), True);
- s := DrawItems.GetString(i,Items);
- s := RV_ReturnProcessedString(s, GetRVStyle.TextStyles[item.StyleNo],
- IsDrawItemLastOnWrappedLine(i), rvoShowSpecialCharacters in Options, False);
- GetMem(arr, (ditem.Length+2)*sizeof(Integer));
- try
- RVU_GetTextExtentExPoint(Canvas, s,
- ditem.Width*10, max, arr, item.ItemOptions);
- {$IFNDEF RVDONOTUSEUNICODE}
- if RVNT and (rvioUnicode in item.ItemOptions) then begin
- SetLength(s, Length(s)+1);
- s[Length(s)] := #0;
- PStart := Pointer(s);
- PCur := PStart;
- prevj := 0;
- while PWord(PCur)^<>0 do begin
- with TRVCharPos(CharEnds.Add) do begin
- j := (PChar(PCur)-PChar(PStart)) div 2;
- Offset := j+2;
- MoveRightTo := 1;
- X := ditem.Left+arr[j]
- {$IFNDEF RVDONOTUSEJUSTIFY}+ditem.SpaceBefore{$ENDIF}
- ;
- DrawItemNo := i;
- if j>prevj+1 then begin
- TRVCharPos(CharEnds.Items[CharEnds.Count-2]).X := ditem.Left+arr[j-1]
- {$IFNDEF RVDONOTUSEJUSTIFY}+ditem.SpaceBefore{$ENDIF}
- ;
- TRVCharPos(CharEnds.Items[CharEnds.Count-2]).Offset := j-1+2;
- end;
- if (i=CaretDrawItemNo) then begin
- if (j=DLOffs) then
- CaretOffs := CharEnds.Count-1
- else if (j>DLOffs) and (prevj<DLOffs) then
- CaretOffs := CharEnds.Count-2;
- end;
- prevj := j;
- end;
- PCur := CharNextW(PCur);
- end;
- CharEnds.Items[CharEnds.Count-1].Free;
- end
- else
- {$ENDIF}
- for j := 0 to max-2 do
- with TRVCharPos(CharEnds.Add) do begin
- Offset := j+2;
- MoveRightTo := 1;
- X := ditem.Left+arr[j]
- {$IFNDEF RVDONOTUSEJUSTIFY}+ditem.SpaceBefore{$ENDIF}
- ;
- DrawItemNo := i;
- if (i=CaretDrawItemNo) and (j=DLOffs) then
- CaretOffs := CharEnds.Count-1;
- end;
- finally
- FreeMem(arr);
- end;
- end;
- with TRVCharPos(CharEnds.Add) do begin
- DrawItemNo := i;
- Offset := GetOffsAfterDrawItem(DrawItemNo);
- if (item.StyleNo<0) and (BiDiMode=rvbdRightToLeft) then begin
- X := ditem.Left;
- MoveRightTo := 1;
- end
- else begin
- X := ditem.Left+ditem.Width;
- if item.StyleNo<0 then
- MoveRightTo := 2
- else
- MoveRightTo := 1;
- end;
- if (i=CaretDrawItemNo-1) and (DLOffs<0) or
- (i=CaretDrawItemNo) and (DLOffs>max-2) then
- CaretOffs := CharEnds.Count-1;
- end;
- end;
- {........................................................}
- function AdvancedBuildCaretPositions(Canvas: TCanvas; i: Integer): Boolean;
- var
- item: TCustomRVItemInfo;
- ditem: TRVDrawLineInfo;
- arr: PRVIntegerArray;
- strt, j: Integer;
- s: String;
- {$IFNDEF RVDONOTUSEUNICODE}
- PStart, PCur: Pointer;
- prevj: Integer;
- {$ENDIF}
- begin
- Result := True;
- ditem := DrawItems[i];
- item := GetItem(ditem.ItemNo);
- if (item.StyleNo<0) or (Items[ditem.ItemNo]='') then begin
- SimpleBuildCaretPositions(Canvas, i);
- exit;
- end;
- s := DrawItems.GetString(i,Items);
- s := RV_ReturnProcessedString(s, GetRVStyle.TextStyles[item.StyleNo],
- IsDrawItemLastOnWrappedLine(i), rvoShowSpecialCharacters in Options, False);
- GetMem(arr, (ditem.Length+1)*sizeof(Integer));
- try
- GetRVStyle.ApplyStyle(Canvas, item.StyleNo, GetParaBiDiMode(item.ParaNo), True);
- Result := RVU_GetTextCaretPos(Canvas, s, arr, item.ItemOptions,
- ditem.Width{$IFNDEF RVDONOTUSEJUSTIFY}-ditem.SpaceBefore{$ENDIF});
- if Result then begin
- {$IFNDEF RVDONOTUSEUNICODE}
- if RVNT and (rvioUnicode in item.ItemOptions) then begin
- SetLength(s, Length(s)+1);
- s[Length(s)] := #0;
- PStart := Pointer(s);
- PCur := PStart;
- prevj := 0;
- if i>First then
- PCur := CharNextW(Pointer(PCur));
- while True do
- with TRVCharPos(CharEnds.Add) do begin
- j := (PChar(PCur)-PChar(PStart)) div 2;
- Offset := j+1;
- MoveRightTo := 0;
- X := ditem.Left+arr[j];
- {$IFNDEF RVDONOTUSEJUSTIFY}inc(X,ditem.SpaceBefore);{$ENDIF}
- DrawItemNo := i;
- if ((i=CaretDrawItemNo) and (DLOffs<0) and (j=0)) or
- ((i=CaretDrawItemNo) and ((j-1=DLOffs))) or
- ((i=CaretDrawItemNo-1) and (DLOffs<0) and (j=ditem.Length)) or
- ((i=CaretDrawItemNo) and (DLOffs>ditem.Length-2) and (j=ditem.Length)) then
- CaretOffs := CharEnds.Count-1
- else if (i=CaretDrawItemNo) and (CharEnds.Count>1) and (j-1>DLOffs) and (prevj-1<DLOffs) then
- CaretOffs := CharEnds.Count-2;
- prevj := j;
- if PWord(PCur)^=0 then
- break;
- PCur := CharNextW(PCur);
- end;
- end
- else
- {$ENDIF}
- begin
- strt := 0;
- if i>First then
- inc(strt);
- for j := strt to ditem.Length do
- with TRVCharPos(CharEnds.Add) do begin
- Offset := j+1;
- MoveRightTo := 0;
- X := ditem.Left+arr[j];
- {$IFNDEF RVDONOTUSEJUSTIFY}inc(X,ditem.SpaceBefore);{$ENDIF}
- DrawItemNo := i;
- if ((i=CaretDrawItemNo) and (DLOffs<0) and (j=0)) or
- ((i=CaretDrawItemNo) and (j-1=DLOffs)) or
- ((i=CaretDrawItemNo-1) and (DLOffs<0) and (j=ditem.Length)) or
- ((i=CaretDrawItemNo) and (DLOffs>ditem.Length-2) and (j=ditem.Length)) then
- CaretOffs := CharEnds.Count-1;
- end;
- end;
- end;
- finally
- FreeMem(arr);
- end;
- end;
- {........................................................}
- begin
- {$IFDEF RVDEBUG}{$I Debugh.inc}{$ENDIF}
- Canvas := GetCanvas;
- CharEnds.Clear;
- if CaretDrawItemNo = -1 then exit;
- CaretOffs := VARGE_VALUE;
- GetScreenLineBounds(CaretDrawItemNo, First, Last);
- {$IFNDEF RVDONOTUSELISTS}
- if GetDrawItemStyle(First)=rvsListMarker then begin
- if CaretDrawItemNo=First then begin
- inc(CaretDrawItemNo);
- DLOffs := GetOffsBeforeDrawItem(CaretDrawItemNo)-2;
- end;
- inc(First);
- end;
- {$ENDIF}
- for i := First to Last do
- if (GetItemBiDiMode(DrawItems[i].ItemNo)=rvbdUnspecified) or not AdvancedBuildCaretPositions(Canvas, i) then
- SimpleBuildCaretPositions(Canvas, i);
- end;
- {------------------------------------------------------------------------------}
- procedure TRVEditRVData.ChangeCaret(ForceCreate, ScrollToCaret, DontChangeStyle, RefreshBefore: Boolean);
- var NewHeight: Integer;
- cx, cy: Integer;
- item: TCustomRVItemInfo;
- {...........................................................}
- procedure MakeHot(JumpIndex: Integer);
- begin
- if not (rvoNoCaretHighlightJumps in
- TCustomRichViewEdit(FRichView).EditorOptions) then begin
- LastJumpMovedAbove := JumpIndex;
- State := State + [rvstDrawHover];
- Invalidate;
- end;
- end;
- {...........................................................}
- procedure MakeCold;
- begin
- if rvstDrawHover in State then begin
- LastJumpMovedAbove := -1;
- State := State - [rvstDrawHover];
- Invalidate;
- end;
- end;
- {...........................................................}
- procedure SwitchStyle(item: TCustomRVItemInfo);
- var NewStyleNo, ActNewStyleNo: Integer;
- begin
- if not DontChangeStyle then begin
- if item.StyleNo>=0 then begin
- NewStyleNo := item.StyleNo;
- ActNewStyleNo := GetActualStyle(item);
- end
- else begin
- NewStyleNo := item.AssociatedTextStyleNo;
- if (NewStyleNo<0) or not item.GetBoolValue(rvbpSwitchToAssStyleNo) then
- exit;
- ActNewStyleNo := NewStyleNo;
- end;
- if rvprDoNotAutoSwitch in GetRVStyle.TextStyles[ActNewStyleNo].Protection then begin
- if not (rvprDoNotAutoSwitch in GetRVStyle.TextStyles[FPrevTextStyleNo].Protection) then
- SetCurTextStyleNo(FPrevTextStyleNo)
- end
- else begin
- SetCurTextStyleNo(NewStyleNo);
- FPrevTextStyleNo := NewStyleNo;
- end;
- end;
- end;
- {...........................................................}
- begin
- if rvstSkipformatting in State then exit;
- if RefreshBefore then begin
- UpdateResizer;
- UpdateView;
- end;
- if (FPartialSelectedItem<>nil) or
- (TCustomRichView(FRichView).InplaceEditor<>nil) or
- (rvstCompletelySelected in State)
- then begin
- HideCaret(GetParentControl.Handle);
- TCustomRichViewEdit(FRichView).AfterCaretMove;
- exit;
- end;
- cx := 0; cy := 0; {<- avoiding warnings}
- if FResizer=nil then begin
- if CaretDrawItemNo=-1 then
- NewHeight := 0
- else begin
- if (CaretOffs<0) or (CaretOffs>=CharEnds.Count) then begin
- CaretDrawItemNo := 0;
- CaretOffs := 0;
- {$IFNDEF RVDONOTUSELISTS}
- AdjustMarkerCaret(True, CaretOffs);
- {$ENDIF}
- OnChangeCaretLine(CaretOffs-2);
- raise ERichViewError.Create(errRVCaretPosition);
- end;
- CaretDrawItemNo := CharEnds.Items[CaretOffs].DrawItemNo;
- NewHeight := DrawItems[CaretDrawItemNo].Height+2;
- if NewHeight>RichViewEditMaxCaretHeight then
- NewHeight := RichViewEditMaxCaretHeight;
- with CharEnds.Items[CaretOffs] do begin
- cx := X-1+MoveRightTo;
- cy := DrawItems[CaretDrawItemNo].Top-1;
- end;
- end;
- if (CaretHeight<>NewHeight) or ForceCreate or True {!!!} then begin
- if (CaretHeight<>0) and GetParentControl.Focused then begin
- HideCaret(GetParentControl.Handle);
- DestroyCaret;
- end;
- if (NewHeight<>0) and
- {$IFNDEF RVDONOTUSEDRAGDROP}
- (GetDragDropCaretInfo=nil) and
- {$ENDIF}
- not (TCustomRichViewEdit(FRichView).ReadOnly and
- (rvoHideReadOnlyCaret in TCustomRichViewEdit(FRichView).EditorOptions)) and
- GetParentControl.Focused then begin
- CreateCaret(GetParentControl.Handle, 0,
- {MulDiv(}RichViewEditCaretWidth{,ZoomPercent,100)},
- {MulDiv(}NewHeight+RichViewEditCaretHeightExtra*2{,ZoomPercent,100)});
- SetCaretPos({MulDiv(}cx-GetHOffs-RichViewEditCaretWidth div 2{, ZoomPercent,100)},
- {MulDiv(}cy-GetVOffs+DrawItems[CaretDrawItemNo].Height+1-RichViewEditCaretHeightExtra-NewHeight{,ZoomPercent,100)});
- ShowCaret(GetParentControl.Handle);
- end;
- CaretHeight := NewHeight;
- end
- else begin
- if (NewHeight<>0) {and Focused} then begin
- if GetParentControl.Focused then SetCaretPos({MulDiv(}cx-GetHOffs-RichViewEditCaretWidth div 2{,ZoomPercent,100)},
- {MulDiv(}cy-GetVOffs+DrawItems[CaretDrawItemNo].Height+1+RichViewEditCaretHeightExtra-NewHeight{,ZoomPercent,100)});
- end;
- end;
- end
- else begin
- HideCaret(GetParentControl.Handle);
- TCustomRichViewEdit(FRichView).AfterCaretMove;
- end;
- if (CaretDrawItemNo<>-1) then begin
- item := GetItem(DrawItems[CaretDrawItemNo].ItemNo);
- if not DontChangeStyle then
- SetCurParaStyleNo(item.ParaNo);
- if item.GetBoolValue(rvbpDisplayActiveState) then begin
- FActiveItem := item;
- Invalidate;
- end
- else
- if FActiveItem<>nil then begin
- FActiveItem := nil;
- invalidate;
- end;
- if (FSelStartNo>=0) and (FSelEndNo>=0) and
- ((FSelStartNo>FSelEndNo) or ((FSelStartNo=FSelEndNo)and(FSelStartOffs>FSelEndOffs))) and
- (FSelEndOffs>=GetOffsAfterDrawItem(FSelEndNo)) and (FSelEndNo+1<DrawItems.Count) and
- GetItem(DrawItems[FSelEndNo+1].ItemNo).SameAsPrev then
- item := GetItem(DrawItems[FSelEndNo+1].ItemNo);
- SwitchStyle(item);
- if (item.StyleNo>=0) then begin
- if item.GetBoolValueEx(rvbpHotColdJump, GetRVStyle) then
- MakeHot(item.JumpID)
- else
- MakeCold;
- end
- else begin
- if item.GetBoolValueEx(rvbpHotColdJump, GetRVStyle) then
- MakeHot(item.JumpID)
- else
- MakeCold;
- end;
- end;
- if (FResizer=nil) and ScrollToCaret and {Focused and} (CaretHeight<>0) and (CaptureMouseItem=nil) then begin { scrolling to caret pos }
- ShowRectangle(cx, cy, 5, CaretHeight);
- end;
- TCustomRichViewEdit(FRichView).AfterCaretMove;
- end;
- {------------------------------------------------------------------------------}
- // Ctrl is not used
- procedure TRVEditRVData.OnDeletePress_(Ctrl: Boolean; MovedFromLineEnd: Boolean);
- {.....................................................................}
- procedure AdjustCaret(SavedCaretNo, SavedCaretOffs: Integer; ApplyPara: Boolean);
- begin
- Item2DrawItem(SavedCaretNo, SavedCaretOffs, CaretDrawItemNo, SavedCaretOffs);
- {$IFNDEF RVDONOTUSELISTS}
- AdjustMarkerCaret(True, SavedCaretOffs);
- {$ENDIF}
- OnChangeCaretLine(SavedCaretOffs-2);
- ChangeCaret(False,True,False,True);
- if ApplyPara then
- ApplyParaStyle(FCurParaStyleNo, rvscParaStyle);
- end;
- {.....................................................................}
- // Deleting current empty string
- // This string can be at the position of caret (CaretToTheNext=True,
- // because caret will be moved to the next item after deleting)
- // or the next line (CaretToTheNext=False)
- // If (ItemNo-1)-th item is a marker, this function deletes it as well.
- procedure Del_DeleteEmptyString(ItemNo, First, Last: Integer;
- CaretToTheNext: Boolean);
- var FullReformat,FR: Boolean;
- ItemsAdded : Integer;
- SavedCaretNo, SavedCaretOffs: Integer;
- {$IFNDEF RVDONOTUSELISTS}
- M_FirstItemNo, M_MarkerIndex: Integer;
- M_ListNos: TRVIntegerList;
- {$ENDIF}
- begin
- if not TCustomRichViewEdit(RichView).BeforeChange(False) then
- exit;
- if IsProtected(ItemNo, rvprDeleteProtect) or
- IsItemParaProtected(ItemNo) or
- ParaHasPersistentCheckpoint(ItemNo) then begin
- Beep;
- exit;
- end;
- {$IFNDEF RVDONOTUSELISTS}
- if (ItemNo>0) and (GetItemStyle(ItemNo-1)=rvsListMarker) and
- IsProtected(ItemNo-1, rvprDeleteProtect) then begin
- Beep;
- exit;
- end;
- {$ENDIF}
- FullReformat := False;
- if CaretToTheNext and (ItemNo<Items.Count-1) and not GetItem(ItemNo).BR then begin
- Do_BR(ItemNo+1,False,FR);
- FullReformat := FullReformat or FR;
- end;
- ItemsAdded := -1;
- {$IFNDEF RVDONOTUSELISTS}
- M_FirstItemNo := -1;
- M_MarkerIndex := -1;
- M_ListNos := nil;
- if (ItemNo>0) and (GetItemStyle(ItemNo-1)=rvsListMarker) then begin
- {$IFNDEF RVDONOTUSELISTS}
- PrepareForUpdateRangeAfterMarkers(ItemNo-1, ItemNo-1, True, M_FirstItemNo, M_MarkerIndex, M_ListNos);
- {$ENDIF}
- Do_DeleteItem(ItemNo, FR);
- FullReformat := FullReformat or FR;
- dec(ItemsAdded);
- dec(ItemNo);
- end;
- {$ENDIF}
- Do_DeleteItem(ItemNo, FR);
- {$IFNDEF RVDONOTUSELIVESPELL}
- if ItemNo<ItemCount then
- LaterSetBackLiveSpellingTo(ItemNo, 0, False);
- {$ENDIF}
- FullReformat := FullReformat or FR;
- if CaretToTheNext then begin
- SavedCaretNo := ItemNo;
- if SavedCaretNo=Items.Count then begin
- dec(SavedCaretNo);
- SavedCaretOffs := GetOffsAfterItem(SavedCaretNo);
- end
- else begin
- {$IFNDEF RVDONOTUSELISTS}
- if GetItemStyle(SavedCaretNo)=rvsListMarker then
- inc(SavedCaretNo);
- {$ENDIF}
- SavedCaretOffs := GetOffsBeforeItem(SavedCaretNo);
- end;
- end
- else begin
- SavedCaretNo := ItemNo-1;
- SavedCaretOffs := GetOffsAfterItem(SavedCaretNo);
- end;
- Reformat_(FullReformat, First, Last, ItemsAdded);
- AdjustCaret(SavedCaretNo, SavedCaretOffs, not CaretToTheNext);
- {$IFNDEF RVDONOTUSELISTS}
- if not FullReformat then
- UpdateAfterMarkers(M_FirstItemNo, M_MarkerIndex, M_ListNos, -1);
- {$ENDIF}
- end;
- {.................................................................}
- // Concatenating two text items into one
- // This function is called only if caret is at the end of line,
- // and the last item in this line and the first item in the next line
- // can be combined.
- procedure Del_ConcateItems(ItemNo, First, Last: Integer);
- var ItemsAdded, OldWidth : Integer;
- SavedCaretOffs: Integer;
- begin
- if not TCustomRichViewEdit(RichView).BeforeChange(False) then
- exit;
- if IsItemParaProtected(ItemNo) or IsItemParaProtected(ItemNo+1) or
- IsProtected(ItemNo+1, rvprParaStartProtect) or
- ParaHasPersistentCheckpoint(ItemNo+1) then begin
- Beep;
- exit;
- end;
- OldWidth := CalculateParaSectionMinWidthDef(ItemNo);
- SavedCaretOffs := GetOffsAfterItem(ItemNo);
- Do_Concate(ItemNo);
- {$IFNDEF RVDONOTUSELIVESPELL}
- LaterSetBackLiveSpellingTo(ItemNo, SavedCaretOffs, True);
- {$ENDIF}
- ItemsAdded := -1;
- Reformat_((OldWidth>=DocumentWidth), First, Last, ItemsAdded);
- AdjustCaret(ItemNo, SavedCaretOffs, True);
- end;
- {.................................................................}
- // Moving the next item to the end of current paragraph
- // This function is called only if caret is at the end of line
- // If next item is a marker, it is deleted
- procedure Del_MoveToThis(ItemNo, First, Last: Integer);
- var ItemsAdded : Integer;
- SavedCaretOffs: Integer;
- FullReformat1,FullReformat2: Boolean;
- {$IFNDEF RVDONOTUSELISTS}
- M_FirstItemNo, M_MarkerIndex: Integer;
- M_ListNos: TRVIntegerList;
- {$IFNDEF RVDONOTUSELIVESPELL}
- Len: Integer;
- {$ENDIF}
- {$ENDIF}
- begin
- if not TCustomRichViewEdit(RichView).BeforeChange(False) then
- exit;
- if IsItemParaProtected(ItemNo) or IsItemParaProtected(ItemNo+1) or
- IsProtected(ItemNo+1, rvprParaStartProtect) or
- ParaHasPersistentCheckpoint(ItemNo+1) then begin
- Beep;
- exit;
- end;
- {$IFNDEF RVDONOTUSELISTS}
- if (GetItemStyle(ItemNo+1)=rvsListMarker) and
- IsProtected(ItemNo+1, rvprDeleteProtect) then begin
- Beep;
- exit;
- end;
- {$ENDIF}
- FullReformat2 := False;
- Do_NewLine(ItemNo+1, True,-1, FullReformat1);
- ItemsAdded := 0;
- SavedCaretOffs := GetOffsAfterItem(ItemNo);
- {$IFNDEF RVDONOTUSELISTS}
- M_FirstItemNo := -1;
- M_MarkerIndex := -1;
- M_ListNos := nil;
- if GetItemStyle(ItemNo+1)=rvsListMarker then begin
- PrepareForUpdateRangeAfterMarkers(ItemNo+1, ItemNo+1, True, M_FirstItemNo, M_MarkerIndex, M_ListNos);
- Do_DeleteItem(ItemNo+1, FullReformat2);
- dec(ItemsAdded);
- if (ItemNo+1<Items.Count) then begin
- if RV_CanConcateItems(ItemNo, GetItem(ItemNo), GetItem(ItemNo+1), False) then begin
- {$IFNDEF RVDONOTUSELIVESPELL}
- Len := ItemLength(ItemNo);
- {$ENDIF}
- Do_Concate(ItemNo);
- {$IFNDEF RVDONOTUSELIVESPELL}
- LaterSetBackLiveSpellingTo(ItemNo, Len+1, True);
- {$ENDIF}
- dec(ItemsAdded);
- end
- {$IFNDEF RVDONOTUSELIVESPELL}
- else begin
- LaterSetBackLiveSpellingTo(ItemNo+1, 0, False);
- end;
- {$ENDIF}
- end
- end;
- {$ENDIF}
- Reformat_(FullReformat1 or FullReformat2, First, Last, ItemsAdded);
- AdjustCaret(ItemNo, SavedCaretOffs, True);
- {$IFNDEF RVDONOTUSELISTS}
- if not (FullReformat1 or FullReformat2) then
- UpdateAfterMarkers(M_FirstItemNo, M_MarkerIndex, M_ListNos, -1);
- {$ENDIF}
- end;
- {.................................................................}
- // Actions at the end of line.
- // This procedure is never called at the end of document, so next item
- // must exist.
- procedure Del_AtTheEndOfParaSection(ItemNo, First, Last: Integer);
- begin
- if (GetItemStyle(ItemNo)>=0) and (ItemLength(ItemNo)=0) then // delete current empty string
- Del_DeleteEmptyString(ItemNo, First, Last, True)
- else if (GetItemStyle(ItemNo+1)>=0) and
- (ItemLength(ItemNo+1)=0) then // delete next empty string
- Del_DeleteEmptyString(ItemNo+1, First, Last, False)
- else if RV_CanConcateItems(ItemNo, GetItem(ItemNo), GetItem(ItemNo+1), True) then
- Del_ConcateItems(ItemNo, First, Last)
- else // move next item to the previous line
- Del_MoveToThis(ItemNo, First, Last)
- end;
- {.................................................................}
- // This procedure is called when caret is not at the end of line (i.e. paragraph section)
- // It can be at the end of screen line, though
- procedure Del_AtTheMiddle(dli: TRVDrawLineInfo; First, Last: Integer);
- begin
- if (CaretOffs=CharEnds.Count-1) then begin // we are at the end of screen line, but not item
- if (dli.ItemNo <> DrawItems[CaretDrawItemNo+1].ItemNo) or
- (DrawItems[CaretDrawItemNo+1].Offs>dli.Offs+dli.Length) then begin
- inc(CaretDrawItemNo); // space character was "eaten" between screen Items
- OnChangeCaretLine(0);
- CaretOffs := 0;
- OnBackspacePress_(False, True, False);
- ChangeCaret(False,True,False,True);
- end
- else begin
- inc(CaretDrawItemNo);
- OnChangeCaretLine(0);
- CaretOffs := 0;
- OnDeletePress_(False, True);
- ChangeCaret(False,True,False,True);
- end;
- end
- else begin
- // "if" checks a special case when space char was "eaten" at the beginning of line
- if not (MovedFromLineEnd and
- (dli.ItemNo<>DrawItems[CaretDrawItemNo-1].ItemNo) and
- (dli.Offs>1)) then
- CaretOffs := CaretOffs+1;
- OnBackSpacePress_(False, True, False);
- ChangeCaret(False,True,False,True);
- end;
- end;
- {.................................................................}
- var dli: TRVDrawLineInfo;
- First, Last: Integer;
- begin
- CaretDrawItemNo := CharEnds.Items[CaretOffs].DrawItemNo;
- dli := DrawItems[CaretDrawItemNo];
- with Items.Objects[dli.ItemNo] as TCustomRVItemInfo do begin
- if IsParaProtected(ParaNo,rvpaoReadOnly) then begin
- Beep;
- exit;
- end;
- if (CaretOffs=CharEnds.Count-1) and
- (
- (StyleNo<0) or
- (dli.Offs+CharEnds.Items[CaretOffs].Offset-1>ItemLength(dli.ItemNo))
- ) then begin
- { we are at the end of item and screen line }
- if GetBoolValue(rvbpFullWidth) or
- (
- (dli.ItemNo+1<Items.Count) and
- (GetItem(dli.ItemNo+1).GetBoolValue(rvbpFullWidth)) and
- not ((StyleNo>=0) and (ItemLength(dli.ItemNo)=0))
- )
- then begin
- OnRightPress(False,False);
- exit;