	subroutine Block( Row, Col )

	character*24 BlockMenu
	character*2 Choices
	integer*2 Item, Key
	logical*1 Abort

	character*7 CnfrmMenu
	character*2 CnfrmChoices
	integer*2 DelKey, MovKey

	integer*2 TermKeys(30), LastKey

	integer*2 Row, Col, Row1, Col1, Row2, Col2, Row1Dest, Col1Dest,
     1   Row2Dest, Col2Dest
	logical*1 Ok

	data BlockMenu /'Move_Block  Delete_Block'/
	data Choices /'MD'/

	data CnfrmMenu /'Yes  No'/
	data CnfrmChoices /'YN'/

	data TermKeys / 2, 2, 141, 27*0 /

c--
c Save screen attribute
c--

	call SaveAttribute

c--
c Mark upper left coordinate of source block
c--

	Row1 = Row
	Col1 = Col

	call RevRegion( Row1, Col1, Row1, Col1 )
	call DspRegion( Row1, Col1, Row1, Col1 )


c--
c Get lower right coordinate of source block
c--

  	Row2 = Row1
	Col2 = Col1

20	continue

	call DspAttribute(2)
  	call DspMessage(
     1   'Move cursor to lower right of source region and press ^B',
     1   'Press F1 to abort' )

	call MoveCsr( Row2, Col2, TermKeys, LastKey )

	if( LastKey .eq. 141 ) then
	  call RevRegion( Row1, Col1, Row1, Col1 )
	  call DspRegion( Row1, Col1, Row1, Col1 )
	  call RstAttribute
	  return
	end if

	call VerfySourceRegion( Row1, Col1, Row2, Col2, Ok )
	if( .not. Ok ) then
	  call ErrMsg( 'Invalid Source Region!' )
	  call RevRegion( Row1, Col1, Row1, Col1 )
	  call DspRegion( Row1, Col1, Row1, Col1 )
	  call RstAttribute
	  return
	end if

	call RevRegion( Row1, Col1, Row1, Col1 )

	call RevRegion( Row1, Col1, Row2, Col2 )
	call DspRegion( Row1, Col1, Row2, Col2 )

c--
c Get operation to perform
c--
35	continue

	call DspAttribute(0)
	call EraseRegion( 23, 1, 24, 80 )
	call CsrPos(23,1)
	call DspAttribute(2)
	call OutString( 'Select block operation' )

	Item = 1
	call Menu1( 24, BlockMenu, Choices, Item, Key, Abort )

 	if( Abort ) then
	  call RevRegion( Row1, Col1, Row1, Col1 )
	  call RevRegion( Row1, Col1, Row2, Col2 )
	  call DspRegion( Row1, Col1, Row2, Col2 )
	  goto 20
	end if


c--
c If "delete" then jump over "get dest block"
c--
	if( Key .eq. 68 ) goto 40

c--
c Get upper left coordinate of destination block
c--

	Row1Dest = Row1
	Col1Dest = Col1

30	continue

	call DspAttribute(2)
	call DspMessage(
     1  'Move cursor to upper left of destination region and press ^B'
     1  ,'Press F1 to abort' )

	call MoveCsr( Row1Dest, Col1Dest, TermKeys, LastKey )

	if( LastKey .eq. 141 ) then
	  goto 35
	end if

	Row2Dest = Row1Dest + ( Row2-Row1 )
	Col2Dest = Col1Dest + ( Col2-Col1 )

c--
c Performat operation
c--

40	continue

