 	subroutine LineEdit( Row, Col, Buffer, TermKeys,
     1   LastKey )


c==============================================================================
c
c	Edit the character string at Row, Col.
c
c	Usuage:
c	  character*N String     ( where N <= 80 )
c	  String = 'Something'
c	  Display String at Row, Col
c	  call LineEdit( String, Row, Col )
c
c
c	Special keys:
c	  right arrow - move cursor frwd ( unless at end of string ).
c	   left arrow - move cursor bkwd ( unless at beginning of string ).
c	           ^H - delete char in front of cursor.
c	          Del - delete char at cursor.
c	           ^J - delete to end of line.
c	           ^K - delete word.
c	           ^W - toggle insert/overwrite mode.
c	           ^U - abort edit and display original string. Continue
c			editing at beginning of string.
c		   ^B - goto beginning of line.
c		   ^E - goto end of line.
c	          tab - goto next word
c	     back tab - goto last word
c	       return,
c	     up arrow,
c	   down arrow,
c           and other
c    termination keys - finish editing, return from routine, and return
c    ( defined in	character code in LastKey.
c      TermKeys   )
c==============================================================================


c	parameters
c	----------

	integer*2 Row, Col, TermKeys( 30 ), LastKey
	character*80 String
	character*(*) Buffer


c	functions
c	---------

	integer*2 Length
	logical*1 Printabl


c	local data elements
c	-------------------

	integer*2 I, Index, FirstIndex, LastIndex, ITK, NTK,
     1   StrLength, Key, Lnth
	character*80 Original

	logical*1 Insert


c	local constants
c	---------------

	integer*2 Idel, NextI, LastI, CR, Left, Right,
     1   CtlH, CtlW, CtlU, CtlB, CtlE, Del, CtlZ, Up, Down,
     1   CtlR, Tab, BackTab, CtlJ, CtlK


	data
     1   CR /13/, Left /130/,
     1   Right /131/, CtlH /8/, CtlW /23/, CtlU /21/, CtlB /2/,
     1   CtlE /5/, Del /127/, CtlZ /26/, Up /128/,
     1   Down /129/, CtlR /18/, Tab /9/, BackTab /132/,
     1   CtlJ /10/, CtlK /11/

	data Insert /.false./
c

c--
c Initialization
c--

	call ShowInsMode( Insert )

	I = 1
	String = ' '
	String = Buffer
	StrLength = len( Buffer )
	Original(1:StrLength) = String
	call RelCsrPos( Row, Col )


c--
c Begin...
c--

c	repeat until key is a termination char but not a special edit key
1000	continue


	  call FPGetChar( Key )

c--
c Application termination characters
c--

c -- Normal
	    LastIndex = TermKeys(1)+1
	    if( LastIndex .gt. 30 ) LastIndex = 30

	    do 1500 Index = 2 , LastIndex
	      if( Key .eq. TermKeys(Index) ) then
	        LastKey = Key
	        goto 2000
	      end if
1500	    continue

c -- Immediate
	  ITK = TermKeys(1) + 2
	  FirstIndex = ITK+1
	  if( FirstIndex .lt. 3 ) goto 1052

	  NTK = TermKeys(ITK)
	  LastIndex = ITK+NTK
	  if( LastIndex .gt. 30 ) LastIndex = 30

	  do 1051 Index = FirstIndex , LastIndex
	    if( Key .eq. TermKeys(Index) ) then
              LastKey = Key
	      goto 2000
	    end if
1051	  continue
1052	  continue

	  if( Printabl(Key) ) then

	    if( I .le. StrLength ) then
	      call PrChar( Key, String(1:StrLength), I, Row,
     1        Col, Insert )
	    else
	      call Beep
	    end if

	  else if( Key .eq. Right ) then

	    if( I .le. StrLength ) then
	      I = I + 1
	      call CsrRight(1)
	    else
	      call Beep
	    end if

	  else if( Key .eq. Left ) then

	    if( I .gt. 1 ) then
	      I = I - 1
	      call CsrLeft(1)
	    else
	      call Beep
	    end if
c

	  else if( Key .eq. Del ) then

	    if( I .le. StrLength ) then
	      Lnth = Length( String )
	      if( I .le. Lnth ) then
	        call DelChr( String, I )
	        call OutString( String(I:Lnth) )
	        call RelCsrPos( Row, Col+I-1 )
	      end if
	    else
	      call Beep
	    end if

	  else if( Key .eq. CtlJ ) then
	    if( I .le. StrLength ) then
	      Lnth = Length( String )
	      if( I .le. Lnth ) then
	        do 1600 Idel = I , Lnth
	          call DelChr( String, I )
1600            continue
	        call OutString( String(I:Lnth) )
	        call RelCsrPos( Row, Col+I-1 )
	      end if
	    end if

	  else if( Key .eq. CtlK ) then
	    if( I .le. StrLength ) then
	      Lnth = Length( String )
	      if( I .lt. Lnth ) then
	        call NextWord( I, String, NextI )
	        do 1700 Idel = I , NextI-1
	          call DelChr( String, I )
