(*
 * Title:   txt.h
 * Purpose: Text display object.
 *
 *)

#ifndef __txt_h
#define __txt_h

(* 
 * A txt is an array of characters, displayed in a window on the screen. It
 * behaves in many ways in a manner similar to a single buffer from a
 * conventional full screen text editor.
 *
 *)

(* 
 * This interface is intended to be independent of any underlying window 
 * system.
 *
 *)

(****************************** TXT DATA TYPE *****************************)

(* This is an abstract handle on a text object. *)

type txt_ptr = ^txt;
     txt = ^txt1_str;
     txt1_str = record end;


(****************************** INTERFACE FUNCTIONS ************************)


(* ------------------------------- txt_new ---------------------------------
 * Description:   Creates a new txt object, containing no charcters, with a
 *                given title (to appear in its window).
 *
 * Parameters:    char *title -- the text title to appear in its window
 * Returns:       pointer to the newly created text.
 * Other Info:    This function does not result in the text being displayed
 *                on the screen; it purely creates a new text object.
 *                0 is returned if there is not enough space to create the
 *                object.
 *
 *)
function txt_new(title : string) : txt; extern;


(* -------------------------------- txt_show -------------------------------
 * Description:   Display a given text object in a free standing window of
 *                its own.
 *
 * Parameters:    txt t -- the text to be displayed.
 * Returns:       void.
 * Other Info:    "t" should have been created using txt_new.
 *
 *)
procedure txt_show(t : txt); extern;


(* ------------------------------ txt_hide ---------------------------------
 * Description:   Hide a text which has been displayed.
 *
 * Parameters:    txt t -- the text to be hidden.
 * Returns:       void.
 * Other Info:    none.
 *
 *)
procedure txt_hide(t : txt); extern;


(* ---------------------------- txt_settitle -------------------------------
 * Description:   Change the title of the window used to display a text
 *                object.
 *
 * Parameters:    txt t -- the text object
 *                char *title -- new title of window.
 * Returns:       void.
 * Other Info:    Long titles may be truncated when displayed.
 *
 *)
procedure txt_settitle(t : txt; title : string); extern;


(* ----------------------------- txt_dispose -------------------------------
 * Description:   Destroy a text and the window associated with it.
 *
 * Parameters:    txt *t -- pointer to the text.
 * Returns:       void.
 * Other Info:    none.
 *
 *)
procedure txt_dispose(var t : txt); extern;


(*************************** General control operations. *******************)

(* A text object's main data content is an array of characters. This resides
 * in a buffer of known size. The characters of the array are not laid out
 * precisely in the buffer, gaps and wraparound of various forms are used in
 * order to make insertion and deletion fast. When initially created a text 
 * has bufsize=0. If the buffer size is precisely the same as the number of
 * characters in the array then some operations (e.g. moving around in the
 * array) become even faster, this may be relevant when building fixed-size
 * VDU emulations.
 *
 *)


(* ----------------------------- txt_bufsize -------------------------------
 * Description:   Informs caller of how many characters can be stored in the
 *                buffer, before more memory needs to be requested from the
 *                operating system.
 *
 * Parameters:    txt t -- the text.
 * Returns:       size of buffer.
 * Other Info:    none.
 *
 *)
function txt_bufsize(t : txt) : integer; extern;


(* --------------------------- txt_setbufsize ------------------------------
 * Description:   Allocates more space for the text buffer.
 *
 * Parameters:    txt t -- the text.
 *                int b -- new buffer size
 * Returns:       TRUE if space could be allocated successfully.
 * Other Info:    This call increases the buffer size, such that at least
 *                "b" characters can be stored, before requiring more from 
 *                the operating system.
 *
 *)
function txt_setbufsize(t : txt; n : integer) : boolean; extern;


(* 
 * The character array is displayed on the screen in a window.  The
 * characters travel horizontally from left to right. If a '\n' is
 * encountered this signifies the end of the current text line, and the 
 * start of a new one. All lines have the same height, although characters
 * may be of differing widths. There is no limit on the number of characters
 * allowed in a line. There is no restriction on the characters allowed in
 * the array, [0..255] are all acceptable.
 * Clearing the DISPLAY flag can be used during a long and complex sequence
 * of edits, to reduce the overall amount of display activity. The UPDATED
 * flag is set by the insertion or deletion of any characters in the array.
 *
 *)
