The editable object in AES
==========================

Formating: 	Tabulator width 5

Andreas Kromke
27.1.98

Last change:
9.5.98

English translation: Peter West, April 99


How do I recognise whether the functions are present?
=====================================================

The editable object is available from MagiC 5.20 onwards. As it is 
implemented as part of the shared library (SLB or SharedLib), 
one only needs to open the library with:

	Slbopen("EDITOBJC.SLB", NULL, 0L, &slb, &slbexec);

(->SHARELIB.TXT).

The library installs a new AES object-type G_EDIT (37)
as well as the AES functions 210..217.


Overview of using a G_EDIT object
=================================

The example code for MGEDIT is the easiest way to show how the
new object type can be used:

- In the RSC file a white G_BOX, without border, is included
- In the program the SharedLib is loaded
- For each G_EDIT object:

  - Create text buffer.
  - Create editable object with edit_create().
  - Alter object type in G_EDIT and place ob_spec on the editable object.
  - Allocate the text buffer with edit_set_buf().
  - If necessary alter the settings of the editable object with 
    edit_set_xxx().
  - Open editable object with edit_open().
  - Only then draw the tree with objc_draw().

- In order to pass keyboard codes and mouse clicks to the editable object,
  one has to call edit_evnt(). The syntax is fully analogous to
  wdlg_evnt(), fslx_evnt() and fnts_evnt().
- When closing, the edit field must be closed with edit_close(), after
  which the memory reserved for the edit field is released again with 
  edit_delete(). No further objc_draw() may be performed! If necessary, 
  set the object type on G_BOX once more.


Which keyboard codes are evaluated by G_EDIT?
=============================================

Cursor					Cursor movements
Ctrl-Cursor-up/down    		Scrolling
Ctrl-Cursor-left/right  		Move cursor word by word
Shift-Cursor-left/right  	Cursor to start/end of line
Esc						Nothing (yet)
Insert					Nothing (yet)
Shift-Insert				Nothing (yet)
Backspace					Delete character left of cursor
Delete					Delete character right of cursor
Ctrl-Delete				Nothing (yet)
ClrHome					Cursor to start of text
End (MF-2)
End (Mac)
Shift-ClrHome				End of text
PgUp (Mac)
Shift-Cursor-up  			Cursor one page up
PgDn (Mac)
Shift-Cursor-down  			Cursor one page down
^A						Select all (from 27.1.98 on)
^C						Copy block to clipboard (leave it in text)
^X						Cut block to clipboard (delete it from text)
^V						Insert clipboard contents at cursor position


What do the system calls look like?
===================================

Create editable object
----------------------

Prototype:         
		void * edit_create( void );

Call:
		contrl[0] = 210		Function number
		contrl[1] = 0			Entries in intin
		contrl[2] = 0			Entries in intout
		contrl[3] = 0			Entries in addrin
		contrl[4] = 1			Entries in addrout

		addrout[0] = editob		Returns a descriptor for any further
							actions, or NULL if an error has 
							occurred (not enough memory).
							The descriptor must be entered as
							ob_spec into the object.

The corresponding descriptor is created (memory is reserved), but the 
editor has not been opened yet. One can now alter several settings with
edit_set(). The default settings are:

	System font, 10 pt
	Black on white
	No line wrap
	Tabulator width 64 pixels


Allocate text buffer
--------------------

Prototype:
		void edit_set_buf( OBJECT *tree, WORD obj,
						char *buf, LONG buflen );

Call:
		contrl[0] = 217		Function number for edit_set()
		contrl[1] = 4			Entries in intin
		contrl[2] = 0			Entries in intout
		contrl[3] = 2			Entries in addrin
		contrl[4] = 0			Entries in addrout

		intin[0]	 = obj		Object number
		intin[1]	 = 0			Subcode for edit_set
		intin[2,3] = buflen		Length of text buffer inclusive
							of closing Nullbyte.

		addrin[0] = tree		Object tree
		addrin[1] = buf		Text buffer. The text is present in
							DOS format with CR/LF as line-end
							identifier and is terminated by a  
							Nullbyte.

The buffer is allocated to the text object, the number of lines are 
determined. The cursor is set to the start of the text.
This call clears the Dirty flag.


Open editable object
--------------------

Prototype:
		WORD edit_open(
			OBJECT *tree,
			WORD obj
			);

