[Back to ENTRY SWAG index] [Back to Main SWAG index] [Original]

    {
    Attached is a very simple single line editor, possibly for inclusion in the
    SWAG archive. It is written using Turbo/Borland Pascal object oriented
    extensions so should, in theory, be easy to use and modify :)

    It supports the following keystrokes:

            Backspace           : Delete previous character
            Ctrl Backspace      : Delete string upto cursor
            Delete              : Delete next character
            Ctrl Delete         : Delete string after cursor
            Home                : Start of string
            End                 : End of string
            Left arrow          : Left one character
            Right arrow         : Right one character
            Ctrl+Left arrow     : Left one word
            Ctrl+Right arrow    : Right one word

    It is setup by passing the coordinates where the field should be
    displayed, the maximum length of the field and the character to use
    for padding the field.

    It is then called, passing in an initial value for the field which is
    then amended, returning true if the enter key is pressed and false
    if escape key is pressed.
    }
    UNIT Edit;

    INTERFACE

    TYPE
    	TextLine	= Object
    		Details		: String;
    		CPos			: Byte;
    		XPos			: Byte;
    		YPos			: Byte;
    		MaxLen		: Byte;
    		PaddingChar	: Char;

    		{ ********************************************************}
    		{ PUBLIC METHODS }

    		{
    			SetupLimits - Set up initial values to be used:
    				X		: X position for the field
    				Y		: Y position for the field
    				Max		: Max length of the field
    				PadChar	: Character to use for padding the line
    		}
    		CONSTRUCTOR SetupLimits
    			(
    			X		: Byte;
    			Y		: Byte;
    			Max		: Byte;
    			PadChar	: Char
    			);

    		{
    			EditLine - Edit the line.
    				Supports
    					Backspace			: Delete previous character
    					Ctrl Backspace		: Delete string upto cursor
    					Delete			: Delete next character
    					Ctrl Delete		: Delete string after cursor
    					Home				: Start of string
    					End				: End of string
    					Left arrow		: Left one character
    					Right arrow		: Right one character
    					Ctrl+Left arrow	: Left one word
    					Ctrl+Right arrow	: Right one word

    				StrEntered	: String to use. Set with start value then
    							  returns value entered.
    				Function returns true if enter pressed, false if escape
    				pressed.
    		}
    		FUNCTION EditLine (VAR StrEntered	: String)	: Boolean;

    		{ ********************************************************}
    		{ PRIVATE METHODS - Do not call }

    		PROCEDURE DisplayLine;
    		FUNCTION AddChar (Ch	: Char)	: Boolean;
    		FUNCTION DeletePrevChar	: Boolean;
    		FUNCTION DeleteNextChar	: Boolean;

    		{ ********************************************************}

    	END;

    IMPLEMENTATION

    USES
    	Crt, Dos;

    CONST
    	End_Key		= #79;
    	Left			= #75;
    	Right		= #77;
    	HomeKey		= #71;
    	Backspace		= #8;
    	CtrlBackspace	= #127;
    	DeleteKey		= #83;
    	CtrlDelete	= #6;
    	CarrRet		= #13;
    	Escape		= #27;
    	CtrlLeft		= #115;
    	CtrlRight		= #116;

    CONSTRUCTOR TextLine.SetupLimits
    	(
    	X		: Byte;
    	Y		: Byte;
    	Max		: Byte;
    	PadChar	: Char
    	);

    BEGIN
    	CPos			:= 1;
    	XPos			:= X;
    	YPos			:= Y;
    	MaxLen		:= Max;
    	PaddingChar	:= PadChar;
    END; { SetupLimits }

    PROCEDURE TextLine.DisplayLine;

    VAR
    	Index	: Byte;

    BEGIN
    	GotoXY (XPos, YPos);
    	Write (Details);
    	FOR Index	:= 1 TO MaxLen - Length (Details) DO
    		Write (PaddingChar);
    	GotoXY (XPos+CPos, YPos);
    END; { DisplayLine }

    FUNCTION TextLine.AddChar (Ch	: Char)	: Boolean;

    VAR
    	AddedChar	: Boolean;

    BEGIN
    	AddedChar	:= TRUE;

    	IF (CPos = Length (Details)) THEN
    	BEGIN
    		IF Length (Details) < MaxLen THEN
    		BEGIN
    			Details	:= Concat (Details, Ch);
    			Inc (CPos);
    		END { If }
    		ELSE
    			AddedChar	:= FALSE;
    	END { If }
    	ELSE
    	BEGIN
    		Inc (CPos);
    		Insert (Ch, Details, CPos);
    		IF Length (Details) > MaxLen THEN
    			Delete (Details, Length(Details), 1);
    	END; { Else }

    	AddChar	:= AddedChar;
    END; { AddChar }

    FUNCTION TextLine.DeletePrevChar	: Boolean;

    VAR
    	DeletedChar	: Boolean;

    BEGIN
    	DeletedChar	:= TRUE;

    	IF CPos < 1 THEN
    		DeletedChar	:= FALSE
    	ELSE

    	IF CPos = Length (Details) THEN
    	BEGIN
    		Delete (Details, CPos, 1);
    		Dec (CPos);
    	END { If }
    	ELSE

    	BEGIN
    		Delete (Details, CPos, 1);
    		Dec (CPos);
    	END; { Else }

    	DeletePrevChar	:= DeletedChar;
    END; { DeletePrevChar }

    FUNCTION TextLine.DeleteNextChar	: Boolean;

    VAR
    	DeletedChar	: Boolean;

    BEGIN
    	DeletedChar	:= TRUE;

    	IF (CPos >= Length (Details)) THEN
    		DeletedChar	:= FALSE
    	ELSE
    		Delete (Details, CPos+1, 1);

    	DeleteNextChar	:= DeletedChar;
    END; { DeleteNextChar }

    FUNCTION Textline.EditLine (VAR StrEntered	: String)	: Boolean;

    VAR
    	Ch		: Char;
    	Changed	: Boolean;
    	Accepted	: Boolean;
    	Finished	: Boolean;

    BEGIN
    	Accepted		:= TRUE;
    	Finished		:= FALSE;

    	{ If they send in a string that is too large then trim it }
    	IF Length (StrEntered) > MaxLen THEN
    		Delete (StrEntered, MaxLen+1, Length (StrEntered));

    	Details		:= StrEntered;
    	CPos			:= Length (Details);

    	DisplayLine;

    	REPEAT
    		Ch		:= Readkey;
    		Changed	:= FALSE;

    		IF Ch = #0 THEN
    		BEGIN
    			Ch	:= Readkey;
    			CASE Ch OF
    		     	End_Key	: BEGIN
    					CPos		:= Length (Details);
    					Changed	:= TRUE;
    				END; { End_Key }

    		     	HomeKey	: BEGIN
    					CPos		:= 0;
    					Changed	:= TRUE;
    				END; { HomeKey }

    		     	Left	: BEGIN
    					IF CPos > 0 THEN
    					BEGIN
    						Dec (CPos);
    						Changed	:= TRUE;
    					END; { If }
    				END; { Left }

    		     	Right	: BEGIN
    					IF CPos < Length (Details) THEN
    					BEGIN
    						Inc (CPos);
    						Changed	:= TRUE;
    					END; { If }
    				END; { Right }

    				CtrlLeft	: BEGIN
    					IF (CPos > 0) THEN
    						Dec (CPos);
    					WHILE (CPos > 0) AND (Details [CPos] <> ' ') DO
    						Dec (CPos);
    					Changed	:= TRUE;
    				END; { CtrlLeft }

    				CtrlRight	: BEGIN
    					IF (CPos < Length(Details)) THEN
    						Inc (CPos);
    					WHILE (CPos < Length(Details)) AND (Details [CPos] <> ' ') DO
    						Inc (CPos);
    					Changed	:= TRUE;
    				END; { CtrlRight }

    				CtrlDelete	: BEGIN
    					Delete (Details, CPos+1, Length (Details));
    					Changed	:= TRUE;
    				END; { CtrlDelete }

    				DeleteKey	: BEGIN
    					Changed	:= DeleteNextChar;
    				END; { DeleteKey }
    			END; { Case }
    		END { If }
    		ELSE

    		BEGIN
    			CASE Ch OF
    				CtrlBackspace	: BEGIN
    					Delete (Details, 1, CPos);
    					CPos		:= 0;
    					Changed	:= TRUE;
    				END; { CtrlBackspace }

    				Backspace	: BEGIN
    					Changed	:= DeletePrevChar;
    				END; { Backspace }

    		     	CarrRet	: Finished	:= TRUE;

    		     	Escape	: BEGIN
    							Finished	:= TRUE;
    							Accepted	:= FALSE;
    				END; { Escape }

    				' '..'}'	: BEGIN
    					Changed	:= AddChar (Ch);
    				END; { Ord (' ') }
    			END; { Case }
    		END; { Else }

    		IF Changed THEN
    			DisplayLine;
    	UNTIL Finished;

    	IF Accepted THEN
    		StrEntered	:= Details;
    	EditLine	:= Accepted;
    END; { EditLine }

    BEGIN
    END.

[Back to ENTRY SWAG index] [Back to Main SWAG index] [Original]