|
@@ -0,0 +1,3733 @@
|
|
|
+unit Editors;
|
|
|
+
|
|
|
+{$i platform.inc}
|
|
|
+
|
|
|
+{$ifdef PPC_FPC}
|
|
|
+ {$H-}
|
|
|
+{$else}
|
|
|
+ {$F+,O+,E+,N+}
|
|
|
+{$endif}
|
|
|
+{$X+,R-,I-,Q-,V-}
|
|
|
+{$ifndef OS_LINUX}
|
|
|
+ {$S-}
|
|
|
+{$endif}
|
|
|
+
|
|
|
+
|
|
|
+{$define UNIXLF}
|
|
|
+
|
|
|
+interface
|
|
|
+
|
|
|
+uses
|
|
|
+ Objects, Drivers,Views,Dialogs,FVCommon,FVConsts;
|
|
|
+
|
|
|
+const
|
|
|
+ { Length constants. }
|
|
|
+ Tab_Stop_Length = 74;
|
|
|
+
|
|
|
+{$ifdef PPC_BP}
|
|
|
+ MaxLineLength = 1024;
|
|
|
+ MinBufLength = $1000;
|
|
|
+ MaxBufLength = $ff00;
|
|
|
+ NotFoundValue = $ffff;
|
|
|
+ LineInfoGrow = 256;
|
|
|
+ MaxLines = 16000;
|
|
|
+{$else}
|
|
|
+ MaxLineLength = 4096;
|
|
|
+ MinBufLength = $1000;
|
|
|
+ MaxBufLength = $7fffff00;
|
|
|
+ NotFoundValue = $ffffffff;
|
|
|
+ LineInfoGrow = 1024;
|
|
|
+ MaxLines = $7ffffff;
|
|
|
+{$endif}
|
|
|
+
|
|
|
+
|
|
|
+ { Editor constants for dialog boxes. }
|
|
|
+ edOutOfMemory = 0;
|
|
|
+ edReadError = 1;
|
|
|
+ edWriteError = 2;
|
|
|
+ edCreateError = 3;
|
|
|
+ edSaveModify = 4;
|
|
|
+ edSaveUntitled = 5;
|
|
|
+ edSaveAs = 6;
|
|
|
+ edFind = 7;
|
|
|
+ edSearchFailed = 8;
|
|
|
+ edReplace = 9;
|
|
|
+ edReplacePrompt = 10;
|
|
|
+
|
|
|
+ edJumpToLine = 11;
|
|
|
+ edPasteNotPossible = 12;
|
|
|
+ edReformatDocument = 13;
|
|
|
+ edReformatNotAllowed = 14;
|
|
|
+ edReformNotPossible = 15;
|
|
|
+ edReplaceNotPossible = 16;
|
|
|
+ edRightMargin = 17;
|
|
|
+ edSetTabStops = 18;
|
|
|
+ edWrapNotPossible = 19;
|
|
|
+
|
|
|
+ { Editor flag constants for dialog options. }
|
|
|
+ efCaseSensitive = $0001;
|
|
|
+ efWholeWordsOnly = $0002;
|
|
|
+ efPromptOnReplace = $0004;
|
|
|
+ efReplaceAll = $0008;
|
|
|
+ efDoReplace = $0010;
|
|
|
+ efBackupFiles = $0100;
|
|
|
+
|
|
|
+ { Constants for object palettes. }
|
|
|
+ CIndicator = #2#3;
|
|
|
+ CEditor = #6#7;
|
|
|
+ CMemo = #26#27;
|
|
|
+
|
|
|
+type
|
|
|
+ TEditorDialog = function (Dialog : Integer; Info : Pointer) : Word;
|
|
|
+
|
|
|
+ PIndicator = ^TIndicator;
|
|
|
+ TIndicator = object (TView)
|
|
|
+ Location : Objects.TPoint;
|
|
|
+ Modified : Boolean;
|
|
|
+ AutoIndent : Boolean; { Added boolean for AutoIndent mode. }
|
|
|
+ WordWrap : Boolean; { Added boolean for WordWrap mode. }
|
|
|
+ constructor Init (var Bounds : TRect);
|
|
|
+ procedure Draw; virtual;
|
|
|
+ function GetPalette : PPalette; virtual;
|
|
|
+ procedure SetState (AState : Word; Enable : Boolean); virtual;
|
|
|
+ procedure SetValue (ALocation : Objects.TPoint; IsAutoIndent : Boolean;
|
|
|
+ IsModified : Boolean;
|
|
|
+ IsWordWrap : Boolean);
|
|
|
+ end;
|
|
|
+
|
|
|
+ TLineInfoRec = record
|
|
|
+ Len,Attr : Sw_word;
|
|
|
+ end;
|
|
|
+ TLineInfoArr = array[0..MaxLines] of TLineInfoRec;
|
|
|
+ PLineInfoArr = ^TLineInfoArr;
|
|
|
+
|
|
|
+ PLineInfo = ^TLineInfo;
|
|
|
+ TLineInfo = object
|
|
|
+ Info : PLineInfoArr;
|
|
|
+ MaxPos : Sw_Word;
|
|
|
+ constructor Init;
|
|
|
+ destructor Done;
|
|
|
+ procedure Grow(pos:Sw_word);
|
|
|
+ procedure SetLen(pos,val:Sw_Word);
|
|
|
+ procedure SetAttr(pos,val:Sw_Word);
|
|
|
+ function GetLen(pos:Sw_Word):Sw_Word;
|
|
|
+ function GetAttr(pos:Sw_Word):Sw_Word;
|
|
|
+ end;
|
|
|
+
|
|
|
+
|
|
|
+ PEditBuffer = ^TEditBuffer;
|
|
|
+ TEditBuffer = array[0..MaxBufLength] of Char;
|
|
|
+
|
|
|
+ PEditor = ^TEditor;
|
|
|
+ TEditor = object (TView)
|
|
|
+ HScrollBar : PScrollBar;
|
|
|
+ VScrollBar : PScrollBar;
|
|
|
+ Indicator : PIndicator;
|
|
|
+ Buffer : PEditBuffer;
|
|
|
+ BufSize : Sw_Word;
|
|
|
+ BufLen : Sw_Word;
|
|
|
+ GapLen : Sw_Word;
|
|
|
+ SelStart : Sw_Word;
|
|
|
+ SelEnd : Sw_Word;
|
|
|
+ CurPtr : Sw_Word;
|
|
|
+ CurPos : Objects.TPoint;
|
|
|
+ Delta : Objects.TPoint;
|
|
|
+ Limit : Objects.TPoint;
|
|
|
+ DrawLine : Sw_Integer;
|
|
|
+ DrawPtr : Sw_Word;
|
|
|
+ DelCount : Sw_Word;
|
|
|
+ InsCount : Sw_Word;
|
|
|
+ Flags : Longint;
|
|
|
+ IsReadOnly : Boolean;
|
|
|
+ IsValid : Boolean;
|
|
|
+ CanUndo : Boolean;
|
|
|
+ Modified : Boolean;
|
|
|
+ Selecting : Boolean;
|
|
|
+ Overwrite : Boolean;
|
|
|
+ AutoIndent : Boolean;
|
|
|
+ NoSelect : Boolean;
|
|
|
+ TabSize : Sw_Word; { tabsize for displaying }
|
|
|
+ BlankLine : Sw_Word; { First blank line after a paragraph. }
|
|
|
+ Word_Wrap : Boolean; { Added boolean to toggle wordwrap on/off. }
|
|
|
+ Line_Number : string[8]; { Holds line number to jump to. }
|
|
|
+ Right_Margin : Sw_Integer; { Added integer to set right margin. }
|
|
|
+ Tab_Settings : String[Tab_Stop_Length]; { Added string to hold tab stops. }
|
|
|
+
|
|
|
+ constructor Init (var Bounds : TRect; AHScrollBar, AVScrollBar : PScrollBar;
|
|
|
+ AIndicator : PIndicator; ABufSize : Sw_Word);
|
|
|
+ constructor Load (var S : Objects.TStream);
|
|
|
+ destructor Done; virtual;
|
|
|
+ function BufChar (P : Sw_Word) : Char;
|
|
|
+ function BufPtr (P : Sw_Word) : Sw_Word;
|
|
|
+ procedure ChangeBounds (var Bounds : TRect); virtual;
|
|
|
+ procedure ConvertEvent (var Event : Drivers.TEvent); virtual;
|
|
|
+ function CursorVisible : Boolean;
|
|
|
+ procedure DeleteSelect;
|
|
|
+ procedure DoneBuffer; virtual;
|
|
|
+ procedure Draw; virtual;
|
|
|
+ procedure FormatLine (var DrawBuf; LinePtr : Sw_Word; Width : Sw_Integer; Colors : Word);virtual;
|
|
|
+ function GetPalette : PPalette; virtual;
|
|
|
+ procedure HandleEvent (var Event : Drivers.TEvent); virtual;
|
|
|
+ procedure InitBuffer; virtual;
|
|
|
+ function InsertBuffer (var P : PEditBuffer; Offset, Length : Sw_Word;AllowUndo, SelectText : Boolean) : Boolean;
|
|
|
+ function InsertFrom (Editor : PEditor) : Boolean; virtual;
|
|
|
+ function InsertText (Text : Pointer; Length : Sw_Word; SelectText : Boolean) : Boolean;
|
|
|
+ procedure ScrollTo (X, Y : Sw_Integer);
|
|
|
+ function Search (const FindStr : String; Opts : Word) : Boolean;
|
|
|
+ function SetBufSize (NewSize : Sw_Word) : Boolean; virtual;
|
|
|
+ procedure SetCmdState (Command : Word; Enable : Boolean);
|
|
|
+ procedure SetSelect (NewStart, NewEnd : Sw_Word; CurStart : Boolean);
|
|
|
+ procedure SetCurPtr (P : Sw_Word; SelectMode : Byte);
|
|
|
+ procedure SetState (AState : Word; Enable : Boolean); virtual;
|
|
|
+ procedure Store (var S : Objects.TStream);
|
|
|
+ procedure TrackCursor (Center : Boolean);
|
|
|
+ procedure Undo;
|
|
|
+ procedure UpdateCommands; virtual;
|
|
|
+ function Valid (Command : Word) : Boolean; virtual;
|
|
|
+
|
|
|
+ private
|
|
|
+ KeyState : Integer;
|
|
|
+ LockCount : Byte;
|
|
|
+ UpdateFlags : Byte;
|
|
|
+ Place_Marker : Array [1..10] of Sw_Word; { Inserted array to hold place markers. }
|
|
|
+ Search_Replace : Boolean; { Added boolean to test for Search and Replace insertions. }
|
|
|
+
|
|
|
+ procedure Center_Text (Select_Mode : Byte);
|
|
|
+ function CharPos (P, Target : Sw_Word) : Sw_Integer;
|
|
|
+ function CharPtr (P : Sw_Word; Target : Sw_Integer) : Sw_Word;
|
|
|
+ procedure Check_For_Word_Wrap (Select_Mode : Byte; Center_Cursor : Boolean);
|
|
|
+ function ClipCopy : Boolean;
|
|
|
+ procedure ClipCut;
|
|
|
+ procedure ClipPaste;
|
|
|
+ procedure DeleteRange (StartPtr, EndPtr : Sw_Word; DelSelect : Boolean);
|
|
|
+ procedure DoSearchReplace;
|
|
|
+ procedure DoUpdate;
|
|
|
+ function Do_Word_Wrap (Select_Mode : Byte; Center_Cursor : Boolean) : Boolean;
|
|
|
+ procedure DrawLines (Y, Count : Sw_Integer; LinePtr : Sw_Word);
|
|
|
+ procedure Find;
|
|
|
+ function GetMousePtr (Mouse : Objects.TPoint) : Sw_Word;
|
|
|
+ function HasSelection : Boolean;
|
|
|
+ procedure HideSelect;
|
|
|
+ procedure Insert_Line (Select_Mode : Byte);
|
|
|
+ function IsClipboard : Boolean;
|
|
|
+ procedure Jump_Place_Marker (Element : Byte; Select_Mode : Byte);
|
|
|
+ procedure Jump_To_Line (Select_Mode : Byte);
|
|
|
+ function LineEnd (P : Sw_Word) : Sw_Word;
|
|
|
+ function LineMove (P : Sw_Word; Count : Sw_Integer) : Sw_Word;
|
|
|
+ function LineStart (P : Sw_Word) : Sw_Word;
|
|
|
+ function LineNr (P : Sw_Word) : Sw_Word;
|
|
|
+ procedure Lock;
|
|
|
+ function NewLine (Select_Mode : Byte) : Boolean;
|
|
|
+ function NextChar (P : Sw_Word) : Sw_Word;
|
|
|
+ function NextLine (P : Sw_Word) : Sw_Word;
|
|
|
+ function NextWord (P : Sw_Word) : Sw_Word;
|
|
|
+ function PrevChar (P : Sw_Word) : Sw_Word;
|
|
|
+ function PrevLine (P : Sw_Word) : Sw_Word;
|
|
|
+ function PrevWord (P : Sw_Word) : Sw_Word;
|
|
|
+ procedure Reformat_Document (Select_Mode : Byte; Center_Cursor : Boolean);
|
|
|
+ function Reformat_Paragraph (Select_Mode : Byte; Center_Cursor : Boolean) : Boolean;
|
|
|
+ procedure Remove_EOL_Spaces (Select_Mode : Byte);
|
|
|
+ procedure Replace;
|
|
|
+ procedure Scroll_Down;
|
|
|
+ procedure Scroll_Up;
|
|
|
+ procedure Select_Word;
|
|
|
+ procedure SetBufLen (Length : Sw_Word);
|
|
|
+ procedure Set_Place_Marker (Element : Byte);
|
|
|
+ procedure Set_Right_Margin;
|
|
|
+ procedure Set_Tabs;
|
|
|
+ procedure StartSelect;
|
|
|
+ procedure Tab_Key (Select_Mode : Byte);
|
|
|
+ procedure ToggleInsMode;
|
|
|
+ procedure Unlock;
|
|
|
+ procedure Update (AFlags : Byte);
|
|
|
+ procedure Update_Place_Markers (AddCount : Word; KillCount : Word; StartPtr,EndPtr : Sw_Word);
|
|
|
+ end;
|
|
|
+
|
|
|
+ TMemoData = record
|
|
|
+ Length : Sw_Word;
|
|
|
+ Buffer : TEditBuffer;
|
|
|
+ end;
|
|
|
+
|
|
|
+ PMemo = ^TMemo;
|
|
|
+ TMemo = object (TEditor)
|
|
|
+ constructor Load (var S : Objects.TStream);
|
|
|
+ function DataSize : Sw_Word; virtual;
|
|
|
+ procedure GetData (var Rec); virtual;
|
|
|
+ function GetPalette : PPalette; virtual;
|
|
|
+ procedure HandleEvent (var Event : Drivers.TEvent); virtual;
|
|
|
+ procedure SetData (var Rec); virtual;
|
|
|
+ procedure Store (var S : Objects.TStream);
|
|
|
+ end;
|
|
|
+
|
|
|
+ PFileEditor = ^TFileEditor;
|
|
|
+ TFileEditor = object (TEditor)
|
|
|
+ FileName : FNameStr;
|
|
|
+ constructor Init (var Bounds : TRect; AHScrollBar, AVScrollBar : PScrollBar;
|
|
|
+ AIndicator : PIndicator; AFileName : FNameStr);
|
|
|
+ constructor Load (var S : Objects.TStream);
|
|
|
+ procedure DoneBuffer; virtual;
|
|
|
+ procedure HandleEvent (var Event : Drivers.TEvent); virtual;
|
|
|
+ procedure InitBuffer; virtual;
|
|
|
+ function LoadFile : Boolean;
|
|
|
+ function Save : Boolean;
|
|
|
+ function SaveAs : Boolean;
|
|
|
+ function SaveFile : Boolean;
|
|
|
+ function SetBufSize (NewSize : Sw_Word) : Boolean; virtual;
|
|
|
+ procedure Store (var S : Objects.TStream);
|
|
|
+ procedure UpdateCommands; virtual;
|
|
|
+ function Valid (Command : Word) : Boolean; virtual;
|
|
|
+ end;
|
|
|
+
|
|
|
+ PEditWindow = ^TEditWindow;
|
|
|
+ TEditWindow = object (TWindow)
|
|
|
+ Editor : PFileEditor;
|
|
|
+ constructor Init (var Bounds : TRect; FileName : FNameStr; ANumber : Integer);
|
|
|
+ constructor Load (var S : Objects.TStream);
|
|
|
+ procedure Close; virtual;
|
|
|
+ function GetTitle (MaxSize : Sw_Integer) : TTitleStr; virtual;
|
|
|
+ procedure HandleEvent (var Event : Drivers.TEvent); virtual;
|
|
|
+ procedure SizeLimits(var Min, Max: TPoint); virtual;
|
|
|
+ procedure Store (var S : Objects.TStream);
|
|
|
+ end;
|
|
|
+
|
|
|
+
|
|
|
+function DefEditorDialog (Dialog : Integer; Info : Pointer) : Word;
|
|
|
+function CreateFindDialog: PDialog;
|
|
|
+function CreateReplaceDialog: PDialog;
|
|
|
+function JumpLineDialog : PDialog;
|
|
|
+function ReformDocDialog : PDialog;
|
|
|
+function RightMarginDialog : PDialog;
|
|
|
+function TabStopDialog : Dialogs.PDialog;
|
|
|
+function StdEditorDialog(Dialog: Integer; Info: Pointer): Word;
|
|
|
+
|
|
|
+const
|
|
|
+ WordChars : set of Char = ['!'..#255];
|
|
|
+
|
|
|
+ LineBreak : string[2]=
|
|
|
+{$ifdef UNIXLF}
|
|
|
+ #10;
|
|
|
+{$else}
|
|
|
+ #13#10;
|
|
|
+{$endif}
|
|
|
+
|
|
|
+
|
|
|
+ { The Allow_Reformat boolean is a programmer hook. }
|
|
|
+ { I've placed this here to allow programmers to }
|
|
|
+ { determine whether or not paragraph and document }
|
|
|
+ { reformatting are allowed if Word_Wrap is not }
|
|
|
+ { active. Some people say don't allow, and others }
|
|
|
+ { say allow it. I've left it up to the programmer. }
|
|
|
+ { Set to FALSE if not allowed, or TRUE if allowed. }
|
|
|
+ Allow_Reformat : Boolean = True;
|
|
|
+
|
|
|
+ EditorDialog : TEditorDialog = {$ifdef fpc}@{$endif}DefEditorDialog;
|
|
|
+ EditorFlags : Word = efBackupFiles + efPromptOnReplace;
|
|
|
+ FindStr : String[80] = '';
|
|
|
+ ReplaceStr : String[80] = '';
|
|
|
+ Clipboard : PEditor = nil;
|
|
|
+
|
|
|
+ ToClipCmds : TCommandSet = ([cmCut,cmCopy,cmClear]);
|
|
|
+ FromClipCmds : TCommandSet = ([cmPaste]);
|
|
|
+ UndoCmds : TCommandSet = ([cmUndo,cmRedo]);
|
|
|
+
|
|
|
+TYPE
|
|
|
+ TFindDialogRec = packed record
|
|
|
+ Find : String[80];
|
|
|
+ Options : Word;
|
|
|
+ end;
|
|
|
+
|
|
|
+ TReplaceDialogRec = packed record
|
|
|
+ Find : String[80];
|
|
|
+ Replace : String[80];
|
|
|
+ Options : Word;
|
|
|
+ end;
|
|
|
+
|
|
|
+ TRightMarginRec = packed record
|
|
|
+ Margin_Position : String[3];
|
|
|
+ end;
|
|
|
+
|
|
|
+ TTabStopRec = packed record
|
|
|
+ Tab_String : String [Tab_Stop_Length];
|
|
|
+ end;
|
|
|
+
|
|
|
+CONST
|
|
|
+ { VMT constants. }
|
|
|
+ REditor : TStreamRec = (ObjType : 70;
|
|
|
+ VmtLink : Ofs (TypeOf (TEditor)^);
|
|
|
+ Load : @TEditor.Load;
|
|
|
+ Store : @TEditor.Store);
|
|
|
+
|
|
|
+ RMemo : TStreamRec = (ObjType : 71;
|
|
|
+ VmtLink : Ofs (TypeOf (TMemo)^);
|
|
|
+ Load : @TMemo.Load;
|
|
|
+ Store : @TMemo.Store);
|
|
|
+
|
|
|
+ RFileEditor : TStreamRec = (ObjType : 72;
|
|
|
+ VmtLink : Ofs (TypeOf (TFileEditor)^);
|
|
|
+ Load : @TFileEditor.Load;
|
|
|
+ Store : @TFileEditor.Store);
|
|
|
+
|
|
|
+ RIndicator : TStreamRec = (ObjType : 73;
|
|
|
+ VmtLink : Ofs (TypeOf (TIndicator)^);
|
|
|
+ Load : @TIndicator.Load;
|
|
|
+ Store : @TIndicator.Store);
|
|
|
+
|
|
|
+ REditWindow : TStreamRec = (ObjType : 74;
|
|
|
+ VmtLink : Ofs (TypeOf (TEditWindow)^);
|
|
|
+ Load : @TEditWindow.Load;
|
|
|
+ Store : @TEditWindow.Store);
|
|
|
+
|
|
|
+procedure RegisterEditors;
|
|
|
+
|
|
|
+
|
|
|
+{****************************************************************************
|
|
|
+ Implementation
|
|
|
+****************************************************************************}
|
|
|
+
|
|
|
+implementation
|
|
|
+
|
|
|
+uses
|
|
|
+ Memory, Dos, App, StdDlg, MsgBox, Resource;
|
|
|
+
|
|
|
+type
|
|
|
+ pword = ^word;
|
|
|
+
|
|
|
+CONST
|
|
|
+ { Update flag constants. }
|
|
|
+ ufUpdate = $01;
|
|
|
+ ufLine = $02;
|
|
|
+ ufView = $04;
|
|
|
+ ufStats = $05;
|
|
|
+
|
|
|
+ { SelectMode constants. }
|
|
|
+ smExtend = $01;
|
|
|
+ smDouble = $02;
|
|
|
+
|
|
|
+ sfSearchFailed = NotFoundValue;
|
|
|
+
|
|
|
+ { Arrays that hold all the command keys and options. }
|
|
|
+ FirstKeys : array[0..46 * 2] of Word = (46, Ord (^A), cmWordLeft,
|
|
|
+ Ord (^B), cmReformPara,
|
|
|
+ Ord (^C), cmPageDown,
|
|
|
+ Ord (^D), cmCharRight,
|
|
|
+ Ord (^E), cmLineUp,
|
|
|
+ Ord (^F), cmWordRight,
|
|
|
+ Ord (^G), cmDelChar,
|
|
|
+ Ord (^H), cmBackSpace,
|
|
|
+ Ord (^I), cmTabKey,
|
|
|
+ Ord (^J), $FF04,
|
|
|
+ Ord (^K), $FF02,
|
|
|
+ Ord (^L), cmSearchAgain,
|
|
|
+ Ord (^M), cmNewLine,
|
|
|
+ Ord (^N), cmInsertLine,
|
|
|
+ Ord (^O), $FF03,
|
|
|
+ Ord (^Q), $FF01,
|
|
|
+ Ord (^R), cmPageUp,
|
|
|
+ Ord (^S), cmCharLeft,
|
|
|
+ Ord (^T), cmDelWord,
|
|
|
+ Ord (^U), cmUndo,
|
|
|
+ Ord (^V), cmInsMode,
|
|
|
+ Ord (^W), cmScrollUp,
|
|
|
+ Ord (^X), cmLineDown,
|
|
|
+ Ord (^Y), cmDelLine,
|
|
|
+ Ord (^Z), cmScrollDown,
|
|
|
+ kbLeft, cmCharLeft,
|
|
|
+ kbRight, cmCharRight,
|
|
|
+ kbCtrlLeft, cmWordLeft,
|
|
|
+ kbCtrlRight, cmWordRight,
|
|
|
+ kbHome, cmLineStart,
|
|
|
+ kbEnd, cmLineEnd,
|
|
|
+ kbCtrlHome, cmHomePage,
|
|
|
+ kbCtrlEnd, cmEndPage,
|
|
|
+ kbUp, cmLineUp,
|
|
|
+ kbDown, cmLineDown,
|
|
|
+ kbPgUp, cmPageUp,
|
|
|
+ kbPgDn, cmPageDown,
|
|
|
+ kbCtrlPgUp, cmTextStart,
|
|
|
+ kbCtrlPgDn, cmTextEnd,
|
|
|
+ kbIns, cmInsMode,
|
|
|
+ kbDel, cmDelChar,
|
|
|
+ kbCtrlBack, cmDelStart,
|
|
|
+ kbShiftIns, cmPaste,
|
|
|
+ kbShiftDel, cmCut,
|
|
|
+ kbCtrlIns, cmCopy,
|
|
|
+ kbCtrlDel, cmClear);
|
|
|
+
|
|
|
+ { SCRLUP - Stop. } { Added ^W to scroll screen up. }
|
|
|
+ { SCRLDN - Stop. } { Added ^Z to scroll screen down. }
|
|
|
+ { REFORM - Stop. } { Added ^B for paragraph reformatting. }
|
|
|
+ { PRETAB - Stop. } { Added ^I for preset tabbing. }
|
|
|
+ { JLINE - Stop. } { Added ^J to jump to a line number. }
|
|
|
+ { INSLIN - Stop. } { Added ^N to insert line at cursor. }
|
|
|
+ { INDENT - Stop. } { Removed ^O and put it into ^QI. }
|
|
|
+ { HOMEND - Stop. } { Added kbCtrlHome and kbCtrlEnd pages. }
|
|
|
+ { CTRLBK - Stop. } { Added kbCtrlBack same as ^QH. }
|
|
|
+
|
|
|
+ QuickKeys : array[0..21 * 2] of Word = (21, Ord ('0'), cmJumpMark0,
|
|
|
+ Ord ('1'), cmJumpMark1,
|
|
|
+ Ord ('2'), cmJumpMark2,
|
|
|
+ Ord ('3'), cmJumpMark3,
|
|
|
+ Ord ('4'), cmJumpMark4,
|
|
|
+ Ord ('5'), cmJumpMark5,
|
|
|
+ Ord ('6'), cmJumpMark6,
|
|
|
+ Ord ('7'), cmJumpMark7,
|
|
|
+ Ord ('8'), cmJumpMark8,
|
|
|
+ Ord ('9'), cmJumpMark9,
|
|
|
+ Ord ('A'), cmReplace,
|
|
|
+ Ord ('C'), cmTextEnd,
|
|
|
+ Ord ('D'), cmLineEnd,
|
|
|
+ Ord ('F'), cmFind,
|
|
|
+ Ord ('H'), cmDelStart,
|
|
|
+ Ord ('I'), cmIndentMode,
|
|
|
+ Ord ('L'), cmUndo,
|
|
|
+ Ord ('R'), cmTextStart,
|
|
|
+ Ord ('S'), cmLineStart,
|
|
|
+ Ord ('U'), cmReformDoc,
|
|
|
+ Ord ('Y'), cmDelEnd);
|
|
|
+
|
|
|
+ { UNDO - Stop. } { Added IDE undo feature of ^QL. }
|
|
|
+ { REFDOC - Stop. } { Added document reformat feature if ^QU pressed. }
|
|
|
+ { MARK - Stop. } { Added cmJumpMark# to allow place marking. }
|
|
|
+ { INDENT - Stop. } { Moved IndentMode here from Firstkeys. }
|
|
|
+
|
|
|
+ BlockKeys : array[0..20 * 2] of Word = (20, Ord ('0'), cmSetMark0,
|
|
|
+ Ord ('1'), cmSetMark1,
|
|
|
+ Ord ('2'), cmSetMark2,
|
|
|
+ Ord ('3'), cmSetMark3,
|
|
|
+ Ord ('4'), cmSetMark4,
|
|
|
+ Ord ('5'), cmSetMark5,
|
|
|
+ Ord ('6'), cmSetMark6,
|
|
|
+ Ord ('7'), cmSetMark7,
|
|
|
+ Ord ('8'), cmSetMark8,
|
|
|
+ Ord ('9'), cmSetMark9,
|
|
|
+ Ord ('B'), cmStartSelect,
|
|
|
+ Ord ('C'), cmPaste,
|
|
|
+ Ord ('D'), cmSave,
|
|
|
+ Ord ('F'), cmSaveAs,
|
|
|
+ Ord ('H'), cmHideSelect,
|
|
|
+ Ord ('K'), cmCopy,
|
|
|
+ Ord ('S'), cmSave,
|
|
|
+ Ord ('T'), cmSelectWord,
|
|
|
+ Ord ('Y'), cmCut,
|
|
|
+ Ord ('X'), cmSaveDone);
|
|
|
+
|
|
|
+ { SELWRD - Stop. } { Added ^KT to select word only. }
|
|
|
+ { SAVE - Stop. } { Added ^KD, ^KF, ^KS, ^KX key commands. }
|
|
|
+ { MARK - Stop. } { Added cmSetMark# to allow place marking. }
|
|
|
+
|
|
|
+ FormatKeys : array[0..5 * 2] of Word = (5, Ord ('C'), cmCenterText,
|
|
|
+ Ord ('T'), cmCenterText,
|
|
|
+ Ord ('I'), cmSetTabs,
|
|
|
+ Ord ('R'), cmRightMargin,
|
|
|
+ Ord ('W'), cmWordWrap);
|
|
|
+
|
|
|
+ { WRAP - Stop. } { Added Wordwrap feature if ^OW pressed. }
|
|
|
+ { RMSET - Stop. } { Added set right margin feature if ^OR pressed. }
|
|
|
+ { PRETAB - Stop. } { Added preset tab feature if ^OI pressed. }
|
|
|
+ { CENTER - Stop. } { Added center text option ^OC for a line. }
|
|
|
+
|
|
|
+ JumpKeys : array[0..1 * 2] of Word = (1, Ord ('L'), cmJumpLine);
|
|
|
+
|
|
|
+ { JLINE - Stop. } { Added jump to line number feature if ^JL pressed. }
|
|
|
+
|
|
|
+ KeyMap : array[0..4] of Pointer = (@FirstKeys,
|
|
|
+ @QuickKeys,
|
|
|
+ @BlockKeys,
|
|
|
+ @FormatKeys,
|
|
|
+ @JumpKeys);
|
|
|
+
|
|
|
+ { WRAP - Stop. } { Added @FormatKeys for new ^O? keys. }
|
|
|
+ { PRETAB - Stop. } { Added @FormatKeys for new ^O? keys. }
|
|
|
+ { JLINE - Stop. } { Added @JumpKeys for new ^J? keys. }
|
|
|
+ { CENTER - Stop. } { Added @FormatKeys for new ^O? keys. }
|
|
|
+
|
|
|
+
|
|
|
+{****************************************************************************
|
|
|
+ Dialogs
|
|
|
+****************************************************************************}
|
|
|
+
|
|
|
+function DefEditorDialog (Dialog : Integer; Info : Pointer) : Word;
|
|
|
+begin
|
|
|
+ DefEditorDialog := cmCancel;
|
|
|
+end; { DefEditorDialog }
|
|
|
+
|
|
|
+
|
|
|
+function CreateFindDialog: PDialog;
|
|
|
+var
|
|
|
+ D: PDialog;
|
|
|
+ Control: PView;
|
|
|
+ R: TRect;
|
|
|
+begin
|
|
|
+ R.Assign(0, 0, 38, 12);
|
|
|
+ D := New(PDialog, Init(R, strings^.get(sFind)));
|
|
|
+ with D^ do
|
|
|
+ begin
|
|
|
+ Options := Options or ofCentered;
|
|
|
+
|
|
|
+ R.Assign(3, 3, 32, 4);
|
|
|
+ Control := New(PInputLine, Init(R, 80));
|
|
|
+ Control^.HelpCtx := hcDFindText;
|
|
|
+ Insert(Control);
|
|
|
+ R.Assign(2, 2, 15, 3);
|
|
|
+ Insert(New(PLabel, Init(R, labels^.get(slTextToFind), Control)));
|
|
|
+ R.Assign(32, 3, 35, 4);
|
|
|
+ Insert(New(PHistory, Init(R, PInputLine(Control), 10)));
|
|
|
+
|
|
|
+ R.Assign(3, 5, 35, 7);
|
|
|
+ Control := New(PCheckBoxes, Init(R,
|
|
|
+ NewSItem (labels^.get(slCaseSensitive),
|
|
|
+ NewSItem (labels^.get(slWholeWordsOnly),nil))));
|
|
|
+ Control^.HelpCtx := hcCCaseSensitive;
|
|
|
+ Insert(Control);
|
|
|
+
|
|
|
+ R.Assign(14, 9, 24, 11);
|
|
|
+ Control := New (PButton, Init(R,labels^.get(slOK),cmOk,bfDefault));
|
|
|
+ Control^.HelpCtx := hcDOk;
|
|
|
+ Insert (Control);
|
|
|
+
|
|
|
+ Inc(R.A.X, 12); Inc(R.B.X, 12);
|
|
|
+ Control := New (PButton, Init(R,labels^.get(slCancel),cmCancel, bfNormal));
|
|
|
+ Control^.HelpCtx := hcDCancel;
|
|
|
+ Insert (Control);
|
|
|
+
|
|
|
+ SelectNext(False);
|
|
|
+ end;
|
|
|
+ CreateFindDialog := D;
|
|
|
+end;
|
|
|
+
|
|
|
+
|
|
|
+function CreateReplaceDialog: PDialog;
|
|
|
+var
|
|
|
+ D: PDialog;
|
|
|
+ Control: PView;
|
|
|
+ R: TRect;
|
|
|
+begin
|
|
|
+ R.Assign(0, 0, 40, 16);
|
|
|
+ D := New(PDialog, Init(R,labels^.get(slReplace)));
|
|
|
+ with D^ do
|
|
|
+ begin
|
|
|
+ Options := Options or ofCentered;
|
|
|
+
|
|
|
+ R.Assign(3, 3, 34, 4);
|
|
|
+ Control := New(PInputLine, Init(R, 80));
|
|
|
+ Control^.HelpCtx := hcDFindText;
|
|
|
+ Insert(Control);
|
|
|
+ R.Assign(2, 2, 15, 3);
|
|
|
+ Insert(New(PLabel, Init(R,labels^.get(slTextToFind), Control)));
|
|
|
+ R.Assign(34, 3, 37, 4);
|
|
|
+ Insert(New(PHistory, Init(R, PInputLine(Control), 10)));
|
|
|
+
|
|
|
+ R.Assign(3, 6, 34, 7);
|
|
|
+ Control := New(PInputLine, Init(R, 80));
|
|
|
+ Control^.HelpCtx := hcDReplaceText;
|
|
|
+ Insert(Control);
|
|
|
+ R.Assign(2, 5, 12, 6);
|
|
|
+ Insert(New(PLabel, Init(R,labels^.get(slNewText), Control)));
|
|
|
+ R.Assign(34, 6, 37, 7);
|
|
|
+ Insert(New(PHistory, Init(R, PInputLine(Control), 11)));
|
|
|
+
|
|
|
+ R.Assign(3, 8, 37, 12);
|
|
|
+ Control := New (Dialogs.PCheckBoxes, Init (R,
|
|
|
+ NewSItem (labels^.get(slCasesensitive),
|
|
|
+ NewSItem (labels^.get(slWholewordsonly),
|
|
|
+ NewSItem (labels^.get(slPromptonreplace),
|
|
|
+ NewSItem (labels^.get(slReplaceall), nil))))));
|
|
|
+ Control^.HelpCtx := hcCCaseSensitive;
|
|
|
+ Insert (Control);
|
|
|
+
|
|
|
+ R.Assign (8, 13, 18, 15);
|
|
|
+ Control := New (PButton, Init (R,labels^.get(slOK), cmOk, bfDefault));
|
|
|
+ Control^.HelpCtx := hcDOk;
|
|
|
+ Insert (Control);
|
|
|
+
|
|
|
+ R.Assign (22, 13, 32, 15);
|
|
|
+ Control := New (PButton, Init (R,labels^.get(slCancel), cmCancel, bfNormal));
|
|
|
+ Control^.HelpCtx := hcDCancel;
|
|
|
+ Insert (Control);
|
|
|
+
|
|
|
+ SelectNext(False);
|
|
|
+ end;
|
|
|
+ CreateReplaceDialog := D;
|
|
|
+end;
|
|
|
+
|
|
|
+
|
|
|
+function JumpLineDialog : PDialog;
|
|
|
+VAR
|
|
|
+ D : PDialog;
|
|
|
+ R : TRect;
|
|
|
+ Control: PView;
|
|
|
+Begin
|
|
|
+ R.Assign (0, 0, 26, 8);
|
|
|
+ D := New(PDialog, Init(R,strings^.get(sJumpTo)));
|
|
|
+ with D^ do
|
|
|
+ begin
|
|
|
+ Options := Options or ofCentered;
|
|
|
+
|
|
|
+ R.Assign (3, 2, 15, 3);
|
|
|
+ Control := New (Dialogs.PStaticText, Init (R,labels^.get(slLineNumber)));
|
|
|
+ Insert (Control);
|
|
|
+
|
|
|
+ R.Assign (15, 2, 21, 3);
|
|
|
+ Control := New (Dialogs.PInputLine, Init (R, 4));
|
|
|
+ Control^.HelpCtx := hcDLineNumber;
|
|
|
+ Insert (Control);
|
|
|
+
|
|
|
+ R.Assign (21, 2, 24, 3);
|
|
|
+ Insert (New (Dialogs.PHistory, Init (R, Dialogs.PInputLine (Control), 12)));
|
|
|
+
|
|
|
+ R.Assign (2, 5, 12, 7);
|
|
|
+ Control := New (Dialogs.PButton, Init (R, labels^.get(slOK), cmOK, Dialogs.bfDefault));
|
|
|
+ Control^.HelpCtx := hcDOk;
|
|
|
+ Insert (Control);
|
|
|
+
|
|
|
+ R.Assign (14, 5, 24, 7);
|
|
|
+ Control := New (Dialogs.PButton, Init (R, labels^.get(slCancel), cmCancel, Dialogs.bfNormal));
|
|
|
+ Control^.HelpCtx := hcDCancel;
|
|
|
+ Insert (Control);
|
|
|
+
|
|
|
+ SelectNext (False);
|
|
|
+ end;
|
|
|
+ JumpLineDialog := D;
|
|
|
+end; { JumpLineDialog }
|
|
|
+
|
|
|
+
|
|
|
+function ReformDocDialog : Dialogs.PDialog;
|
|
|
+ { This is a local function that brings up a dialog box }
|
|
|
+ { that asks where to start reformatting the document. }
|
|
|
+VAR
|
|
|
+ R : TRect;
|
|
|
+ D : Dialogs.PDialog;
|
|
|
+ Control : PView;
|
|
|
+Begin
|
|
|
+ R.Assign (0, 0, 32, 11);
|
|
|
+ D := New (Dialogs.PDialog, Init (R, strings^.get(sReformatDocument)));
|
|
|
+ with D^ do
|
|
|
+ begin
|
|
|
+ Options := Options or ofCentered;
|
|
|
+
|
|
|
+ R.Assign (2, 2, 30, 3);
|
|
|
+ Control := New (Dialogs.PStaticText, Init (R, strings^.get(sSelectWhereToBegin)));
|
|
|
+ Insert (Control);
|
|
|
+
|
|
|
+ R.Assign (3, 3, 29, 4);
|
|
|
+ Control := New (Dialogs.PStaticText, Init (R, strings^.get(sReformattingTheDocument)));
|
|
|
+ Insert (Control);
|
|
|
+
|
|
|
+ R.Assign (50, 5, 68, 6);
|
|
|
+ Control := New (Dialogs.PLabel, Init (R, strings^.get(sReformatDocument), Control));
|
|
|
+ Insert (Control);
|
|
|
+
|
|
|
+ R.Assign (5, 5, 26, 7);
|
|
|
+ Control := New (Dialogs.PRadioButtons, Init (R,
|
|
|
+ NewSItem (labels^.get(slCurrentLine),
|
|
|
+ NewSItem (labels^.get(slEntireDocument), Nil))));
|
|
|
+ Control^.HelpCtx := hcDReformDoc;
|
|
|
+ Insert (Control);
|
|
|
+
|
|
|
+ R.Assign (4, 8, 14, 10);
|
|
|
+ Control := New (Dialogs.PButton, Init (R,labels^.get(slOK), cmOK, Dialogs.bfDefault));
|
|
|
+ Control^.HelpCtx := hcDOk;
|
|
|
+ Insert (Control);
|
|
|
+
|
|
|
+ R.Assign (17, 8, 27, 10);
|
|
|
+ Control := New (Dialogs.PButton, Init (R, labels^.get(slCancel), cmCancel, Dialogs.bfNormal));
|
|
|
+ Control^.HelpCtx := hcDCancel;
|
|
|
+ Insert (Control);
|
|
|
+
|
|
|
+ SelectNext (False);
|
|
|
+ end;
|
|
|
+ ReformDocDialog := D;
|
|
|
+end; { ReformDocDialog }
|
|
|
+
|
|
|
+
|
|
|
+function RightMarginDialog : Dialogs.PDialog;
|
|
|
+ { This is a local function that brings up a dialog box }
|
|
|
+ { that allows the user to change the Right_Margin. }
|
|
|
+VAR
|
|
|
+ R : TRect;
|
|
|
+ D : PDialog;
|
|
|
+ Control : PView;
|
|
|
+Begin
|
|
|
+ R.Assign (0, 0, 26, 8);
|
|
|
+ D := New (Dialogs.PDialog, Init (R, strings^.get(sRightMargin)));
|
|
|
+ with D^ do
|
|
|
+ begin
|
|
|
+ Options := Options or ofCentered;
|
|
|
+
|
|
|
+ R.Assign (5, 2, 13, 3);
|
|
|
+ Control := New (Dialogs.PStaticText, Init (R, strings^.get(sSetting)));
|
|
|
+ Insert (Control);
|
|
|
+
|
|
|
+ R.Assign (13, 2, 18, 3);
|
|
|
+ Control := New (Dialogs.PInputLine, Init (R, 3));
|
|
|
+ Control^.HelpCtx := hcDRightMargin;
|
|
|
+ Insert (Control);
|
|
|
+
|
|
|
+ R.Assign (18, 2, 21, 3);
|
|
|
+ Insert (New (Dialogs.PHistory, Init (R, Dialogs.PInputLine (Control), 13)));
|
|
|
+
|
|
|
+ R.Assign (2, 5, 12, 7);
|
|
|
+ Control := New (Dialogs.PButton, Init (R, labels^.get(slOK), cmOK, Dialogs.bfDefault));
|
|
|
+ Control^.HelpCtx := hcDOk;
|
|
|
+ Insert (Control);
|
|
|
+
|
|
|
+ R.Assign (14, 5, 24, 7);
|
|
|
+ Control := New (Dialogs.PButton, Init (R, labels^.get(slCancel), cmCancel, Dialogs.bfNormal));
|
|
|
+ Control^.HelpCtx := hcDCancel;
|
|
|
+ Insert (Control);
|
|
|
+
|
|
|
+ SelectNext (False);
|
|
|
+ end;
|
|
|
+ RightMarginDialog := D;
|
|
|
+end; { RightMarginDialog; }
|
|
|
+
|
|
|
+
|
|
|
+function TabStopDialog : Dialogs.PDialog;
|
|
|
+ { This is a local function that brings up a dialog box }
|
|
|
+ { that allows the user to set their own tab stops. }
|
|
|
+VAR
|
|
|
+ Index : Sw_Integer; { Local Indexing variable. }
|
|
|
+ R : TRect;
|
|
|
+ D : PDialog;
|
|
|
+ Control : PView;
|
|
|
+ Tab_Stop : String[2]; { Local string to print tab column number. }
|
|
|
+Begin
|
|
|
+ R.Assign (0, 0, 80, 8);
|
|
|
+ D := New (Dialogs.PDialog, Init (R, strings^.get(sTabSettings)));
|
|
|
+ with D^ do
|
|
|
+ begin
|
|
|
+ Options := Options or ofCentered;
|
|
|
+
|
|
|
+ R.Assign (2, 2, 77, 3);
|
|
|
+ Control := New (Dialogs.PStaticText, Init (R,
|
|
|
+ ' ....|....|....|....|....|....|....|....|....|....|....|....|....|....|....'));
|
|
|
+ Insert (Control);
|
|
|
+
|
|
|
+ for Index := 1 to 7 do
|
|
|
+ begin
|
|
|
+ R.Assign (Index * 10 + 1, 1, Index * 10 + 3, 2);
|
|
|
+ Str (Index * 10, Tab_Stop);
|
|
|
+ Control := New (Dialogs.PStaticText, Init (R, Tab_Stop));
|
|
|
+ Insert (Control);
|
|
|
+ end;
|
|
|
+
|
|
|
+ R.Assign (2, 3, 78, 4);
|
|
|
+ Control := New (Dialogs.PInputLine, Init (R, 74));
|
|
|
+ Control^.HelpCtx := hcDTabStops;
|
|
|
+ Insert (Control);
|
|
|
+
|
|
|
+ R.Assign (38, 5, 41, 6);
|
|
|
+ Insert (New (Dialogs.PHistory, Init (R, Dialogs.PInputLine (Control), 14)));
|
|
|
+
|
|
|
+ R.Assign (27, 5, 37, 7);
|
|
|
+ Control := New (Dialogs.PButton, Init (R, labels^.get(slOK), cmOK, Dialogs.bfDefault));
|
|
|
+ Control^.HelpCtx := hcDOk;
|
|
|
+ Insert (Control);
|
|
|
+
|
|
|
+ R.Assign (42, 5, 52, 7);
|
|
|
+ Control := New (Dialogs.PButton, Init (R, labels^.get(slCancel), cmCancel, Dialogs.bfNormal));
|
|
|
+ Control^.HelpCtx := hcDCancel;
|
|
|
+ Insert (Control);
|
|
|
+ SelectNext (False);
|
|
|
+ end;
|
|
|
+ TabStopDialog := D;
|
|
|
+end { TabStopDialog };
|
|
|
+
|
|
|
+
|
|
|
+function StdEditorDialog(Dialog: Integer; Info: Pointer): Word;
|
|
|
+var
|
|
|
+ R: TRect;
|
|
|
+ T: TPoint;
|
|
|
+begin
|
|
|
+ case Dialog of
|
|
|
+ edOutOfMemory:
|
|
|
+ StdEditorDialog := MessageBox(strings^.get(sOutOfMemory), nil, mfError + mfOkButton);
|
|
|
+ edReadError:
|
|
|
+ StdEditorDialog := MessageBox(strings^.get(sFileReadError), @Info, mfError + mfOkButton);
|
|
|
+ edWriteError:
|
|
|
+ StdEditorDialog := MessageBox(strings^.get(sFileWriteError), @Info, mfError + mfOkButton);
|
|
|
+ edCreateError:
|
|
|
+ StdEditorDialog := MessageBox(strings^.get(sFileCreateError), @Info, mfError + mfOkButton);
|
|
|
+ edSaveModify:
|
|
|
+ StdEditorDialog := MessageBox(strings^.get(sModified), @Info, mfInformation + mfYesNoCancel);
|
|
|
+ edSaveUntitled:
|
|
|
+ StdEditorDialog := MessageBox(strings^.get(sFileUntitled), nil, mfInformation + mfYesNoCancel);
|
|
|
+ edSaveAs:
|
|
|
+ StdEditorDialog := Application^.ExecuteDialog(New(PFileDialog, Init('*.*',
|
|
|
+ labels^.get(slSaveFileAs), labels^.get(slName), fdOkButton, 101)), Info);
|
|
|
+ edFind:
|
|
|
+ StdEditorDialog := Application^.ExecuteDialog(CreateFindDialog, Info);
|
|
|
+ edSearchFailed:
|
|
|
+ StdEditorDialog := MessageBox(strings^.get(sSearchStringNotFound), nil, mfError + mfOkButton);
|
|
|
+ edReplace:
|
|
|
+ StdEditorDialog := Application^.ExecuteDialog(CreateReplaceDialog, Info);
|
|
|
+ edReplacePrompt:
|
|
|
+ begin
|
|
|
+ { Avoid placing the dialog on the same line as the cursor }
|
|
|
+ R.Assign(0, 1, 40, 8);
|
|
|
+ R.Move((Desktop^.Size.X - R.B.X) div 2, 0);
|
|
|
+ Desktop^.MakeGlobal(R.B, T);
|
|
|
+ Inc(T.Y);
|
|
|
+ if PPoint(Info)^.Y <= T.Y then
|
|
|
+ R.Move(0, Desktop^.Size.Y - R.B.Y - 2);
|
|
|
+ StdEditorDialog := MessageBoxRect(R, strings^.get(sReplaceThisOccurence),
|
|
|
+ nil, mfYesNoCancel + mfInformation);
|
|
|
+ end;
|
|
|
+ edJumpToLine:
|
|
|
+ StdEditorDialog := Application^.ExecuteDialog(JumpLineDialog, Info);
|
|
|
+ edSetTabStops:
|
|
|
+ StdEditorDialog := Application^.ExecuteDialog(TabStopDialog, Info);
|
|
|
+ edPasteNotPossible:
|
|
|
+ StdEditorDialog := MessageBox (strings^.get(sPasteNotPossible), nil, mfError + mfOkButton);
|
|
|
+ edReformatDocument:
|
|
|
+ StdEditorDialog := Application^.ExecuteDialog(ReformDocDialog, Info);
|
|
|
+ edReformatNotAllowed:
|
|
|
+ StdEditorDialog := MessageBox (strings^.get(sWordWrapOff), nil, mfError + mfOkButton);
|
|
|
+ edReformNotPossible:
|
|
|
+ StdEditorDialog := MessageBox (strings^.get(sReformatNotPossible), nil, mfError + mfOkButton);
|
|
|
+ edReplaceNotPossible:
|
|
|
+ StdEditorDialog := MessageBox (strings^.get(sReplaceNotPossible), nil, mfError + mfOkButton);
|
|
|
+ edRightMargin:
|
|
|
+ StdEditorDialog := Application^.ExecuteDialog(RightMarginDialog, Info);
|
|
|
+ edWrapNotPossible:
|
|
|
+ StdEditorDialog := MessageBox (strings^.get(sWordWrapNotPossible), nil, mfError + mfOKButton);
|
|
|
+ else
|
|
|
+ StdEditorDialog := MessageBox (strings^.get(sUnknownDialog), nil, mfError + mfOkButton);
|
|
|
+ end;
|
|
|
+end;
|
|
|
+
|
|
|
+
|
|
|
+{****************************************************************************
|
|
|
+ Helpers
|
|
|
+****************************************************************************}
|
|
|
+
|
|
|
+function CountLines(var Buf; Count: sw_Word): sw_Integer;
|
|
|
+var
|
|
|
+ p : pchar;
|
|
|
+ lines : sw_word;
|
|
|
+begin
|
|
|
+ p:=pchar(@buf);
|
|
|
+ lines:=0;
|
|
|
+ while (count>0) do
|
|
|
+ begin
|
|
|
+ if p^ in [#10,#13] then
|
|
|
+ begin
|
|
|
+ inc(lines);
|
|
|
+ if ord((p+1)^)+ord(p^)=23 then
|
|
|
+ begin
|
|
|
+ inc(p);
|
|
|
+ dec(count);
|
|
|
+ if count=0 then
|
|
|
+ break;
|
|
|
+ end;
|
|
|
+ end;
|
|
|
+ inc(p);
|
|
|
+ dec(count);
|
|
|
+ end;
|
|
|
+ CountLines:=Lines;
|
|
|
+end;
|
|
|
+
|
|
|
+
|
|
|
+procedure GetLimits(var Buf; Count: sw_Word;var lim:objects.TPoint);
|
|
|
+{ Get the limits needed for Buf, its an extended version of countlines (lim.y),
|
|
|
+ which also gets the maximum line length in lim.x }
|
|
|
+var
|
|
|
+ p : pchar;
|
|
|
+ len : sw_word;
|
|
|
+begin
|
|
|
+ lim.x:=0;
|
|
|
+ lim.y:=0;
|
|
|
+ len:=0;
|
|
|
+ p:=pchar(@buf);
|
|
|
+ while (count>0) do
|
|
|
+ begin
|
|
|
+ if p^ in [#10,#13] then
|
|
|
+ begin
|
|
|
+ if len>lim.x then
|
|
|
+ lim.x:=len;
|
|
|
+ inc(lim.y);
|
|
|
+ if ord((p+1)^)+ord(p^)=23 then
|
|
|
+ begin
|
|
|
+ inc(p);
|
|
|
+ dec(count);
|
|
|
+ end;
|
|
|
+ len:=0;
|
|
|
+ end
|
|
|
+ else
|
|
|
+ inc(len);
|
|
|
+ inc(p);
|
|
|
+ dec(count);
|
|
|
+ end;
|
|
|
+end;
|
|
|
+
|
|
|
+
|
|
|
+function ScanKeyMap(KeyMap: Pointer; KeyCode: Word): Word;
|
|
|
+var
|
|
|
+ p : pword;
|
|
|
+ count : sw_word;
|
|
|
+begin
|
|
|
+ p:=keymap;
|
|
|
+ count:=p^;
|
|
|
+ inc(p);
|
|
|
+ while (count>0) do
|
|
|
+ begin
|
|
|
+ if (lo(p^)=lo(keycode)) and
|
|
|
+ ((hi(p^)=0) or (hi(p^)=hi(keycode))) then
|
|
|
+ begin
|
|
|
+ inc(p);
|
|
|
+ scankeymap:=p^;
|
|
|
+ exit;
|
|
|
+ end;
|
|
|
+ inc(p,2);
|
|
|
+ dec(count);
|
|
|
+ end;
|
|
|
+ scankeymap:=0;
|
|
|
+end;
|
|
|
+
|
|
|
+
|
|
|
+Type
|
|
|
+ Btable = Array[0..255] of Byte;
|
|
|
+Procedure BMMakeTable(const s:string; Var t : Btable);
|
|
|
+{ Makes a Boyer-Moore search table. s = the search String t = the table }
|
|
|
+Var
|
|
|
+ x : sw_integer;
|
|
|
+begin
|
|
|
+ FillChar(t,sizeof(t),length(s));
|
|
|
+ For x := length(s) downto 1 do
|
|
|
+ if (t[ord(s[x])] = length(s)) then
|
|
|
+ t[ord(s[x])] := length(s) - x;
|
|
|
+end;
|
|
|
+
|
|
|
+
|
|
|
+function Scan(var Block; Size: Sw_Word;const Str: String): Sw_Word;
|
|
|
+Var
|
|
|
+ buffer : Array[0..MaxBufLength-1] of Byte Absolute block;
|
|
|
+ s2 : String;
|
|
|
+ len,
|
|
|
+ numb : Sw_Word;
|
|
|
+ found : Boolean;
|
|
|
+ bt : Btable;
|
|
|
+begin
|
|
|
+ BMMakeTable(str,bt);
|
|
|
+ len:=length(str);
|
|
|
+ s2[0]:=chr(len); { sets the length to that of the search String }
|
|
|
+ found:=False;
|
|
|
+ numb:=pred(len);
|
|
|
+ While (not found) and (numb<(size-len)) do
|
|
|
+ begin
|
|
|
+ { partial match }
|
|
|
+ if buffer[numb] = ord(str[len]) then
|
|
|
+ begin
|
|
|
+ { less partial! }
|
|
|
+ if buffer[numb-pred(len)] = ord(str[1]) then
|
|
|
+ begin
|
|
|
+ move(buffer[numb-pred(len)],s2[1],len);
|
|
|
+ if (str=s2) then
|
|
|
+ begin
|
|
|
+ found:=true;
|
|
|
+ break;
|
|
|
+ end;
|
|
|
+ end;
|
|
|
+ inc(numb);
|
|
|
+ end
|
|
|
+ else
|
|
|
+ inc(numb,Bt[buffer[numb]]);
|
|
|
+ end;
|
|
|
+ if not found then
|
|
|
+ Scan := NotFoundValue
|
|
|
+ else
|
|
|
+ Scan := numb - pred(len);
|
|
|
+end;
|
|
|
+
|
|
|
+
|
|
|
+function IScan(var Block; Size: Sw_Word;const Str: String): Sw_Word;
|
|
|
+Var
|
|
|
+ buffer : Array[0..MaxBufLength-1] of Char Absolute block;
|
|
|
+ s : String;
|
|
|
+ len,
|
|
|
+ numb,
|
|
|
+ x : Sw_Word;
|
|
|
+ found : Boolean;
|
|
|
+ bt : Btable;
|
|
|
+ p : pchar;
|
|
|
+ c : char;
|
|
|
+begin
|
|
|
+ len:=length(str);
|
|
|
+ { create uppercased string }
|
|
|
+ s[0]:=chr(len);
|
|
|
+ for x:=1to len do
|
|
|
+ begin
|
|
|
+ if str[x] in ['a'..'z'] then
|
|
|
+ s[x]:=chr(ord(str[x])-32)
|
|
|
+ else
|
|
|
+ s[x]:=str[x];
|
|
|
+ end;
|
|
|
+ BMMakeTable(s,bt);
|
|
|
+ found:=False;
|
|
|
+ numb:=pred(len);
|
|
|
+ While (not found) and (numb<(size-len)) do
|
|
|
+ begin
|
|
|
+ { partial match }
|
|
|
+ c:=buffer[numb];
|
|
|
+ if c in ['a'..'z'] then
|
|
|
+ c:=chr(ord(c)-32);
|
|
|
+ if (c=s[len]) then
|
|
|
+ begin
|
|
|
+ { less partial! }
|
|
|
+ p:=@buffer[numb-pred(len)];
|
|
|
+ x:=1;
|
|
|
+ while (x<=len) do
|
|
|
+ begin
|
|
|
+ if not(((p^ in ['a'..'z']) and (chr(ord(p^)-32)=s[x])) or
|
|
|
+ (p^=s[x])) then
|
|
|
+ break;
|
|
|
+ inc(p);
|
|
|
+ inc(x);
|
|
|
+ end;
|
|
|
+ if (x>len) then
|
|
|
+ begin
|
|
|
+ found:=true;
|
|
|
+ break;
|
|
|
+ end;
|
|
|
+ inc(numb);
|
|
|
+ end
|
|
|
+ else
|
|
|
+ inc(numb,Bt[ord(c)]);
|
|
|
+ end;
|
|
|
+ if not found then
|
|
|
+ IScan := NotFoundValue
|
|
|
+ else
|
|
|
+ IScan := numb - pred(len);
|
|
|
+end;
|
|
|
+
|
|
|
+
|
|
|
+{****************************************************************************
|
|
|
+ TIndicator
|
|
|
+****************************************************************************}
|
|
|
+
|
|
|
+constructor TIndicator.Init (var Bounds : TRect);
|
|
|
+begin
|
|
|
+ Inherited Init (Bounds);
|
|
|
+ GrowMode := gfGrowLoY + gfGrowHiY;
|
|
|
+end; { TIndicator.Init }
|
|
|
+
|
|
|
+
|
|
|
+procedure TIndicator.Draw;
|
|
|
+VAR
|
|
|
+ Color : Byte;
|
|
|
+ Frame : Char;
|
|
|
+ L : array[0..1] of Longint;
|
|
|
+ S : String[15];
|
|
|
+ B : TDrawBuffer;
|
|
|
+begin
|
|
|
+ if State and sfDragging = 0 then
|
|
|
+ begin
|
|
|
+ Color := GetColor (1);
|
|
|
+ Frame := #205;
|
|
|
+ end
|
|
|
+ else
|
|
|
+ begin
|
|
|
+ Color := GetColor (2);
|
|
|
+ Frame := #196;
|
|
|
+ end;
|
|
|
+ MoveChar (B, Frame, Color, Size.X);
|
|
|
+ { If the text has been modified, put an 'M' in the TIndicator display. }
|
|
|
+ if Modified then
|
|
|
+ WordRec (B[1]).Lo := 77;
|
|
|
+ { If WordWrap is active put a 'W' in the TIndicator display. }
|
|
|
+ if WordWrap then
|
|
|
+ WordRec (B[2]).Lo := 87
|
|
|
+ else
|
|
|
+ WordRec (B[2]).Lo := Byte (Frame);
|
|
|
+ { If AutoIndent is active put an 'I' in TIndicator display. }
|
|
|
+ if AutoIndent then
|
|
|
+ WordRec (B[0]).Lo := 73
|
|
|
+ else
|
|
|
+ WordRec (B[0]).Lo := Byte (Frame);
|
|
|
+ L[0] := Location.Y + 1;
|
|
|
+ L[1] := Location.X + 1;
|
|
|
+ FormatStr (S, ' %d:%d ', L);
|
|
|
+ MoveStr (B[9 - Pos (':', S)], S, Color); { Changed original 8 to 9. }
|
|
|
+ WriteBuf (0, 0, Size.X, 1, B);
|
|
|
+end; { TIndicator.Draw }
|
|
|
+
|
|
|
+
|
|
|
+function TIndicator.GetPalette : PPalette;
|
|
|
+const
|
|
|
+ P : string[Length (CIndicator)] = CIndicator;
|
|
|
+begin
|
|
|
+ GetPalette := @P;
|
|
|
+end; { TIndicator.GetPalette }
|
|
|
+
|
|
|
+
|
|
|
+procedure TIndicator.SetState (AState : Word; Enable : Boolean);
|
|
|
+begin
|
|
|
+ Inherited SetState (AState, Enable);
|
|
|
+ if AState = sfDragging then
|
|
|
+ DrawView;
|
|
|
+end; { TIndicator.SetState }
|
|
|
+
|
|
|
+
|
|
|
+procedure TIndicator.SetValue (ALocation : Objects.TPoint; IsAutoIndent : Boolean;
|
|
|
+ IsModified : Boolean;
|
|
|
+ IsWordWrap : Boolean);
|
|
|
+begin
|
|
|
+ if (Location.X<>ALocation.X) or
|
|
|
+ (Location.Y<>ALocation.Y) or
|
|
|
+ (AutoIndent <> IsAutoIndent) or
|
|
|
+ (Modified <> IsModified) or
|
|
|
+ (WordWrap <> IsWordWrap) then
|
|
|
+ begin
|
|
|
+ Location := ALocation;
|
|
|
+ AutoIndent := IsAutoIndent; { Added provisions to show AutoIndent. }
|
|
|
+ Modified := IsModified;
|
|
|
+ WordWrap := IsWordWrap; { Added provisions to show WordWrap. }
|
|
|
+ DrawView;
|
|
|
+ end;
|
|
|
+end; { TIndicator.SetValue }
|
|
|
+
|
|
|
+
|
|
|
+{****************************************************************************
|
|
|
+ TLineInfo
|
|
|
+****************************************************************************}
|
|
|
+
|
|
|
+constructor TLineInfo.Init;
|
|
|
+begin
|
|
|
+ MaxPos:=0;
|
|
|
+ Grow(1);
|
|
|
+end;
|
|
|
+
|
|
|
+
|
|
|
+destructor TLineInfo.Done;
|
|
|
+begin
|
|
|
+ FreeMem(Info,MaxPos*sizeof(TLineInfoRec));
|
|
|
+end;
|
|
|
+
|
|
|
+
|
|
|
+procedure TLineInfo.Grow(pos:Sw_word);
|
|
|
+var
|
|
|
+ NewSize : Sw_word;
|
|
|
+ P : pointer;
|
|
|
+begin
|
|
|
+ NewSize:=(Pos+LineInfoGrow-(Pos mod LineInfoGrow));
|
|
|
+ GetMem(P,NewSize*sizeof(TLineInfoRec));
|
|
|
+ FillChar(P^,NewSize*sizeof(TLineInfoRec),0);
|
|
|
+ Move(Info^,P^,MaxPos*sizeof(TLineInfoRec));
|
|
|
+ Freemem(Info,MaxPos*sizeof(TLineInfoRec));
|
|
|
+ Info:=P;
|
|
|
+end;
|
|
|
+
|
|
|
+
|
|
|
+procedure TLineInfo.SetLen(pos,val:Sw_Word);
|
|
|
+begin
|
|
|
+ if pos>=MaxPos then
|
|
|
+ Grow(Pos);
|
|
|
+ Info^[Pos].Len:=val
|
|
|
+end;
|
|
|
+
|
|
|
+
|
|
|
+procedure TLineInfo.SetAttr(pos,val:Sw_Word);
|
|
|
+begin
|
|
|
+ if pos>=MaxPos then
|
|
|
+ Grow(Pos);
|
|
|
+ Info^[Pos].Attr:=val
|
|
|
+end;
|
|
|
+
|
|
|
+
|
|
|
+function TLineInfo.GetLen(pos:Sw_Word):Sw_Word;
|
|
|
+begin
|
|
|
+ GetLen:=Info^[Pos].Len;
|
|
|
+end;
|
|
|
+
|
|
|
+
|
|
|
+function TLineInfo.GetAttr(pos:Sw_Word):Sw_Word;
|
|
|
+begin
|
|
|
+ GetAttr:=Info^[Pos].Attr;
|
|
|
+end;
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+{****************************************************************************
|
|
|
+ TEditor
|
|
|
+****************************************************************************}
|
|
|
+
|
|
|
+constructor TEditor.Init (var Bounds : TRect;
|
|
|
+ AHScrollBar, AVScrollBar : PScrollBar;
|
|
|
+ AIndicator : PIndicator; ABufSize : Sw_Word);
|
|
|
+var
|
|
|
+ Element : Byte; { Place_Marker array element to initialize array with. }
|
|
|
+begin
|
|
|
+ Inherited Init (Bounds);
|
|
|
+ GrowMode := gfGrowHiX + gfGrowHiY;
|
|
|
+ Options := Options or ofSelectable;
|
|
|
+ Flags := EditorFlags;
|
|
|
+ EventMask := evMouseDown + evKeyDown + evCommand + evBroadcast;
|
|
|
+ ShowCursor;
|
|
|
+
|
|
|
+ HScrollBar := AHScrollBar;
|
|
|
+ VScrollBar := AVScrollBar;
|
|
|
+
|
|
|
+ Indicator := AIndicator;
|
|
|
+ BufSize := ABufSize;
|
|
|
+ CanUndo := True;
|
|
|
+ InitBuffer;
|
|
|
+
|
|
|
+ if assigned(Buffer) then
|
|
|
+ IsValid := True
|
|
|
+ else
|
|
|
+ begin
|
|
|
+ EditorDialog (edOutOfMemory, nil);
|
|
|
+ BufSize := 0;
|
|
|
+ end;
|
|
|
+
|
|
|
+ SetBufLen (0);
|
|
|
+
|
|
|
+ for Element := 1 to 10 do
|
|
|
+ Place_Marker[Element] := 0;
|
|
|
+
|
|
|
+ Element := 1;
|
|
|
+ while Element <= 70 do
|
|
|
+ begin
|
|
|
+ if Element mod 5 = 0 then
|
|
|
+ Insert ('x', Tab_Settings, Element)
|
|
|
+ else
|
|
|
+ Insert (#32, Tab_Settings, Element);
|
|
|
+ Inc (Element);
|
|
|
+ end;
|
|
|
+ { Default Right_Margin value. Change it if you want another. }
|
|
|
+ Right_Margin := 76;
|
|
|
+ TabSize:=8;
|
|
|
+end; { TEditor.Init }
|
|
|
+
|
|
|
+
|
|
|
+constructor TEditor.Load (var S : Objects.TStream);
|
|
|
+begin
|
|
|
+ Inherited Load (S);
|
|
|
+ GetPeerViewPtr (S, HScrollBar);
|
|
|
+ GetPeerViewPtr (S, VScrollBar);
|
|
|
+ GetPeerViewPtr (S, Indicator);
|
|
|
+ S.Read (BufSize, SizeOf (Sw_Word));
|
|
|
+ S.Read (CanUndo, SizeOf (Boolean));
|
|
|
+ S.Read (AutoIndent, SizeOf (AutoIndent));
|
|
|
+ S.Read (Line_Number, SizeOf (Line_Number));
|
|
|
+ S.Read (Place_Marker, SizeOf (Place_Marker));
|
|
|
+ S.Read (Right_Margin, SizeOf (Right_Margin));
|
|
|
+ S.Read (Tab_Settings, SizeOf (Tab_Settings));
|
|
|
+ S.Read (Word_Wrap, SizeOf (Word_Wrap));
|
|
|
+ InitBuffer;
|
|
|
+ if Assigned(Buffer) then
|
|
|
+ IsValid := True
|
|
|
+ else
|
|
|
+ begin
|
|
|
+ EditorDialog (edOutOfMemory, nil);
|
|
|
+ BufSize := 0;
|
|
|
+ end;
|
|
|
+ Lock;
|
|
|
+ SetBufLen (0);
|
|
|
+end; { TEditor.Load }
|
|
|
+
|
|
|
+
|
|
|
+destructor TEditor.Done;
|
|
|
+begin
|
|
|
+ DoneBuffer;
|
|
|
+ Inherited Done;
|
|
|
+end; { TEditor.Done }
|
|
|
+
|
|
|
+
|
|
|
+function TEditor.BufChar(P: Sw_Word): Char;
|
|
|
+begin
|
|
|
+ if P>=CurPtr then
|
|
|
+ inc(P,Gaplen);
|
|
|
+ BufChar:=Buffer^[P];
|
|
|
+end;
|
|
|
+
|
|
|
+
|
|
|
+function TEditor.BufPtr(P: Sw_Word): Sw_Word;
|
|
|
+begin
|
|
|
+ if P>=CurPtr then
|
|
|
+ BufPtr:=P+GapLen
|
|
|
+ else
|
|
|
+ BufPtr:=P;
|
|
|
+end;
|
|
|
+
|
|
|
+
|
|
|
+procedure TEditor.Center_Text (Select_Mode : Byte);
|
|
|
+{ This procedure will center the current line of text. }
|
|
|
+{ Centering is based on the current Right_Margin. }
|
|
|
+{ If the Line_Length exceeds the Right_Margin, or the }
|
|
|
+{ line is just a blank line, we exit and do nothing. }
|
|
|
+VAR
|
|
|
+ Spaces : array [1..80] of Char; { Array to hold spaces we'll insert. }
|
|
|
+ Index : Byte; { Index into Spaces array. }
|
|
|
+ Line_Length : Sw_Integer; { Holds the length of the line. }
|
|
|
+ E,S : Sw_Word; { End of the current line. }
|
|
|
+begin
|
|
|
+ E := LineEnd (CurPtr);
|
|
|
+ S := LineStart (CurPtr);
|
|
|
+ { If the line is blank (only a CR/LF on it) then do noting. }
|
|
|
+ if E = S then
|
|
|
+ Exit;
|
|
|
+ { Set CurPtr to start of line. Check if line begins with a space. }
|
|
|
+ { We must strip out any spaces from the beginning, or end of lines. }
|
|
|
+ { If line does not start with space, make sure line length does not }
|
|
|
+ { exceed the Right_Margin. If it does, then do nothing. }
|
|
|
+ SetCurPtr (S, Select_Mode);
|
|
|
+ Remove_EOL_Spaces (Select_Mode);
|
|
|
+ if Buffer^[CurPtr] = #32 then
|
|
|
+ begin
|
|
|
+ { If the next word is greater than the end of line then do nothing. }
|
|
|
+ { If the line length is greater than Right_Margin then do nothing. }
|
|
|
+ { Otherwise, delete all spaces at the start of line. }
|
|
|
+ { Then reset end of line and put CurPtr at start of modified line. }
|
|
|
+ E := LineEnd (CurPtr);
|
|
|
+ if NextWord (CurPtr) > E then
|
|
|
+ Exit;
|
|
|
+ if E - NextWord (CurPtr) > Right_Margin then
|
|
|
+ Exit;
|
|
|
+ DeleteRange (CurPtr, NextWord (CurPtr), True);
|
|
|
+ E := LineEnd (CurPtr);
|
|
|
+ SetCurPtr (LineStart (CurPtr), Select_Mode);
|
|
|
+ end
|
|
|
+ else
|
|
|
+ if E - CurPtr > Right_Margin then
|
|
|
+ Exit;
|
|
|
+ { Now we determine the real length of the line. }
|
|
|
+ { Then we subtract the Line_Length from Right_Margin. }
|
|
|
+ { Dividing the result by two tells us how many spaces }
|
|
|
+ { must be inserted at start of line to center it. }
|
|
|
+ { When we're all done, set the CurPtr to end of line. }
|
|
|
+ Line_Length := E - CurPtr;
|
|
|
+ for Index := 1 to ((Right_Margin - Line_Length) shr 1) do
|
|
|
+ Spaces[Index] := #32;
|
|
|
+ InsertText (@Spaces, Index, False);
|
|
|
+ SetCurPtr (LineEnd (CurPtr), Select_Mode);
|
|
|
+end; { TEditor.Center_Text }
|
|
|
+
|
|
|
+
|
|
|
+procedure TEditor.ChangeBounds (var Bounds : TRect);
|
|
|
+begin
|
|
|
+ SetBounds (Bounds);
|
|
|
+ Delta.X := Max (0, Min (Delta.X, Limit.X - Size.X));
|
|
|
+ Delta.Y := Max (0, Min (Delta.Y, Limit.Y - Size.Y));
|
|
|
+ Update (ufView);
|
|
|
+end; { TEditor.ChangeBounds }
|
|
|
+
|
|
|
+
|
|
|
+function TEditor.CharPos (P, Target : Sw_Word) : Sw_Integer;
|
|
|
+VAR
|
|
|
+ Pos : Sw_Integer;
|
|
|
+begin
|
|
|
+ Pos := 0;
|
|
|
+ while P < Target do
|
|
|
+ begin
|
|
|
+ if BufChar (P) = #9 then
|
|
|
+ Pos := Pos or 7;
|
|
|
+ Inc (Pos);
|
|
|
+ Inc (P);
|
|
|
+ end;
|
|
|
+ CharPos := Pos;
|
|
|
+end; { TEditor.CharPos }
|
|
|
+
|
|
|
+
|
|
|
+function TEditor.CharPtr (P : Sw_Word; Target : Sw_Integer) : Sw_Word;
|
|
|
+VAR
|
|
|
+ Pos : Sw_Integer;
|
|
|
+begin
|
|
|
+ Pos := 0;
|
|
|
+ while (Pos < Target) and (P < BufLen) and not(BufChar (P) in [#10,#13]) do
|
|
|
+ begin
|
|
|
+ if BufChar (P) = #9 then
|
|
|
+ Pos := Pos or 7;
|
|
|
+ Inc (Pos);
|
|
|
+ Inc (P);
|
|
|
+ end;
|
|
|
+ if Pos > Target then
|
|
|
+ Dec (P);
|
|
|
+ CharPtr := P;
|
|
|
+end; { TEditor.CharPtr }
|
|
|
+
|
|
|
+
|
|
|
+procedure TEditor.Check_For_Word_Wrap (Select_Mode : Byte;
|
|
|
+ Center_Cursor : Boolean);
|
|
|
+{ This procedure checks if CurPos.X > Right_Margin. }
|
|
|
+{ If it is, then we Do_Word_Wrap. Simple, eh? }
|
|
|
+begin
|
|
|
+ if CurPos.X > Right_Margin then
|
|
|
+ Do_Word_Wrap (Select_Mode, Center_Cursor);
|
|
|
+end; {Check_For_Word_Wrap}
|
|
|
+
|
|
|
+
|
|
|
+function TEditor.ClipCopy : Boolean;
|
|
|
+begin
|
|
|
+ ClipCopy := False;
|
|
|
+ if Assigned(Clipboard) and (Clipboard <> @Self) then
|
|
|
+ begin
|
|
|
+ ClipCopy := Clipboard^.InsertFrom (@Self);
|
|
|
+ Selecting := False;
|
|
|
+ Update (ufUpdate);
|
|
|
+ end;
|
|
|
+end; { TEditor.ClipCopy }
|
|
|
+
|
|
|
+
|
|
|
+procedure TEditor.ClipCut;
|
|
|
+begin
|
|
|
+ if ClipCopy then
|
|
|
+ begin
|
|
|
+ Update_Place_Markers (0,
|
|
|
+ Self.SelEnd - Self.SelStart,
|
|
|
+ Self.SelStart,
|
|
|
+ Self.SelEnd);
|
|
|
+ DeleteSelect;
|
|
|
+ end;
|
|
|
+end; { TEditor.ClipCut }
|
|
|
+
|
|
|
+
|
|
|
+procedure TEditor.ClipPaste;
|
|
|
+begin
|
|
|
+ if Assigned(Clipboard) and (Clipboard <> @Self) then
|
|
|
+ begin
|
|
|
+ { Do not allow paste operations that will exceed }
|
|
|
+ { the Right_Margin when Word_Wrap is active and }
|
|
|
+ { cursor is at EOL. }
|
|
|
+ if Word_Wrap and (CurPos.X > Right_Margin) then
|
|
|
+ begin
|
|
|
+ EditorDialog (edPasteNotPossible, nil);
|
|
|
+ Exit;
|
|
|
+ end;
|
|
|
+ { The editor will not copy selected text if the CurPtr }
|
|
|
+ { is not the same value as the SelStart. However, it }
|
|
|
+ { does return an InsCount. This may, or may not, be a }
|
|
|
+ { bug. We don't want to update the Place_Marker if }
|
|
|
+ { there's no text copied. }
|
|
|
+ if CurPtr = SelStart then
|
|
|
+ Update_Place_Markers (Clipboard^.SelEnd - Clipboard^.SelStart,
|
|
|
+ 0,
|
|
|
+ Clipboard^.SelStart,
|
|
|
+ Clipboard^.SelEnd);
|
|
|
+ InsertFrom (Clipboard);
|
|
|
+ end;
|
|
|
+end; { TEditor.ClipPaste }
|
|
|
+
|
|
|
+
|
|
|
+procedure TEditor.ConvertEvent (var Event : Drivers.TEvent);
|
|
|
+VAR
|
|
|
+ ShiftState : Byte;
|
|
|
+ Key : Word;
|
|
|
+begin
|
|
|
+ ShiftState:=GetShiftState;
|
|
|
+ if Event.What = evKeyDown then
|
|
|
+ begin
|
|
|
+ if (ShiftState and $03 <> 0)
|
|
|
+ and (Event.ScanCode >= $47)
|
|
|
+ and (Event.ScanCode <= $51) then
|
|
|
+ Event.CharCode := #0;
|
|
|
+ Key := Event.KeyCode;
|
|
|
+ if KeyState <> 0 then
|
|
|
+ begin
|
|
|
+ if (Lo (Key) >= $01) and (Lo (Key) <= $1A) then
|
|
|
+ Inc (Key, $40);
|
|
|
+ if (Lo (Key) >= $61) and (Lo (Key) <= $7A) then
|
|
|
+ Dec (Key, $20);
|
|
|
+ end;
|
|
|
+ Key := ScanKeyMap (KeyMap[KeyState], Key);
|
|
|
+ KeyState := 0;
|
|
|
+ if Key <> 0 then
|
|
|
+ if Hi (Key) = $FF then
|
|
|
+ begin
|
|
|
+ KeyState := Lo (Key);
|
|
|
+ ClearEvent (Event);
|
|
|
+ end
|
|
|
+ else
|
|
|
+ begin
|
|
|
+ Event.What := evCommand;
|
|
|
+ Event.Command := Key;
|
|
|
+ end;
|
|
|
+ end;
|
|
|
+end; { TEditor.ConvertEvent }
|
|
|
+
|
|
|
+
|
|
|
+function TEditor.CursorVisible : Boolean;
|
|
|
+begin
|
|
|
+ CursorVisible := (CurPos.Y >= Delta.Y) and (CurPos.Y < Delta.Y + Size.Y);
|
|
|
+end; { TEditor.CursorVisible }
|
|
|
+
|
|
|
+
|
|
|
+procedure TEditor.DeleteRange (StartPtr, EndPtr : Sw_Word; DelSelect : Boolean);
|
|
|
+begin
|
|
|
+ { This will update Place_Marker for all deletions. }
|
|
|
+ { EXCEPT the Remove_EOL_Spaces deletion. }
|
|
|
+ Update_Place_Markers (0, EndPtr - StartPtr, StartPtr, EndPtr);
|
|
|
+ if HasSelection and DelSelect then
|
|
|
+ DeleteSelect
|
|
|
+ else
|
|
|
+ begin
|
|
|
+ SetSelect (CurPtr, EndPtr, True);
|
|
|
+ DeleteSelect;
|
|
|
+ SetSelect (StartPtr, CurPtr, False);
|
|
|
+ DeleteSelect;
|
|
|
+ end;
|
|
|
+end; { TEditor.DeleteRange }
|
|
|
+
|
|
|
+
|
|
|
+procedure TEditor.DeleteSelect;
|
|
|
+begin
|
|
|
+ InsertText (nil, 0, False);
|
|
|
+end; { TEditor.DeleteSelect }
|
|
|
+
|
|
|
+
|
|
|
+procedure TEditor.DoneBuffer;
|
|
|
+begin
|
|
|
+ if assigned(Buffer) then
|
|
|
+ begin
|
|
|
+ FreeMem (Buffer, BufSize);
|
|
|
+ Buffer := nil;
|
|
|
+ end;
|
|
|
+end; { TEditor.DoneBuffer }
|
|
|
+
|
|
|
+
|
|
|
+procedure TEditor.DoSearchReplace;
|
|
|
+VAR
|
|
|
+ I : Sw_Word;
|
|
|
+ C : Objects.TPoint;
|
|
|
+begin
|
|
|
+ repeat
|
|
|
+ I := cmCancel;
|
|
|
+ if not Search (FindStr, Flags) then
|
|
|
+ begin
|
|
|
+ if Flags and (efReplaceAll + efDoReplace) <> (efReplaceAll + efDoReplace) then
|
|
|
+ EditorDialog (edSearchFailed, nil)
|
|
|
+ end
|
|
|
+ else
|
|
|
+ if Flags and efDoReplace <> 0 then
|
|
|
+ begin
|
|
|
+ I := cmYes;
|
|
|
+ if Flags and efPromptOnReplace <> 0 then
|
|
|
+ begin
|
|
|
+ MakeGlobal (Cursor, C);
|
|
|
+ I := EditorDialog (edReplacePrompt, Pointer(@C));
|
|
|
+ end;
|
|
|
+ if I = cmYes then
|
|
|
+ begin
|
|
|
+ { If Word_Wrap is active and we are at EOL }
|
|
|
+ { disallow replace by bringing up a dialog }
|
|
|
+ { stating that replace is not possible. }
|
|
|
+ if Word_Wrap and
|
|
|
+ ((CurPos.X + (Length (ReplaceStr) - Length (FindStr))) > Right_Margin) then
|
|
|
+ EditorDialog (edReplaceNotPossible, nil)
|
|
|
+ else
|
|
|
+ begin
|
|
|
+ Lock;
|
|
|
+ Search_Replace := True;
|
|
|
+ if length (ReplaceStr) < length (FindStr) then
|
|
|
+ Update_Place_Markers (0,
|
|
|
+ Length (FindStr) - Length (ReplaceStr),
|
|
|
+ CurPtr - Length (FindStr) + Length (ReplaceStr),
|
|
|
+ CurPtr)
|
|
|
+ else
|
|
|
+ if length (ReplaceStr) > length (FindStr) then
|
|
|
+ Update_Place_Markers (Length (ReplaceStr) - Length (FindStr),
|
|
|
+ 0,
|
|
|
+ CurPtr,
|
|
|
+ CurPtr + (Length (ReplaceStr) - Length (FindStr)));
|
|
|
+ InsertText (@ReplaceStr[1], Length (ReplaceStr), False);
|
|
|
+ Search_Replace := False;
|
|
|
+ TrackCursor (False);
|
|
|
+ Unlock;
|
|
|
+ end;
|
|
|
+ end;
|
|
|
+ end;
|
|
|
+ until (I = cmCancel) or (Flags and efReplaceAll = 0);
|
|
|
+end; { TEditor.DoSearchReplace }
|
|
|
+
|
|
|
+
|
|
|
+procedure TEditor.DoUpdate;
|
|
|
+begin
|
|
|
+ if UpdateFlags <> 0 then
|
|
|
+ begin
|
|
|
+ SetCursor (CurPos.X - Delta.X, CurPos.Y - Delta.Y);
|
|
|
+ if UpdateFlags and ufView <> 0 then
|
|
|
+ DrawView
|
|
|
+ else
|
|
|
+ if UpdateFlags and ufLine <> 0 then
|
|
|
+ DrawLines (CurPos.Y - Delta.Y, 1, LineStart (CurPtr));
|
|
|
+ if assigned(HScrollBar) then
|
|
|
+ HScrollBar^.SetParams (Delta.X, 0, Limit.X - Size.X, Size.X div 2, 1);
|
|
|
+ if assigned(VScrollBar) then
|
|
|
+ VScrollBar^.SetParams (Delta.Y, 0, Limit.Y - Size.Y, Size.Y - 1, 1);
|
|
|
+ if assigned(Indicator) then
|
|
|
+ Indicator^.SetValue (CurPos, AutoIndent, Modified, Word_Wrap);
|
|
|
+ if State and sfActive <> 0 then
|
|
|
+ UpdateCommands;
|
|
|
+ UpdateFlags := 0;
|
|
|
+ end;
|
|
|
+end; { TEditor.DoUpdate }
|
|
|
+
|
|
|
+
|
|
|
+function TEditor.Do_Word_Wrap (Select_Mode : Byte;
|
|
|
+ Center_Cursor : Boolean) : Boolean;
|
|
|
+{ This procedure does the actual wordwrap. It always assumes the CurPtr }
|
|
|
+{ is at Right_Margin + 1. It makes several tests for special conditions }
|
|
|
+{ and processes those first. If they all fail, it does a normal wrap. }
|
|
|
+VAR
|
|
|
+ A : Sw_Word; { Distance between line start and first word on line. }
|
|
|
+ C : Sw_Word; { Current pointer when we come into procedure. }
|
|
|
+ L : Sw_Word; { BufLen when we come into procedure. }
|
|
|
+ P : Sw_Word; { Position of pointer at any given moment. }
|
|
|
+ S : Sw_Word; { Start of a line. }
|
|
|
+begin
|
|
|
+ Do_Word_Wrap := False;
|
|
|
+ Select_Mode := 0;
|
|
|
+ if BufLen >= (BufSize - 1) then
|
|
|
+ exit;
|
|
|
+ C := CurPtr;
|
|
|
+ L := BufLen;
|
|
|
+ S := LineStart (CurPtr);
|
|
|
+ { If first character in the line is a space and autoindent mode is on }
|
|
|
+ { then we check to see if NextWord(S) exceeds the CurPtr. If it does, }
|
|
|
+ { we set CurPtr as the AutoIndent marker. If it doesn't, we will set }
|
|
|
+ { NextWord(S) as the AutoIndent marker. If neither, we set it to S. }
|
|
|
+ if AutoIndent and (Buffer^[S] = ' ') then
|
|
|
+ begin
|
|
|
+ if NextWord (S) > CurPtr then
|
|
|
+ A := CurPtr
|
|
|
+ else
|
|
|
+ A := NextWord (S);
|
|
|
+ end
|
|
|
+ else
|
|
|
+ A := NextWord (S);
|
|
|
+ { Though NewLine will remove EOL spaces, we do it here too. }
|
|
|
+ { This catches the instance where a user may try to space }
|
|
|
+ { completely across the line, in which case CurPtr.X = 0. }
|
|
|
+ Remove_EOL_Spaces (Select_Mode);
|
|
|
+ if CurPos.X = 0 then
|
|
|
+ begin
|
|
|
+ NewLine (Select_Mode);
|
|
|
+ Do_Word_Wrap := True;
|
|
|
+ Exit;
|
|
|
+ end;
|
|
|
+ { At this point we have one of five situations: }
|
|
|
+ { }
|
|
|
+ { 1) AutoIndent is on and this line is all spaces before CurPtr. }
|
|
|
+ { 2) AutoIndent is off and this line is all spaces before CurPtr. }
|
|
|
+ { 3) AutoIndent is on and this line is continuous characters before CurPtr. }
|
|
|
+ { 4) AutoIndent is off and this line is continuous characters before CurPtr. }
|
|
|
+ { 5) This is just a normal line of text. }
|
|
|
+ { }
|
|
|
+ { Conditions 1 through 4 have to be taken into account before condition 5. }
|
|
|
+ { First, we see if there are all spaces and/or all characters. }
|
|
|
+ { Then we determine which one it really is. Finally, we take }
|
|
|
+ { a course of action based on the state of AutoIndent. }
|
|
|
+ if PrevWord (CurPtr) <= S then
|
|
|
+ begin
|
|
|
+ P := CurPtr - 1;
|
|
|
+ while ((Buffer^[P] <> ' ') and (P > S)) do
|
|
|
+ Dec (P);
|
|
|
+ { We found NO SPACES. Conditions 4 and 5 are treated the same. }
|
|
|
+ { We can NOT do word wrap and put up a dialog box stating such. }
|
|
|
+ { Delete character just entered so we don't exceed Right_Margin. }
|
|
|
+ if P = S then
|
|
|
+ begin
|
|
|
+ EditorDialog (edWrapNotPossible, nil);
|
|
|
+ DeleteRange (PrevChar (CurPtr), CurPtr, True);
|
|
|
+ Exit;
|
|
|
+ end
|
|
|
+ else
|
|
|
+ begin
|
|
|
+ { There are spaces. Now find out if they are all spaces. }
|
|
|
+ { If so, see if AutoIndent is on. If it is, turn it off, }
|
|
|
+ { do a NewLine, and turn it back on. Otherwise, just do }
|
|
|
+ { the NewLine. We go through all of these gyrations for }
|
|
|
+ { AutoIndent. Being way out here with a preceding line }
|
|
|
+ { of spaces and wrapping with AutoIndent on is real dumb! }
|
|
|
+ { However, the user expects something. The wrap will NOT }
|
|
|
+ { autoindent, but they had no business being here anyway! }
|
|
|
+ P := CurPtr - 1;
|
|
|
+ while ((Buffer^[P] = ' ') and (P > S)) do
|
|
|
+ Dec (P);
|
|
|
+ if P = S then
|
|
|
+ begin
|
|
|
+ if Autoindent then
|
|
|
+ begin
|
|
|
+ AutoIndent := False;
|
|
|
+ NewLine (Select_Mode);
|
|
|
+ AutoIndent := True;
|
|
|
+ end
|
|
|
+ else
|
|
|
+ NewLine (Select_Mode);
|
|
|
+ end; { AutoIndent }
|
|
|
+ end; { P = S for spaces }
|
|
|
+ end { P = S for no spaces }
|
|
|
+ else { PrevWord (CurPtr) <= S }
|
|
|
+ begin
|
|
|
+ { Hooray! We actually had a plain old line of text to wrap! }
|
|
|
+ { Regardless if we are pushing out a line beyond the Right_Margin, }
|
|
|
+ { or at the end of a line itself, the following will determine }
|
|
|
+ { exactly where to do the wrap and re-set the cursor accordingly. }
|
|
|
+ { However, if P = A then we can't wrap. Show dialog and exit. }
|
|
|
+ P := CurPtr;
|
|
|
+ while P - S > Right_Margin do
|
|
|
+ P := PrevWord (P);
|
|
|
+ if (P = A) then
|
|
|
+ begin
|
|
|
+ EditorDialog (edReformNotPossible, nil);
|
|
|
+ SetCurPtr (P, Select_Mode);
|
|
|
+ Exit;
|
|
|
+ end;
|
|
|
+ SetCurPtr (P, Select_Mode);
|
|
|
+ NewLine (Select_Mode);
|
|
|
+ end; { PrevWord (CurPtr <= S }
|
|
|
+ { Track the cursor here (it is at CurPos.X = 0) so the view }
|
|
|
+ { will redraw itself at column 0. This eliminates having it }
|
|
|
+ { redraw starting at the current cursor and not being able }
|
|
|
+ { to see text before the cursor. Of course, we also end up }
|
|
|
+ { redrawing the view twice, here and back in HandleEvent. }
|
|
|
+ { }
|
|
|
+ { Reposition cursor so user can pick up where they left off. }
|
|
|
+ TrackCursor (Center_Cursor);
|
|
|
+ SetCurPtr (C - (L - BufLen), Select_Mode);
|
|
|
+ Do_Word_Wrap := True;
|
|
|
+end; { TEditor.Do_Word_Wrap }
|
|
|
+
|
|
|
+
|
|
|
+procedure TEditor.Draw;
|
|
|
+begin
|
|
|
+ if DrawLine <> Delta.Y then
|
|
|
+ begin
|
|
|
+ DrawPtr := LineMove (DrawPtr, Delta.Y - DrawLine);
|
|
|
+ DrawLine := Delta.Y;
|
|
|
+ end;
|
|
|
+ DrawLines (0, Size.Y, DrawPtr);
|
|
|
+end; { TEditor.Draw }
|
|
|
+
|
|
|
+
|
|
|
+procedure TEditor.DrawLines (Y, Count : Sw_Integer; LinePtr : Sw_Word);
|
|
|
+VAR
|
|
|
+ Color : Word;
|
|
|
+ B : array[0..MaxLineLength - 1] of Sw_Word;
|
|
|
+begin
|
|
|
+ Color := GetColor ($0201);
|
|
|
+ while Count > 0 do
|
|
|
+ begin
|
|
|
+ FormatLine (B, LinePtr, Delta.X + Size.X, Color);
|
|
|
+ WriteBuf (0, Y, Size.X, 1, B[Delta.X]);
|
|
|
+ LinePtr := NextLine (LinePtr);
|
|
|
+ Inc (Y);
|
|
|
+ Dec (Count);
|
|
|
+ end;
|
|
|
+end; { TEditor.DrawLines }
|
|
|
+
|
|
|
+
|
|
|
+procedure TEditor.Find;
|
|
|
+VAR
|
|
|
+ FindRec : TFindDialogRec;
|
|
|
+begin
|
|
|
+ with FindRec do
|
|
|
+ begin
|
|
|
+ Find := FindStr;
|
|
|
+ Options := Flags;
|
|
|
+ if EditorDialog (edFind, @FindRec) <> cmCancel then
|
|
|
+ begin
|
|
|
+ FindStr := Find;
|
|
|
+ Flags := Options and not efDoReplace;
|
|
|
+ DoSearchReplace;
|
|
|
+ end;
|
|
|
+ end;
|
|
|
+end; { TEditor.Find }
|
|
|
+
|
|
|
+
|
|
|
+procedure TEditor.FormatLine (var DrawBuf; LinePtr : Sw_Word;
|
|
|
+ Width : Sw_Integer;
|
|
|
+ Colors : Word);
|
|
|
+var
|
|
|
+ outptr : pword;
|
|
|
+ outcnt,
|
|
|
+ idxpos : Sw_Word;
|
|
|
+ attr : Word;
|
|
|
+
|
|
|
+ procedure FillSpace(i:Sw_Word);
|
|
|
+ var
|
|
|
+ w : word;
|
|
|
+ begin
|
|
|
+ inc(OutCnt,i);
|
|
|
+ w:=32 or attr;
|
|
|
+ while (i>0) do
|
|
|
+ begin
|
|
|
+ OutPtr^:=w;
|
|
|
+ inc(OutPtr);
|
|
|
+ dec(i);
|
|
|
+ end;
|
|
|
+ end;
|
|
|
+
|
|
|
+ function FormatUntil(endpos:Sw_word):boolean;
|
|
|
+ var
|
|
|
+ p : pchar;
|
|
|
+ begin
|
|
|
+ FormatUntil:=false;
|
|
|
+ p:=pchar(Buffer)+idxpos;
|
|
|
+ while endpos>idxpos do
|
|
|
+ begin
|
|
|
+ if OutCnt>=Width then
|
|
|
+ exit;
|
|
|
+ case p^ of
|
|
|
+ #9 :
|
|
|
+ FillSpace(Tabsize-(outcnt mod Tabsize));
|
|
|
+ #10,#13 :
|
|
|
+ begin
|
|
|
+ FillSpace(Width-OutCnt);
|
|
|
+ FormatUntil:=true;
|
|
|
+ exit;
|
|
|
+ end;
|
|
|
+ else
|
|
|
+ begin
|
|
|
+ inc(OutCnt);
|
|
|
+ OutPtr^:=ord(p^) or attr;
|
|
|
+ inc(OutPtr);
|
|
|
+ end;
|
|
|
+ end; { case }
|
|
|
+ inc(p);
|
|
|
+ inc(idxpos);
|
|
|
+ end;
|
|
|
+ end;
|
|
|
+
|
|
|
+begin
|
|
|
+ OutCnt:=0;
|
|
|
+ OutPtr:=@DrawBuf;
|
|
|
+ idxPos:=LinePtr;
|
|
|
+ attr:=lo(Colors) shl 8;
|
|
|
+ if FormatUntil(SelStart) then
|
|
|
+ exit;
|
|
|
+ attr:=hi(Colors) shl 8;
|
|
|
+ if FormatUntil(CurPtr) then
|
|
|
+ exit;
|
|
|
+ inc(idxPos,GapLen);
|
|
|
+ if FormatUntil(SelEnd+GapLen) then
|
|
|
+ exit;
|
|
|
+ attr:=lo(Colors) shl 8;
|
|
|
+ if FormatUntil(BufSize) then
|
|
|
+ exit;
|
|
|
+{ fill up until width }
|
|
|
+ FillSpace(Width-OutCnt);
|
|
|
+end; {TEditor.FormatLine}
|
|
|
+
|
|
|
+
|
|
|
+function TEditor.GetMousePtr (Mouse : Objects.TPoint) : Sw_Word;
|
|
|
+begin
|
|
|
+ MakeLocal (Mouse, Mouse);
|
|
|
+ Mouse.X := Max (0, Min (Mouse.X, Size.X - 1));
|
|
|
+ Mouse.Y := Max (0, Min (Mouse.Y, Size.Y - 1));
|
|
|
+ GetMousePtr := CharPtr (LineMove (DrawPtr, Mouse.Y + Delta.Y - DrawLine),
|
|
|
+ Mouse.X + Delta.X);
|
|
|
+end; { TEditor.GetMousePtr }
|
|
|
+
|
|
|
+
|
|
|
+function TEditor.GetPalette : PPalette;
|
|
|
+CONST
|
|
|
+ P : String[Length (CEditor)] = CEditor;
|
|
|
+begin
|
|
|
+ GetPalette := @P;
|
|
|
+end; { TEditor.GetPalette }
|
|
|
+
|
|
|
+
|
|
|
+procedure TEditor.HandleEvent (var Event : Drivers.TEvent);
|
|
|
+VAR
|
|
|
+ ShiftState : Byte;
|
|
|
+ CenterCursor : Boolean;
|
|
|
+ SelectMode : Byte;
|
|
|
+ D : Objects.TPoint;
|
|
|
+ Mouse : Objects.TPoint;
|
|
|
+
|
|
|
+ function CheckScrollBar (P : PScrollBar; var D : Sw_Integer) : Boolean;
|
|
|
+ begin
|
|
|
+ CheckScrollBar := FALSE;
|
|
|
+ if (Event.InfoPtr = P) and (P^.Value <> D) then
|
|
|
+ begin
|
|
|
+ D := P^.Value;
|
|
|
+ Update (ufView);
|
|
|
+ CheckScrollBar := TRUE;
|
|
|
+ end;
|
|
|
+ end; {CheckScrollBar}
|
|
|
+
|
|
|
+begin
|
|
|
+ Inherited HandleEvent (Event);
|
|
|
+ ConvertEvent (Event);
|
|
|
+ CenterCursor := not CursorVisible;
|
|
|
+ SelectMode := 0;
|
|
|
+ ShiftState:=GetShiftState;
|
|
|
+ if Selecting or (ShiftState and $03 <> 0) then
|
|
|
+ SelectMode := smExtend;
|
|
|
+ case Event.What of
|
|
|
+ Drivers.evMouseDown:
|
|
|
+ begin
|
|
|
+ if Event.Double then
|
|
|
+ SelectMode := SelectMode or smDouble;
|
|
|
+ repeat
|
|
|
+ Lock;
|
|
|
+ if Event.What = evMouseAuto then
|
|
|
+ begin
|
|
|
+ MakeLocal (Event.Where, Mouse);
|
|
|
+ D := Delta;
|
|
|
+ if Mouse.X < 0 then
|
|
|
+ Dec (D.X);
|
|
|
+ if Mouse.X >= Size.X then
|
|
|
+ Inc (D.X);
|
|
|
+ if Mouse.Y < 0 then
|
|
|
+ Dec (D.Y);
|
|
|
+ if Mouse.Y >= Size.Y then
|
|
|
+ Inc (D.Y);
|
|
|
+ ScrollTo (D.X, D.Y);
|
|
|
+ end;
|
|
|
+ SetCurPtr (GetMousePtr (Event.Where), SelectMode);
|
|
|
+ SelectMode := SelectMode or smExtend;
|
|
|
+ Unlock;
|
|
|
+ until not MouseEvent (Event, evMouseMove + evMouseAuto);
|
|
|
+ end; { Drivers.evMouseDown }
|
|
|
+
|
|
|
+ Drivers.evKeyDown:
|
|
|
+ case Event.CharCode of
|
|
|
+ #32..#255:
|
|
|
+ begin
|
|
|
+ Lock;
|
|
|
+ if Overwrite and not HasSelection then
|
|
|
+ if CurPtr <> LineEnd (CurPtr) then
|
|
|
+ SelEnd := NextChar (CurPtr);
|
|
|
+ InsertText (@Event.CharCode, 1, False);
|
|
|
+ if Word_Wrap then
|
|
|
+ Check_For_Word_Wrap (SelectMode, CenterCursor);
|
|
|
+ TrackCursor (CenterCursor);
|
|
|
+ Unlock;
|
|
|
+ end;
|
|
|
+
|
|
|
+ else
|
|
|
+ Exit;
|
|
|
+ end; { Drivers.evKeyDown }
|
|
|
+
|
|
|
+ Drivers.evCommand:
|
|
|
+ case Event.Command of
|
|
|
+ cmFind : Find;
|
|
|
+ cmReplace : Replace;
|
|
|
+ cmSearchAgain : DoSearchReplace;
|
|
|
+ else
|
|
|
+ begin
|
|
|
+ Lock;
|
|
|
+ case Event.Command of
|
|
|
+ cmCut : ClipCut;
|
|
|
+ cmCopy : ClipCopy;
|
|
|
+ cmPaste : ClipPaste;
|
|
|
+ cmUndo : Undo;
|
|
|
+ cmClear : DeleteSelect;
|
|
|
+ cmCharLeft : SetCurPtr (PrevChar (CurPtr), SelectMode);
|
|
|
+ cmCharRight : SetCurPtr (NextChar (CurPtr), SelectMode);
|
|
|
+ cmWordLeft : SetCurPtr (PrevWord (CurPtr), SelectMode);
|
|
|
+ cmWordRight : SetCurPtr (NextWord (CurPtr), SelectMode);
|
|
|
+ cmLineStart : SetCurPtr (LineStart (CurPtr), SelectMode);
|
|
|
+ cmLineEnd : SetCurPtr (LineEnd (CurPtr), SelectMode);
|
|
|
+ cmLineUp : SetCurPtr (LineMove (CurPtr, -1), SelectMode);
|
|
|
+ cmLineDown : SetCurPtr (LineMove (CurPtr, 1), SelectMode);
|
|
|
+ cmPageUp : SetCurPtr (LineMove (CurPtr, - (Size.Y - 1)), SelectMode);
|
|
|
+ cmPageDown : SetCurPtr (LineMove (CurPtr, Size.Y - 1), SelectMode);
|
|
|
+ cmTextStart : SetCurPtr (0, SelectMode);
|
|
|
+ cmTextEnd : SetCurPtr (BufLen, SelectMode);
|
|
|
+ cmNewLine : NewLine (SelectMode);
|
|
|
+ cmBackSpace : DeleteRange (PrevChar (CurPtr), CurPtr, True);
|
|
|
+ cmDelChar : DeleteRange (CurPtr, NextChar (CurPtr), True);
|
|
|
+ cmDelWord : DeleteRange (CurPtr, NextWord (CurPtr), False);
|
|
|
+ cmDelStart : DeleteRange (LineStart (CurPtr), CurPtr, False);
|
|
|
+ cmDelEnd : DeleteRange (CurPtr, LineEnd (CurPtr), False);
|
|
|
+ cmDelLine : DeleteRange (LineStart (CurPtr), NextLine (CurPtr), False);
|
|
|
+ cmInsMode : ToggleInsMode;
|
|
|
+ cmStartSelect : StartSelect;
|
|
|
+ cmHideSelect : HideSelect;
|
|
|
+ cmIndentMode : begin
|
|
|
+ AutoIndent := not AutoIndent;
|
|
|
+ Update (ufStats);
|
|
|
+ end; { Added provision to update TIndicator if ^QI pressed. }
|
|
|
+ cmCenterText : Center_Text (SelectMode);
|
|
|
+ cmEndPage : SetCurPtr (LineMove (CurPtr, Delta.Y - CurPos.Y + Size.Y - 1), SelectMode);
|
|
|
+ cmHomePage : SetCurPtr (LineMove (CurPtr, -(CurPos.Y - Delta.Y)), SelectMode);
|
|
|
+ cmInsertLine : Insert_Line (SelectMode);
|
|
|
+ cmJumpLine : Jump_To_Line (SelectMode);
|
|
|
+ cmReformDoc : Reformat_Document (SelectMode, CenterCursor);
|
|
|
+ cmReformPara : Reformat_Paragraph (SelectMode, CenterCursor);
|
|
|
+ cmRightMargin : Set_Right_Margin;
|
|
|
+ cmScrollDown : Scroll_Down;
|
|
|
+ cmScrollUp : Scroll_Up;
|
|
|
+ cmSelectWord : Select_Word;
|
|
|
+ cmSetTabs : Set_Tabs;
|
|
|
+ cmTabKey : Tab_Key (SelectMode);
|
|
|
+ cmWordWrap : begin
|
|
|
+ Word_Wrap := not Word_Wrap;
|
|
|
+ Update (ufStats);
|
|
|
+ end; { Added provision to update TIndicator if ^OW pressed. }
|
|
|
+ cmSetMark0 : Set_Place_Marker (10);
|
|
|
+ cmSetMark1 : Set_Place_Marker (1);
|
|
|
+ cmSetMark2 : Set_Place_Marker (2);
|
|
|
+ cmSetMark3 : Set_Place_Marker (3);
|
|
|
+ cmSetMark4 : Set_Place_Marker (4);
|
|
|
+ cmSetMark5 : Set_Place_Marker (5);
|
|
|
+ cmSetMark6 : Set_Place_Marker (6);
|
|
|
+ cmSetMark7 : Set_Place_Marker (7);
|
|
|
+ cmSetMark8 : Set_Place_Marker (8);
|
|
|
+ cmSetMark9 : Set_Place_Marker (9);
|
|
|
+ cmJumpMark0 : Jump_Place_Marker (10, SelectMode);
|
|
|
+ cmJumpMark1 : Jump_Place_Marker (1, SelectMode);
|
|
|
+ cmJumpMark2 : Jump_Place_Marker (2, SelectMode);
|
|
|
+ cmJumpMark3 : Jump_Place_Marker (3, SelectMode);
|
|
|
+ cmJumpMark4 : Jump_Place_Marker (4, SelectMode);
|
|
|
+ cmJumpMark5 : Jump_Place_Marker (5, SelectMode);
|
|
|
+ cmJumpMark6 : Jump_Place_Marker (6, SelectMode);
|
|
|
+ cmJumpMark7 : Jump_Place_Marker (7, SelectMode);
|
|
|
+ cmJumpMark8 : Jump_Place_Marker (8, SelectMode);
|
|
|
+ cmJumpMark9 : Jump_Place_Marker (9, SelectMode);
|
|
|
+ else
|
|
|
+ Unlock;
|
|
|
+ Exit;
|
|
|
+ end; { Event.Command (Inner) }
|
|
|
+ TrackCursor (CenterCursor);
|
|
|
+ { If the user presses any key except cmNewline or cmBackspace }
|
|
|
+ { we need to check if the file has been modified yet. There }
|
|
|
+ { can be no spaces at the end of a line, or wordwrap doesn't }
|
|
|
+ { work properly. We don't want to do this if the file hasn't }
|
|
|
+ { been modified because the user could be bringing in an ASCII }
|
|
|
+ { file from an editor that allows spaces at the EOL. If we }
|
|
|
+ { took them out in that scenario the "M" would appear on the }
|
|
|
+ { TIndicator line and the user would get upset or confused. }
|
|
|
+ if (Event.Command <> cmNewLine) and
|
|
|
+ (Event.Command <> cmBackSpace) and
|
|
|
+ (Event.Command <> cmTabKey) and
|
|
|
+ Modified then
|
|
|
+ Remove_EOL_Spaces (SelectMode);
|
|
|
+ Unlock;
|
|
|
+ end; { Event.Command (Outer) }
|
|
|
+ end; { Drivers.evCommand }
|
|
|
+
|
|
|
+ Drivers.evBroadcast:
|
|
|
+ case Event.Command of
|
|
|
+ cmScrollBarChanged:
|
|
|
+ if (Event.InfoPtr = HScrollBar) or
|
|
|
+ (Event.InfoPtr = VScrollBar) then
|
|
|
+ begin
|
|
|
+ CheckScrollBar (HScrollBar, Delta.X);
|
|
|
+ CheckScrollBar (VScrollBar, Delta.Y);
|
|
|
+ end
|
|
|
+ else
|
|
|
+ exit;
|
|
|
+ else
|
|
|
+ Exit;
|
|
|
+ end; { Drivers.evBroadcast }
|
|
|
+
|
|
|
+ end;
|
|
|
+ ClearEvent (Event);
|
|
|
+end; { TEditor.HandleEvent }
|
|
|
+
|
|
|
+
|
|
|
+function TEditor.HasSelection : Boolean;
|
|
|
+begin
|
|
|
+ HasSelection := SelStart <> SelEnd;
|
|
|
+end; { TEditor.HasSelection }
|
|
|
+
|
|
|
+
|
|
|
+procedure TEditor.HideSelect;
|
|
|
+begin
|
|
|
+ Selecting := False;
|
|
|
+ SetSelect (CurPtr, CurPtr, False);
|
|
|
+end; { TEditor.HideSelect }
|
|
|
+
|
|
|
+
|
|
|
+procedure TEditor.InitBuffer;
|
|
|
+begin
|
|
|
+ Buffer := MemAlloc (BufSize);
|
|
|
+end; { TEditor.InitBuffer }
|
|
|
+
|
|
|
+
|
|
|
+function TEditor.InsertBuffer (var P : PEditBuffer;
|
|
|
+ Offset, Length : Sw_Word;
|
|
|
+ AllowUndo, SelectText : Boolean) : Boolean;
|
|
|
+VAR
|
|
|
+ SelLen : Sw_Word;
|
|
|
+ DelLen : Sw_Word;
|
|
|
+ SelLines : Sw_Word;
|
|
|
+ Lines : Sw_Word;
|
|
|
+ NewSize : Longint;
|
|
|
+begin
|
|
|
+ InsertBuffer := True;
|
|
|
+ Selecting := False;
|
|
|
+ SelLen := SelEnd - SelStart;
|
|
|
+ if (SelLen = 0) and (Length = 0) then
|
|
|
+ Exit;
|
|
|
+ DelLen := 0;
|
|
|
+ if AllowUndo then
|
|
|
+ if CurPtr = SelStart then
|
|
|
+ DelLen := SelLen
|
|
|
+ else
|
|
|
+ if SelLen > InsCount then
|
|
|
+ DelLen := SelLen - InsCount;
|
|
|
+ NewSize := Longint (BufLen + DelCount - SelLen + DelLen) + Length;
|
|
|
+ if NewSize > BufLen + DelCount then
|
|
|
+ if (NewSize > MaxBufLength) or not SetBufSize (NewSize) then
|
|
|
+ begin
|
|
|
+ EditorDialog (edOutOfMemory, nil);
|
|
|
+ InsertBuffer := False;
|
|
|
+ SelEnd := SelStart;
|
|
|
+ Exit;
|
|
|
+ end;
|
|
|
+ SelLines := CountLines (Buffer^[BufPtr (SelStart)], SelLen);
|
|
|
+ if CurPtr = SelEnd then
|
|
|
+ begin
|
|
|
+ if AllowUndo then
|
|
|
+ begin
|
|
|
+ if DelLen > 0 then
|
|
|
+ Move (Buffer^[SelStart], Buffer^[CurPtr + GapLen - DelCount - DelLen], DelLen);
|
|
|
+ Dec (InsCount, SelLen - DelLen);
|
|
|
+ end;
|
|
|
+ CurPtr := SelStart;
|
|
|
+ Dec (CurPos.Y, SelLines);
|
|
|
+ end;
|
|
|
+ if Delta.Y > CurPos.Y then
|
|
|
+ begin
|
|
|
+ Dec (Delta.Y, SelLines);
|
|
|
+ if Delta.Y < CurPos.Y then
|
|
|
+ Delta.Y := CurPos.Y;
|
|
|
+ end;
|
|
|
+ if Length > 0 then
|
|
|
+ Move (P^[Offset], Buffer^[CurPtr], Length);
|
|
|
+ Lines := CountLines (Buffer^[CurPtr], Length);
|
|
|
+ Inc (CurPtr, Length);
|
|
|
+ Inc (CurPos.Y, Lines);
|
|
|
+ DrawLine := CurPos.Y;
|
|
|
+ DrawPtr := LineStart (CurPtr);
|
|
|
+ CurPos.X := CharPos (DrawPtr, CurPtr);
|
|
|
+ if not SelectText then
|
|
|
+ SelStart := CurPtr;
|
|
|
+ SelEnd := CurPtr;
|
|
|
+ if Length>Sellen then
|
|
|
+ begin
|
|
|
+ Inc (BufLen, Length - SelLen);
|
|
|
+ Dec (GapLen, Length - SelLen);
|
|
|
+ end
|
|
|
+ else
|
|
|
+ begin
|
|
|
+ Dec (BufLen, Sellen - Length);
|
|
|
+ Inc (GapLen, Sellen - Length);
|
|
|
+ end;
|
|
|
+ if AllowUndo then
|
|
|
+ begin
|
|
|
+ Inc (DelCount, DelLen);
|
|
|
+ Inc (InsCount, Length);
|
|
|
+ end;
|
|
|
+ Inc (Limit.Y, Lines - SelLines);
|
|
|
+ Delta.Y := Max (0, Min (Delta.Y, Limit.Y - Size.Y));
|
|
|
+ if not IsClipboard then
|
|
|
+ Modified := True;
|
|
|
+ SetBufSize (BufLen + DelCount);
|
|
|
+ if (SelLines = 0) and (Lines = 0) then
|
|
|
+ Update (ufLine)
|
|
|
+ else
|
|
|
+ Update (ufView);
|
|
|
+end; { TEditor.InsertBuffer }
|
|
|
+
|
|
|
+
|
|
|
+function TEditor.InsertFrom (Editor : PEditor) : Boolean;
|
|
|
+begin
|
|
|
+ InsertFrom := InsertBuffer (Editor^.Buffer,
|
|
|
+ Editor^.BufPtr (Editor^.SelStart),
|
|
|
+ Editor^.SelEnd - Editor^.SelStart, CanUndo, IsClipboard);
|
|
|
+end; { TEditor.InsertFrom }
|
|
|
+
|
|
|
+
|
|
|
+procedure TEditor.Insert_Line (Select_Mode : Byte);
|
|
|
+{ This procedure inserts a newline at the current cursor position }
|
|
|
+{ if a ^N is pressed. Unlike cmNewLine, the cursor will return }
|
|
|
+{ to its original position. If the cursor was at the end of a }
|
|
|
+{ line, and its spaces were removed, the cursor returns to the }
|
|
|
+{ end of the line instead. }
|
|
|
+begin
|
|
|
+ NewLine (Select_Mode);
|
|
|
+ SetCurPtr (LineEnd (LineMove (CurPtr, -1)), Select_Mode);
|
|
|
+end; { TEditor.Insert_Line }
|
|
|
+
|
|
|
+
|
|
|
+function TEditor.InsertText (Text : Pointer;
|
|
|
+ Length : Sw_Word;
|
|
|
+ SelectText : Boolean) : Boolean;
|
|
|
+begin
|
|
|
+ if assigned(Text) and not Search_Replace then
|
|
|
+ Update_Place_Markers (Length, 0, Self.SelStart, Self.SelEnd);
|
|
|
+ InsertText := InsertBuffer (PEditBuffer (Text),
|
|
|
+ 0, Length, CanUndo, SelectText);
|
|
|
+end; { TEditor.InsertText }
|
|
|
+
|
|
|
+
|
|
|
+function TEditor.IsClipboard : Boolean;
|
|
|
+begin
|
|
|
+ IsClipboard := Clipboard = @Self;
|
|
|
+end; { TEditor.IsClipboard }
|
|
|
+
|
|
|
+
|
|
|
+procedure TEditor.Jump_Place_Marker (Element : Byte; Select_Mode : Byte);
|
|
|
+{ This procedure jumps to a place marker if ^Q# is pressed. }
|
|
|
+{ We don't go anywhere if Place_Marker[Element] is not zero. }
|
|
|
+begin
|
|
|
+ if (not IsClipboard) and (Place_Marker[Element] <> 0) then
|
|
|
+ SetCurPtr (Place_Marker[Element], Select_Mode);
|
|
|
+end; { TEditor.Jump_Place_Marker }
|
|
|
+
|
|
|
+
|
|
|
+procedure TEditor.Jump_To_Line (Select_Mode : Byte);
|
|
|
+{ This function brings up a dialog box that allows }
|
|
|
+{ the user to select a line number to jump to. }
|
|
|
+VAR
|
|
|
+ Code : Integer; { Used for Val conversion. }
|
|
|
+ Temp_Value : Longint; { Holds converted dialog value. }
|
|
|
+begin
|
|
|
+ if EditorDialog (edJumpToLine, @Line_Number) <> cmCancel then
|
|
|
+ begin
|
|
|
+ { Convert the Line_Number string to an interger. }
|
|
|
+ { Put it into Temp_Value. If the number is not }
|
|
|
+ { in the range 1..9999 abort. If the number is }
|
|
|
+ { our current Y position, abort. Otherwise, }
|
|
|
+ { go to top of document, and jump to the line. }
|
|
|
+ { There are faster methods. This one's easy. }
|
|
|
+ { Note that CurPos.Y is always 1 less than what }
|
|
|
+ { the TIndicator line says. }
|
|
|
+ val (Line_Number, Temp_Value, Code);
|
|
|
+ if (Temp_Value < 1) or (Temp_Value > 9999999) then
|
|
|
+ Exit;
|
|
|
+ if Temp_Value = CurPos.Y + 1 then
|
|
|
+ Exit;
|
|
|
+ SetCurPtr (0, Select_Mode);
|
|
|
+ SetCurPtr (LineMove (CurPtr, Temp_Value - 1), Select_Mode);
|
|
|
+ end;
|
|
|
+end; {TEditor.Jump_To_Line}
|
|
|
+
|
|
|
+
|
|
|
+function TEditor.LineEnd (P : Sw_Word) : Sw_Word;
|
|
|
+var
|
|
|
+ start,
|
|
|
+ i : Sw_word;
|
|
|
+ pc : pchar;
|
|
|
+begin
|
|
|
+ if P<CurPtr then
|
|
|
+ begin
|
|
|
+ i:=CurPtr-P;
|
|
|
+ pc:=pchar(Buffer)+P;
|
|
|
+ while (i>0) do
|
|
|
+ begin
|
|
|
+ if pc^ in [#10,#13] then
|
|
|
+ begin
|
|
|
+ LineEnd:=pc-pchar(Buffer);
|
|
|
+ exit;
|
|
|
+ end;
|
|
|
+ inc(pc);
|
|
|
+ dec(i);
|
|
|
+ end;
|
|
|
+ start:=CurPtr;
|
|
|
+ end
|
|
|
+ else
|
|
|
+ start:=P;
|
|
|
+ i:=BufLen-Start;
|
|
|
+ pc:=pchar(Buffer)+GapLen+start;
|
|
|
+ while (i>0) do
|
|
|
+ begin
|
|
|
+ if pc^ in [#10,#13] then
|
|
|
+ begin
|
|
|
+ LineEnd:=pc-(pchar(Buffer)+Gaplen);
|
|
|
+ exit;
|
|
|
+ end;
|
|
|
+ inc(pc);
|
|
|
+ dec(i);
|
|
|
+ end;
|
|
|
+ LineEnd:=pc-(pchar(Buffer)+Gaplen);
|
|
|
+end; { TEditor.LineEnd }
|
|
|
+
|
|
|
+
|
|
|
+function TEditor.LineMove (P : Sw_Word; Count : Sw_Integer) : Sw_Word;
|
|
|
+VAR
|
|
|
+ Pos : Sw_Integer;
|
|
|
+ I : Sw_Word;
|
|
|
+begin
|
|
|
+ I := P;
|
|
|
+ P := LineStart (P);
|
|
|
+ Pos := CharPos (P, I);
|
|
|
+ while Count <> 0 do
|
|
|
+ begin
|
|
|
+ I := P;
|
|
|
+ if Count < 0 then
|
|
|
+ begin
|
|
|
+ P := PrevLine (P);
|
|
|
+ Inc (Count);
|
|
|
+ end
|
|
|
+ else
|
|
|
+ begin
|
|
|
+ P := NextLine (P);
|
|
|
+ Dec (Count);
|
|
|
+ end;
|
|
|
+ end;
|
|
|
+ if P <> I then
|
|
|
+ P := CharPtr (P, Pos);
|
|
|
+ LineMove := P;
|
|
|
+end; { TEditor.LineMove }
|
|
|
+
|
|
|
+
|
|
|
+function TEditor.LineStart (P : Sw_Word) : Sw_Word;
|
|
|
+var
|
|
|
+ i : Sw_word;
|
|
|
+ start,pc : pchar;
|
|
|
+ oc : char;
|
|
|
+begin
|
|
|
+ if P>CurPtr then
|
|
|
+ begin
|
|
|
+ start:=pchar(Buffer)+GapLen;
|
|
|
+ pc:=start;
|
|
|
+ i:=P-CurPtr;
|
|
|
+ dec(pc);
|
|
|
+ while (i>0) do
|
|
|
+ begin
|
|
|
+ if pc^ in [#10,#13] then
|
|
|
+ break;
|
|
|
+ dec(pc);
|
|
|
+ dec(i);
|
|
|
+ end;
|
|
|
+ end
|
|
|
+ else
|
|
|
+ i:=0;
|
|
|
+ if i=0 then
|
|
|
+ begin
|
|
|
+ start:=pchar(Buffer);
|
|
|
+ i:=P;
|
|
|
+ pc:=start+p;
|
|
|
+ dec(pc);
|
|
|
+ while (i>0) do
|
|
|
+ begin
|
|
|
+ if pc^ in [#10,#13] then
|
|
|
+ break;
|
|
|
+ dec(pc);
|
|
|
+ dec(i);
|
|
|
+ end;
|
|
|
+ if i=0 then
|
|
|
+ begin
|
|
|
+ LineStart:=0;
|
|
|
+ exit;
|
|
|
+ end;
|
|
|
+ end;
|
|
|
+ oc:=pc^;
|
|
|
+ LineStart:=pc-start+1;
|
|
|
+end; { TEditor.LineStart }
|
|
|
+
|
|
|
+
|
|
|
+function TEditor.LineNr (P : Sw_Word) : Sw_Word;
|
|
|
+var
|
|
|
+ pc,endp : pchar;
|
|
|
+ lines : sw_word;
|
|
|
+begin
|
|
|
+ endp:=pchar(Buffer)+BufPtr(P);
|
|
|
+ pc:=pchar(Buffer);
|
|
|
+ lines:=0;
|
|
|
+ while (pc<endp) do
|
|
|
+ begin
|
|
|
+ if pc^ in [#10,#13] then
|
|
|
+ begin
|
|
|
+ inc(lines);
|
|
|
+ if ord((pc+1)^)+ord(pc^)=23 then
|
|
|
+ begin
|
|
|
+ inc(pc);
|
|
|
+ if (pc>=endp) then
|
|
|
+ break;
|
|
|
+ end;
|
|
|
+ end;
|
|
|
+ inc(pc);
|
|
|
+ end;
|
|
|
+ LineNr:=Lines;
|
|
|
+end;
|
|
|
+
|
|
|
+
|
|
|
+procedure TEditor.Lock;
|
|
|
+begin
|
|
|
+ Inc (LockCount);
|
|
|
+end; { TEditor.Lock }
|
|
|
+
|
|
|
+
|
|
|
+function TEditor.NewLine (Select_Mode : Byte) : Boolean;
|
|
|
+VAR
|
|
|
+ I : Sw_Word; { Used to track spaces for AutoIndent. }
|
|
|
+ P : Sw_Word; { Position of Cursor when we arrive and after Newline. }
|
|
|
+begin
|
|
|
+ P := LineStart (CurPtr);
|
|
|
+ I := P;
|
|
|
+ { The first thing we do is remove any End Of Line spaces. }
|
|
|
+ { Then we check to see how many spaces are on beginning }
|
|
|
+ { of a line. We need this check to add them after CR/LF }
|
|
|
+ { if AutoIndenting. Last of all we insert spaces required }
|
|
|
+ { for the AutoIndenting, if it was on. }
|
|
|
+ Remove_EOL_Spaces (Select_Mode);
|
|
|
+ while (I < CurPtr) and ((Buffer^[I] in [#9,' '])) do
|
|
|
+ Inc (I);
|
|
|
+ if InsertText (@LineBreak[1], length(LineBreak), False) = FALSE then
|
|
|
+ exit;
|
|
|
+ if AutoIndent then
|
|
|
+ InsertText (@Buffer^[P], I - P, False);
|
|
|
+ { Remember where the CurPtr is at this moment. }
|
|
|
+ { Remember the length of the buffer at the moment. }
|
|
|
+ { Go to the previous line and remove EOL spaces. }
|
|
|
+ { Once removed, re-set the cursor to where we were }
|
|
|
+ { minus any spaces that might have been removed. }
|
|
|
+ I := BufLen;
|
|
|
+ P := CurPtr;
|
|
|
+ SetCurPtr (LineMove (CurPtr, - 1), Select_Mode);
|
|
|
+ Remove_EOL_Spaces (Select_Mode);
|
|
|
+ if I - BufLen <> 0 then
|
|
|
+ SetCurPtr (P - (I - BufLen), Select_Mode)
|
|
|
+ else
|
|
|
+ SetCurPtr (P, Select_Mode);
|
|
|
+ NewLine:=true;
|
|
|
+end; { TEditor.NewLine }
|
|
|
+
|
|
|
+
|
|
|
+function TEditor.NextChar (P : Sw_Word) : Sw_Word;
|
|
|
+var
|
|
|
+ pc : pchar;
|
|
|
+begin
|
|
|
+ if P<>BufLen then
|
|
|
+ begin
|
|
|
+ inc(P);
|
|
|
+ if P<>BufLen then
|
|
|
+ begin
|
|
|
+ pc:=pchar(Buffer);
|
|
|
+ if P>=CurPtr then
|
|
|
+ inc(pc,GapLen);
|
|
|
+ inc(pc,P-1);
|
|
|
+ if ord(pc^)+ord((pc+1)^)=23 then
|
|
|
+ inc(p);
|
|
|
+ end;
|
|
|
+ end;
|
|
|
+ NextChar:=P;
|
|
|
+end; { TEditor.NextChar }
|
|
|
+
|
|
|
+
|
|
|
+function TEditor.NextLine (P : Sw_Word) : Sw_Word;
|
|
|
+begin
|
|
|
+ NextLine := NextChar (LineEnd (P));
|
|
|
+end; { TEditor.NextLine }
|
|
|
+
|
|
|
+
|
|
|
+function TEditor.NextWord (P : Sw_Word) : Sw_Word;
|
|
|
+begin
|
|
|
+ { skip word }
|
|
|
+ while (P < BufLen) and (BufChar (P) in WordChars) do
|
|
|
+ P := NextChar (P);
|
|
|
+ { skip spaces }
|
|
|
+ while (P < BufLen) and not (BufChar (P) in WordChars) do
|
|
|
+ P := NextChar (P);
|
|
|
+ NextWord := P;
|
|
|
+end; { TEditor.NextWord }
|
|
|
+
|
|
|
+
|
|
|
+function TEditor.PrevChar (P : Sw_Word) : Sw_Word;
|
|
|
+var
|
|
|
+ pc : pchar;
|
|
|
+begin
|
|
|
+ if p<>0 then
|
|
|
+ begin
|
|
|
+ dec(p);
|
|
|
+ if p<>0 then
|
|
|
+ begin
|
|
|
+ pc:=pchar(Buffer);
|
|
|
+ if P>=CurPtr then
|
|
|
+ inc(pc,GapLen);
|
|
|
+ inc(pc,P-1);
|
|
|
+ if ord(pc^)+ord((pc+1)^)=23 then
|
|
|
+ dec(p);
|
|
|
+ end;
|
|
|
+ end;
|
|
|
+ PrevChar:=P;
|
|
|
+end; { TEditor.PrevChar }
|
|
|
+
|
|
|
+
|
|
|
+function TEditor.PrevLine (P : Sw_Word) : Sw_Word;
|
|
|
+begin
|
|
|
+ PrevLine := LineStart (PrevChar (P));
|
|
|
+end; { TEditor.PrevLine }
|
|
|
+
|
|
|
+
|
|
|
+function TEditor.PrevWord (P : Sw_Word) : Sw_Word;
|
|
|
+begin
|
|
|
+ { skip spaces }
|
|
|
+ while (P > 0) and not (BufChar (PrevChar (P)) in WordChars) do
|
|
|
+ P := PrevChar (P);
|
|
|
+ { skip word }
|
|
|
+ while (P > 0) and (BufChar (PrevChar (P)) in WordChars) do
|
|
|
+ P := PrevChar (P);
|
|
|
+ PrevWord := P;
|
|
|
+end; { TEditor.PrevWord }
|
|
|
+
|
|
|
+
|
|
|
+procedure TEditor.Reformat_Document (Select_Mode : Byte; Center_Cursor : Boolean);
|
|
|
+{ This procedure will do a reformat of the entire document, or just }
|
|
|
+{ from the current line to the end of the document, if ^QU is pressed. }
|
|
|
+{ It simply brings up the correct dialog box, and then calls the }
|
|
|
+{ TEditor.Reformat_Paragraph procedure to do the actual reformatting. }
|
|
|
+CONST
|
|
|
+ efCurrentLine = $0000; { Radio button #1 selection for dialog box. }
|
|
|
+ efWholeDocument = $0001; { Radio button #2 selection for dialog box. }
|
|
|
+VAR
|
|
|
+ Reformat_Options : Word; { Holds the dialog options for reformatting. }
|
|
|
+begin
|
|
|
+ { Check if Word_Wrap is toggled on. If NOT on, check if programmer }
|
|
|
+ { allows reformatting of document and if not show user dialog that }
|
|
|
+ { says reformatting is not permissable. }
|
|
|
+ if not Word_Wrap then
|
|
|
+ begin
|
|
|
+ if not Allow_Reformat then
|
|
|
+ begin
|
|
|
+ EditorDialog (edReformatNotAllowed, nil);
|
|
|
+ Exit;
|
|
|
+ end;
|
|
|
+ Word_Wrap := True;
|
|
|
+ Update (ufStats);
|
|
|
+ end;
|
|
|
+ { Default radio button option to 1st one. Bring up dialog box. }
|
|
|
+ Reformat_Options := efCurrentLine;
|
|
|
+ if EditorDialog (edReformatDocument, @Reformat_Options) <> cmCancel then
|
|
|
+ begin
|
|
|
+ { If the option to reformat the whole document was selected }
|
|
|
+ { we need to go back to start of document. Otherwise we stay }
|
|
|
+ { on the current line. Call Reformat_Paragraph until we get }
|
|
|
+ { to the end of the document to do the reformatting. }
|
|
|
+ if Reformat_Options and efWholeDocument <> 0 then
|
|
|
+ SetCurPtr (0, Select_Mode);
|
|
|
+ Unlock;
|
|
|
+ repeat
|
|
|
+ Lock;
|
|
|
+ if NOT Reformat_Paragraph (Select_Mode, Center_Cursor) then
|
|
|
+ Exit;
|
|
|
+ TrackCursor (False);
|
|
|
+ Unlock;
|
|
|
+ until CurPtr = BufLen;
|
|
|
+ end;
|
|
|
+end; { TEditor.Reformat_Document }
|
|
|
+
|
|
|
+
|
|
|
+function TEditor.Reformat_Paragraph (Select_Mode : Byte;
|
|
|
+ Center_Cursor : Boolean) : Boolean;
|
|
|
+{ This procedure will do a reformat of the current paragraph if ^B pressed. }
|
|
|
+{ The feature works regardless if wordrap is on or off. It also supports }
|
|
|
+{ the AutoIndent feature. Reformat is not possible if the CurPos exceeds }
|
|
|
+{ the Right_Margin. Right_Margin is where the EOL is considered to be. }
|
|
|
+CONST
|
|
|
+ Space : array [1..2] of Char = #32#32;
|
|
|
+VAR
|
|
|
+ C : Sw_Word; { Position of CurPtr when we come into procedure. }
|
|
|
+ E : Sw_Word; { End of a line. }
|
|
|
+ S : Sw_Word; { Start of a line. }
|
|
|
+begin
|
|
|
+ Reformat_Paragraph := False;
|
|
|
+ { Check if Word_Wrap is toggled on. If NOT on, check if programmer }
|
|
|
+ { allows reformatting of paragraph and if not show user dialog that }
|
|
|
+ { says reformatting is not permissable. }
|
|
|
+ if not Word_Wrap then
|
|
|
+ begin
|
|
|
+ if not Allow_Reformat then
|
|
|
+ begin
|
|
|
+ EditorDialog (edReformatNotAllowed, nil);
|
|
|
+ Exit;
|
|
|
+ end;
|
|
|
+ Word_Wrap := True;
|
|
|
+ Update (ufStats);
|
|
|
+ end;
|
|
|
+ C := CurPtr;
|
|
|
+ E := LineEnd (CurPtr);
|
|
|
+ S := LineStart (CurPtr);
|
|
|
+ { Reformat possible only if current line is NOT blank! }
|
|
|
+ if E <> S then
|
|
|
+ begin
|
|
|
+ { Reformat is NOT possible if the first word }
|
|
|
+ { on the line is beyond the Right_Margin. }
|
|
|
+ S := LineStart (CurPtr);
|
|
|
+ if NextWord (S) - S >= Right_Margin - 1 then
|
|
|
+ begin
|
|
|
+ EditorDialog (edReformNotPossible, nil);
|
|
|
+ Exit;
|
|
|
+ end;
|
|
|
+ { First objective is to find the first blank line }
|
|
|
+ { after this paragraph so we know when to stop. }
|
|
|
+ { That could be the end of the document. }
|
|
|
+ Repeat
|
|
|
+ SetCurPtr (LineMove (CurPtr, 1), Select_Mode);
|
|
|
+ E := LineEnd (CurPtr);
|
|
|
+ S := LineStart (CurPtr);
|
|
|
+ BlankLine := E;
|
|
|
+ until ((CurPtr = BufLen) or (E = S));
|
|
|
+ SetCurPtr (C, Select_Mode);
|
|
|
+ repeat
|
|
|
+ { Set CurPtr to LineEnd and remove the EOL spaces. }
|
|
|
+ { Pull up the next line and remove its EOL space. }
|
|
|
+ { First make sure the next line is not BlankLine! }
|
|
|
+ { Insert spaces as required between the two lines. }
|
|
|
+ SetCurPtr (LineEnd (CurPtr), Select_Mode);
|
|
|
+ Remove_EOL_Spaces (Select_Mode);
|
|
|
+ if CurPtr <> Blankline - 2 then
|
|
|
+ DeleteRange (CurPtr, Nextword (CurPtr), True);
|
|
|
+ Remove_EOL_Spaces (Select_Mode);
|
|
|
+ case Buffer^[CurPtr-1] of
|
|
|
+ '!' : InsertText (@Space, 2, False);
|
|
|
+ '.' : InsertText (@Space, 2, False);
|
|
|
+ ':' : InsertText (@Space, 2, False);
|
|
|
+ '?' : InsertText (@Space, 2, False);
|
|
|
+ else
|
|
|
+ InsertText (@Space, 1, False);
|
|
|
+ end;
|
|
|
+ { Reset CurPtr to EOL. While line length is > Right_Margin }
|
|
|
+ { go Do_Word_Wrap. If wordrap failed, exit routine. }
|
|
|
+ SetCurPtr (LineEnd (CurPtr), Select_Mode);
|
|
|
+ while LineEnd (CurPtr) - LineStart (CurPtr) > Right_Margin do
|
|
|
+ if not Do_Word_Wrap (Select_Mode, Center_Cursor) then
|
|
|
+ Exit;
|
|
|
+ { If LineEnd - LineStart > Right_Margin then set CurPtr }
|
|
|
+ { to Right_Margin on current line. Otherwise we set the }
|
|
|
+ { CurPtr to LineEnd. This gyration sets up the conditions }
|
|
|
+ { to test for time of loop exit. }
|
|
|
+ if LineEnd (CurPtr) - LineStart (CurPtr) > Right_Margin then
|
|
|
+ SetCurPtr (LineStart (CurPtr) + Right_Margin, Select_Mode)
|
|
|
+ else
|
|
|
+ SetCurPtr (LineEnd (CurPtr), Select_Mode);
|
|
|
+ until ((CurPtr >= BufLen) or (CurPtr >= BlankLine - 2));
|
|
|
+ end;
|
|
|
+ { If not at the end of the document reset CurPtr to start of next line. }
|
|
|
+ { This should be a blank line between paragraphs. }
|
|
|
+ if CurPtr < BufLen then
|
|
|
+ SetCurPtr (LineMove (CurPtr, 1), Select_Mode);
|
|
|
+ Reformat_Paragraph := True;
|
|
|
+end; { TEditor.Reformat_Paragraph }
|
|
|
+
|
|
|
+
|
|
|
+procedure TEditor.Remove_EOL_Spaces (Select_Mode : Byte);
|
|
|
+{ This procedure tests to see if there are consecutive spaces }
|
|
|
+{ at the end of a line (EOL). If so, we delete all spaces }
|
|
|
+{ after the last non-space character to the end of line. }
|
|
|
+{ We then reset the CurPtr to where we ended up at. }
|
|
|
+VAR
|
|
|
+ C : Sw_Word; { Current pointer when we come into procedure. }
|
|
|
+ E : Sw_Word; { End of line. }
|
|
|
+ P : Sw_Word; { Position of pointer at any given moment. }
|
|
|
+ S : Sw_Word; { Start of a line. }
|
|
|
+begin
|
|
|
+ C := CurPtr;
|
|
|
+ E := LineEnd (CurPtr);
|
|
|
+ P := E;
|
|
|
+ S := LineStart (CurPtr);
|
|
|
+ { Start at the end of a line and move towards the start. }
|
|
|
+ { Find first non-space character in that direction. }
|
|
|
+ while (P > S) and (BufChar (PrevChar (P)) = #32) do
|
|
|
+ P := PrevChar (P);
|
|
|
+ { If we found any spaces then delete them. }
|
|
|
+ if P < E then
|
|
|
+ begin
|
|
|
+ SetSelect (P, E, True);
|
|
|
+ DeleteSelect;
|
|
|
+ Update_Place_Markers (0, E - P, P, E);
|
|
|
+ end;
|
|
|
+ { If C, our pointer when we came into this procedure, }
|
|
|
+ { is less than the CurPtr then reset CurPtr to C so }
|
|
|
+ { cursor is where we started. Otherwise, set it to }
|
|
|
+ { the new CurPtr, for we have deleted characters. }
|
|
|
+ if C < CurPtr then
|
|
|
+ SetCurPtr (C, Select_Mode)
|
|
|
+ else
|
|
|
+ SetCurPtr (CurPtr, Select_Mode);
|
|
|
+end; { TEditor.Remove_EOL_Spaces }
|
|
|
+
|
|
|
+
|
|
|
+procedure TEditor.Replace;
|
|
|
+VAR
|
|
|
+ ReplaceRec : TReplaceDialogRec;
|
|
|
+begin
|
|
|
+ with ReplaceRec do
|
|
|
+ begin
|
|
|
+ Find := FindStr;
|
|
|
+ Replace := ReplaceStr;
|
|
|
+ Options := Flags;
|
|
|
+ if EditorDialog (edReplace, @ReplaceRec) <> cmCancel then
|
|
|
+ begin
|
|
|
+ FindStr := Find;
|
|
|
+ ReplaceStr := Replace;
|
|
|
+ Flags := Options or efDoReplace;
|
|
|
+ DoSearchReplace;
|
|
|
+ end;
|
|
|
+ end;
|
|
|
+end; { TEditor.Replace }
|
|
|
+
|
|
|
+
|
|
|
+procedure TEditor.Scroll_Down;
|
|
|
+{ This procedure will scroll the screen up, and always keep }
|
|
|
+{ the cursor on the CurPos.Y position, but not necessarily on }
|
|
|
+{ the CurPos.X. If CurPos.Y scrolls off the screen, the cursor }
|
|
|
+{ will stay in the upper left corner of the screen. This will }
|
|
|
+{ simulate the same process in the IDE. The CurPos.X coordinate }
|
|
|
+{ only messes up if we are on long lines and we then encounter }
|
|
|
+{ a shorter or blank line beneath the current one as we scroll. }
|
|
|
+{ In that case, it goes to the end of the new line. }
|
|
|
+VAR
|
|
|
+ C : Sw_Word; { Position of CurPtr when we enter procedure. }
|
|
|
+ P : Sw_Word; { Position of CurPtr at any given time. }
|
|
|
+ W : Objects.TPoint; { CurPos.Y of CurPtr and P ('.X and '.Y). }
|
|
|
+begin
|
|
|
+ { Remember current cursor position. Remember current CurPos.Y position. }
|
|
|
+ { Now issue the equivalent of a [Ctrl]-[End] command so the cursor will }
|
|
|
+ { go to the bottom of the current screen. Reset the cursor to this new }
|
|
|
+ { position and then send FALSE to TrackCursor so we fool it into }
|
|
|
+ { incrementing Delta.Y by only +1. If we didn't do this it would try }
|
|
|
+ { to center the cursor on the screen by fiddling with Delta.Y. }
|
|
|
+ C := CurPtr;
|
|
|
+ W.X := CurPos.Y;
|
|
|
+ P := LineMove (CurPtr, Delta.Y - CurPos.Y + Size.Y);
|
|
|
+ SetCurPtr (P, 0);
|
|
|
+ TrackCursor (False);
|
|
|
+ { Now remember where the new CurPos.Y is. See if distance between new }
|
|
|
+ { CurPos.Y and old CurPos.Y are greater than the current screen size. }
|
|
|
+ { If they are, we need to move cursor position itself down by one. }
|
|
|
+ { Otherwise, send the cursor back to our original CurPtr. }
|
|
|
+ W.Y := CurPos.Y;
|
|
|
+ if W.Y - W.X > Size.Y - 1 then
|
|
|
+ SetCurPtr (LineMove (C, 1), 0)
|
|
|
+ else
|
|
|
+ SetCurPtr (C, 0);
|
|
|
+end; { TEditor.Scroll_Down }
|
|
|
+
|
|
|
+
|
|
|
+procedure TEditor.Scroll_Up;
|
|
|
+{ This procedure will scroll the screen down, and always keep }
|
|
|
+{ the cursor on the CurPos.Y position, but not necessarily on }
|
|
|
+{ the CurPos.X. If CurPos.Y scrolls off the screen, the cursor }
|
|
|
+{ will stay in the bottom left corner of the screen. This will }
|
|
|
+{ simulate the same process in the IDE. The CurPos.X coordinate }
|
|
|
+{ only messes up if we are on long lines and we then encounter }
|
|
|
+{ a shorter or blank line beneath the current one as we scroll. }
|
|
|
+{ In that case, it goes to the end of the new line. }
|
|
|
+VAR
|
|
|
+ C : Sw_Word; { Position of CurPtr when we enter procedure. }
|
|
|
+ P : Sw_Word; { Position of CurPtr at any given time. }
|
|
|
+ W : Objects.TPoint; { CurPos.Y of CurPtr and P ('.X and '.Y). }
|
|
|
+begin
|
|
|
+ { Remember current cursor position. Remember current CurPos.Y position. }
|
|
|
+ { Now issue the equivalent of a [Ctrl]-[Home] command so the cursor will }
|
|
|
+ { go to the top of the current screen. Reset the cursor to this new }
|
|
|
+ { position and then send FALSE to TrackCursor so we fool it into }
|
|
|
+ { decrementing Delta.Y by only -1. If we didn't do this it would try }
|
|
|
+ { to center the cursor on the screen by fiddling with Delta.Y. }
|
|
|
+ C := CurPtr;
|
|
|
+ W.Y := CurPos.Y;
|
|
|
+ P := LineMove (CurPtr, -(CurPos.Y - Delta.Y + 1));
|
|
|
+ SetCurPtr (P, 0);
|
|
|
+ TrackCursor (False);
|
|
|
+ { Now remember where the new CurPos.Y is. See if distance between new }
|
|
|
+ { CurPos.Y and old CurPos.Y are greater than the current screen size. }
|
|
|
+ { If they are, we need to move the cursor position itself up by one. }
|
|
|
+ { Otherwise, send the cursor back to our original CurPtr. }
|
|
|
+ W.X := CurPos.Y;
|
|
|
+ if W.Y - W.X > Size.Y - 1 then
|
|
|
+ SetCurPtr (LineMove (C, -1), 0)
|
|
|
+ else
|
|
|
+ SetCurPtr (C, 0);
|
|
|
+end; { TEditor.Scroll_Up }
|
|
|
+
|
|
|
+
|
|
|
+procedure TEditor.ScrollTo (X, Y : Sw_Integer);
|
|
|
+begin
|
|
|
+ X := Max (0, Min (X, Limit.X - Size.X));
|
|
|
+ Y := Max (0, Min (Y, Limit.Y - Size.Y));
|
|
|
+ if (X <> Delta.X) or (Y <> Delta.Y) then
|
|
|
+ begin
|
|
|
+ Delta.X := X;
|
|
|
+ Delta.Y := Y;
|
|
|
+ Update (ufView);
|
|
|
+ end;
|
|
|
+end; { TEditor.ScrollTo }
|
|
|
+
|
|
|
+
|
|
|
+function TEditor.Search (const FindStr : String; Opts : Word) : Boolean;
|
|
|
+VAR
|
|
|
+ I,Pos : Sw_Word;
|
|
|
+begin
|
|
|
+ Search := False;
|
|
|
+ Pos := CurPtr;
|
|
|
+ repeat
|
|
|
+ if Opts and efCaseSensitive <> 0 then
|
|
|
+ I := Scan (Buffer^[BufPtr (Pos)], BufLen - Pos, FindStr)
|
|
|
+ else
|
|
|
+ I := IScan (Buffer^[BufPtr (Pos)], BufLen - Pos, FindStr);
|
|
|
+ if (I <> sfSearchFailed) then
|
|
|
+ begin
|
|
|
+ Inc (I, Pos);
|
|
|
+ if (Opts and efWholeWordsOnly = 0) or
|
|
|
+ not (((I <> 0) and (BufChar (I - 1) in WordChars)) or
|
|
|
+ ((I + Length (FindStr) <> BufLen) and
|
|
|
+ (BufChar (I + Length (FindStr)) in WordChars))) then
|
|
|
+ begin
|
|
|
+ Lock;
|
|
|
+ SetSelect (I, I + Length (FindStr), False);
|
|
|
+ TrackCursor (not CursorVisible);
|
|
|
+ Unlock;
|
|
|
+ Search := True;
|
|
|
+ Exit;
|
|
|
+ end
|
|
|
+ else
|
|
|
+ Pos := I + 1;
|
|
|
+ end;
|
|
|
+ until I = sfSearchFailed;
|
|
|
+end; { TEditor.Search }
|
|
|
+
|
|
|
+
|
|
|
+procedure TEditor.Select_Word;
|
|
|
+{ This procedure will select the a word to put into the clipboard. }
|
|
|
+{ I've added it just to maintain compatibility with the IDE editor. }
|
|
|
+{ Note that selection starts at the current cursor position and ends }
|
|
|
+{ when a space or the end of line is encountered. }
|
|
|
+VAR
|
|
|
+ E : Sw_Word; { End of the current line. }
|
|
|
+ Select_Mode : Byte; { Allows us to turn select mode on inside procedure. }
|
|
|
+begin
|
|
|
+ E := LineEnd (CurPtr);
|
|
|
+ { If the cursor is on a space or at the end of a line, abort. }
|
|
|
+ { Stupid action on users part for you can't select blanks! }
|
|
|
+ if (BufChar (CurPtr) = #32) or (CurPtr = E) then
|
|
|
+ Exit;
|
|
|
+ { Turn on select mode and tell editor to start selecting text. }
|
|
|
+ { As long as we have a character > a space (this is done to }
|
|
|
+ { exclude CR/LF pairs at end of a line) and we are NOT at the }
|
|
|
+ { end of a line, set the CurPtr to the next character. }
|
|
|
+ { Once we find a space or CR/LF, selection is done and we }
|
|
|
+ { automatically put the selected word into the Clipboard. }
|
|
|
+ Select_Mode := smExtend;
|
|
|
+ StartSelect;
|
|
|
+ while (BufChar (NextChar (CurPtr)) > #32) and (CurPtr < E) do
|
|
|
+ SetCurPtr (NextChar (CurPtr), Select_Mode);
|
|
|
+ SetCurPtr (NextChar (CurPtr), Select_Mode);
|
|
|
+ ClipCopy;
|
|
|
+end; {TEditor.Select_Word }
|
|
|
+
|
|
|
+
|
|
|
+procedure TEditor.SetBufLen (Length : Sw_Word);
|
|
|
+begin
|
|
|
+ BufLen := Length;
|
|
|
+ GapLen := BufSize - Length;
|
|
|
+ SelStart := 0;
|
|
|
+ SelEnd := 0;
|
|
|
+ CurPtr := 0;
|
|
|
+ CurPos.X:=0;
|
|
|
+ CurPos.Y:=0;
|
|
|
+ Delta.X:=0;
|
|
|
+ Delta.Y:=0;
|
|
|
+ GetLimits(Buffer^[GapLen], BufLen,Limit);
|
|
|
+ inc(Limit.X);
|
|
|
+ inc(Limit.Y);
|
|
|
+ DrawLine := 0;
|
|
|
+ DrawPtr := 0;
|
|
|
+ DelCount := 0;
|
|
|
+ InsCount := 0;
|
|
|
+ Modified := False;
|
|
|
+ Update (ufView);
|
|
|
+end; { TEditor.SetBufLen }
|
|
|
+
|
|
|
+
|
|
|
+function TEditor.SetBufSize (NewSize : Sw_Word) : Boolean;
|
|
|
+begin
|
|
|
+ SetBufSize := NewSize <= BufSize;
|
|
|
+end; { TEditor.SetBufSize }
|
|
|
+
|
|
|
+
|
|
|
+procedure TEditor.SetCmdState (Command : Word; Enable : Boolean);
|
|
|
+VAR
|
|
|
+ S : TCommandSet;
|
|
|
+begin
|
|
|
+ S := [Command];
|
|
|
+ if Enable and (State and sfActive <> 0) then
|
|
|
+ EnableCommands (S)
|
|
|
+ else
|
|
|
+ DisableCommands (S);
|
|
|
+end; { TEditor.SetCmdState }
|
|
|
+
|
|
|
+
|
|
|
+procedure TEditor.SetCurPtr (P : Sw_Word; SelectMode : Byte);
|
|
|
+VAR
|
|
|
+ Anchor : Sw_Word;
|
|
|
+begin
|
|
|
+ if SelectMode and smExtend = 0 then
|
|
|
+ Anchor := P
|
|
|
+ else
|
|
|
+ if CurPtr = SelStart then
|
|
|
+ Anchor := SelEnd
|
|
|
+ else
|
|
|
+ Anchor := SelStart;
|
|
|
+ if P < Anchor then
|
|
|
+ begin
|
|
|
+ if SelectMode and smDouble <> 0 then
|
|
|
+ begin
|
|
|
+ P := PrevLine (NextLine (P));
|
|
|
+ Anchor := NextLine (PrevLine (Anchor));
|
|
|
+ end;
|
|
|
+ SetSelect (P, Anchor, True);
|
|
|
+ end
|
|
|
+ else
|
|
|
+ begin
|
|
|
+ if SelectMode and smDouble <> 0 then
|
|
|
+ begin
|
|
|
+ P := NextLine (P);
|
|
|
+ Anchor := PrevLine (NextLine (Anchor));
|
|
|
+ end;
|
|
|
+ SetSelect (Anchor, P, False);
|
|
|
+ end;
|
|
|
+end; { TEditor.SetCurPtr }
|
|
|
+
|
|
|
+
|
|
|
+procedure TEditor.Set_Place_Marker (Element : Byte);
|
|
|
+{ This procedure sets a place marker for the CurPtr if ^K# is pressed. }
|
|
|
+begin
|
|
|
+ if not IsClipboard then
|
|
|
+ Place_Marker[Element] := CurPtr;
|
|
|
+end; { TEditor.Set_Place_Marker }
|
|
|
+
|
|
|
+
|
|
|
+procedure TEditor.Set_Right_Margin;
|
|
|
+{ This procedure will bring up a dialog box }
|
|
|
+{ that allows the user to set Right_Margin. }
|
|
|
+{ Values must be < MaxLineLength and > 9. }
|
|
|
+VAR
|
|
|
+ Code : Integer; { Used for Val conversion. }
|
|
|
+ Margin_Data : TRightMarginRec; { Holds dialog results. }
|
|
|
+ Temp_Value : Sw_Integer; { Holds converted dialog value. }
|
|
|
+begin
|
|
|
+ with Margin_Data do
|
|
|
+ begin
|
|
|
+ Str (Right_Margin, Margin_Position);
|
|
|
+ if EditorDialog (edRightMargin, @Margin_Position) <> cmCancel then
|
|
|
+ begin
|
|
|
+ val (Margin_Position, Temp_Value, Code);
|
|
|
+ if (Temp_Value <= MaxLineLength) and (Temp_Value > 9) then
|
|
|
+ Right_Margin := Temp_Value;
|
|
|
+ end;
|
|
|
+ end;
|
|
|
+end; { TEditor.Set_Right_Margin }
|
|
|
+
|
|
|
+
|
|
|
+procedure TEditor.SetSelect (NewStart, NewEnd : Sw_Word; CurStart : Boolean);
|
|
|
+VAR
|
|
|
+ UFlags : Byte;
|
|
|
+ P : Sw_Word;
|
|
|
+ L : Sw_Word;
|
|
|
+begin
|
|
|
+ if CurStart then
|
|
|
+ P := NewStart
|
|
|
+ else
|
|
|
+ P := NewEnd;
|
|
|
+ UFlags := ufUpdate;
|
|
|
+ if (NewStart <> SelStart) or (NewEnd <> SelEnd) then
|
|
|
+ if (NewStart <> NewEnd) or (SelStart <> SelEnd) then
|
|
|
+ UFlags := ufView;
|
|
|
+ if P <> CurPtr then
|
|
|
+ begin
|
|
|
+ if P > CurPtr then
|
|
|
+ begin
|
|
|
+ L := P - CurPtr;
|
|
|
+ Move (Buffer^[CurPtr + GapLen], Buffer^[CurPtr], L);
|
|
|
+ Inc (CurPos.Y, CountLines (Buffer^[CurPtr], L));
|
|
|
+ CurPtr := P;
|
|
|
+ end
|
|
|
+ else
|
|
|
+ begin
|
|
|
+ L := CurPtr - P;
|
|
|
+ CurPtr := P;
|
|
|
+ Dec (CurPos.Y, CountLines (Buffer^[CurPtr], L));
|
|
|
+ Move (Buffer^[CurPtr], Buffer^[CurPtr + GapLen], L);
|
|
|
+ end;
|
|
|
+ DrawLine := CurPos.Y;
|
|
|
+ DrawPtr := LineStart (P);
|
|
|
+ CurPos.X := CharPos (DrawPtr, P);
|
|
|
+ DelCount := 0;
|
|
|
+ InsCount := 0;
|
|
|
+ SetBufSize (BufLen);
|
|
|
+ end;
|
|
|
+ SelStart := NewStart;
|
|
|
+ SelEnd := NewEnd;
|
|
|
+ Update (UFlags);
|
|
|
+end; { TEditor.Select }
|
|
|
+
|
|
|
+
|
|
|
+procedure TEditor.SetState (AState : Word; Enable : Boolean);
|
|
|
+begin
|
|
|
+ Inherited SetState (AState, Enable);
|
|
|
+ case AState of
|
|
|
+ sfActive: begin
|
|
|
+ if assigned(HScrollBar) then
|
|
|
+ HScrollBar^.SetState (sfVisible, Enable);
|
|
|
+ if assigned(VScrollBar) then
|
|
|
+ VScrollBar^.SetState (sfVisible, Enable);
|
|
|
+ if assigned(Indicator) then
|
|
|
+ Indicator^.SetState (sfVisible, Enable);
|
|
|
+ UpdateCommands;
|
|
|
+ end;
|
|
|
+ sfExposed: if Enable then Unlock;
|
|
|
+ end;
|
|
|
+end; { TEditor.SetState }
|
|
|
+
|
|
|
+
|
|
|
+procedure TEditor.Set_Tabs;
|
|
|
+{ This procedure will bring up a dialog box }
|
|
|
+{ that allows the user to set tab stops. }
|
|
|
+VAR
|
|
|
+ Index : Sw_Integer; { Index into string array. }
|
|
|
+ Tab_Data : TTabStopRec; { Holds dialog results. }
|
|
|
+begin
|
|
|
+ with Tab_Data do
|
|
|
+ begin
|
|
|
+ { Assign current Tab_Settings to Tab_String. }
|
|
|
+ { Bring up the tab dialog so user can set tabs. }
|
|
|
+ Tab_String := Copy (Tab_Settings, 1, Tab_Stop_Length);
|
|
|
+ if EditorDialog (edSetTabStops, @Tab_String) <> cmCancel then
|
|
|
+ begin
|
|
|
+ { If Tab_String comes back as empty then set Tab_Settings to nil. }
|
|
|
+ { Otherwise, find the last character in Tab_String that is not }
|
|
|
+ { a space and copy Tab_String into Tab_Settings up to that spot. }
|
|
|
+ if Length (Tab_String) = 0 then
|
|
|
+ begin
|
|
|
+ FillChar (Tab_Settings, SizeOf (Tab_Settings), #0);
|
|
|
+ Tab_Settings[0] := #0;
|
|
|
+ Exit;
|
|
|
+ end
|
|
|
+ else
|
|
|
+ begin
|
|
|
+ Index := Length (Tab_String);
|
|
|
+ while Tab_String[Index] <= #32 do
|
|
|
+ Dec (Index);
|
|
|
+ Tab_Settings := Copy (Tab_String, 1, Index);
|
|
|
+ end;
|
|
|
+ end;
|
|
|
+ end;
|
|
|
+end; { TEditor.Set_Tabs }
|
|
|
+
|
|
|
+
|
|
|
+procedure TEditor.StartSelect;
|
|
|
+begin
|
|
|
+ HideSelect;
|
|
|
+ Selecting := True;
|
|
|
+end; { TEditor.StartSelect }
|
|
|
+
|
|
|
+
|
|
|
+procedure TEditor.Store (var S : Objects.TStream);
|
|
|
+begin
|
|
|
+ Inherited Store (S);
|
|
|
+ PutPeerViewPtr (S, HScrollBar);
|
|
|
+ PutPeerViewPtr (S, VScrollBar);
|
|
|
+ PutPeerViewPtr (S, Indicator);
|
|
|
+ S.Write (BufSize, SizeOf (Sw_Word));
|
|
|
+ S.Write (Canundo, SizeOf (Boolean));
|
|
|
+ S.Write (AutoIndent, SizeOf (AutoIndent));
|
|
|
+ S.Write (Line_Number, SizeOf (Line_Number));
|
|
|
+ S.Write (Place_Marker, SizeOf (Place_Marker));
|
|
|
+ S.Write (Right_Margin, SizeOf (Right_Margin));
|
|
|
+ S.Write (Tab_Settings, SizeOf (Tab_Settings));
|
|
|
+ S.Write (Word_Wrap, SizeOf (Word_Wrap));
|
|
|
+end; { Editor.Store }
|
|
|
+
|
|
|
+
|
|
|
+procedure TEditor.Tab_Key (Select_Mode : Byte);
|
|
|
+{ This function determines if we are in overstrike or insert mode, }
|
|
|
+{ and then moves the cursor if overstrike, or adds spaces if insert. }
|
|
|
+VAR
|
|
|
+ E : Sw_Word; { End of current line. }
|
|
|
+ Index : Sw_Integer; { Loop counter. }
|
|
|
+ Position : Sw_Integer; { CurPos.X position. }
|
|
|
+ S : Sw_Word; { Start of current line. }
|
|
|
+ Spaces : array [1..80] of Char; { Array to hold spaces for insertion. }
|
|
|
+begin
|
|
|
+ E := LineEnd (CurPtr);
|
|
|
+ S := LineStart (CurPtr);
|
|
|
+ { Find the current horizontal cursor position. }
|
|
|
+ { Now loop through the Tab_Settings string and }
|
|
|
+ { find the next available tab stop. }
|
|
|
+ Position := CurPos.X + 1;
|
|
|
+ repeat
|
|
|
+ Inc (Position);
|
|
|
+ until (Tab_Settings[Position] <> #32) or (Position >= Ord (Tab_Settings[0]));
|
|
|
+ E := CurPos.X;
|
|
|
+ Index := 1;
|
|
|
+ { Now we enter a loop to go to the next tab position. }
|
|
|
+ { If we are in overwrite mode, we just move the cursor }
|
|
|
+ { through the text to the next tab stop. If we are in }
|
|
|
+ { insert mode, we add spaces to the Spaces array for }
|
|
|
+ { the number of times we loop. }
|
|
|
+ while Index < Position - E do
|
|
|
+ begin
|
|
|
+ if Overwrite then
|
|
|
+ begin
|
|
|
+ if (Position > LineEnd (CurPtr) - LineStart (CurPtr))
|
|
|
+ or (Position > Ord (Tab_Settings[0])) then
|
|
|
+ begin
|
|
|
+ SetCurPtr (LineStart (LineMove (CurPtr, 1)), Select_Mode);
|
|
|
+ Exit;
|
|
|
+ end
|
|
|
+ else
|
|
|
+ if CurPtr < BufLen then
|
|
|
+ SetCurPtr (NextChar (CurPtr), Select_Mode);
|
|
|
+ end
|
|
|
+ else
|
|
|
+ begin
|
|
|
+ if (Position > Right_Margin) or (Position > Ord (Tab_Settings[0])) then
|
|
|
+ begin
|
|
|
+ SetCurPtr (LineStart (LineMove (CurPtr, 1)), Select_Mode);
|
|
|
+ Exit;
|
|
|
+ end
|
|
|
+ else
|
|
|
+ Spaces[Index] := #32;
|
|
|
+ end;
|
|
|
+ Inc (Index);
|
|
|
+ end;
|
|
|
+ { If we are insert mode, we insert spaces to the next tab stop. }
|
|
|
+ { When we're all done, the cursor will be sitting on the new tab stop. }
|
|
|
+ if not OverWrite then
|
|
|
+ InsertText (@Spaces, Index - 1, False);
|
|
|
+end; { TEditor.Tab_Key }
|
|
|
+
|
|
|
+
|
|
|
+procedure TEditor.ToggleInsMode;
|
|
|
+begin
|
|
|
+ Overwrite := not Overwrite;
|
|
|
+ SetState (sfCursorIns, not GetState (sfCursorIns));
|
|
|
+end; { TEditor.ToggleInsMode }
|
|
|
+
|
|
|
+
|
|
|
+procedure TEditor.TrackCursor (Center : Boolean);
|
|
|
+begin
|
|
|
+ if Center then
|
|
|
+ ScrollTo (CurPos.X - Size.X + 1, CurPos.Y - Size.Y div 2)
|
|
|
+ else
|
|
|
+ ScrollTo (Max (CurPos.X - Size.X + 1, Min (Delta.X, CurPos.X)),
|
|
|
+ Max (CurPos.Y - Size.Y + 1, Min (Delta.Y, CurPos.Y)));
|
|
|
+end; { TEditor.TrackCursor }
|
|
|
+
|
|
|
+
|
|
|
+procedure TEditor.Undo;
|
|
|
+VAR
|
|
|
+ Length : Sw_Word;
|
|
|
+begin
|
|
|
+ if (DelCount <> 0) or (InsCount <> 0) then
|
|
|
+ begin
|
|
|
+ Update_Place_Markers (DelCount, 0, CurPtr, CurPtr + DelCount);
|
|
|
+ SelStart := CurPtr - InsCount;
|
|
|
+ SelEnd := CurPtr;
|
|
|
+ Length := DelCount;
|
|
|
+ DelCount := 0;
|
|
|
+ InsCount := 0;
|
|
|
+ InsertBuffer (Buffer, CurPtr + GapLen - Length, Length, False, True);
|
|
|
+ end;
|
|
|
+end; { TEditor.Undo }
|
|
|
+
|
|
|
+
|
|
|
+procedure TEditor.Unlock;
|
|
|
+begin
|
|
|
+ if LockCount > 0 then
|
|
|
+ begin
|
|
|
+ Dec (LockCount);
|
|
|
+ if LockCount = 0 then
|
|
|
+ DoUpdate;
|
|
|
+ end;
|
|
|
+end; { TEditor.Unlock }
|
|
|
+
|
|
|
+
|
|
|
+procedure TEditor.Update (AFlags : Byte);
|
|
|
+begin
|
|
|
+ UpdateFlags := UpdateFlags or AFlags;
|
|
|
+ if LockCount = 0 then
|
|
|
+ DoUpdate;
|
|
|
+end; { TEditor.Update }
|
|
|
+
|
|
|
+
|
|
|
+procedure TEditor.UpdateCommands;
|
|
|
+begin
|
|
|
+ SetCmdState (cmUndo, (DelCount <> 0) or (InsCount <> 0));
|
|
|
+ if not IsClipboard then
|
|
|
+ begin
|
|
|
+ SetCmdState (cmCut, HasSelection);
|
|
|
+ SetCmdState (cmCopy, HasSelection);
|
|
|
+ SetCmdState (cmPaste, assigned(Clipboard) and (Clipboard^.HasSelection));
|
|
|
+ end;
|
|
|
+ SetCmdState (cmClear, HasSelection);
|
|
|
+ SetCmdState (cmFind, True);
|
|
|
+ SetCmdState (cmReplace, True);
|
|
|
+ SetCmdState (cmSearchAgain, True);
|
|
|
+end; { TEditor.UpdateCommands }
|
|
|
+
|
|
|
+
|
|
|
+procedure TEditor.Update_Place_Markers (AddCount : Word; KillCount : Word;
|
|
|
+ StartPtr,EndPtr : Sw_Word);
|
|
|
+{ This procedure updates the position of the place markers }
|
|
|
+{ as the user inserts and deletes text in the document. }
|
|
|
+VAR
|
|
|
+ Element : Byte; { Place_Marker array element to traverse array with. }
|
|
|
+begin
|
|
|
+ for Element := 1 to 10 do
|
|
|
+ begin
|
|
|
+ if AddCount > 0 then
|
|
|
+ begin
|
|
|
+ if (Place_Marker[Element] >= Curptr)
|
|
|
+ and (Place_Marker[Element] <> 0) then
|
|
|
+ Place_Marker[Element] := Place_Marker[Element] + AddCount;
|
|
|
+ end
|
|
|
+ else
|
|
|
+ begin
|
|
|
+ if Place_Marker[Element] >= StartPtr then
|
|
|
+ begin
|
|
|
+ if (Place_Marker[Element] >= StartPtr) and
|
|
|
+ (Place_Marker[Element] < EndPtr) then
|
|
|
+ Place_marker[Element] := 0
|
|
|
+ else
|
|
|
+ begin
|
|
|
+ if integer (Place_Marker[Element]) - integer (KillCount) > 0 then
|
|
|
+ Place_Marker[Element] := Place_Marker[Element] - KillCount
|
|
|
+ else
|
|
|
+ Place_Marker[Element] := 0;
|
|
|
+ end;
|
|
|
+ end;
|
|
|
+ end;
|
|
|
+ end;
|
|
|
+ if AddCount > 0 then
|
|
|
+ BlankLine := BlankLine + AddCount
|
|
|
+ else
|
|
|
+ begin
|
|
|
+ if integer (BlankLine) - Integer (KillCount) > 0 then
|
|
|
+ BlankLine := BlankLine - KillCount
|
|
|
+ else
|
|
|
+ BlankLine := 0;
|
|
|
+ end;
|
|
|
+end; { TEditor.Update_Place_Markers }
|
|
|
+
|
|
|
+
|
|
|
+function TEditor.Valid (Command : Word) : Boolean;
|
|
|
+begin
|
|
|
+ Valid := IsValid;
|
|
|
+end; { TEditor.Valid }
|
|
|
+
|
|
|
+
|
|
|
+{****************************************************************************
|
|
|
+ TMEMO
|
|
|
+****************************************************************************}
|
|
|
+
|
|
|
+constructor TMemo.Load (var S : Objects.TStream);
|
|
|
+VAR
|
|
|
+ Length : Sw_Word;
|
|
|
+begin
|
|
|
+ Inherited Load (S);
|
|
|
+ S.Read (Length, SizeOf (Sw_Word));
|
|
|
+ if IsValid then
|
|
|
+ begin
|
|
|
+ S.Read (Buffer^[BufSize - Length], Length);
|
|
|
+ SetBufLen (Length);
|
|
|
+ end
|
|
|
+ else
|
|
|
+ S.Seek (S.GetPos + Length);
|
|
|
+end; { TMemo.Load }
|
|
|
+
|
|
|
+
|
|
|
+function TMemo.DataSize : Sw_Word;
|
|
|
+begin
|
|
|
+ DataSize := BufSize + SizeOf (Sw_Word);
|
|
|
+end; { TMemo.DataSize }
|
|
|
+
|
|
|
+
|
|
|
+procedure TMemo.GetData (var Rec);
|
|
|
+VAR
|
|
|
+ Data : TMemoData absolute Rec;
|
|
|
+begin
|
|
|
+ Data.Length := BufLen;
|
|
|
+ Move (Buffer^, Data.Buffer, CurPtr);
|
|
|
+ Move (Buffer^[CurPtr + GapLen], Data.Buffer[CurPtr], BufLen - CurPtr);
|
|
|
+ FillChar (Data.Buffer[BufLen], BufSize - BufLen, 0);
|
|
|
+end; { TMemo.GetData }
|
|
|
+
|
|
|
+
|
|
|
+function TMemo.GetPalette : PPalette;
|
|
|
+CONST
|
|
|
+ P : String[Length (CMemo)] = CMemo;
|
|
|
+begin
|
|
|
+ GetPalette := @P;
|
|
|
+end; { TMemo.GetPalette }
|
|
|
+
|
|
|
+
|
|
|
+procedure TMemo.HandleEvent (var Event : Drivers.TEvent);
|
|
|
+begin
|
|
|
+ if (Event.What <> Drivers.evKeyDown) or (Event.KeyCode <> Drivers.kbTab) then
|
|
|
+ Inherited HandleEvent (Event);
|
|
|
+end; { TMemo.HandleEvent }
|
|
|
+
|
|
|
+
|
|
|
+procedure TMemo.SetData (var Rec);
|
|
|
+VAR
|
|
|
+ Data : TMemoData absolute Rec;
|
|
|
+begin
|
|
|
+ Move (Data.Buffer, Buffer^[BufSize - Data.Length], Data.Length);
|
|
|
+ SetBufLen (Data.Length);
|
|
|
+end; { TMemo.SetData }
|
|
|
+
|
|
|
+
|
|
|
+procedure TMemo.Store (var S : Objects.TStream);
|
|
|
+begin
|
|
|
+ Inherited Store (S);
|
|
|
+ S.Write (BufLen, SizeOf (Sw_Word));
|
|
|
+ S.Write (Buffer^, CurPtr);
|
|
|
+ S.Write (Buffer^[CurPtr + GapLen], BufLen - CurPtr);
|
|
|
+end; { TMemo.Store }
|
|
|
+
|
|
|
+
|
|
|
+{****************************************************************************
|
|
|
+ TFILEEDITOR
|
|
|
+****************************************************************************}
|
|
|
+
|
|
|
+
|
|
|
+constructor TFileEditor.Init (var Bounds : TRect;
|
|
|
+ AHScrollBar, AVScrollBar : PScrollBar;
|
|
|
+ AIndicator : PIndicator;
|
|
|
+ AFileName : FNameStr);
|
|
|
+begin
|
|
|
+ Inherited Init (Bounds, AHScrollBar, AVScrollBar, AIndicator, 0);
|
|
|
+ if AFileName <> '' then
|
|
|
+ begin
|
|
|
+ FileName := FExpand (AFileName);
|
|
|
+ if IsValid then
|
|
|
+ IsValid := LoadFile;
|
|
|
+ end;
|
|
|
+end; { TFileEditor.Init }
|
|
|
+
|
|
|
+
|
|
|
+constructor TFileEditor.Load (var S : Objects.TStream);
|
|
|
+VAR
|
|
|
+ SStart,SEnd,Curs : Sw_Word;
|
|
|
+begin
|
|
|
+ Inherited Load (S);
|
|
|
+ BufSize := 0;
|
|
|
+ S.Read (FileName[0], SizeOf (Char));
|
|
|
+ S.Read (Filename[1], Length (FileName));
|
|
|
+ if IsValid then
|
|
|
+ IsValid := LoadFile;
|
|
|
+ S.Read (SStart, SizeOf (Sw_Word));
|
|
|
+ S.Read (SEnd, SizeOf (Sw_Word));
|
|
|
+ S.Read (Curs, SizeOf (Sw_Word));
|
|
|
+ if IsValid and (SEnd <= BufLen) then
|
|
|
+ begin
|
|
|
+ SetSelect (SStart, SEnd, Curs = SStart);
|
|
|
+ TrackCursor (True);
|
|
|
+ end;
|
|
|
+end; { TFileEditor.Load }
|
|
|
+
|
|
|
+
|
|
|
+procedure TFileEditor.DoneBuffer;
|
|
|
+begin
|
|
|
+ if assigned(Buffer) then
|
|
|
+ DisposeBuffer (Buffer);
|
|
|
+end; { TFileEditor.DoneBuffer }
|
|
|
+
|
|
|
+
|
|
|
+procedure TFileEditor.HandleEvent (var Event : Drivers.TEvent);
|
|
|
+begin
|
|
|
+ Inherited HandleEvent (Event);
|
|
|
+ case Event.What of
|
|
|
+ Drivers.evCommand:
|
|
|
+ case Event.Command of
|
|
|
+ cmSave : Save;
|
|
|
+ cmSaveAs : SaveAs;
|
|
|
+ cmSaveDone : if Save then
|
|
|
+ Message (Owner, Drivers.evCommand, cmClose, nil);
|
|
|
+ else
|
|
|
+ Exit;
|
|
|
+ end;
|
|
|
+ else
|
|
|
+ Exit;
|
|
|
+ end;
|
|
|
+ ClearEvent (Event);
|
|
|
+end; { TFileEditor.HandleEvent }
|
|
|
+
|
|
|
+
|
|
|
+procedure TFileEditor.InitBuffer;
|
|
|
+begin
|
|
|
+ NewBuffer(Pointer(Buffer), MinBufLength);
|
|
|
+end; { TFileEditor.InitBuffer }
|
|
|
+
|
|
|
+
|
|
|
+function TFileEditor.LoadFile: Boolean;
|
|
|
+VAR
|
|
|
+ Length : Sw_Word;
|
|
|
+ FSize : Longint;
|
|
|
+ FRead : Sw_Integer;
|
|
|
+ F : File;
|
|
|
+begin
|
|
|
+ LoadFile := False;
|
|
|
+ Length := 0;
|
|
|
+ Assign(F, FileName);
|
|
|
+ Reset(F, 1);
|
|
|
+ if IOResult <> 0 then
|
|
|
+ EditorDialog(edReadError, @FileName)
|
|
|
+ else
|
|
|
+ begin
|
|
|
+ FSize := FileSize(F);
|
|
|
+ if (FSize > MaxBufLength) or not SetBufSize(FSize) then
|
|
|
+ EditorDialog(edOutOfMemory, nil)
|
|
|
+ else
|
|
|
+ begin
|
|
|
+ BlockRead(F, Buffer^[BufSize-FSize], FSize, FRead);
|
|
|
+ if (IOResult <> 0) or (FRead<>FSize) then
|
|
|
+ EditorDialog(edReadError, @FileName)
|
|
|
+ else
|
|
|
+ begin
|
|
|
+ LoadFile := True;
|
|
|
+ Length := FRead;
|
|
|
+ end;
|
|
|
+ end;
|
|
|
+ Close(F);
|
|
|
+ end;
|
|
|
+ SetBufLen(Length);
|
|
|
+end; { TFileEditor.LoadFile }
|
|
|
+
|
|
|
+
|
|
|
+function TFileEditor.Save : Boolean;
|
|
|
+begin
|
|
|
+ if FileName = '' then
|
|
|
+ Save := SaveAs
|
|
|
+ else
|
|
|
+ Save := SaveFile;
|
|
|
+end; { TFileEditor.Save }
|
|
|
+
|
|
|
+
|
|
|
+function TFileEditor.SaveAs : Boolean;
|
|
|
+begin
|
|
|
+ SaveAs := False;
|
|
|
+ if EditorDialog (edSaveAs, @FileName) <> cmCancel then
|
|
|
+ begin
|
|
|
+ FileName := FExpand (FileName);
|
|
|
+ Message (Owner, Drivers.evBroadcast, cmUpdateTitle, nil);
|
|
|
+ SaveAs := SaveFile;
|
|
|
+ if IsClipboard then
|
|
|
+ FileName := '';
|
|
|
+ end;
|
|
|
+end; { TFileEditor.SaveAs }
|
|
|
+
|
|
|
+
|
|
|
+function TFileEditor.SaveFile : Boolean;
|
|
|
+VAR
|
|
|
+ F : File;
|
|
|
+ BackupName : Objects.FNameStr;
|
|
|
+ D : DOS.DirStr;
|
|
|
+ N : DOS.NameStr;
|
|
|
+ E : DOS.ExtStr;
|
|
|
+begin
|
|
|
+ SaveFile := False;
|
|
|
+ if Flags and efBackupFiles <> 0 then
|
|
|
+ begin
|
|
|
+ FSplit (FileName, D, N, E);
|
|
|
+ BackupName := D + N + '.bak';
|
|
|
+ Assign (F, BackupName);
|
|
|
+ Erase (F);
|
|
|
+ Assign (F, FileName);
|
|
|
+ Rename (F, BackupName);
|
|
|
+ InOutRes := 0;
|
|
|
+ end;
|
|
|
+ Assign (F, FileName);
|
|
|
+ Rewrite (F, 1);
|
|
|
+ if IOResult <> 0 then
|
|
|
+ EditorDialog (edCreateError, @FileName)
|
|
|
+ else
|
|
|
+ begin
|
|
|
+ BlockWrite (F, Buffer^, CurPtr);
|
|
|
+ BlockWrite (F, Buffer^[CurPtr + GapLen], BufLen - CurPtr);
|
|
|
+ if IOResult <> 0 then
|
|
|
+ EditorDialog (edWriteError, @FileName)
|
|
|
+ else
|
|
|
+ begin
|
|
|
+ Modified := False;
|
|
|
+ Update (ufUpdate);
|
|
|
+ SaveFile := True;
|
|
|
+ end;
|
|
|
+ Close (F);
|
|
|
+ end;
|
|
|
+end; { TFileEditor.SaveFile }
|
|
|
+
|
|
|
+
|
|
|
+function TFileEditor.SetBufSize (NewSize : Sw_Word) : Boolean;
|
|
|
+VAR
|
|
|
+ N : Sw_Word;
|
|
|
+begin
|
|
|
+ SetBufSize := False;
|
|
|
+ if NewSize = 0 then
|
|
|
+ NewSize := MinBufLength
|
|
|
+ else
|
|
|
+ if NewSize > (MaxBufLength-MinBufLength) then
|
|
|
+ NewSize := MaxBufLength
|
|
|
+ else
|
|
|
+ NewSize := (NewSize + (MinBufLength-1)) and (MaxBufLength and (not (MinBufLength-1)));
|
|
|
+ if NewSize <> BufSize then
|
|
|
+ begin
|
|
|
+ if NewSize > BufSize then
|
|
|
+ if not SetBufferSize(pointer(Buffer), NewSize) then
|
|
|
+ Exit;
|
|
|
+ N := BufLen - CurPtr + DelCount;
|
|
|
+ Move(Buffer^[BufSize - N], Buffer^[NewSize - N], N);
|
|
|
+ if NewSize < BufSize then
|
|
|
+ SetBufferSize(pointer(Buffer), NewSize);
|
|
|
+ BufSize := NewSize;
|
|
|
+ GapLen := BufSize - BufLen;
|
|
|
+ end;
|
|
|
+ SetBufSize := True;
|
|
|
+end; { TFileEditor.SetBufSize }
|
|
|
+
|
|
|
+
|
|
|
+procedure TFileEditor.Store (var S : Objects.TStream);
|
|
|
+begin
|
|
|
+ Inherited Store (S);
|
|
|
+ S.Write (FileName, Length (FileName) + 1);
|
|
|
+ S.Write (SelStart, SizeOf (Sw_Word) * 3);
|
|
|
+end; { TFileEditor.Store }
|
|
|
+
|
|
|
+
|
|
|
+procedure TFileEditor.UpdateCommands;
|
|
|
+begin
|
|
|
+ Inherited UpdateCommands;
|
|
|
+ SetCmdState (cmSave, True);
|
|
|
+ SetCmdState (cmSaveAs, True);
|
|
|
+ SetCmdState (cmSaveDone, True);
|
|
|
+end; { TFileEditor.UpdateCommands }
|
|
|
+
|
|
|
+
|
|
|
+function TFileEditor.Valid (Command : Word) : Boolean;
|
|
|
+VAR
|
|
|
+ D : Integer;
|
|
|
+begin
|
|
|
+ if Command = cmValid then
|
|
|
+ Valid := IsValid
|
|
|
+ else
|
|
|
+ begin
|
|
|
+ Valid := True;
|
|
|
+ if Modified then
|
|
|
+ begin
|
|
|
+ if FileName = '' then
|
|
|
+ D := edSaveUntitled
|
|
|
+ else
|
|
|
+ D := edSaveModify;
|
|
|
+ case EditorDialog (D, @FileName) of
|
|
|
+ cmYes : Valid := Save;
|
|
|
+ cmNo : Modified := False;
|
|
|
+ cmCancel : Valid := False;
|
|
|
+ end;
|
|
|
+ end;
|
|
|
+ end;
|
|
|
+end; { TFileEditor.Valid }
|
|
|
+
|
|
|
+
|
|
|
+{****************************************************************************
|
|
|
+ TEDITWINDOW
|
|
|
+****************************************************************************}
|
|
|
+
|
|
|
+constructor TEditWindow.Init (var Bounds : TRect;
|
|
|
+ FileName : Objects.FNameStr;
|
|
|
+ ANumber : Integer);
|
|
|
+var
|
|
|
+ HScrollBar : PScrollBar;
|
|
|
+ VScrollBar : PScrollBar;
|
|
|
+ Indicator : PIndicator;
|
|
|
+ R : TRect;
|
|
|
+begin
|
|
|
+ Inherited Init (Bounds, '', ANumber);
|
|
|
+ Options := Options or ofTileable;
|
|
|
+
|
|
|
+ R.Assign (18, Size.Y - 1, Size.X - 2, Size.Y);
|
|
|
+ HScrollBar := New (PScrollBar, Init (R));
|
|
|
+ HScrollBar^.Hide;
|
|
|
+ Insert (HScrollBar);
|
|
|
+
|
|
|
+ R.Assign (Size.X - 1, 1, Size.X, Size.Y - 1);
|
|
|
+ VScrollBar := New (PScrollBar, Init (R));
|
|
|
+ VScrollBar^.Hide;
|
|
|
+ Insert (VScrollBar);
|
|
|
+
|
|
|
+ R.Assign (2, Size.Y - 1, 16, Size.Y);
|
|
|
+ Indicator := New (PIndicator, Init (R));
|
|
|
+ Indicator^.Hide;
|
|
|
+ Insert (Indicator);
|
|
|
+
|
|
|
+ GetExtent (R);
|
|
|
+ R.Grow (-1, -1);
|
|
|
+ Editor := New (PFileEditor, Init (R, HScrollBar, VScrollBar, Indicator, FileName));
|
|
|
+ Insert (Editor);
|
|
|
+end; { TEditWindow.Init }
|
|
|
+
|
|
|
+
|
|
|
+constructor TEditWindow.Load (var S : Objects.TStream);
|
|
|
+begin
|
|
|
+ Inherited Load (S);
|
|
|
+ GetSubViewPtr (S, Editor);
|
|
|
+end; { TEditWindow.Load }
|
|
|
+
|
|
|
+
|
|
|
+procedure TEditWindow.Close;
|
|
|
+begin
|
|
|
+ if Editor^.IsClipboard then
|
|
|
+ Hide
|
|
|
+ else
|
|
|
+ Inherited Close;
|
|
|
+end; { TEditWindow.Close }
|
|
|
+
|
|
|
+
|
|
|
+function TEditWindow.GetTitle (MaxSize : Sw_Integer) : TTitleStr;
|
|
|
+begin
|
|
|
+ if Editor^.IsClipboard then
|
|
|
+ GetTitle := strings^.get(sClipboard)
|
|
|
+ else
|
|
|
+ if Editor^.FileName = '' then
|
|
|
+ GetTitle := strings^.get(sUntitled)
|
|
|
+ else
|
|
|
+ GetTitle := Editor^.FileName;
|
|
|
+end; { TEditWindow.GetTile }
|
|
|
+
|
|
|
+
|
|
|
+procedure TEditWindow.HandleEvent (var Event : Drivers.TEvent);
|
|
|
+begin
|
|
|
+ Inherited HandleEvent (Event);
|
|
|
+ if (Event.What = Drivers.evBroadcast) then
|
|
|
+ { and (Event.Command = cmUpdateTitle) then }
|
|
|
+ { Changed if statement above so I could test for cmBlugeonStats. }
|
|
|
+ { Stats would not show up when loading a file until a key was pressed. }
|
|
|
+ case Event.Command of
|
|
|
+ cmUpdateTitle :
|
|
|
+ begin
|
|
|
+ Frame^.DrawView;
|
|
|
+ ClearEvent (Event);
|
|
|
+ end;
|
|
|
+ cmBludgeonStats :
|
|
|
+ begin
|
|
|
+ Editor^.Update (ufStats);
|
|
|
+ ClearEvent (Event);
|
|
|
+ end;
|
|
|
+ end;
|
|
|
+end; { TEditWindow.HandleEvent }
|
|
|
+
|
|
|
+
|
|
|
+procedure TEditWindow.SizeLimits(var Min, Max: TPoint);
|
|
|
+begin
|
|
|
+ inherited SizeLimits(Min, Max);
|
|
|
+ Min.X := 23;
|
|
|
+end;
|
|
|
+
|
|
|
+
|
|
|
+procedure TEditWindow.Store (var S : Objects.TStream);
|
|
|
+begin
|
|
|
+ Inherited Store (S);
|
|
|
+ PutSubViewPtr (S, Editor);
|
|
|
+end; { TEditWindow.Store }
|
|
|
+
|
|
|
+
|
|
|
+procedure RegisterEditors;
|
|
|
+begin
|
|
|
+ RegisterType (REditor);
|
|
|
+ RegisterType (RMemo);
|
|
|
+ RegisterType (RFileEditor);
|
|
|
+ RegisterType (RIndicator);
|
|
|
+ RegisterType (REditWindow);
|
|
|
+end; { RegisterEditors }
|
|
|
+
|
|
|
+
|
|
|
+end. { Unit NewEdit }
|