DEFINITION MODULE DMTextFields;
(*******************************************************************
Module DMTextFields ('Dialog Machine' DM_V3.0)
Copyright (c) 1989-2006 by Andreas Fischlin and ETH Zurich.
Purpose Extension of DMEditFields. This module provides
the needed operations to make an ordinary text
field as installed by DMEditFields to behave like
a full blown text editor.
Remarks Implementation restriction: Only texts to a maximum
size of 32000 characters (ca. 32KBytes) can be edited
in a single text field. However, there can be any
number of text fields.
This module belongs to the 'Dialog Machine'.
Programming
o Design
Andreas Fischlin 07/12/1989
o Implementation
Andreas Fischlin 07/12/1989
ETH Zurich
Systems Ecology
CHN E 35.1
Universitaetstrasse 16
8092 Zurich
SWITZERLAND
URLs:
<mailto:RAMSES@env.ethz.ch>
<http://www.sysecol.ethz.ch>
<http://www.sysecol.ethz.ch/SimSoftware/RAMSES>
Last revision of definition: 31/01/1990 AF
*******************************************************************)
FROM DMWindows IMPORT WindowFrame;
FROM DMEditFields IMPORT EditItem;
TYPE
TextPointer = POINTER TO TextSegment;
TextSegment = ARRAY [0..32000] OF CHAR;
PROCEDURE RedefineTextField(textField: EditItem; wf: WindowFrame;
withFrame: BOOLEAN);
(*
Redefines the outer dimensions and position as given by wf of
the text field textField requiring a previous installation of
the text field via the procedure DMEditFields.TextField. It
also allows to suppress the frame, which, by default, is drawn
around a text field. Note that eventually attached scroll bars
will also be resized according to the new sizes. Typically you
call this procedure to hide the frame, when you wan't to program
an actual text editor and from within the redefine mouse handler
as installed in DMMaster.
*)
PROCEDURE CopyWTextIntoTextField (textField: EditItem; VAR done: BOOLEAN);
PROCEDURE CopyTextFromFieldToWText (textField: EditItem);
(*
Transfers the textual content of the text field textField back
and forth between the so-called window text of the window to
which the text field belongs; the window text is a textual data
structure associated with a particular window (at a time one
such data structure per window only) and if the window is the
current output window. See also routines from module DMWTextIO
or PrintText from DMPrinting. Text objects can be of any size
as long as there is enough memory available; however, text
fields can hold only a TextSegment, i.e. a string of length <=
32000. CopyWTextIntoTextField returns false if the window text
exceeds this limit.
*)
PROCEDURE SetSelection(textField: EditItem; beforeCh,afterCh: INTEGER);
PROCEDURE GetSelection (textField: EditItem; VAR beforeCh,afterCh: INTEGER);
(*
Sets or returns the current selection in the text of a text
field. The current selection is automatically made visible in
the text field via inversion. All characters are numbered
according to their position in a TextSegment. beforeCh and
afterCh denote the index of the first respectively the last
character in the selection. If beforeCh and afterCh have the
same value, the selection represents the so-called insertion
point, denoting that if the user presses keys, these characters
will be inserted in the text segment before the character
beforeCh, i.e. the first typed character will become
text[beforeCh], the next text[beforeCh+1] etc. Note that the
old text[beforeCh] will be automatically shifted to the next
higher, available position. Setting the selection outside the
currently visible lines will automatically scroll the text, so
that the selection becomes visible. All these activities will
be automatically taken care of by the Dialog Machine.
*)
PROCEDURE GetSelectedChars(textField: EditItem; VAR text: ARRAY OF CHAR);
(* Copies the currently selected chars into text *)
PROCEDURE DeleteSelection(textField: EditItem);
(* Deletes currently selected chars *)
PROCEDURE InsertBeforeCh(textField: EditItem; VAR text: ARRAY OF CHAR;
beforeCh: INTEGER);
(*
Inserts the text text in the text field textField before the
character beforeCh, shifting all characters at positions >=
beforeCh to the next higher available positions.
*)
PROCEDURE GetTextSizes(textField: EditItem; VAR curTextLength, nrLns, charHeight,
firstLnVis, lastLnVis: INTEGER);
(* Returns several properties of the text currently contained in the text
field ei, where
- curTextLength Number of characters in text
- nrLns Number of lines in the text
- charHeight Height of a character or a line in pixels
- firstLnVis Ordinal number of first visible line (if text
has been scrolled, this number is different
from 1, the very first line of the text)
- lastLnVis Ordinal number of last visible line
(number of currently visible lines = lastLnVis-firstLnVis+1 )
*)
PROCEDURE WrapText (textField: EditItem; wrap: BOOLEAN);
(*
Sets the mode in which text is displayed, i.e. if wrap is true
the portions of lines longer than what can be currently
displayed in the text field are wrapped onto the next line. If
wrap is false, line contents are always displayed on just one
line regardless of their length.
*)
PROCEDURE GrabText(textField: EditItem; VAR txtbeg: TextPointer;
VAR curTextLength: INTEGER);
(*
Makes the text contained in the text field available for
inspection at memory location starting with address txtbeg
without having to make a copy of it by calling procedure
GetText (also from this module). Since the text is internally
contained in a so-called handle, it can move in memory, which
would make the access dangerous, unless it is temporarily
locked to a particular position. This procedure does exactly
do this (calls HLock of the memory manager) and hence, it is
very important to release the text with procedure ReleaseText
once you are through with the inspection of the text.
WARNING: Never forget to call ReleaseText after a call to
GrabText or the normal editing process in the text field might
no longer function properly.
*)
PROCEDURE ReleaseText(textField: EditItem);
(*
Relases the text from a particular memory location after a call
to procedure GrabText
*)
PROCEDURE FindInText(textField: EditItem; stringToFind: ARRAY OF CHAR;
VAR firstCh,lastCh: INTEGER): BOOLEAN;
(*
Predefined pattern matching alogorithm to find in the text of
the text field textField the string stringToFind starting with
the search from the current position as given by the current
selection. If it finds the string the algorithm returns TRUE
and returns the position of the found string in the values of
firstCh and lastCh according to the rules as valid for a
selection. If it can't find the sring, the values in firstCh
and lastCh represent those of the current selection and FALSE
is returned. The implementation of this procedure is:
PROCEDURE FindInText(textField: EditItem; stringToFind: ARRAY OF CHAR;
VAR firstCh,lastCh: INTEGER): BOOLEAN;
VAR
searched,ch: CHAR; i,j,lasti,len,startPos: INTEGER; theText: TextPointer;
BEGIN
GrabText(textField,theText,lasti);
len:=Length(stringToFind); DEC(lasti,len);
(* start with search after selection
otherwise begin with current insertion point: *)
GetSelection(textField,firstCh,lastCh);
IF firstCh<>lastCh THEN startPos := lastCh+1 ELSE startPos := firstCh END;
IF (startPos > lasti) OR (len = 0) THEN (* no search possible *)
ReleaseText(textField); RETURN FALSE
ELSE (* search is possible *)
i:= startPos;
WHILE i<=lasti DO
j:= 0; (* index in 'stringToFind' *)
REPEAT
searched:= stringToFind[j];
ch := theText^[i+j];
INC(j);
UNTIL (ch # searched) OR (j=len);
IF (ch # searched) THEN (* start with next position *)
INC(i);
ELSE (* position found *)
firstCh := i; lastCh := firstCh+len-1;
ReleaseText(textField); RETURN TRUE
END(*IF*);
END(*WHILE*);
ReleaseText(textField); RETURN FALSE
END(*IF*);
END FindInText;
Feel free to write and use your own.
*)
PROCEDURE ScrollText(textField: EditItem; dcols,dlines: INTEGER);
(*
Scrolls the text by dcols columns and dlines lines. If a
scroll bar is attached to the text field, the corresponding
position of the scroll box will be set. Positive dlines will
scroll the text up, negatives down; positive dcols will scroll
the text to the right, negative ones to the left
*)
PROCEDURE ScrollTextWithWindowScrollBars(textField: EditItem);
PROCEDURE AddScrollBarsToText(textField: EditItem; withVerticalScrollBar,
withHorizontalScrollBar: BOOLEAN);
(*
Above two procedures associate a scroll bar with the text
content of the text field textField. The vertical sroll bar
will be shown at the right of the text field, the horizontal
below the text field. The procedure
ScrollTextWithWindowScrollBars uses the scroll bars of the
Dialog Machine window (see DMWindows) and does not attach
additional scroll bars to the text field. If they are missing
in the window of the text field, no action takes place and
EditFieldsDone becomes FALSE. Once called, the effect of these
procedures will be that all scrolling of the text in the text
field will be taken care of by the Dialog Machine. In
particular this is valid for all scrolling by the user via the
scroll bars (page up/down, line up/down, scroll box) and by
clicking the mouse in the middle of a text field and moving it
outside of the field while still holding down the mouse button
(so-called auto scrolling), via text insertion or
cutting/deletion, as well as via moving the selection (see
SetSelection) outside of the currently visible portion of the
text.
*)
END DMTextFields.