a view for editable text - adds editing functionality to TextView
Also, it adds accept functionality, and defines a new actionBlock:
acceptAction to be performed for accept
If used with a model, this is informed by sending it a changeMsg with
the current contents as argument.
(however, it is possible to define both changeMsg and acceptAction)
Please read the historic notice in the ListView class.
[Instance variables:]
cursorLine <Number> line where cursor sits (1..)
cursorVisibleLine <Number> visible line where cursor sits (1..nLinesShown)
cursorCol <Number> col where cursor sits (1..)
cursorShown <Boolean> true, if cursor is currently shown
readOnly <Boolean> true, if text may not be edited
modifiedChannel <ValueHolder> holding true, if text has been modified.
cleared on accept.
acceptChannel <ValueHolder> holding true, if text has been accepted.
fixedSize <Boolean> true, if no lines may be added/removed
exceptionBlock <Block> block to be evaluated when readonly text is about to be modified
if it returns true, the modification will be done anyway.
if it returns anything else, the modification is not done.
cursorFgColor <Color> color used for cursor drawing
cursorBgColor <Color> color used for cursor drawing
cursorType <Symbol> how the cursor is drawn; currently implemented
are #none, #block (solid-block cursor), #ibeam
(vertical bar at insertion point)
and #caret (caret below insertion-point).
see cursorType: for an up-to-date list.
cursorTypeNoFocus <Symbol> like above, if view has no focus
nil means: hide the cursor.
undoAction <Block> block which undoes last cut, paste or replace
(not yet fully implemented)
typeOfSelection <Symbol> #paste, if selection created by paste, nil otherwise
this affects the next keyPress: if #paste it does not
replace; otherwise it replaces the selection.
lastCut <String> last cut or replaced string
lastReplacementInfo <LastReplacementInfo> holds the information about the last replace action
lastStringToReplace is the string to be replaced by lastReplacement
lastReplacement is the string to replace lastStringToReplace
lastStringFromReplaceForNextSearch <String> string to be taken be the next search action
(cleared after a new selection)
replacing <Boolean> true if entered characters replace last selection
showMatchingParenthesis <Boolean> if true, shows matching parenthesis
when entering one; this is the default.
hasKeyboardFocus <Boolean> true if this view has the focus
acceptAction <Block> accept action - evaluated passing the contents as
argument
tabMeansNextField <Boolean> if true, Tab is ignored as input and shifts keyboard
focus to the next field. For editTextViews, this is false
by default (i.e. tabs can be entered into the text).
For some subclasses (inputFields), this may be true.
trimBlankLines <Boolean> if true, trailing blanks are
removed when editing.
Also, empty lines are represented as nil in the lines collection.
Default is true.
wordWrap <Boolean> Currently not used.
lockUpdates <Boolean> internal, private
prevCursorState <Boolean> temporary, private
cursorMovementWhenUpdating
<Symbol> defines where the cursor is to be positioned if the
model changes its value by some outside activity
(i.e. not by user input into the field).
Can be one of:
#keep / nil -> stay where it was
#endOfText -> cursor to the end
#endOfLine -> stay in the line, but move to end
#beginOfText -> cursor to the beginning
#beginOfLine -> stay in the line, but move to begin
The default is #beginOfText
dropTarget <DropTarget|nil> drop operation descriptor or nil (drop disabled)
userPreference values:
userPreferences.st80EditMode
<Boolean> if true, cursor positioning is
done as in vi or ST80; i.e.
wysiwyg mode is somewhat relaxed,
in that the cursor cannot be
positioned behind a lines end.
This is not yet completely implemented.
used globals:
DeleteHistory <Text> last 1000 lines of deleted text
(but only if this variable exists already)
[styleSheet parameters:]
textCursorForegroundColor <Color> cursor fg color; default: text background
textCursorBackgroundColor <Color> cursor bg color; default: text foreground
textCursorNoFocusForegroundColor
<Color> cursor fg color if no focus; default: cursor fg color
textCursorType <Symbol> cursor type; default: #block

return true, if the st80 editing mode is turned on.
This setting affects the behavior of the cursor, when positioned
beyond the end of a line or the end of the text.
This method is here for backward compatibility, when this flag was stored
in a class var. It is now in the user's settings.
Please do not call it, but go to the prefs directly, to make it easier to find those getters.

turns on/off st80 behavior, where the cursor cannot be positioned
beyond the end of a line or the last line.
This method is here for backward compatibility, when this flag was stored
in a class var. It is now in the user's settings.
Please do not call it, but go to the prefs directly, to make it easier to find those setters.

