module Unpack_m

  implicit NONE

contains

  subroutine Unpack ( InBuf, OutBuf, Insert )
  ! Unpack an image in Buf represented by groups of
  !   RC, followed by RC removed instances of Insert (default blank), and
  !   SC, followed by SC significant characters.
  ! The counters have had 32 added to them after being mangled, so subtract
  ! 32 and then run them through MAP.

    character(len=*), intent(in) :: InBuf
    character(len=*), intent(out) :: OutBuf
    character, intent(in), optional :: Insert

    integer :: I, J   ! Buffer indices
    integer :: RC, SC ! Removed count, Significant count
    integer :: IR, IS ! Counters for RC, SC
    character :: MyInsert

    myInsert = ''
    if ( present(insert) ) myinsert = insert

    j = 0
    i = 0
o:  do
      i = i + 1
      if ( i > len(inBuf) .or. j >= len(outbuf) ) &
    exit o
      rc = map(inBuf(i:i))
      do ir = 1, rc
        j = j + 1
        if ( j > len(outBuf) ) &
    exit o
        outbuf(j:j) = ''
      end do ! ir
      i = i + 1
      if ( i > len(inBuf) .or. j >= len(outbuf) ) &
    exit o
      sc = map(inBuf(i:i))
      do is = 1, sc
        i = i + 1
        if ( i > len(inBuf) ) &
    exit o
        j = j + 1
        if ( j > len(outBuf) ) &
    exit o
        outbuf(j:j) = inbuf(i:i)
      end do ! is
    end do o

    outbuf(j+1:) = ''

  contains
    integer function Map ( CH )
    ! Map CH to a count
      character, intent(in) :: CH
      character :: CBUF(len_trim(inbuf))
      integer :: L, IBUF(len_trim(inbuf))
      integer :: Tab(0:63)
      data Tab / &
        !    0   1   2   3   4   5   6   7
        &   05, 45, 62, 03, 39, 42, 38, 58, & ! O'00'
        &   41, 32, 40, 34, 46, 33, 61, 60, & ! O'10'
        &   48, 49, 50, 51, 52, 53, 54, 55, & ! O'20'
        &   56, 57, 43, 59, 35, 36, 37, 44, & ! O'30'
        &   00, 06, 07, 08, 09, 10, 11, 12, & ! O'40'
        &   13, 14, 15, 16, 17, 18, 19, 20, & ! O'50'
        &   21, 22, 23, 24, 25, 26, 27, 28, & ! O'60'
        &   29, 30, 31, 01, 47, 02, 04, 63  / ! O'70'

      map = tab(iachar(ch)-32)
      if ( map < 0 ) then
        print '(a,o3.2,3(a,i0))', '<<< No count mapping for ', iachar(ch)-32, &
          & ' in column ', i, ' of input and column ', j+1, ' of output.'
        do l = 1, len_trim(inbuf)
          cbuf(l) = inbuf(l:l)
          ibuf(l) = iachar(cbuf(l))-32
        end do
        print '(16(2x,a))', cbuf
        print '(16o3.2)', ibuf
      end if
    end function Map
  end subroutine Unpack

end module Unpack_m