Call:
		contrl[0] = 211		Function number
		contrl[1] = 1			Entries in intin
		contrl[2] = 1			Entries in intout
		contrl[3] = 1			Entries in addrin
		contrl[4] = 0			Entries in addrout

		addrin[0] = tree		RSC-tree of object
		intin[0]  = obj		Object number

		intout[0] = err		1, if OK

The number of lines and columns of text visible for the object size is 
calculated, and corresponding pointers are created. Memory is then 
requested for it.


Close editable object
---------------------

Prototype:
		void edit_close(
			OBJECT *tree, WORD obj,
			);

Call:
		contrl[0] = 212		Function number
		contrl[1] = 1			Entries in intin
		contrl[2] = 0			Entries in intout
		contrl[3] = 1			Entries in addrin
		contrl[4] = 0			Entries in addrout

		addrin[0] = tree		RSC-tree of object
		intin[0]  = obj		Object number

The object-size-dependent management structures are closed and the  
memory used is released. The descriptor itself, though, is preserved.
Text management is now no longer possible.


Remove editable object
----------------------

Prototype:
		void edit_delete(
			void *editinfo,
			);

Call:
		contrl[0] = 213		Function number
		contrl[1] = 0			Entries in intin
		contrl[2] = 0			Entries in intout
		contrl[3] = 1			Entries in addrin
		contrl[4] = 0			Entries in addrout

		addrin[0] = editinfo	Pointer of edit_create()

The descriptor is released. If the object is to be used further then the 
object type has to be placed back on G_BOX.


Cursor on/off
-------------

Prototype:
		void edit_cursor(
			OBJECT *tree, WORD obj,
			WORD whdl,
			WORD show
			);

Call:
		contrl[0] = 214		Function number
		contrl[1] = 3			Entries in intin
		contrl[2] = 1			Entries in intout
		contrl[3] = 1			Entries in addrin
		contrl[4] = 0			Entries in addrout

		addrin[0] = tree		RSC-tree of object
		intin[0]  = obj		Object number
		intin[1]  = whdl		Window handle or -1
		intin[2]  = show		

The cursor is switched on (show == 1), switched off (show == 0) or 
examined (show == -1).
The call can be nested. Return value is the cursor-off counter.


Service editable object
-----------------------

Prototype:
		WORD edit_evnt(
			OBJECT *tree,
			WORD obj,
			WORD whdl,
			EVNT *events,
			LONG *errcode
			);

Call:
		contrl[0] = 215		Function number
		contrl[1] = 2			Entries in intin
		contrl[2] = 3			Entries in intout
		contrl[3] = 2			Entries in addrin
		contrl[4] = 0			Entries in addrout

		intin[0]  = obj		Object number
		intin[1]  = whdl		Window handle or -1
		addrin[0] = tree		RSC-tree of object
		addrin[1] = events		EVENT structure as for wdlg_evnt(),
							fnts_evnt. The events are serviced by 
							the dialog if they are intended for the 
							associated window.

		intout[0]				Is 0 if the passed events were not all
							serviced, say because the text buffer 
							was full or an error arose.
		intout[1,2]			Error code (-200 = text buffer full)

Events, i.e. mouse clicks and key presses, are forwarded to the editable 
object and serviced by it if appropriate. When an event has been serviced, 
the corresponding bit in the EVENT structure is cleared.
The error code <errcode> is present only from version 7 of the SLB onwards; 
the binding in MT_AES ensures that old SLB versions always return Nulls. 
Vice versa, the new SLB versions recognise via contrl[2] whether an error 
code was requested.


Examine settings: Text buffer
-----------------------------

Prototype:
		WORD edit_get_buf(
			OBJECT *tree,
			WORD obj,
			char **buf, LONG *buflen,
			LONG *txtlen,
			);

Call:
		contrl[0] = 216		Function number for edit_get()
		contrl[1] = 2			Entries in intin
		contrl[2] = 5			Entries in intout
		contrl[3] = 1			Entries in addrin
		contrl[4] = 1			Entries in addrout

		intin[0]  = obj		Object number
		intin[1]  = 0			Subcode for function
		addrin[0] = tree		RSC-tree of object

		intout[0]				0 for error, else 1
		intout[1,2]=buflen		Buffer length
		intout[3,4]=txtlen		Current text length without EOS
		addrout[0]= buf		Address of buffer



Examine settings: Formating
---------------------------