return what is be done with the cursor,
when I get a new text (via the model or the #contents/#list)
Allowed arguments are:
#keep / nil -> stay where it was
#endOfText -> position cursor to the end
#beginOfText -> position cursor to the beginning
#endOfLine -> position cursor to the current lines end
#beginOfLine -> position cursor to the current lines start
The default is #beginOfText.
This may be useful for fields which get new values assigned from
the program (i.e. not from the user)

define what should be done with the cursor,
when I get a new text (via the model or the #contents/#list)
Allowed arguments are:
#keep / nil -> stay where it was
#endOfText -> position cursor to the end
#beginOfText -> position cursor to the beginning
#endOfLine -> position cursor to the current lines end
#beginOfLine -> position cursor to the current lines start
The default is #beginOfText.
This may be useful for fields which get new values assigned from
the program (i.e. not from the user)

remember that the current selection was created by a paste operation
(as opposed to an explicit selection by the user).
This selection will not be replaced by followup user input,
so multiple pastes will be possible.

some applications may want to dynamically generate lines below the bottom line,
when the cursor is moved there.
For example, disassembly views or memory dumps (hex-dumps),
which want to automatically generate additional lines lazily,
but which cannot afford to generate the whole text in advance
(eg: who wants to disassemble gigabytes?).
If set, this hook is called whenever the cursor is about to be moved below the
last line, getting the new lineNr (i.e > contents size) as argument.
It may generate more text (by setting my contents) and return a new cursor line
number, into which the cursor should be moved
(eg. if 10 additional lines are generated, it may want to return oldSize+1,
to make the cursor end in the last line which was inserted)

some applications may want to dynamically generate lines above the top
line, when the cursor is moved there.
For example, disassembly views or memory dumps (hex-dumps),
which want to automatically generate additional lines lazily,
but which cannot afford to generate the whole text in advance
(eg: who wants to disassemble gigabytes?).
If set, this hook is called whenever the cursor is about to be moved above the
top, getting the new lineNr (i.e < 1) as argument.
It may generate more text (by setting my contents) and return a new cursor line
number, into which the cursor should be moved
(eg. if 10 additional lines are generated, it may want to return 10, to make the
cursor end in the last line which was inserted)

set/clear the st80Mode flag.
If on, the cursor wraps at the line end (like in vi or st80);
if off, we have the Rand-editor behavior (random access)
if nil, the setting follows the current userPref setting.

set/clear tabbing to the next field.
If true, Tab is ignored and shifts the keyboard focus.
If false, tabs can be entered into the text.
The default is true for editTextView, false for single-line
input fields.

return the character under the cursor - space if beyond line.
For non-block cursors, this is the character immediately to the right
of the insertion-bar or caret.
For block cursors, this is the highlighted cursor-character

return a valueHolder for the cursors line and column as an info string
of the form 'line : col'.
This can be used directly as a model for a GUI label showing the cursor position (eg in the lower right)

accept the current contents by executing the accept-action and/or
changeMessage.
Historically, ST/X used a callBack (acceptAction);
and ST80/VW used the model, into which the text is stored.
We support both; if there is a mode, it gets a value: message,
If there is an acceptAction, it is called.

return true, if the user may move the cursor around
(via button-click, or cursor-key with selection).
By default, true is returned, but this may be redefined
in special subclasses (such as a terminal view), where
this is not wanted

check of col is a valid cursor position; return a new col-nr if not.
Here, no limits are enforced (and col is returned),
but it may be redefined in EditFields or views which don't like the
cursor to be positioned behind the end of a textLine (vi/st-80 behavior)

check if line is a valid cursor line; return a fixed line-nr if not.
Here, no limits are enforced (and line is returned), but it may be
redefined in views which don't like the cursor to be positioned
behind the end of the text (vi/st-80 behavior), or want to
skip reserved regions

undoably delete the selection (if any) and insert something, a character or string;
leave cursor after insertion or leave it, depending on keep.
If selectNewText is true, select the new text; otherwise deselect

insert a bunch of lines before line lineNr; the view is not redrawn.
Tabs are expanded here with a tab=8 setting (independent of any editor-setting,
because the text might have been pasted from an alien view.

paste the copybuffer; if there is a selection, replace it.
otherwise paste at cursor position.
Replace is not done for selections which were created by a paste,
to allow multiple paste operations in a row.

search for a string - show a box to enter searchpattern
replace for the found searchpattern or replace all searchpattern found to a new pattern - show a box to enter replacepattern
- currently no regular expressions are handled.

check if the text can be modified (i.e. is not readOnly), return true or false.
If not, and an exceptionBlock has been defined, evaluate it.
The exceptionBlock can be provided by the application or user of the textView,
and may show a warnBox or whatever, or ask again.
It can return true to allow the modification

check if the text can be modified (i.e. is not readOnly), return true or false.
If not, and an exceptionBlock has been defined, evaluate it.
The exceptionBlock can be provided by the application or user of the textView,
and may show a warnBox or whatever, or ask again.
It can return true to allow the modification.
If either no exceptionBlock was defined or it returned false,
and doFlashIfNot is true then flash the view to tell the user.

my text was modified (internally).
Sent whenever text has been edited (not to confuse with
contentsChanged, which is triggered when the size has changed, and
is used to notify scrollers, other views etc.).

As some authors of this code have been very sloppy in the past
(not sending contentsChanged, but textChanged),
we do it here despite what is written above, to ensure that scrollers update correctly.

my text was modified (internally).
Sent whenever text has been edited (not to confuse with
contentsChanged, which is triggered when the size has changed, and
is used to notify scrollers, other views etc.)

return the number of pixels by which we may scroll more than the actual
width of the document would allow.
This is redefined by editable textViews, to allo for the cursor
to be visible if it is positioned right behind the longest line of text.
The default returned here is 10 pixels, which should be ok for most cursors

search for a matching parenthesis starting at cursor position.
Search for the corresponding character is done forward if it's an opening,
backwards if it's a closing parenthesis.
Positions the cursor if found, beeps if not

evaluate aBlock while unselected.
Restore the previous selection afterwards.
CG: I am not sure, if this is a leftover and is still used at all.
It is therefore temporarily marked as obsolete. Please check
and let me know.

** This is an obsolete interface - do not use it (it may vanish in future versions) **

select the whole text. This is called only once during the initialization
for editFields which are shown in a table or tree.
The selectAll is called via this method to allow for easier redefinition and
to distinguish auto-select from user-initiated selects.