const txt_DISPLAY = 1;     (* display changes to text as made *)
      txt_CARET = 2;       (* give visible indictaion of "dot" *)
      txt_UPDATED = 4;     (* set when chars are inserted/deleted *)

type txt_charoption = integer;


(* ----------------------------- txt_charoptions ---------------------------
 * Description:   Informs caller of currenly set charoptions.
 *
 * Parameters:    txt t -- text object.
 * Returns:       Currently set charoptions.
 * Other Info:    none.
 *
 *)
function txt_charoptions(t : txt) : txt_charoption; extern;


(* ----------------------------- txt_setcharoptions ------------------------
 * Description:   Sets flags which are used to control display of text in
 *                screen window.
 *
 * Parameters:    txt t -- text object
 *                txt_charoption affect -- flags to affect
 *                txt_charoption values -- values to give to affected flags
 * Returns:       void.
 * Other Info:    Only the flags named in "affect" are affected - they are
 *                set to the value "values".
 *                Thus this has the meaning:
 *                  (previousState & ~affect) | (affect & values).
 *
 *)
procedure txt_setcharoptions(t : txt_charoption;
                affect : txt_charoption;
                values : txt_charoption); extern;

(* ----------------------------- txt_lastref -------------------------------
 * Description:   Returns last_ref field (for Message_DataSaved).
 *
 * Parameters:    txt t -- text object.
 * Returns:       Current value of last_ref (for Message_DataSaved).
 * Other Info:    none.
 *
 *)
function txt_lastref(t : txt) : integer; extern;


(* ----------------------------- txt_setlastref ----------------------------
 * Description:   Sets value of last_ref (for Message_DataSaved).
 *
 * Parameters:    txt t -- text object
 *                int newvalue -- new value
 * Returns:       void.
 * Other Info:    Sets the last_ref field in a txt, so that subsequently a
 *                Message_DataSaved can mark the data unmodified.
 *
 *)
procedure txt_setlastref(t : txt; newvalue : integer); extern;


(* -------------------------- txt_setdisplayok -----------------------------
 * Description:   Sets the display flag in charoptions for a given text
 *
 * Parameters:    txt t -- text object
 * Returns:       void.
 * Other Info:    You may have unset the display flag during a long/complex
 *                update to the array of characters. A call to this function
 *                turns display back on.
 *
 *)
procedure txt_setdisplayok(t : txt); extern;


(******************** Operations on the array of characters. ***************)

(* 
 * "dot" is an index into the character array. If there are n chars in the
 * array, with indices in [0..n-1], then dot is in [0..n]. It is thought of
 * as pointing just before the character with the same index, but it can also
 * point just after the last one. When the text is displayed, the character
 * after the dot is always visible. The Caret is a visible indication of the
 * position of the dot within the array, it can be made visible using
 * SetCharOptions above.
 *)
type txt_index = integer; (* An index into the char array *)


(* ------------------------------ txt_dot ----------------------------------
 * Description:   Informs caller of where the "dot" (current position) is in
 *                the array of characters.
 *
 * Parameters:    txt t -- text object 
 * Returns:       An index into the array of characters.
 * Other Info:    none.
 *
 *)
function txt_dot(t : txt) : txt_index; extern;


(* ------------------------------- txt_size --------------------------------
 * Description:   Informs the caller as to the maximum value "dot" can take
 *
 * Parameters:    txt t -- text object.
 * Returns:       Maximum permissible value of "dot".
 * Other Info:    none.
 *
 *)
function txt_size(t : txt) : txt_index; extern;


(* ------------------------------- txt_setdot ------------------------------
 * Description:   Sets the "dot" at a given index in the array of characters.
 *
 * Parameters:    txt t -- text object.
 *                txt_index i -- index at which to set "dot".
 * Returns:       void.
 * Other Info:    If "i" is outside the bounds of the array it is set to the
 *                beginning/end of the array appropriately.
 *
 *)