c--
c Move
c--
	if( Key .eq. 77 ) then

	call CopyRegion( Row1, Col1, Row2, Col2 )
	call DelRegion( Row1, Col1, Row2, Col2 )

	call VerfyDestRegion( Row1Dest, Col1Dest, Row2Dest,
     1   Col2Dest, Ok )
	if( .not. Ok ) then
	  call ErrMsg( 'Invalid Destination Region!' )
	  call RestoreRegion( Row1, Col1, Row2, Col2 )
	  goto 30
	end if

	call RestoreRegion( Row1Dest, Col1Dest, Row2Dest, Col2Dest )
	call DspRegion( Row1Dest, Col1Dest, Row2Dest, Col2Dest )

	call DspAttribute(0)
	call EraseRegion( 23, 1, 24, 80 )
	call CsrPos(23,1)
	call DspAttribute(2)
	call OutString( 'Confirm move' )

	Item = 1
	call Menu1( 24, CnfrmMenu, CnfrmChoices, Item, MovKey, Abort )
	if( Abort .or. MovKey .eq. 78 ) then
	  call DelRegion( Row1Dest, Col1Dest, Row2Dest, Col2Dest )
	  call DspRegion( Row1Dest, Col1Dest, Row2Dest, Col2Dest )
	  call RestoreRegion( Row1, Col1, Row2, Col2 )
	  call DspRegion( Row1, Col1, Row2, Col2 )
	  goto 30
	end if

	call DspRegion( Row1, Col1, Row2, Col2 )

	call UpdateTables( Row1Dest, Col1Dest, Row2Dest, Col2Dest )
	call RevRegion( Row1Dest, Col1Dest, Row2Dest, Col2Dest )
	call DspRegion( Row1Dest, Col1Dest, Row2Dest, Col2Dest )

	Row = Row1Dest
	Col = Col1Dest

c--
c Delete
c--
	else if( Key .eq. 68 ) then

	call DspAttribute(0)
	call EraseRegion( 23, 1, 24, 80 )
	call CsrPos(23,1)
	call DspAttribute(2)
	call OutString( 'Confirm delete' )

	Item = 1
	call Menu1( 24, CnfrmMenu, CnfrmChoices, Item, DelKey, Abort )

	if( Abort .or. DelKey .eq. 78 ) then
	  call RevRegion( Row1, Col1, Row2, Col2 )
	  call DspRegion( Row1, Col1, Row2, Col2 )
	  call RstAttribute
	  return
	end if

	call DelTableEntries( Row1, Col1, Row2, Col2 )
	call DelRegion( Row1, Col1, Row2, Col2 )
	call DspRegion( Row1, Col1, Row2, Col2 )

	Row = Row1
	Col = Col1

	call RstAttribute

	end if


	end


	subroutine VerfySourceRegion( Row1, Col1, Row2, Col2, Ok )

c-------------------------------------------------------------------------
c
c Verify a source move region.
c
c Row1, Col1 is upper left.
c Row2, Col2 is lower right.
c
c If the upper left and lower right coordinates are not reasonable then
c Ok will be false.
c
c If the region cuts through any data field then Ok will be false.
c
c Otherwise, Ok will be true.
c
c---------------------------------------------------------------------------

	integer*2 Row1, Col1, Row2, Col2, Map(21,80,3), I
	logical*1 Ok

	logical*1 LegalReg

	common /Blk1/ Map

c	call rpt( 'in VerfySourceRegion' )

c--
c Make sure upper left and lower right coordinates are reasonable
c--
	if( .not. LegalReg( Row1, Col1, Row2, Col2 ) ) then
	  Ok = .false.
	  return
	end if

c--
c Check if left side of region cuts through a data field ( Don't check
c if Col1 is 1 ).
c--

	if( Col1 .ne. 1 ) then

 	  do 10 I = Row1 , Row2

c      --- if this location is a data field then...
	    if( Map(I,Col1,1) .eq. 6 ) then

c        --- if this data field number is the same as the one at col1-1 then...
	      if( Map(I,Col1,3) .eq. Map(I,Col1-1,3) ) then
	        Ok = .false.
	        return
	      end if

	    end if

10	  continue

	end if


c--
c Check if right side of region cuts through a data field ( Don't check
c if Col2 is 79 ).
c--

	if( Col2 .ne. 79 ) then

 	  do 20 I = Row1 , Row2

c      --- if this location is a data field then...
	    if( Map(I,Col2,1) .eq. 6 ) then