Prototype:
		WORD edit_get_format(
			OBJECT *tree,
			WORD obj,
			WORD *tabwidth, WORD *autowrap
			);

Call:
		contrl[0] = 216		Function number for edit_get()
		contrl[1] = 2			Entries in intin
		contrl[2] = 3			Entries in intout
		contrl[3] = 1			Entries in addrin
		contrl[4] = 0			Entries in addrout

		intin[0]  = obj		Object number
		intin[1]  = 1			Subcode for function
		addrin[0] = tree		RSC-tree of object

		intout[0]				0 for error, else 1
		intout[1]	= tabwidth	Tabulator width
		intout[2]	= autowrap	> 0: Pixel width for auto line wrap
							     (generally == object width)
							= 0: No wrapping, but horiz. scrolling


Examine settings: Colours
-------------------------

Prototype:
		WORD edit_get_colour(
			OBJECT *tree,
			WORD obj,
			WORD *tcolour, WORD *bcolour
			);

Call:
		contrl[0] = 216		Function number for edit_get()
		contrl[1] = 2			Entries in intin
		contrl[2] = 3			Entries in intout
		contrl[3] = 1			Entries in addrin
		contrl[4] = 0			Entries in addrout

		intin[0]  = obj		Object number
		intin[1]  = 2			Subcode for function
		addrin[0] = tree		RSC-tree of object
		intout[0]				0 for error, else 1
		intout[1]	= tcolour		Text colour
		intout[2]	= bcolour		Background colour


Examine settings: Font
----------------------

Prototype:
		WORD edit_get_font(
			OBJECT *tree,
			WORD obj,
			WORD *fontID, WORD *fontH, WORD *fontPix, WORD *mono,
			);

Call:
		contrl[0] = 216		Function number for edit_get()
		contrl[1] = 2			Entries in intin
		contrl[2] = 5			Entries in intout
		contrl[3] = 1			Entries in addrin
		contrl[4] = 0			Entries in addrout

		intin[0]  = obj		Object number
		intin[1]  = 3			Subcode for function
		addrin[0] = tree		RSC-tree of object

		intout[0]				0 for error, else 1
		intout[1]	= fontID		Font-ID
		intout[2]	= fontH		Height for vst_point()
		intout[3]	= mono		Flag for equidistant font
		intout[4] = fontPix		0=points, 1=pixels (from 3.5.98 on)

fontPix is only available from version 8 of the SLB. MT_AES ensures that 
old SLB versionen always retrun a Null. Vice versa, new SLB versions 
recognise with contrl[2] whether fontPix was requested.


Examine settings: Absolute cursor position
------------------------------------------

Prototype:
		WORD edit_get_cursor(
			OBJECT *tree,
			WORD obj,
			char **cursorpos
			);

Call:
		contrl[0] = 216		Function number for edit_get()
		contrl[1] = 2			Entries in intin
		contrl[2] = 1			Entries in intout
		contrl[3] = 1			Entries in addrin
		contrl[4] = 1			Entries in addrout

		intin[0]  = obj		Object number
		intin[1]  = 4			Subcode for function
		addrin[0] = tree		RSC-tree of object

		intout[0]	= err		0 (error) or 1 (OK)
		addrout[0]= cursorpos	Cursor position in text


Examine settings: Dirty flag
----------------------------

Prototype:
		WORD edit_get_dirty(
			OBJECT *tree,
			WORD obj
			);

Call:
		contrl[0] = 216		Function number for edit_get()
		contrl[1] = 2			Entries in intin
		contrl[2] = 1			Entries in intout
		contrl[3] = 1			Entries in addrin
		contrl[4] = 0			Entries in addrout

		intin[0]  = obj		Object number
		intin[1]  = 7			Subcode for function
		addrin[0] = tree		RSC-tree of object

		intout[0]	= dirty		0 or 1

With this one can ascertain whether the text was altered in the meantime.
The flag can be cleared again with edit_set_dirty() or edit_set_buf().


Examine settings: Selected region
---------------------------------

Prototype:
		WORD edit_get_sel(
			OBJECT *tree,
			WORD obj,
			char **bsel, char **esel
			);

Call:
		contrl[0] = 216		Function number for edit_get()
		contrl[1] = 2			Entries in intin
		contrl[2] = 0			Entries in intout
		contrl[3] = 1			Entries in addrin
		contrl[4] = 2			Entries in addrout

		intin[0]  = obj		Object number
		intin[1]  = 8			Subcode for function
		addrin[0] = tree		RSC-tree of object

		addrout[0]= bsel		Start of selected region
		addrout[1]= esel		After the end of the selected region