procedure txt_setdot(t : txt; i : txt_index); extern;


(* ------------------------------ txt_movedot ------------------------------
 * Description:   Move the "dot" by a given distance in the array.
 *
 * Parameters:    txt t -- text object
 *                int by -- distance to move by.
 * Returns:       void
 * Other Info:    If the resulting "dot" is outside the bounds of the array
 *                it is set to the beginning/end of the array appropriately.
 *
 *)
procedure txt_movedot(t : txt; by : integer); extern;


(* ----------------------------- txt_insertchar ----------------------------
 * Description:   Insert a character into the text just after the "dot".
 *
 * Parameters:    txt t -- text object
 *                char c -- the character to be inserted.
 * Returns:       void.
 * Other Info:    If the DISPLAY option flag is set, the window is
 *                redisplayed after insertion.
 *
 *)
procedure txt_insertchar(t : txt; c : char); extern;


(* --------------------------- txt_insertstring ----------------------------
 * Description:   Inserts a given character string into a text.
 *
 * Parameters:    txt t -- text object
 *                char *s -- the character string.
 * Returns:       void.
 * Other Info:    If the DISPLAY option flag is set, the window is
 *                redisplayed after insertion.
 *
 *)
procedure txt_insertstring(t : txt; s : string); extern;


(* ------------------------------ txt_delete -------------------------------
 * Description:   Deletes "n" characters from the "dot" onwards.
 *
 * Parameters:    txt t -- text object
 *                int n -- number of characters to delete.
 * Returns:       void.
 * Other Info:    If "dot +n" is beyond the end of the array, then deletion
 *                is to end of array.
 *
 *)
procedure txt_delete(t : txt; n : integer); extern;


(* ---------------------------- txt_replacechars ---------------------------
 * Description:   Deletes "ntodelete" charcters from "dot", and inserts "n"
 *                characters in their place, where the characters are
 *                pointed at by "a".
 *
 * Parameters:    txt t -- text object
 *                int ntodelete -- number of characters to delete
 *                char *a -- pointer to characters to insert
 *                int n -- number of characters to insert.
 * Returns:       void.
 * Other Info:    none.
 *
 *)
procedure txt_replacechars(t : txt;
                ntodelete : integer;
                a : string;
                n : integer); extern;


(* ---------------------------- txt_charatdot ------------------------------
 * Description:   Informs caller of the character held at "dot" in the array.
 *
 * Parameters:    txt t -- text object.
 * Returns:       Character at "dot".
 * Other Info:    Returns 0 if "dot" is at/beyond end of array.
 *
 *)
function txt_charatdot(t : txt) : char; extern;


(* ------------------------------ txt_charat -------------------------------
 * Description:   Informs caller of the character at a given index in the
 *                array.
 *
 * Parameters:    txt t -- text object
 *                txt_index i -- the index into the array.
 * Returns:       Character at given index in array.
 * Other Info:    Returns 0 if index is at/beyond end of array.
 *
 *)
function txt_charat(t : txt; i : txt_index) : char; extern;


(* ---------------------------- txt_charsatdot -----------------------------
 * Description:   Copies at most "n" characters from "dot" in the array into
 *                a supplied buffer.
 *
 * Parameters:    txt t -- text object
 *                char *buffer -- the buffer
 *                int *n -- maximum characters to copy.
 * Returns:       void.
 * Other Info:    If you are close to the end of the array, then "n" chars
 *                may not be available. In this case, chars up to the end of
 *                the array are copied, and *n is updated to report how many
 *                were copied.
 *
 *)
procedure txt_charsatdot(t : txt;
                buffer : string;
                var n : integer); extern;


(* -------------------------- txt_replaceatend -----------------------------
 * Description:   Deletes a specified number of characters from the end of
 *                the array and then inserts specified characters.
 *
 * Parameters:    txt t -- text object
 *                int ntodelete -- number of characters to delete
 *                char *s -- pointer to characters to insert
 *                int n -- number of characters to insert.
 * Returns:       void.
 * Other Info:    none.
 *
 *)
