/*
 * ADAPT2D : a software for automatic mesh adaptation in 2D
 *
 * AUTHOR : Manuel J. Castro Diaz(e-mail:castro@gamba.cie.uma.es)
 * ADAPTED FOR FREEFEM : Prud'homme Christophe (e-mail:prudhomm@ann.jussieu.fr) 
 *
 * this code is public domain
 * 
 * You may copy freely these files and use it for    
 * teaching or research. These or part of these may   
 * not be sold or used for a commercial purpose without
 * our consent
 * 
 * Any problems should be reported to the AUTHOR
 * at the following address : castro@gamba.cie.uma.es
 */


#ifndef _trianguloT0dlist_h
#define _trianguloT0dlist_h

#include <t_t0.hxx>

struct Triangulo_T0_dlink {
       Triangulo_T0* t;
       Triangulo_T0_dlink* suc;
       Triangulo_T0_dlink* prev;

       Triangulo_T0_dlink () {t=NIL; suc=NIL; prev=NIL;}
       Triangulo_T0_dlink (Triangulo_T0& tr, Triangulo_T0_dlink* ss,Triangulo_T0_dlink* pp)
            {t=&tr;suc=ss;prev=pp;}
       Triangulo_T0_dlink (Triangulo_T0* tr, Triangulo_T0_dlink* ss,Triangulo_T0_dlink* pp) {
             t=tr; suc=ss; prev=pp;} 

       void set (Triangulo_T0& tr, Triangulo_T0_dlink* ss, Triangulo_T0_dlink* pp)
             {t=&tr; suc=ss;prev=pp;}
       void set (Triangulo_T0* tr, Triangulo_T0_dlink* ss, Triangulo_T0_dlink* pp) {
              t=tr; suc=ss; prev=pp;} 

       Triangulo_T0_dlink* sig() {return suc;}
       Triangulo_T0_dlink* ant() {return prev;}
    };

    class Triangulo_T0_dlist {

       Triangulo_T0_dlink* last;
       Triangulo_T0_dlink* begin;

       friend ostream& operator<<(ostream&, Triangulo_T0_dlist&);
       friend void t_vecinos(Vertice_T0*, Triangulo_T0_dlist&);
   public:
       Triangulo_T0_dlist () {last=NIL; begin=NIL;}
       Triangulo_T0_dlist (Triangulo_T0_dlink* r) {last=begin=r;}
       void insert (Triangulo_T0_dlink* r) {//an~ade al principio de la lista.
           if (begin) {
               r->suc=begin;
               begin->prev=r;
               begin=r;

           }
           else {
               last=r;
               begin=r;
           }
       }
       void append(Triangulo_T0_dlink* r) {//an~ade al final de la lista.
           if (last) {
              last->suc=r;
              r->prev=last;
              last=r;
           }
           else {
              last=r;
              begin=r;
           }
       }
       void  enlaza (Triangulo_T0_dlist* rll) {  //une this+rll
        if (begin) {
           if (rll->begin) {
              last->suc=rll->begin;
              (rll->begin)->prev=last;
              last=rll->last;
              rll->begin=NIL;
              rll->last=NIL;
           }
        }
        else {
           begin=rll->begin;
           last=rll->last;
           rll->begin=NIL;
           rll->last=NIL;
       }
   }
       void  enlaza (Triangulo_T0_dlist& rll) {  //une this+rll
        if (begin) {
           if (rll.begin) {
              last->suc=rll.begin;
              (rll.begin)->prev=last;
              last=rll.last;
              rll.begin=NIL;
              rll.last=NIL;
           }
        }
        else {
           begin=rll.begin;
           last=rll.last;
           rll.begin=NIL;
           rll.last=NIL;
       }

    }
       void kill (Triangulo_T0_dlink* r) { //elimina un elmento de la dlista
         if (r) {
           if (r==begin) {
              begin=r->suc;
              begin->prev=NIL;
           }
           else {
             if (r==last) {
                last=r->prev;
                last->suc=NIL;
             }
             else {
               (r->prev)->suc=r->suc;
               (r->suc)->prev=r->prev;
             }
           }
           delete r; r=NIL;
         }
       }

       Triangulo_T0_dlink* principio () {return begin;}
       Triangulo_T0_dlink* fin () {return last;}
       int num_elem () {
           int num=0;
           Triangulo_T0_dlink* aux=begin;
           while (aux) {
            num++;
            aux=aux->suc;
           }
           return num;
       } 
       Scalar area();
       Boolean contiene(Vertice_T0*);
       void clear () {
           Triangulo_T0_dlink* aux;
           while (begin) {
              aux=begin->suc;
              delete begin;
              begin=aux;
           }
           last=begin=NIL;
       }                             
       void operator delete (void* p){
         if (p) {
           ((Triangulo_T0_dlist*)p)->clear();
           delete p; p=NIL;
         }
       }
       void write (ostream&);
    };
#endif       