1700            continue
	        call OutString( String(I:Lnth) )
	        call RelCsrPos( Row, Col+I-1 )
	      else if( I .eq. Lnth ) then
	        call DelChr( String, I )
	        call OutString( String(I:Lnth) )
	        call RelCsrPos( Row, Col+I-1 )
	      end if
	    end if

	  else if( Key .eq. CtlH ) then

	    if( I .gt. 1 ) then
	      Lnth = Length( String )
	      I = I - 1
	      call CsrLeft(1)
	      if( I .le. Lnth ) then
	        call DelChr( String, I )
	        call OutString( String(I:Lnth) )
C	        if( I .lt. Lnth ) call OutString( Space )
	        call RelCsrPos( Row, Col+I-1 )
	      end if
	    else
	      call Beep
	    end if

	  else if( Key .eq. CtlU ) then

	    String = Original( 1:StrLength )
	    call RelErase( Row, Col, StrLength )
	    call RelCsrPos( Row, Col )
	    Lnth = Length( String )
	    if( Lnth .gt. 0 ) call OutString( String(1:Lnth) )
	    call RelCsrPos( Row, Col )
	    I = 1

	  else if( Key .eq. CtlW ) then

	    if( Insert ) then
	      Insert = .false.
	    else
	      Insert = .true.
	    end if

	    call ShowInsMode( Insert )
	    call RelCsrPos( Row, Col+I-1 )

c

	  else if( Key .eq. CtlB ) then
	    call RelCsrPos( Row, Col )
	    I = 1

	  else if( Key .eq. CtlE ) then
	    Lnth = Length( String )
	    call RelCsrPos( Row, Col+Lnth )
	    I = Lnth+1

	  else if( Key .eq. Tab ) then
	    call NextWord( I, String, NextI )
	    I = NextI
	    call RelCsrPos( Row, Col+I-1 )

	  else if( Key .eq. BackTab ) then
	    call LastWord( I, String, LastI )
	    I = LastI
	    call RelCsrPos( Row, Col+I-1 )


	  else
c    >>   ( check if key is a termination key )

c--
c LineEdit system termination characters
c--
	    if( Key .eq. CtlR ) then
	      LastKey = Key
	      goto 2000
	    end if

	    if( Key .eq. CR .or.
     1  	Key .eq.   Up .or.
     1  	Key .eq. Down .or.
     1  	Key .eq. CtlZ      ) then
	      LastKey = Key
	      goto 2000
	    end if

c--
c not a termination char so illegal
c--
	    call beep

	  end if

	goto 1000

c	end repeat
2000	continue

	Buffer = ' '
	Buffer = String

	if( Original(1:StrLength) .ne. String ) call SetChangeFlag

	return
	end
c


	subroutine ShowInsMode( Insert )

	logical*1 Insert

	if( Insert ) then
	  call SaveAttribute
	  call DspAttribute(2)
	  call CsrPos(23,75)
	  call OutString( 'Insert' )
	  call RstAttribute
	else
	  call SaveAttribute
	  call DspAttribute(0)
	  call CsrPos(23,75)
	  call OutString( '      ' )
	  call RstAttribute
	end if

	return
	end



	subroutine PrChar( Key, String, CurPos, Row, Col, Insert )

c--
c Display a edit field character and update "String" with the new character
c if the current position is within the edit field otherwise beep the CRT.
c
c If "Insert" is true then insert the character and shift other characters
c right otherwise write the character over any pre-existing character
c
c	Key - key just entered
c	String - string being edited
c	CurPos - current position of interest within the string
c	Row - cursor row
c	Col - cursor column
c	Insert - entry mode - if true then character is to be inserted
c			      otherwise character is to be written over
c			      pre-existing character in string
c--

	integer*2 Key, CurPos, Row, Col, StrLength, Lnth, Length
	logical*1 Insert, NoRoom
	character*(*) String
	character*1 Chr

	StrLength = len( String )

	if( CurPos .le. StrLength ) then

	  Chr = char( Key )

	  if( Insert ) then
	    call InsChr( Chr, String, CurPos, NoRoom )
	    if( NoRoom ) then
	      call Beep
	      call FlushBuffer
	    else
	      Lnth = Length( String )
	      if( CurPos .le. Lnth ) then
	        call OutString( String(CurPos:Lnth) )
	      else
	        call OutString( String(CurPos:CurPos) )
	      end if
	      CurPos = CurPos + 1
	      call RelCsrPos( Row, Col+CurPos-1 )
	    end if

	  else

	    call OverWriteChr( Chr, String, CurPos )
	    call OutString( Chr )
	    CurPos = CurPos + 1

	  end if
c


	else

	  call Beep
	  call FlushBuffer

	end if

	return

   	end