procedure txt_replaceatend(t : txt;
                ntodelete : integer;
                s : string;
                n : integer); extern;


(************************ Layout-dependent Operations. *********************)

(* 
 * These operations are provided specifically for the support of cursor-
 * key-driven editing.
 *)


(* ------------------------- txt_movevertical ------------------------------
 * Description:   Moves the "dot" by a specified number of textual lines,
 *                with the caret staying in the same horizontal position
 *                on the screen.
 *
 * Parameters:    txt t -- text object
 *                int by -- number of lines to move by
 *                int caretstill -- set to non-zero, if you want the text to
 *                                  move rather than the caret.
 * Returns:       void.
 * Other Info:    none.
 *
 *)
procedure txt_movevertical(t : txt;
                by : integer;
                caretstill : integer); extern;


(* --------------------------- txt_movehorizontal --------------------------
 * Description:   Move the caret (and "dot") "horizontally".
 *
 * Parameters:    txt t -- text object
 *                int by -- distance to move by.
 * Returns:       void.
 * Other Info:    This behaves like txt_movedot(), except that if "by" is
 *                positive and the end of the current text line is
 *                encountered, then the caret will continue to move to the
 *                right on the screen.
 *
 *)
procedure txt_movehorizontal(t : txt; by : integer); extern;


(* -------------------------- txt_visiblelinecount -------------------------
 * Description:   Gives the number of lines visible or partially visible
 *                on the display.
 *
 * Parameters:    txt t -- text object.
 * Returns:       Number of visible lines.
 * Other Info:    Takes into account current window size, font etc.
 *
 *)
function txt_visiblelinecount(t : txt) : integer; extern;


(* -------------------------- txt_visiblecolcount --------------------------
 * Description:   Gives the number of columns currently visible.
 *
 * Parameters:    txt t -- text object.
 * Returns:       Visible column count.
 * Other Info:    If a fixed pitch font is currently in use, then this gives
 *                the number of display columns, otherwise it makes a guess
 *                for "average" characters.
 *
 *)
function txt_visiblecolcount(t : txt) : integer; extern;


(*************************** Operations on Markers. ************************)

(* 
 * Markers are indices into the array. Once set, a marker will point to the
 * same character in the array regardless of insertions or deletions within
 * the array. If the character pointed at by the marker is deleted then the
 * marker will point to the next character. Markers never "fall off the end"
 * of the array, but stay at the top or bottom of it if that's where they
 * end up.
 *)
type txt_marker_ptr = ^txt_marker;
     txt_marker =
       record
         a, b : integer
       end;
(* Abstract record, uses of fields not public. *)


(* ---------------------------- txt_newmarker ------------------------------
 * Description:   Create a new "marker" in the text.
 *
 * Parameters:    txt t -- text object
 *                txt_marker *mark -- pointer to your text marker.
 * Returns:       void.
 * Other Info:    Marker itself is kept by the client of this function, but
 *                the text object retains a pointer to it. The client's
 *                marker is updated by the text object whenever necessary.
 *                Its initial value is the same as "dot". If the character
 *                at which a marker points is deleted, then the marker gets
 *                moved to the value of "dot" when the deletion occurred. If
 *                characters are inserted when the marker is at dot, the 
 *                marker stays with "dot".
 *
 *)
procedure txt_newmarker(t : txt; mark : txt_marker_ptr); extern;


(* -------------------------- txt_movemarker -------------------------------
 * Description:   Resets an existing marker.
 *
 * Parameters:    txt t  - text object
 *                txt_marker *mark -- the marker
 *                txt_index to -- place to move the marker to
 * Returns:       void.
 * Other Info:    The amrker must already point into this text object
 *
 *)
procedure txt_movemarker(t : txt;
                mark : txt_marker_ptr;
                _to : txt_index); extern;


(* ------------------------- txt_movedottomarker ---------------------------
 * Description:   Moves the "dot" to a given marker.
 *
 * Parameters:    txt t -- text object
 *                txt_marker *mark -- pointer to the marker
 * Returns:       void.
 * Other Info:    none.
 *
 *)
