Basic Univers
; Auteur : Nico

 ;/ Les fonctions:
;----------------------------
;/ CreateList(size.l)       crée une nouvelle liste chainée
;/ Add_Element(index.l)     ajoute un nouvel element vide à la fin
;/ First_Element(index.l)   premier element de la liste
;/ End_Element(index.l)     dernier element de la liste
;/ Next_Element(index.l)    element suivant
;/ Delete_element(index.l)  efface l'element courant
;/ DestructList(index.l)    détruit la liste chainée
;/ Count_Element(index.l)   compte le nombre d'élément
;/ Current_element(index.l) renvoie le pointeur courant
;----------------------------

ProcedureDLL CreateList_Init()

  Structure liste
    *Pointeur_debut
    *Pointeur_fin
    *pointeur_courant
    size_struct.l
    debut.l
    flag.b
    count.l
    index.l
  EndStructure
 
  NewList liste.liste()
EndProcedure

Procedure FindList(index)
  ForEach liste()
    If liste()\index = index
      ProcedureReturn 1
    EndIf
  Next
  ProcedureReturn 0
EndProcedure

ProcedureDLL CreateList(size.l)
  Static index
  index = index + 1
  AddElement(liste())
  liste()\size_struct = size + 4
  liste()\index = index
  ProcedureReturn index
EndProcedure

ProcedureDLL Add_Element(index.l)
  If FindList(index)
    *nouveau = AllocateMemory(liste()\size_struct)
    ; Debug *nouveau
    If liste()\debut = 0
      liste()\count = 0
      liste()\Pointeur_debut =*nouveau
      liste()\debut = 1
    Else
      PokeL(liste()\Pointeur_fin, *nouveau)
    EndIf
    liste()\count = liste()\count + 1
    liste()\Pointeur_fin =*nouveau + liste()\size_struct
    PokeL(liste()\Pointeur_fin, 0)
    liste()\pointeur_courant = liste()\Pointeur_fin
    ProcedureReturn *nouveau
  EndIf
  ProcedureReturn 0
EndProcedure
 
ProcedureDLL First_Element(index.l)
  If FindList(index)
    liste()\pointeur_courant = liste()\Pointeur_debut + liste()\size_struct
    ; Debug "First_Element"
    ; Debug liste()\Pointeur_debut
    liste()\flag = 0
    ProcedureReturn liste()\Pointeur_debut
  EndIf
  ProcedureReturn 0
EndProcedure

ProcedureDLL End_Element(index.l)
  If FindList(index)
    liste()\pointeur_courant = liste()\Pointeur_fin
    ProcedureReturn liste()\Pointeur_fin - liste()\size_struct
  EndIf
  ProcedureReturn 0
EndProcedure

ProcedureDLL Next_Element(index.l)
If FindList(index)
  If liste()\flag = 0
    suivant = PeekL(liste()\pointeur_courant)
    liste()\pointeur_courant = suivant + liste()\size_struct
    ; Debug "Next_Element"
    ; Debug suivant
    ProcedureReturn suivant
  Else
    liste()\flag = 0
    ProcedureReturn liste()\Pointeur_debut
  EndIf
EndIf
ProcedureReturn 0
EndProcedure

ProcedureDLL Delete_element(index.l)
  If FindList(index)
    If liste()\debut<>0
      *pointeur = liste()\Pointeur_debut + liste()\size_struct
     
      Select liste()\pointeur_courant
        Case *pointeur
          If PeekL(*pointeur)<>0
            liste()\Pointeur_debut = PeekL(*pointeur)
            *memory = liste()\pointeur_courant - liste()\size_struct
            liste()\pointeur_courant = liste()\Pointeur_debut + liste()\size_struct
            liste()\count = liste()\count - 1
          Else
            *memory = liste()\pointeur_courant - liste()\size_struct
            liste()\Pointeur_debut = 0
            liste()\debut = 0: liste()\count = 0
          EndIf
          liste()\flag = 1
         
        Default
          *pointeur = liste()\Pointeur_debut
          While *pointeur
            If liste()\pointeur_courant = PeekL(*pointeur + liste()\size_struct )+ liste()\size_struct
              *Pointeur_precedent =*pointeur + liste()\size_struct
              If liste()\Pointeur_fin = liste()\pointeur_courant
                liste()\Pointeur_fin =*Pointeur_precedent
              EndIf
              *memory = liste()\pointeur_courant - liste()\size_struct
              Break
            EndIf
            *pointeur = PeekL(*pointeur + liste()\size_struct )
          Wend
          PokeL(*Pointeur_precedent, PeekL(liste()\pointeur_courant))
          *memory = liste()\pointeur_courant - liste()\size_struct
          liste()\pointeur_courant =*Pointeur_precedent
          liste()\count = liste()\count - 1
      EndSelect
     
      If *memory
        If FreeMemory(*memory)
          ; Debug "FreeMemory(*memory)"
          ; Debug *memory
          ProcedureReturn 1
        EndIf
      EndIf
     
    EndIf
    ProcedureReturn 0
  EndIf
  ProcedureReturn 0
EndProcedure

ProcedureDLL DestructList(index.l)
  If FindList(index)
    *liste = First_Element(index)
    While *liste
      Delete_element(index)
      *liste = Next_Element(index)
    Wend
    DeleteElement(liste())
    ProcedureReturn 1
  EndIf
  ProcedureReturn 0
EndProcedure
           
ProcedureDLL Count_Element(index.l)
  If FindList(index)
    ProcedureReturn liste()\count
  EndIf
  ProcedureReturn 0
EndProcedure

ProcedureDLL Current_Element(index.l)
  If FindList(index)
    ProcedureReturn liste()\pointeur_courant - liste()\size_struct
  EndIf
  ProcedureReturn 0
EndProcedure

;- Exemple :
;

Structure liste
  valeur.l
EndStructure

index1 = CreateList(SizeOf(liste))

*liste.liste = Add_Element(index1)
*liste\valeur = 11

*liste = Add_Element(index1)
*liste\valeur = 11

*liste = Add_Element(index1)
*liste\valeur = 22

*liste = Add_Element(index1)
*liste\valeur = 33

*liste = Add_Element(index1)
*liste\valeur = 44

Debug Count_Element(index1)

Delete_element(index1)
Delete_element(index1)


*liste = First_Element(index1)
While *liste
  If *liste\valeur = 11
    Delete_element(index1)
  EndIf
*liste = Next_Element(index1)
Wend
;
Debug "---------------"



*liste = Add_Element(index1)
*liste\valeur = 55

Debug "---------------"

*liste = First_Element(index1)
While *liste
  Debug *liste\valeur
  *liste = Next_Element(index1)
Wend

Debug "---------------"
DestructList(index1)