! Program Example from "Essential Fortran 90 & 95" by Loren P. Meissner
! Copyright 1996. Copying for sale requires permission from the author.
! Otherwise, distribution is permitted if these three lines are included.

  module G30M
    use F26M
    use Element_M
    implicit none
    private  ! Required because this module imports another module.
    public :: Find, Print_List
    integer, parameter, private :: TBL_SIZE = 50
    type, private :: Table  ! Structure to hold list and current list size
      integer :: L_Size  ! Current list size
      type (Chem_El_Type_1), dimension(TBL_SIZE) :: Data  ! Array of compounds
    end type Table
    integer, private :: I  ! I is an ACID variable
    type (Table), private, save :: C_Table &
      = Table(0, (/ (Chem_El_Type_1( "", "", 0, 0.0 ), I = 1, TBL_SIZE) /) )

  contains

    subroutine Find( Element, Fit )
      type (Chem_El_Type_1), intent (in) :: Element  ! Element to find or insert in list
      ! Fit is .false. on attempt to insert when Tbl is full.
      logical, intent (out) :: Fit
      integer, dimension(2) :: Loc  ! To hold result from Search
      integer :: S
  ! start subroutine Find
      S = C_Table % L_Size
      Loc = Search( C_Table % Data(: S) % Element_Name, Element % Element_Name )
      if (Loc(1) == Loc(2)) then
        write (unit = *, fmt = *) " Found:  ", Loc(2), " of ", S, ": ", Element % Element_Name
        C_Table % Data(Loc(2)) % Atomic_Number = C_Table % Data(Loc(2)) % Atomic_Number + 1
        Fit = .true.
      else   ! No matching element; insert.
        if (S < TBL_SIZE) then
          write (unit = *, fmt = *) " Insert: ", Loc(2), " of ", S + 1, ": ", Element % Element_Name
          ! Move elements up to make space at insertion point.
          C_Table % Data(Loc(2) + 1 : S + 1) = C_Table % Data(Loc(2) : S)
          C_Table % Data(Loc(2)) = Element  ! Insert.
          C_Table % L_Size = S + 1   ! Adjust current size.
          Fit = .true.
        else   ! There is no room to insert element.
          write (unit = *, fmt = *) " Full: . ", Loc(2), " of ", S, ": ", Element % Element_Name
          Fit = .false.
        end if
      end if
      return
    end subroutine Find

    subroutine Print_List ( )
      integer :: Loop
  ! start subroutine Print_List
      write (unit = *, fmt = *) " Final size: ", C_Table % L_Size
      do Loop = 1, C_Table % L_Size
        write (unit = *, fmt = *) C_Table % Data(Loop)
      end do
      return
    end subroutine Print_List

  end module G30M