If no region is selected then bsel == NULL.


Examine settings: Scroll information
------------------------------------

Prototype:
		void edit_get_scrollinfo(
			OBJECT *tree,
			WORD obj,
			LONG *nlines, LONG *yscroll,
			WORD *yvis, WORD *yval,
			WORD *ncols, WORD *xscroll, WORD *xvis
			);

Call:
		contrl[0] = 216		Function number for edit_get()
		contrl[1] = 2			Entries in intin
		contrl[2] = 10			Entries in intout
		contrl[3] = 1			Entries in addrin
		contrl[4] = 0			Entries in addrout

		intin[0]  = obj		Object number
		intin[1]  = 9			Subcode for function
		addrin[0] = tree		RSC-tree of object

		intout[0]				Undefined
		intout[1,2]= nlines		Number of lines in text
		intout[3,4]= yscroll	First visible line
		intout[5]	= yvis		Number of max. visible lines
		intout[6]	= yval		Number of currently visible lines
		intout[7]	= ncols		Number of columns, or -1 (unknown)
		intout[8]	= xscroll		Horiz. scroll offset in pixels
		intout[9]	= xvis		Number of visible columns (in pixels)

This information is required in order to set the horizontal and vertical 
scroll bars. As the editable object would have to make a vq_extend() for 
each individual line, actually at each alteration of a line, the number 
of columns is currently not defined and the call returns -1.
MGEDIT here simply assumes a fixed width, in the same way as other programs 
e.g. VIEW.PRG and PC.PRG do as well.
<yval> is always smaller or equal to <yvis>. If the text has fewer lines 
that <yvis>, then <yval> is always smaller.


Alter settings: Text buffer
---------------------------

Prototype:
		void edit_set_buf(
			OBJECT *tree, WORD obj,
			char *buf, LONG buflen
			);

As this call is always required, it is specified above.
So see above.


Alter settings: Formating
-------------------------

Prototype:
		void edit_set_format(
			OBJECT *tree, WORD obj,
			WORD tabwidth, WORD autowrap
			);

Call:
		contrl[0] = 217		Function number for edit_set()
		contrl[1] = 4			Entries in intin
		contrl[2] = 0			Entries in intout
		contrl[3] = 1			Entries in addrin
		contrl[4] = 0			Entries in addrout

		intin[0]	= obj		Object number
		intin[1]	= 1			Subcode for edit_set
		intin[2]	= tabwidth	-1 or tabulator width in pixels
		intin[3]	= autowrap	-1: Do not change
							> 0: Pixel width for auto line wrap
							     (generally == object width)
							= 0: No wrapping, but horiz. scrolling

		addrin[0] = tree		Object tree

If one of the two attributes is to remain unchanged then -1 can be passed.
If the editable object was opened previously then one should generally 
trigger a redraw when changing one of the attributes. From version 9 of 
the SLB the number of lines is recalculated when the <autowrap> setting 
is altered. In older versions this only happens with edit_set_buf().


Alter settings: Colours
-----------------------

Prototype:
		void edit_set_colour(
			OBJECT *tree, WORD obj,
			WORD tcolour, WORD bcolour
			);

Call:
		contrl[0] = 217		Function number for edit_set()
		contrl[1] = 4			Entries in intin
		contrl[2] = 0			Entries in intout
		contrl[3] = 1			Entries in addrin
		contrl[4] = 0			Entries in addrout

		intin[0]	= obj		Object number
		intin[1]	= 2			Subcode for edit_set
		intin[2]	= tcolour		-1 or text colour
		intin[3]	= bcolour		-1 or background colour

		addrin[0] = tree		Object tree

If one of the two attributes is to remain unchanged then -1 can be passed.
If the editable object was opened previously, then one should generally 
trigger a redraw when changing one of the attributes.


Alter settings: Font
--------------------

Prototype:
		void edit_set_font(
			OBJECT *tree, WORD obj,
			WORD fontID, WORD fontH, WORD fontPix, WORD mono
			);