procedure txt_movedottomarker(t : txt; mark : txt_marker_ptr); extern;


(* ----------------------- txt_indexofmarker -------------------------------
 * Description:   Gives the current index into the array of a given marker
 *
 * Parameters:    txt t -- text object
 *                txt_marker *mark.
 * Returns:       Index of marker
 * Other Info:    none.
 *
 *)
function txt_indexofmarker(t : txt;
                mark : txt_marker_ptr) : txt_index; extern;


(* ---------------------------- txt_disposemarker --------------------------
 * Description:   Delete a marker from a text object.
 *
 * Parameters:    txt t -- text object
 *                txt_marker *mark -- the marker to be deleted.
 * Returns:       void.
 * Other Info:    WARNING: You should remember to dispose of a marker which
 *                logically ceases to exist, otherwise the text object will
 *                continue to update the location where it was!.
 *
 *)
procedure txt_disposemarker(t : txt; mark : txt_marker_ptr); extern;


(*********************** Operations on a selection. ************************)

(* The selection is a contiguous portion of the array which is
 * displayed highlighted.
 *)

(* ---------------------------- txt_selectset ------------------------------
 * Description:   Informs caller whether there is a selction made in a text.
 *
 * Parameters:    txt t -- text object.
 * Returns:       TRUE if there is a selection in this text.
 * Other Info:    none.
 *
 *)
function txt_selectset(t : txt) : boolean; extern;


(* --------------------------- txt_selectstart -----------------------------
 * Description:   Gives the index into the array of the start of the current
 *                selection.
 * 
 * Parameters:    txt t -- text object.
 * Returns:       Index of selection start.
 * Other Info:    none.
 *
 *)
function txt_selectstart(t : txt) : txt_index; extern;


(* --------------------------- txt_selectend -------------------------------
 * Description:   Gives the index into the array of the end of the current
 *                selection.
 *
 * Parameters:    txt t -- text object.
 * Returns:       Index of selection end.
 * Other Info:    none.
 *
 *)
function txt_selectend(t : txt) : txt_index; extern;


(* -------------------------- txt_setselect --------------------------------
 * Description:   Sets a selection in a given text, from "start" to "end"
 *
 * Parameters:    txt t -- text object
 *                txt_index start -- array index of start of selection
 *                txt_index end -- array index of end of selection.
 *
 * Returns:       void.
 * Other Info:    If "start" >= "end" then the selection will be unset.
 *
 *)
procedure txt_setselect(t : txt; start, _end : txt_index); extern;


(*************************** Input from the user ***************************)

(* Characters entered into the keyboard, and various mouse events, are
buffered up by the text object for use by the client. *)

type txt_eventcode = integer;


(* ------------------------------- txt_get ---------------------------------
 * Description:   Gives the next user event code to the caller.
 *
 * Parameters:    txt t -- text object.
 * Returns:       The event code.
 * Other Info:    The returned code can be ASCII, or various other (system-
 *                specific) values for function keys etc.
 *
 *)
function txt_get(t : txt) : txt_eventcode; extern;


(* ------------------------------- txt_queue -------------------------------
 * Description:   Informs caller of how many event codes are currently
 *                buffered for a given text.
 *
 * Parameters:    txt t -- text object.
 * Returns:       No. of buffered event codes.
 * Other Info:    none.
 *
 *)
function txt_queue(t : txt) : integer; extern;  


(* ----------------------------- txt_unget ---------------------------------
 * Description:   Puts an event code back on the front of the event queue
 *                for a given text.
 *
 * Parameters:    txt t -- text object
 *                txt_eventcode code -- the event code.
 * Returns:       void.
 * Other Info:    none.
 *
 *)
procedure txt_unget(t : txt; code : txt_eventcode); extern;


(****************************** Mouse events *******************************)

const
  txt_MSELECT = $01000000;
  txt_MEXTEND = $02000000;
  txt_MSELOLD = $04000000;
  txt_MEXTOLD = $08000000;
  txt_MEXACT = $10000000;
  txt_EXTRACODE = $40000000;
  txt_MOUSECODE = unot($7fffffff);