c        --- if this data field number is the same as the one at col2+1 then...
	      if( Map(I,Col2,3) .eq. Map(I,Col2+1,3) ) then
	        Ok = .false.
	        return
	      end if

	    end if

20	  continue

	end if


	Ok = .true.

	end


	subroutine VerfyDestRegion( Row1, Col1, Row2, Col2, Ok )

c-------------------------------------------------------------------------
c
c Verify a destination move region.
c
c Row1, Col1 is upper left.
c Row2, Col2 is lower right.
c
c If the upper left and lower right coordinates are not reasonable then
c Ok will be false.
c
c If any location in the region is non-zero and a non-reverse space then
c Ok will be false.
c
c Otherwise, Ok will be true.
c
c---------------------------------------------------------------------------

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

	integer*2 Row1, Col1, Row2, Col2
	logical*1 Ok

c	commons
c	-------

	integer*2 Map(21,80,3)

c	locals
c	------

	integer*2 ReverseBit, J, I
	logical*1 LegalReg

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

	integer*2 Iand

	common /Blk1/ Map


	data ReverseBit  /1/

c	call rpt( 'in VerfyDestRegion' )


c--
c Make sure upper left and lower right coordinates are reasonable
c--
	if( .not. LegalReg( Row1, Col1, Row2, Col2 ) ) then
	  Ok = .false.
	  return
	end if

	do 10 I = Row1, Row2

	  do 10 J = Col1, Col2

c --- if the contents of the map is anything other than a non-reverse
c --- attribute space or a null, then the region is invalid.
	    if( Map(I,J,1) .ne. 0 ) then
	      if( Map(I,J,1) .eq. 32 ) then
	        if( Iand( Map(I,J,2), ReverseBit ) .ne. 0 ) then
	          Ok = .false.
	          return
	        end if
	      else
	        Ok = .false.
	        return
	      end if
	    end if

10	continue

	Ok = .true.

	end

	subroutine DelRegion( Row1, Col1, Row2, Col2 )

c-------------------------------------------------------------------------
c
c Delete a move region ( fill it with nulls )
c
c Row1, Col1 is upper left.
c Row2, Col2 is lower right.
c
c If the upper left and lower right coordinates are not reasonable then
c just return.
c
c---------------------------------------------------------------------------

	integer*2 Row1, Col1, Row2, Col2, Map(21,80,3), I, J

	logical*1 LegalReg

	common /Blk1/ Map

c	call rpt( 'in DelRegion' )


c--
c Make sure upper left and lower right coordinates are reasonable
c--
	if( .not. LegalReg( Row1, Col1, Row2, Col2 ) ) then
	  return
	end if

	do 10 I = Row1, Row2

	  do 10 J = Col1, Col2

	    Map(I,J,1) = 0
	    Map(I,J,2) = 0
	    Map(I,J,3) = 0

10	continue

	end


	subroutine FindDataField( Row1, Col1, Row2, Col2, CsrRow,
     1   CsrCol, FieldNum )

c------------------------------------------------------------------------
c
c Starting at the coordinate (CsrRow,CsrCol), search a region left to
c right, up to down, for a data field. If one is found, Place its
c coordinate in CsrRow and CsrCol and set FieldNum to its number.
c If one is not found, set FieldNum to 0.
c
c Upon entry to this routine, if the cursor is on a data field, then
c don't begin the search until after this current field.
c
c------------------------------------------------------------------------

	integer*2 Row1, Col1, Row2, Col2, CsrRow, CsrCol, FieldNum,
     1   Map(21,80,3), Num, I, J

	logical*1 LegalReg


	common /Blk1/ Map

c	call rpt( 'in FindDataField' )


c--
c Make sure upper left and lower right coordinates are reasonable
c--
	if( .not. LegalReg( Row1, Col1, Row2, Col2 ) ) then
	  FieldNum = 0
	  return
	end if

	if( CsrRow .gt. Row2 ) then
	  FieldNum = 0
	  return
	end if