Call:
		contrl[0] = 217		Function number for edit_set()
		contrl[1] = 6			Entries in intin
		contrl[2] = 0			Entries in intout
		contrl[3] = 1			Entries in addrin
		contrl[4] = 0			Entries in addrout

		intin[0]	= obj		Object number
		intin[1]	= 3			Subcode for edit_set
		intin[2]	= fontID		Font-ID
		intin[3]	= fontH		Character height in "points"
		intin[4]	= mono		"Equidistant" flag
		intin[5]	= fontPix		0=points, 1=pixels (from 3.5.98 on)

		addrin[0] = tree		Object tree

If the editable object was opened previously, then one should generally 
trigger a redraw when changing the font.
The "mono" flag is required to give the editable object the possibility to 
handle equidistant fonts (mono == 1) appreciably faster that proportional
fonts (mono == 0).
fontPix is only available from version 8 of the SLB onwards. Older versions 
always assume fontPix=0, i.e. exclusiely use vst_point() for setting the 
character height. The SLB recognises from contrl[1] whether fontPix was 
passed. If not then 0 will be asumed.


Alter settings: Absolute positioning of cursor
----------------------------------------------

Prototype:
		void edit_set_cursor(
			OBJECT *tree, WORD obj,
			char *cursorpos
			);

Call:
		contrl[0] = 217		Function number for edit_set()
		contrl[1] = 2			Entries in intin
		contrl[2] = 0			Entries in intout
		contrl[3] = 1			Entries in addrin
		contrl[4] = 0			Entries in addrout

		intin[0]	= obj		Object number
		intin[1]	= 4			Subcode for edit_set

		addrin[0] = tree		Object tree
		addrin[1] = cursorpos	Absolute cursor position


Alter settings: Object size
---------------------------

Prototype:
		WORD edit_resized(
			OBJECT *tree,
			WORD obj,
			WORD *oldrh, WORD *newrh
			);

Call:
		contrl[0] = 217		Function number for edit_set()
		contrl[1] = 2			Entries in intin
		contrl[2] = 3			Entries in intout
		contrl[3] = 1			Entries in addrin
		contrl[4] = 0			Entries in addrout

		intin[0]  = obj		Object number
		intin[1]  = 6			Subcode for function

		addrin[0] = tree		RSC-tree of object

		intout[0]	= err		1 (OK) or 0 (error)
		intout[1]	= *oldrh		Old net height of object
		intout[2]	= *newrh		New net height of object

For changes of the object size the editable object must release and reserve 
memory. Thus it is possible that in extreme circumstances the operation 
fails due to a shortage of memory. In that case the return value is 0.
So that the calling program can execute a correct redraw, the previous and 
new actual height is returned. In fact it means here the number of visible 
lines multiplied by the line height, i.e. the object height without the 
unused bottom white border.


Alter settings: Dirty flag
--------------------------

Prototype:
		void edit_set_dirty(
			OBJECT *tree, WORD obj,
			WORD dirty
			);

Call:
		contrl[0] = 217		Function number for edit_get()
		contrl[1] = 3			Entries in intin
		contrl[2] = 0			Entries in intout
		contrl[3] = 1			Entries in addrin
		contrl[4] = 0			Entries in addrout

		intin[0]  = obj		Object number
		intin[1]  = 7			Subcode for function
		intin[2]	= dirty		0 or 1
		addrin[0] = tree		RSC-tree of object

With this one can clear the Dirty flag when the text has been saved.


Alter settings: Scroll positions
--------------------------------

Prototype:
		WORD edit_scroll(
			OBJECT *tree, WORD obj,
			WORD whdl,
			LONG yscroll,
			WORD xscroll
			);

Call:
		contrl[0] = 217		Function number for edit_get()
		contrl[1] = 6			Entries in intin
		contrl[2] = 1			Entries in intout
		contrl[3] = 1			Entries in addrin
		contrl[4] = 0			Entries in addrout

		intin[0]  = obj		Object number
		intin[1]  = 9			Subcode for function
		intin[2]	= whdl		Window handle or -1
		intin[3,4]= yscroll		Vertical scroll offset in lines
		intin[5]	= xscroll		Horizontal scroll offset in pixels
		addrin[0] = tree		RSC-tree of object

		intout[0]	= err		1 (OK) or 0 (Error)

With this one scrolls horizontally and vertically absolutely. This call 
is required when a scroll bar or arrow has been clicked on.
The window handle is required so that the rectangle list is taken into 
consideration during scrolling.
An error code will be returned if the number of lines has been exceeded.