type txt_mouseeventflag = integer; (* used as a set *)

(* A mouse event occurs when the mouse is pointing in the text object and a
 * button is pressed or released, or the mouse moves while any button is
 * depressed. A mouse event will result in Get producing an EventCode with
 * bit 31 set, bits 24..28 as a mouseeventflags value, and the rest of the
 * word containing an index value.
 *
 * The index shows where in the visible representation of the array the mouse
 * event happened. If all three index bytes are 255 then the event happened
 * outside the window. The mouseeventflags show what button transitions
 * occurred:
 *    MSELECT -- select's new value
 *    MEXTEND -- extend's new value
 *    MSELOLD -- select's old value
 *    MEXTOLD -- extend's old value
 *    MEXACT -- the event is in exactly the same place as the last one
 * The byte gives the values of the select and extend buttons, 1 for
 * depressed and 0 for not depressed. It gives their previous values,
 * allowing transitions to be detected. It says if the position of the mouse
 * is exactly the same as for the last event, so that multiple clicks may be
 * detected. No assumptions should be made concerning the relationship of
 * these bits to the last mouse event sent to the programmer, as polling
 * delays etc. could cause any combinations to happen. 
 *
 * If txt_EXTRACODE is set then the identity of the event is not defined
 * by this interface. This is used for any expansion. Clients of this
 * interface which receive such events that they do not recognise, should
 * ignore them without reporting an error. 
 *
 * The menu button on the mouse is not transmitted through this interface,
 * but caught elsewhere.
 * 
 *)
type txt_event_proc = ^procedure event_proc(t : txt; handle : pointer);


(* ---------------------------- txt_eventhandler ---------------------------
 * Description:   Register an eventhandler function for a given text, 
 *                which will be called whenever there is a value ready which
 *                can be picked up by txt_get().
 *
 * Parameters:    txt t -- text object
 *                txt_event_proc func -- event handler function
 *                void *handle -- caller-defined handle to be passed to func.
 * Returns:       void.
 * Other Info:    If func==0 then no function is registered.
 *
 *)
procedure txt_eventhandler(t : txt;
                p : txt_event_proc;
                handle : pointer); extern;


(* -------------------------- txt_readeventhandler -------------------------
 * Description:   Informs caller of the currently registered eventhandler
 *                function associated with a given text, and the handle which
 *                is passed to it.
 *
 * Parameters:    txt t -- text object
 *                txt_event_proc *func -- returned pointer to handler func
 *                void **handle -- returned pointer to handle.
 * Returns:       void.
 * Other Info:    none.
 *
 *)
procedure txt_readeventhandler(t : txt;
                var func : txt_event_proc;
                var handle : pointer); extern;


(******************* Direct Access to the array of characters **************)

(* ---------------------------- txt_arrayseg -------------------------------
 * Description:   Gives a direct pointer into the memory used to hold the
 *                characters in a text.
 *
 * Parameters:    txt t -- text object
 *                txt_index at -- index into the text
 *                char **a -- *a will point at the character whose index
 *                            in the text is "at"
 *                int *n -- *n == no. of contiguous bytes after "at"
 * Returns:       void.
 * Other Info:    It is permissible for the caller of this function to change
 *                the characters pointed at by *a, provided that a redsiplay
 *                is prompted (using setcharoptions).
 *
 *)
procedure txt_arrayseg(t : txt;
                at : txt_index;
                var a : string;
                var n : integer); extern;


(******************************* System hook *******************************)


(* ---------------------------- txt_syshandle ------------------------------
 * Description:   Obtains a system_dependent handle on the object underlying
 *                a text.
 *
 * Parameters:    txt t -- text object.
 * Returns:       System-dependent handle for the given text.
 * Other Info:    none.
 *
 *)
function txt_syshandle(t : txt) : integer; extern;


(* ---------------------------------- txt_init -----------------------------
 * Description:   Initialise the txt module of the library
 *
 * Parameters:    void.
 * Returns:       void.
 * Other Info:    none.
 *
 *)
procedure txt_init; extern;

# endif

(* end txt.h *)
