  ------------------------------------------------------------------------
  LineEdit unit                             by Sebastian Groeneveld (2000)
  ------------------------------------------------------------------------


Features
========

- Maximum string length and maximum edit length may differ
- Default text (start value) can be specified
- Function returns last key press
- Optional callback routine address can be specified (see below)
- Edit field is padded using FLEXCHR$
- Insert/Overwrite mode supported
- Ctrl-left and Ctrl-right for quick cursor movement
- Ctrl-home and Ctrl-end for quick erase
- Variable initial cursor placement
- Release timeslices when idle in Windows DOS box


Usage
=====

ReturnKey = LineEdit( Row%, Col%, StrLen%, EditLen%, Txt$, _
					  Idle_CallBack???, KeyPress_CallBack??? )

Parameters:
	Row%      = Text row to place edit field (normally between 1 and 25)
    Col%      = Text column to place edit field (normally between 1 and 80)
    StrLen%   = Maximum string length allowed
    EditLen%  = Width of edit field
    Txt$	  = Upon function call it contains the default text to be
    		    displayed, and after return it contains the new text

	Idle_CallBack     = 32-bit code pointer to a callback routine
    KeyPress_CallBack = 32-bit code pointer to a callback routine

Return:
	ReturnKey = Key that caused the routine to exit (Return or Escape)


Remarks
=======

When the user presses Escape (or the callback routine returns a non-zero
value to simulate the Escape key) the text in the edit field is changed
back to its original (default) value and the routine is exited.

The ASCII characters 0-31 are interpreted in the edit field, so Alt+Key8
would be processed as if backspace was pressed, and Alt+Key1 (smiley face)
would do nothing at all.

There is a public variable declared as:
    DIM LineEdit_cursor  AS SHARED INTEGER

This variable controls the initial cursor placement. If this variable is
set to zero, the cursor is placed at the end of the string. So in order to
put the cursor on the first position, set LineEdit_cursor to 1. When the
LineEdit routine is exited, the current cursor position is saved in this
variable.


Idle Callback
=============

The idle callback routine is called continuously while waiting for a
keypress. It must be declared in the following form:

	SUB CallbackProc(STRING, INTEGER)

The first parameter is passed to the callback routine and contains
the current string in the edit field. It should NOT be changed!

The second parameter is an abortflag. The callback routine can set
this to non-zero to simulate the Escape key to exit the LineEdit
function.

Some useful purposes of this callback routine are to:
- check the mouse coordinates and buttons
- update other parts of the screen (no cursor movement allowed though)
- check whether the current string is a valid entry (eg. existing folder)


KeyPress Callback
=================

The keypress callback routine is called whenever the user has pressed
a key or when the idle callback routine has simulated the Escape key.
It must be declared in the following form:

	SUB CallbackProc(STRING, INTEGER)

The first parameter that is passed to the callback routine contains the
last keypress (eg. CHR$(0,72) when user pressed the Up-arrow). This key
has not yet been processed by the LineEdit function, so you can change
the parameter to another string to simulate any other key. Change it to
CHR$(0) to ignore the keystroke.

The second parameter is an abortflag. The callback routine can set
this to non-zero to leave the LineEdit function as if a Return key was
pressed. The return value of LineEdit holds the original keypress (or
the one you changed it to in this callback routine).

Some useful purposes of this callback routine are to:
- check keystrokes for validity (eg. numbers only)
- move to another edit field (so abort the routine) when the up or down
  arrow or the Tab key is pressed


Callback notes
==============

Either callback routine should NOT change the cursor location, so any
text should be directly printed to the screen, using QPRINT (PB unit)
or DirectPrint (my unit).

Further, it should execute very quickly to make LineEdit work smoothly.


Example
=======

'------------------------------------------------------------------
  $INCLUDE "Colors.inc"
  $INCLUDE "Direct.inc"
  $INCLUDE "FileUtil.inc"
  $INCLUDE "LineEdit.inc"

  DECLARE SUB idle_callback_routine( STRING, INTEGER )
  DECLARE SUB key_callback_routine( STRING, INTEGER )

  DIM idle_callback_addr 	AS DWORD
  DIM key_callback_addr	AS DWORD
  DIM usertext			AS STRING
  DIM returnkey			AS STRING

  idle_callback_addr  = CODEPTR32( idle_callback_routine )
  key_callback_addr	= CODEPTR32( key_callback_routine )

  CLS
  LOCATE 2, 1
  PRINT "Enter a pathname: "

  COLOR 7, 1

  returnkey = LineEdit( 2, 18, 50, 50, usertext, _
                        idle_callback_addr, key_callback_addr )


  '===== Show current edit field contents =====
  SUB idle_callback_routine( Text AS STRING, Abort AS INTEGER )
      DIM Attr AS INTEGER

      IF PathExists(MakePath(Text)) THEN
          Attr = MakeAttr(10, 0)
      ELSE
          Attr = MakeAttr(12, 0)
      END IF

      DirectPrint 25, 1, "Folder = " & Text & SPACE$(50 - LEN(Text)), Attr

  END SUB

  '===== Change lowercase to uppercase =====
  SUB key_callback_routine( KeyPress AS STRING, Abort AS INTEGER )

      DIM AscVal	AS BYTE
      AscVal = ASC(KeyPress)
      IF AscVal >= ASC("a") AND AscVal <= ASC("z") THEN
          KeyPress = CHR$(AscVal - 32)
      END IF

  END SUB
'------------------------------------------------------------------