c--
c If the cursor is on a data field, then don't
c begin the search until after this field ( unless
c this is the first field of the region ).
c--

	if( CsrRow .ne. Row1 .or. CsrCol .ne. Col1 ) then

	  if( Map(CsrRow,CsrCol,1) .eq. 6 ) then

	    Num = Map(CsrRow,CsrCol,3)

	    do 1 J = CsrCol , Col2
	      if( Map(CsrRow,J,3) .ne. Num ) then
	        CsrCol = J
	        goto 2
	      end if
1	    continue

	    CsrCol = Col1
	    CsrRow = CsrRow + 1

2	    continue

	  end if

	end if


c--
c Do the search
c--

c -- Search to end of current row
	if( CsrRow .le. Row2 ) then
	  do 10 J = CsrCol , Col2
	    if( Map(CsrRow,J,1) .eq. 6 ) then
	      FieldNum = Map(CsrRow,J,3)
	      CsrCol = J
	      return
	    end if
10	  continue
	end if

	do 20 I = CsrRow+1 , Row2

	  do 20 J = Col1 , Col2

	    if( Map(I,J,1) .eq. 6 ) then
	      FieldNum = Map(I,J,3)
	      CsrRow = I
	      CsrCol = J
	      return
	    end if

20	continue

	FieldNum = 0

	end


	subroutine UpdateTables( Row1, Col1, Row2, Col2 )

c--
c Update the row and col values in the data tables to reflect the
c values in the map. This routine would be called after fields
c have been moved.
c--

	integer*2 MaxFields
	parameter ( MaxFields=250 )

	integer*2 Row1, Col1, Row2, Col2, CsrRow, CsrCol, FieldNum, I


	integer*2 Fcount
	integer*2 Orig(MaxFields,3)

	logical*1 LegalReg

	common /field2/Orig,fcount

c	call rpt( 'in UpdateTables' )


c--
c Make sure upper left and lower right coordinates are reasonable
c--
	if( .not. LegalReg( Row1, Col1, Row2, Col2 ) ) then
	  FieldNum = 0
	  return
	end if


c--
c Search the region for data fields. As each is found, search the
c data field tables for the same field number and update the
c x and y coordinate values.
c--

	CsrRow = Row1
	CsrCol = Col1

10	continue

	call FindDataField( Row1, Col1, Row2, Col2, CsrRow,
     1   CsrCol, FieldNum )

	if( FieldNum .eq. 0 ) return

	do 20 I = 1 , Fcount

	  if( Orig(I,3) .eq. FieldNum ) then
	    Orig(I,1) = CsrRow
	    Orig(I,2) = CsrCol
	    CsrCol = CsrCol + 1
	    if( CsrCol .gt. Col2 ) then
	      CsrCol = Col1
	      CsrRow = CsrRow + 1
	    end if
	    goto 10
	  end if

20	continue

	end


	subroutine DelTableEntries( Row1, Col1, Row2, Col2 )

c--
c Delete the fields that are found in the map over the given
c region from the data field tables.
c--

	integer*2 Row1, Col1, Row2, Col2, CsrRow, CsrCol, FieldNum


	logical*1 LegalReg


c--
c Make sure upper left and lower right coordinates are reasonable
c--
	if( .not. LegalReg( Row1, Col1, Row2, Col2 ) ) then
	  FieldNum = 0
	  return
	end if


c--
c Search the region for data fields. As each is found, delete from table.
c--

	CsrRow = Row1
	CsrCol = Col1

10	continue

	call FindDataField( Row1, Col1, Row2, Col2, CsrRow,
     1   CsrCol, FieldNum )

	if( FieldNum .eq. 0 ) then
	  return
	else
	  Call DelField( CsrRow, CsrCol )
	end if

	CsrCol = CsrCol + 1
	if( CsrCol .gt. Col2 ) then
	  CsrCol = Col1
	  CsrRow = CsrRow + 1
	end if

	goto 10

	end

