dos_compilers/Borland Turbo Pascal v6/DOC/EDITORS.DOC

774 lines
24 KiB
Plaintext
Raw Normal View History

2024-07-02 16:11:05 +02:00
EDITORS
-------
TEditor implements a small, fast 64K editor for use in Turbo
Vision applications. It features mouse support, undo, clipboard
cut, copy and paste, autoindent and overwrite modes, WordStar
key bindings, and search and replace. This editor can be used not
only for editing files, but as a multi-line memo field in dialogs
or forms.
The use of TEditor is demonstrated in TVEDIT.PAS for editing
files and TVFORM.PAS as a memo field. Both of these file can be
found in the \T6\TVDEMOS directory.
Object summary
--------------
TEditor
-------
TEditor is the base object for all editors. It implements most of
the editor's functionality. If a TEditor object is created, it
will allocate its buffer out of the heap with the given size. The
buffer will initially be empty.
TMemo
-----
TMemo is a descendant of TEditor that is intended to go into a
dialog or form. It supports GetData and SetData and allows the Tab
key to be processed by TDialog. It also has a different palette
than TEditor. GetData/SetData expect a record like the following,
TMemoRec = record
TextLen: Word;
TextData: array[1..MaxMemoLen] of Char;
end;
where MaxMemoLen is the BufSize value passed to TMemo. TMemo
allocates its buffer from the heap.
TFileEditor
-----------
TFileEditor edits the contents of a file, which it stores in memory
allocated from the Buffers unit. This allows several editors to share
the same memory pool. Instead of allocating 64k for each editor, you
can allocate, say, 128k for all your editors. If the first editor only
takes up 16k, it will leave 112k for other editors. The editor takes
only the memory it needs at the time out of the pool. An editor will
grow by 4k at a time whenever the "gap" shrinks to 0, and will shrink
by 4k at a time if the gap grows larger than 4K. See below for a
description of the "gap." See BUFFERS.DOC for further information on
dynamic buffers.
TEditWindow
-----------
TEditWindow is a window designed to hold a TFileEditor or the
clipboard. It will change its title to display the file name
being edited and will initialize scroll bars and an indicator for
the editor. If the name passed to TEditWindow is blank, it
assumes that you are initializing the clipboard.
TIndicator
----------
TIndicator is the line and column counter in the lower left
corner of the edit window. It is initialized by TEditWindow and
passed as the fourth parameter to a TEditor.
Key Bindings
------------
Keys are bound to many of the the familiar WordStar key bindings
used in the IDE. The only exceptions are the block commands. Since
TEditor does not use persistent blocks, the block commands are
simulated by copying the information to and from the clipboard.
For example, ^K^B will begin selecting text. ^K^K will copy the
text to the clipboard. ^K^C will paste the contents from the
clipboard to the editor. This simulates, quite closely, the
keystrokes to do the same thing using WordStar bindings.
The selection can be started by holding down the shift key with
any of the cursor movement commands instead of using the ^K
bindings.
These key bindings can be changed by overriding the ConvertEvent
method which translates the given key event to a command event.
Internals
---------
Buffer structure
----------------
TEditor implements a "buffer gap" editor. It stores the text in
two pieces. Any text before the cursor is stored at the beginning
of the buffer, and text after the cursor is stored at the end
of the buffer. The space between the text is called the "gap."
When a character is inserted into the editor it is inserted into
the gap. The editor supports undo by recording deleted text in the
gap and maintaining the the number of characters inserted and
deleted. When asked to perform an undo, the characters that were
inserted are deleted, the deleted characters are copied to the
beginning of the gap, and the cursor is positioned after the
formerly-deleted text.
To illustrate how the buffer operates, consider the following
diagram of an editor buffer after the characters
"abcdefghijkxxxopqrstuvwxyz" are inserted,
CurPtr
|
v<-- GapLen -->
===========================................
|abcdefghijkxxxopqrstuvwxyz |
===========================................
<-------- BufLen -------->
<---------------- BufSize -------------->
Buffer after text inserted
CurPtr records the position of the cursor, GapLen is the length
of the gap, and BufLen is the total number of characters in the
buffer. BufSize is the size of the buffer which is always the sum
of GapLen and BufLen. If the cursor is then moved to just after
the "xxx" characters, the buffer would look like,
CurPtr
|
v<-- GapLen -->
===============...............=============
|abcdefghijkxxx opqrstuvwxyz|
===============...............=============
BufLen = <------------> + <----------->
<--------------- BufSize --------------->
Buffer after cursor movement
Note that the gap is kept in front of the cursor. This allow for
quick insertion of characters without moving any text. If "xxx"
is deleted using the backspace key the characters are copied to
the bottom of the gap and the cursor is moved backwards. The
DelCount field records the number of characters deleted.
CurPtr
|
v<--- GapLen ---->
============..................=============
|abcdefghijk xxxopqrstuvwxyz|
============..................=============
<-> DelCount
BufLen = <------------> + <----------->
<--------------- BufSize --------------->
Buffer after "xxx" is deleted
When characters are inserted, the insertion count, InsCount, is
incremented to record how to many characters to delete with an
undo. If "lmn" are now typed, the buffer would look like this:
CurPtr
|
v<-- GapLen -->
===============...............=============
|abcdefghijklmn xxxopqrstuvwxyz|
===============...............=============
<-> InsCount <-> DelCount
BufLen = <------------> + <----------->
<--------------- BufSize --------------->
Buffer after "lmn" is inserted
InsCount records the number of characters inserted. If an undo is
now requested "lmn" are deleted and "xxx" are copied on top of them,
restoring the buffer to what it was before the edits.
CurPtr
|
v<-- GapLen -->
===============...............=============
|abcdefghijkxxx opqrstuvwxyz|
===============...............=============
BufLen = <------------> + <----------->
<--------------- BufSize --------------->
Buffer after undo
If the cursor is moved before the undo is performed, all undo
information is lost because the gap moves. Undo will only undo
operations done between cursor movements. As soon as the cursor
moves, the edits performed are considered "accepted." Note also
that undo takes space inside the buffer which could prevent the
user from inserting text. The space can be recovered by moving
the cursor.
Selection or block
------------------
The Selection or block mark is always either before or after the
cursor. If text is inserted into the editor, either through a key
press, or through InsertText, the contents of the selection are
replaced by the inserted text. If there is no selection, the text
is just inserted. The selection is marked by the fields SelStart
and SelEnd. The selection can be set by the call SetSelection,
which will also move the cursor.
Options
-------
TEditor provides several options, the state of which are stored in
Boolean fields. CanUndo indicates whether the editor records undo
information. Since undo takes space temporarily from inserts, you
might find it advantageous to disable undo. This is done
automatically for the clipboard. Overwrite indicates whether the
editor is in overwrite or insert mode. AutoIndent records whether
the editor will, when the Enter key is pressed, indent the cursor
to the column of the first non-space character of the previous
line. This is convenient if the editor is used to edit source
code.
Objects
-------
TEditor
-----------------------------------------------------------------
Fields
------
HScrollBar: PScrollBar;
Pointer to the horizontal scroll bar, nil if the scroll bar
does not exist.
VScrollBar: PScrollBar;
Pointer to the vertical scroll bar, nil if the scroll bar does
not exist.
Indicator: PIndicator;
Pointer to the indicator, nil if the indicator does not exist.
Buffer: PEditBuffer;
Pointer to the buffer used to hold the text.
BufSize: Word;
Size of Buffer.
BufLen: Word;
The amount of text currently in buffer.
GapLen: Word;
The size of the "gap" between the text before the cursor and
the text after the cursor. See above description of the "gap."
SelStart: Word;
Starting offset of the selection.
SelEnd: Word;
Ending offset of the selection.
CurPtr: Word;
Offset of the cursor.
CurPos: TPoint;
Line/Column location of the cursor in the file.
Delta: TPoint;
The top line and left most column shown in the view.
Limit: TPoint;
The maximum number of columns to display, and the number of lines
in the file. Records the limits of the scroll bars.
DelCount: Word;
Number of characters in the end of the gap that were deleted
from the text. Used to implement undo.
InsCount: Word;
Number of characters inserted into the text since the last
cursor movement. Used to implement undo.
IsValid: Boolean;
True if the view is valid. Used by the Valid method.
CanUndo: Boolean;
True if the editor is to support undo.
Modified: Boolean;
True if the buffer has been modified.
Selecting: Boolean;
True if the editor is in selecting mode (i.e., ^K^B has been
pressed).
Overwrite: Boolean;
True if in overwrite mode, otherwise the editor is in insert
mode.
AutoIndent: Boolean;
True if the editor is in autoindent mode.
Methods
-------
constructor Init(var Bounds: TRect; AHScrollBar, AVScrollBar: PScrollBar;
AIndicator: PIndicator; ABufSize: Word);
Creates a TEditor object with the given scroll bars and indicator,
and with a buffer of size ABufSize. Options are set to
sfSelectable and the EventMask additionally allows handling of
broadcast events. Any of AHScrollBar, AVScrollBar or
AIndicator can be nil if you do not want to use them.
constructor Load(var S: TStream);
Creates and initializes a TEditor object off the given stream.
It does not load the previous contents of the buffer, but
instead initializes the buffer to empty.
function BufChar(P: Word): Char;
Returns the P'th character in the file, factoring in the gap.
function BufPtr(P: Word): Word;
Returns the offset into Buffer of the P'th character in the
file, factoring in the gap.
procedure ChangeBounds(var Bounds: TRect); virtual;
Overridden to ensure the file stays within view if the parent
size changes.
procedure ConvertEvent(var Event: TEvent); virtual;
Converts key events into command events. Used to implement the
WordStar key-bindings. Override if you wish to change or
extend the default key-bindings.
function CursorVisible: Boolean;
Returns true if the cursor (or insertion point) is visible
within the view.
procedure DeleteSelect;
Deletes selection if one exists.
procedure DoneBuffer; virtual;
Called whenever the buffer should be disposed. By default it
calls FreeMem with Buffer and BufSize. It should be overridden
if you wish not to use the heap to store the buffer. This is
done in TFileEditor.
procedure Draw; virtual;
Overridden to draw the editor. This should not be overridden
by descendants of TEditor.
function GetPalette: PPalette; virtual;
Returns the Editor palette, CEditor. Override if you wish to
change the palette of the editor.
procedure HandleEvent(var Event: TEvent); virtual;
Provides the event handling for the editor. Override if you
wish to extend the commands the editor handles.
procedure InitBuffer; virtual;
Called whenever the buffer should be allocated. By default, an
editor will call GetMem with Buffer and BufSize. You should
override this method if you do not want the editor to allocate
the buffer from the heap.
function InsertBuffer(var P: PEditBuffer; Offset, Length: Word;
AllowUndo, SelectText: Boolean): Boolean;
This is the lowest-level text insertion method. It will
insert Length bytes of text from the given pointer to text into
the buffer from the given offset into the buffer, P. It will
optionally record undo information and select the text
inserted. This method need never be called directly, since it
is called from InsertFrom and InsertText. This method should
be used if the buffer to be copied from could move (e.g., P was
allocated using the Buffers unit).
function InsertFrom(Editor: PEditor): Boolean; virtual;
Insert the selection from the given editor into this editor.
This method is used to implement Cut, Copy, and Paste. It need
never be overridden by the user.
function InsertText(Text: Pointer; Length: Word;
SelectText: Boolean): Boolean;
Insert the given text of length Length into the buffer,
optionally selecting the text. This is an easier-to-use
version of InsertBuffer.
procedure ScrollTo(X, Y: Integer);
Move column X and line Y to the upper-left corner of the editor.
function Search(FindStr: String; Opts: Word): Boolean;
Search for the given string in the editor with the given
options. The options words are,
efCaseSensitive Case sensitive search
efWholeWordsOnly Find whole words only
function SetBufSize(NewSize: Word): Boolean; virtual;
Called whenever the buffer can be grown or shrunk to the given
value. It should return true if the the buffer can be of the
given size. By default, it returns true if NewSize is less than
or equal to the new size.
procedure SetCmdState(Command: Word; Enable: Boolean);
Disables or enables the given command. The command is always
disabled if the editor is not the selected view. Used as a
convenient way to enable and disable command instead of using
EnableCommands and DisableCommands.
procedure SetSelect(NewStart, NewEnd: Word; CurStart: Boolean);
Set the selection to the given offsets into the file. This
method will either place the cursor in front of behind the
selection pending on the value of CurStart.
procedure SetState(AState: Word; Enable: Boolean); virtual;
SetState is overridden to hide and show scroll bars and the
indicator and to enable and disable commands. If you wish to
enable and disable additional commands, override UpdateCommands
instead. This is called whenever the command states should be
updated.
procedure Store(var S: TStream);
Stores the editor on the given stream.
procedure TrackCursor(Center: Boolean);
Forces the cursor to be visible. If Center is True, the
cursor is forced to be in the center of the screen in the Y
access. The X, or column, is not changed.
procedure Undo;
Undo the changes since the last cursor movement.
procedure UpdateCommands; virtual;
Called whenever the commands should be updated. This is used
to enable and disable commands such as cmUndo, cmClip, cmCopy,
etc.
function Valid(Command: Word): Boolean; virtual;
Returns whether the view is valid given Command. By default it
returns the value of IsValid which is True if Buffer is non-nil.
TMemo
-----------------------------------------------------------------
Methods
-------
constructor Load(var S: TStream);
Creates and initializes a TMemo object off the given stream.
function DataSize: Word; virtual;
Returns the size of the data written by GetData and read by
SetData. By default it return SizeOf(Word) + BufSize.
procedure GetData(var Rec); virtual;
Writes the contents of the buffer into the given Rec.
function GetPalette: PPalette; virtual;
Returns a palette, CMemo, suitable for TMemo's use in a
TDialog.
procedure HandleEvent(var Event: TEvent); virtual;
Prevents TMemo from handling kbTab, otherwise handles events the
same as a TEditor.
procedure SetData(var Rec); virtual;
Read the contents of the buffer from the given Rec.
procedure Store(var S: TStream);
Store the TMemo to the given stream.
TFileEditor
-----------------------------------------------------------------
Fields
------
FileName: FNameStr;
Name of the file being edited.
Methods
-------
constructor Init(var Bounds: TRect;
AHScrollBar, AVScrollBar: PScrollBar;
AIndicator: PIndicator; AFileName: FNameStr);
Creates a TFileEditor object with the given scroll bars and
indicator and loads the contents of the given file. If the
file is not found or invalid an error message will be displayed
and the object's Valid method will return false. Options are
set to sfSelectable and the EventMask additionally allows
handling of broadcast events. Any of AHScrollBar, AVScrollBar
or AIndicator can be nil if you do not want them.
constructor Load(var S: TStream);
Creates and initializes a TFileEditor object off the given
stream. The file is reloaded into the editor and the cursor is
positioned back to the location it was when the Store was
performed. It is ideal for use with a "Desktop save" option.
procedure DoneBuffer; virtual;
Disposes of the buffer allocated from the Buffers unit.
procedure HandleEvent(var Event: TEvent); virtual;
Overridden to implement the cmSave and cmSaveAs commands.
procedure InitBuffer; virtual;
Allocates memory from the Buffers unit to use for the editor
buffer.
function LoadFile: Boolean;
Read the file from disk and check for errors. Sets IsValid to
False if the file was not loaded into the buffer.
function Save: Boolean;
Saves the file to disk. Returns false if the save failed or
was canceled. If EditorFlags has the efBackupFiles bit set, a
.BAK file is created. Will call SaveAs if the editor is
"Untitled."
function SaveAs: Boolean;
Saves the editor with a different name. The name is derived
from a dialog brought up using the EditorDialogs function
pointer. Returns True if the editor was saved, False otherwise
(i.e., the operation was canceled).
function SaveFile: Boolean;
Saves the file to disk. Returns False if the save failed. If
EditorFlags has the efBackupFiles bit set, a .BAK file is
created.
function SetBufSize(NewSize: Word): Boolean; virtual;
Overridden to grow and shrink the buffer with calls to the
Buffers unit. Will grow and shrink the buffer in 4k
increments.
procedure Store(var S: TStream);
Store the TFileEditor object on the given stream. The file
name, not the file contents, are stored on the stream.
procedure UpdateCommands; virtual;
Overridden to enable and disable the cmSave and cmSaveAs
commands. They are only valid if the selected view is an
editor, otherwise they should be disabled.
function Valid(Command: Word): Boolean; virtual;
Overridden to make sure the file is saved before the program
exits. Returns False if the user cancels the save.
TEditWindow
-----------------------------------------------------------------
Fields
------
Editor: PFileEditor;
Pointer to the editor object in the edit window.
constructor Init(var Bounds: TRect; FileName: FNameStr;
ANumber: Integer);
Creates a TEditWindow object that will edit the given file
name with window number ANumber. This method initializes a
TFileEditor with scroll bars and an indicator. If the file
name is a null string, it is assumed to be an untitled file. If
Editor is equal to the Clipboard variable, the editor is assumed
to be the clipboard.
constructor Load(var S: TStream);
Creates and initializes a TEditWindow off the given stream.
procedure Close; virtual;
Overridden to hide, instead of close, the window if the editor
is a clipboard.
function GetTitle(MaxSize: Integer): TTitleStr; virtual;
Returns the name of the file being edited by the editor or
'Clipboard' if the editor is the clipboard.
procedure HandleEvent(var Event: TEvent); virtual;
Handles cmUpdateTitle to redraw the frame of the window. Used
in SaveAs to change the title of the window if the file being
edited changes names.
procedure Store(var S: TStream);
Saves the TEditWindow object to the given stream.
TIndicator
-----------------------------------------------------------------
Fields
------
Location: TPoint;
Stores the location to display. Updated by a TEditor.
Modified: Boolean;
True if the associated TEditor has been modified. Displays a
special character if true.
Methods
-------
constructor Init(var Bounds: TRect);
Creates a TIndicator object.
procedure Draw; virtual;
Draws the indicator.
function GetPalette: PPalette; virtual;
Return the a pointer to CIndicator, the TIndicator default
palette.
procedure SetState(AState: Word; Enable: Boolean); virtual;
Draws the indicator in the frame dragging color if dragging.
procedure SetValue(ALocation: TPoint; AModified: Boolean);
Method called by TEditor to update the values to the fields of
a TIndicator.
Globals
-------
Variables
---------
WordChars: set of Char;
Set of characters that define a word. Used when handling the
cmWordLeft and cmWordRight commands. The default value is
['0'..'9', 'A'..'Z', '_', 'a'..'z'].
EditorDialog: TEditorDialog;
EditorDialog is a procedure variable that is used by TEditor
objects to display various dialogs. Since dialogs are very
application-dependent, EDITORS cannot display its own dialogs.
Instead it calls this function variable instead. For an
example of an EditorDialog function, see TVEDIT.PAS. The various
dialog values are
edOutOfMemory
edReadError
edWriteError
edCreateError
edSaveModify
edSaveUntitled
edSaveAs
edFind
edSearchFailed
edReplace
edReplacePrompt
EditorFlags: Word;
EditorFlags contains various flags for use in the editor. The
value of which are
efCaseSensitive Default to case sensitive search
efWholeWordsOnly Default to whole words only search
efPromptOnReplace Prompt on replace
efReplaceAll Replace all occurrences.
efDoReplace Do replace.
efBackupFiles Create .BAK files on saves.
The default value is efBackupFiles + efPromptOnReplace.
FindStr: String[80];
Stores the last value used for a find.
ReplaceStr: String[80];
Stores the last value of a replace.
Clipboard: PEditor = nil;
Pointer to the clipboard. Any TEditor can be the clipboard, it
just needs be assigned to this variable. The clipboard should
not support undo (i.e., its CanUndo should be false).
Procedures
----------
procedure RegisterEditors;
Register all object types in EDITORS.