/*
 $Id: readboxes.cc,v 1.1.1.1 1996/10/02 10:35:45 roitzsch Exp $
 (C)opyright 1996 by Konrad-Zuse-Center, Berlin
 All rights reserved.
 Part of the Kaskade distribution
*/

#include <ctype.h>

#include "boxes.h"



#define SKIP_WHITE while(isspace(*(text))) text++
#define SKIP_SPACE while((*(text)==' ')||(*(text)=='\t')||(*text==',')\
  ||(*text==':')||(*text=='(')||(*text==')')) text++
#define SKIP_LINE while((*text!='\n')&&(*text!='\0'))text++; line_number++;\
  text++;line =  text;
#define GET_LINE bi= 0;\
  while((*text!='\n')&&(*text!='\0'))buffer[bi++]= *(text++);\
  text--; buffer[bi] =  '\0';
#define GET_UNIT bi= 0;\
  while((*text!='\n')&&(*text!='\0')&&(*text!=' ')&&(*text!=',')&&\
        (*text!=':')&&(*text!='(')&&(*text!=')'))buffer[bi++]= *(text++);\
  buffer[bi] =  '\0'; if (*text!='\n')text++;


#define DEFAULT_LINE_BUFFER_SIZE 256
#define DEFAULT_HIGHEST_POINT_INDEX 1000
#define DEFAULT_HIGHEST_BOX_INDEX 1000
#define DEFAULT_HIGHEST_TRIANGLE_INDEX 1000

#define DEFAULT_AREA_CLASS 0
#define DEFAULT_BOUNDARY_CLASS 0


#define ENTER_BOX_POINT(B,P) if((P)->b1==nil)(P)->b1= (B);else\
  if((P)->b2==nil)(P)->b2= (B);else if((P)->b3==nil)(P)->b3= (B);else (P)->b4= (B)
#define ENTER_EDGE_POINT(ED,P) if((P)->e1==nil)(P)->e1= (ED);else\
  if((P)->e2==nil)(P)->e2= (ED);else if((P)->e3==nil)(P)->e3= (ED);else (P)->e4= (ED);
#define SQUARE_P(B) ((((B)->p1->x)*((B)->p2->x)+((B)->p1->y)*((B)->p2->y)<eps)&&\
(((B)->p2->x)*((B)->p3->x)+((B)->p2->y)*((B)->p3->y)<eps)&&\
(((B)->p3->x)*((B)->p4->x)+((B)->p3->y)*((B)->p4->y)<eps)&&\
((((B)->p1->x)*((B)->p1->x)+((B)->p1->y)*((B)->p1->y))-\
(((B)->p2->x)*((B)->p2->x)+((B)->p2->y)*((B)->p2->y))<eps))



#define ERROR_MISSING_NUMBER { sprintf(globBuf,"Missing point number on line %d\n'%10.10s'...\n",\
      line_number,line); ZIBStdOut(globBuf); no_error_occured =  false; break; }
#define NOT_REAL_NUMBER {sprintf(globBuf,"'%s' is not a real number on line %d\n'%10.10s'...\n",\
      buffer,line_number,line); ZIBStdOut(globBuf); no_error_occured =  false; break;}
#define LINE_END_ERROR if ((*text=='\0')||(*text=='\n'))\
  {sprintf(globBuf,"Line ended before command completion, line %d\n'%10.10s'...\n",\
      line_number,line); ZIBStdOut(globBuf); no_error_occured =  false; break;}
#define WRONG_ID(S,N) {sprintf(globBuf,"%d is not allowed as %s identifier\n",\
      N,S); ZIBStdOut(globBuf); no_error_occured =  false; break;}
#define POINT_NOT_DEFINED(N) {sprintf(globBuf,"Point %d is not defined\n",N); ZIBStdOut(globBuf);break;}
#define UNKNOWN_COMMAND {sprintf(globBuf,"Unknown command '%c' on line %d,\n%s",\
      *text,line_number,buffer); ZIBStdOut(globBuf); no_error_occured =  false; break;};
#define EDGE_NOT_FOUND(K1,K2) {sprintf(globBuf,"Edge not found between %d and %d at line %d\n",\
      K1,K2,line_number); ZIBStdOut(globBuf); no_error_occured =  false; break;}
#define EDGE_ALREADY_REFINED(K1,K2) {sprintf(globBuf,"Edge not found between %d and %d at line %d\n",\
      K1,K2,line_number); ZIBStdOut(globBuf); no_error_occured =  false; break;}
#define UNKNOWN_PARAMETER(C) {sprintf(globBuf,"Unknown parameter '%c' of '%c' at line %d\n",\
      *text,C,line_number); ZIBStdOut(globBuf); no_error_occured =  false; break;}
#define TOO_MANY_BOXES(I) {sprintf(globBuf,"Impossible: too many boxes on point %d\n",I); ZIBStdOut(globBuf);\
      no_error_occured =  false; break;}
#define THIRD_BOX_ON_EDGE {sprintf(globBuf,"Three boxes on one edge\n"); ZIBStdOut(globBuf); no_error_occured =  false; break;}
#define MORE_THAN_ONE_POINT(E,P) {sprintf(globBuf,"More than one point (%d,%d) on a edge (%d-%d)\n",\
    E->pm->id,P->id,E->p1->id,E->p2->id); ZIBStdOut(globBuf); no_error_occured =  false; break;}
#define DOUBLE_DEFINED(S,I) {sprintf(globBuf,"%s %d double defined\n",S,I); no_error_occured =  false; break;}
#define MISSING_NUMBER(C,P) {sprintf(globBuf,"Missing number for parameter '%c' of '%c'\n",\
    C,P); ZIBStdOut(globBuf); no_error_occured =  false; break;}
#define NO_EDGE_INDEX(N) {sprintf(globBuf,"Line %d: %d is no edge number\n",line_number,\
    N); ZIBStdOut(globBuf); no_error_occured =  false; break;}
#define WRONG_MIDPOINT_NUMBER(N) {sprintf(globBuf,"Line %d: %d not a midpoint number after 'R'\n",line_number,\
    N); ZIBStdOut(globBuf); no_error_occured =  false; break;}
#define WRONG_NUMBER(N) {sprintf(globBuf,"Line %d: %d not a number after 'A'\n",line_number,\
    N); ZIBStdOut(globBuf); no_error_occured =  false; break;}
#define NOT_A_SQUARE(B) {sprintf(globBuf,"Line %d: box %d id not a square\n",line_number,\
    (B)->id); ZIBStdOut(globBuf); no_error_occured =  false; break;}
#define POINTS_ON_LINE(BID,P1ID,P2ID,P3ID) {sprintf(globBuf,"Line %d: box %d, points %d, %d, %d on a line\n",\
    line_number,BID,P1ID,P2ID,P3ID); ZIBStdOut(globBuf);no_error_occured =  false; break;}
#define BOX_NOT_ORIENTED(BID) {sprintf(globBuf,"Line %d: box %d not oriented\n",\
    line_number,BID); ZIBStdOut(globBuf);no_error_occured =  false; break;}



#define NOT_ENOUGH_MEMORY(S,M) {sprintf(globBuf,"Read_Boxes.%s: not enough memory %d bytes/n",\
      S,M); ZIBStdOut(globBuf); exit(6);}


static line_buffer_size= DEFAULT_LINE_BUFFER_SIZE;
static max_user_point_index= DEFAULT_HIGHEST_POINT_INDEX;
static max_user_box_index= DEFAULT_HIGHEST_BOX_INDEX;
static max_user_triangle_index= DEFAULT_HIGHEST_TRIANGLE_INDEX;

static int current_area_class= DEFAULT_AREA_CLASS;
static int current_boundary_x_class= DEFAULT_BOUNDARY_CLASS;

static char *text, *line, *buffer;
static int line_number,bi,p_counter,b_counter,t_counter;
static point**user_points= nil;
static box**user_boxes= nil;
static triangle**user_triangles= nil;

static int no_error_occured= true;

/*-------------------------------------------------------------------------*/


edge* Boxes::search_edge(point* p1,point* p2)
{
    edge*ed= first_edge;
    
    while(ed)
    {
        if(((ed->p1==p1)&&(ed->p2==p2))||((ed->p1==p2)&&(ed->p2==p1)))return ed;
        ed= ed->next;
    }
    return nil;
}


int Boxes::Read_Boxes(char* tp)
{
    double x,y,sol,dx1,dy1,dx2,dy2, lng1, lng2, area;
    int index,i,k,k1,k2,k3,k4, x_class, e_no, e_x_class,
    		second_x_class,circle_type,c_type;
    point* p,**pts,*save_point;
    triangle*t;
    box*b;
    edge* e1,*e2,*e3,*e4,**eds_point,*e_p,**eds_box, *e_b, *ed;
    char save_char;
    
    
    line= text= tp;line_number= 1;
    
    buffer= ZIBAlloc((long)line_buffer_size*sizeof(char));
    if(buffer==nil)
    NOT_ENOUGH_MEMORY("buffer",line_buffer_size*sizeof(char));
    
    user_points= (point**)ZIBAlloc((long)max_user_point_index*sizeof(point*));
    if(user_points==nil)
    NOT_ENOUGH_MEMORY("user_points",max_user_point_index*sizeof(point*));
    for(k= 0;k<max_user_point_index;k++)user_points[k]= nil;
    
    user_boxes= (box**)ZIBAlloc((long)max_user_box_index*sizeof(box*));
    if(user_boxes==nil)
    NOT_ENOUGH_MEMORY("user_boxes",max_user_box_index*sizeof(box*));
    for(k= 0;k<max_user_box_index;k++)user_boxes[k]= nil;
    
    user_triangles= (triangle**)ZIBAlloc((long)max_user_triangle_index*sizeof(triangle*));
    if(user_triangles==nil)
    NOT_ENOUGH_MEMORY("user_triangles",max_user_triangle_index*sizeof(box*));
    for(k= 0;k<max_user_box_index;k++)user_triangles[k]= nil;
    
    p_counter= b_counter= t_counter= 0;
    
    /* :5 */
    
    no_error_occured= true;
    while(*text)
    {
        SKIP_SPACE;
        switch(*text)
        {
            case 'P':case 'p':
            /* 7: */
            
            
            text++;SKIP_SPACE;
            GET_UNIT;
            if(sscanf(buffer,"%d",&index)==0)ERROR_MISSING_NUMBER;
            LINE_END_ERROR;SKIP_SPACE;
            GET_UNIT;
            if(sscanf(buffer,"%le",&x)==0)NOT_REAL_NUMBER;
            LINE_END_ERROR;SKIP_SPACE;
            GET_UNIT;
            if(sscanf(buffer,"%le",&y)==0)NOT_REAL_NUMBER;
            x_class= current_boundary_x_class;
            sol= ZERO;
            
            /* :7 *//* 8: */
            
            
            if((index<0)||(index>max_user_point_index))WRONG_ID("Point",index);
            
            p= GET_POINT;
            p->id= index;p->x= x;p->y= y;
            p_counter++;
            
            /* :8 *//* 9: */
            
            
            if(first_point==nil)
            {first_point= p;last_point= p;}
            else
            {
                p->last= last_point;
                last_point->next= p;
                last_point= p;
                }
            if(user_points[index]==nil)user_points[index]= p;
            else DOUBLE_DEFINED("Point",index);
            
            /* :9 *//* 10: */
            
            
            k1= k2= -1;
            while((*text!='\n')&&(*text!='\0'))
            {
                SKIP_SPACE;
                save_char= *text;
                text++;
                SKIP_SPACE;GET_UNIT;
                switch(save_char)
                {
                    case 'T':case 't':
                    if(sscanf(buffer,"%d",&x_class)==0)MISSING_NUMBER('P','T');
                    break;
                    case 'D':case 'd':
                    p->boundary_type= DIRICHLET;
                    break;
                    case 'N':case 'n':
                    p->boundary_type= NEUMANN;
                    break;
                    case 'C':case 'c':
                    p->boundary_type= CAUCHY;
                    break;
                    case 'S':case 's':
                    if(sscanf(buffer,"%le",&sol)==0)MISSING_NUMBER('P','S');
                    break;
                    case 'A':case 'a':
                    if(sscanf(buffer,"%d",&k1)==0)MISSING_NUMBER('P','A');
                    break;
                    case 'B':case 'b':
                    if(sscanf(buffer,"%d",&k2)==0)MISSING_NUMBER('P','B');
                    break;
                    case '\n':case '\0':
                    break;
                    default:
                    UNKNOWN_PARAMETER('P');
                    }
                }
            p->point_class= x_class;
            p->sol= sol;
            
            /* :10 *//* 11: */
            
            
            if((k1!=-1)&&(k2!=-1))
            {
                if((k1<0)||(k1>max_user_point_index))WRONG_ID("Point",k1);
                if((k2<0)||(k2>max_user_point_index))WRONG_ID("Point",k2);
                ed= search_edge(user_points[k1],user_points[k2]);
                if(ed==nil)EDGE_NOT_FOUND(k1,k2);
                if((ed->pm)!=nil)EDGE_ALREADY_REFINED(k1,k2);
                
                ed->pm= p;p->valid= true;
                e1= GET_EDGE;e2= GET_EDGE;
                e1->p1= ed->p1;e1->p2= p;
                e2->p1= p;e2->p2= ed->p2;
                ed->son1= e1;ed->son2= e2;
                ed->div_factor= EDGE_LENGTH(e1)/EDGE_LENGTH(ed);
                e1->father= e2->father= ed;
                e1->boundary_type= e2->boundary_type= ed->boundary_type;
                e1->edge_class= e2->edge_class= ed->edge_class;
                if(first_edge==nil)
                {first_edge= e1;last_edge= e2;}
                else
                {
                    e1->last= last_edge;
                    last_edge->next= e1;
                    last_edge= e2;
                    }
                e2->last= e1;
                e1->next= e2;
                }
            
            /* :11 */
            break;
            case 'B':case 'b':
            /* 12: */
            
            text++;SKIP_SPACE;
            GET_UNIT;
            if(sscanf(buffer,"%d",&index)==0)ERROR_MISSING_NUMBER;
            LINE_END_ERROR;SKIP_SPACE;
            GET_UNIT;
            if(sscanf(buffer,"%d",&k1)==0)ERROR_MISSING_NUMBER;
            LINE_END_ERROR;SKIP_SPACE;
            GET_UNIT;
            if(sscanf(buffer,"%d",&k2)==0)ERROR_MISSING_NUMBER;
            LINE_END_ERROR;SKIP_SPACE;
            GET_UNIT;
            if(sscanf(buffer,"%d",&k3)==0)ERROR_MISSING_NUMBER;
            LINE_END_ERROR;SKIP_SPACE;
            GET_UNIT;
            if(sscanf(buffer,"%d",&k4)==0)ERROR_MISSING_NUMBER;
            x_class= current_area_class;
            c_type= 0;
            
            /* :12 *//* 13: */
            
            
            if((index<0)||(index>max_user_box_index))WRONG_ID("box",index);
            if((k1<0)||(k1>max_user_box_index))WRONG_ID("Point",k1);
            if((k2<0)||(k2>max_user_box_index))WRONG_ID("Point",k2);
            if((k3<0)||(k3>max_user_box_index))WRONG_ID("Point",k3);
            if((k4<0)||(k4>max_user_box_index))WRONG_ID("Point",k4);
            if(user_points[k1]==nil)POINT_NOT_DEFINED(k1);
            if(user_points[k2]==nil)POINT_NOT_DEFINED(k2);
            if(user_points[k3]==nil)POINT_NOT_DEFINED(k3);
            if(user_points[k4]==nil)POINT_NOT_DEFINED(k4);
            
            b= GET_BOX;
            b->id= index;
            b->p1= user_points[k1];b->p2= user_points[k2];
            b->p3= user_points[k3];b->p4= user_points[k4];
            b->area_class= x_class;
            (b->p1)->valid= true;(b->p2)->valid= true;
            (b->p3)->valid= true;(b->p4)->valid= true;
            b_counter++;
            
            /* :13 *//* 14: */
            
            
            if(first_box==nil)
            {first_box= b;last_box= b;}
            else
            {
                b->last= last_box;
                last_box->next= b;
                last_box= b;
                }
            if(user_boxes[index]==nil)user_boxes[index]= b;
            else DOUBLE_DEFINED("box",index);
            
            /* :14 *//* 15: */
            
            
            ENTER_BOX_POINT(b,b->p1);
            ENTER_BOX_POINT(b,b->p2);
            ENTER_BOX_POINT(b,b->p3);
            ENTER_BOX_POINT(b,b->p4);
            
            /* :15 *//* 16: */
            
            
            b->e1= e1= GET_EDGE;
            b->e2= e2= GET_EDGE;
            b->e3= e3= GET_EDGE;
            b->e4= e4= GET_EDGE;
            if(e4==nil)NOT_ENOUGH_MEMORY("edge",sizeof(edge));
            e1->id= -(new_edge_counter++);
            e2->id= -(new_edge_counter++);
            e3->id= -(new_edge_counter++);
            e4->id= -(new_edge_counter++);
            
            e1->p1= e4->p2= b->p1;
            e2->p1= e1->p2= b->p2;
            e3->p1= e2->p2= b->p3;
            e4->p1= e3->p2= b->p4;
            
            e1->b1= e2->b1= e3->b1= e4->b1= b;
            
            /* :16 *//* 17: */
            
            
            if(first_edge==nil)
            {first_edge= e1;last_edge= e4;}
            else
            {
                e1->last= last_edge;
                last_edge->next= e1;
                last_edge= e4;
                }
            e2->last= e1;
            e3->last= e1->next= e2;
            e4->last= e2->next= e3;
            e3->next= e4;
            
            /* :17 *//* 18: */
            
            
            eds_box= EDGES_OF_BOX(b);
            pts= POINTS_OF_BOX(b);
            
            for(i= 0;i<4;i++)
            {
                e_b= eds_box[i];
                eds_point= EDGES_OF_POINT(pts[i]);
                for(k= 0;k<4;k++)
                {
                    e_p= eds_point[k];
                    if(e_p==nil)
                    {eds_point[k]= eds_box[i];break;}
                    /* 19: */
                    
                    
                    if(((e_p->p1==pts[i])&&(e_p->p2==pts[(i+1)%4]))||
                    ((e_p->p2==pts[i])&&(e_p->p1==pts[(i+1)%4])))
                    {
                        if((e_b->b2)!=nil)THIRD_BOX_ON_EDGE;
                        
                        if(e_b==first_edge)
                        {first_edge= first_edge->next;first_edge->last= nil;}
                        else(e_b->last)->next= e_b->next;
                        if(e_b==last_edge)
                        {last_edge= last_edge->last;last_edge->next= nil;}
                        else(e_b->next)->last= e_b->last;
                        RETURN_EDGE(e_b);
                        eds_box[i]= eds_point[k];
                        eds_box[i]->b2= b;
                        break;
                        }
                    
                    
                    if((e_p->p1)==pts[i])
                    {
                        dx1= (e_p->p2)->x-pts[i]->x;
                        dy1= (e_p->p2)->y-pts[i]->y;
                        }
                    else
                    {
                        dx1= (e_p->p1)->x-pts[i]->x;
                        dy1= (e_p->p1)->y-pts[i]->y;
                        }
                    lng1= sqrt(dx1*dx1+dy1*dy1);
                    
                    dx2= pts[(i+1)%4]->x-pts[i]->x;
                    dy2= pts[(i+1)%4]->y-pts[i]->y;
                    lng2= sqrt(dx2*dx2+dy2*dy2);
                    
                    area= dx1*dy2-dx2*dy1;
                    
                    if(fabs(area)>eps*lng1*lng2)continue;
                    if((dx1*dx2<0.0)||(dy1*dy2<0.0))continue;
                    
                    e_b->b2= e_p->b1;
                    e_p->b2= b;
                    
                    /* :20 *//* 21: */
                    
                    
                    if(lng1>=lng2)
                    {
                        eds_point[k]->son2= eds_box[i];
                        eds_box[i]->father= eds_point[k];
                        if((eds_point[k]->pm)&&
                        ((eds_point[k]->pm)!=(eds_box[i]->p2)))
                        MORE_THAN_ONE_POINT(eds_point[k],eds_box[i]->p2);
                        eds_point[k]->pm= eds_box[i]->p2;
                        
                        save_point= eds_box[i]->p1;
                        eds_box[i]->p1= eds_box[i]->p2;
                        eds_box[i]->p2= save_point;
                        
                        eds_point[k]->div_factor= 1.0-lng2/lng1;
                        }
                    else
                    {
                        eds_box[i]->son1= eds_point[k];
                        eds_point[k]->father= eds_box[i];
                        if((eds_box[i]->pm)&&
                        ((eds_point[k]->pm)!=(eds_point[k]->p1)))
                        MORE_THAN_ONE_POINT(eds_point[k],eds_point[k]->p1);
                        eds_box[i]->pm= eds_point[k]->p1;
                        
                        save_point= eds_point[k]->p1;
                        eds_point[k]->p1= eds_point[k]->p2;
                        eds_point[k]->p2= save_point;
                        
                        eds_box[i]->div_factor= lng1/lng2;
                        }
                    
                    /* :21 */
                    
                    break;
                    }
                if(k==4)TOO_MANY_BOXES(pts[i]->id);
                
                eds_point= EDGES_OF_POINT(pts[(i+1)%4]);
                for(k= 0;k<4;k++)
                {
                    e_p= eds_point[k];
                    if(e_p==nil)
                    {eds_point[k]= eds_box[i];break;}
                    /* 22: */
                    
                    
                    if(((e_p->p1==pts[i])&&(e_p->p2==pts[(i+1)%4]))||
                    ((e_p->p2==pts[i])&&(e_p->p1==pts[(i+1)%4])))break;
                    if((e_p->p1)==pts[(i+1)%4])
                    {
                        dx1= (e_p->p2)->x-pts[(i+1)%4]->x;
                        dy1= (e_p->p2)->y-pts[(i+1)%4]->y;
                        }
                    else
                    {
                        dx1= (e_p->p1)->x-pts[(i+1)%4]->x;
                        dy1= (e_p->p1)->y-pts[(i+1)%4]->y;
                        }
                    
                    lng1= sqrt(dx1*dx1+dy1*dy1);
                    
                    dx2= pts[i]->x-pts[(i+1)%4]->x;
                    dy2= pts[i]->y-pts[(i+1)%4]->y;
                    lng2= sqrt(dx2*dx2+dy2*dy2);
                    
                    area= dx1*dy2-dx2*dy1;
                    
                    if(fabs(area)>eps*lng1*lng2)continue;
                    if((dx1*dx2<0.0)||(dy1*dy2<0.0))continue;
                    
                    e_b->b2= e_p->b1;
                    e_p->b2= b;
                    
                    if(lng1>lng2)
                    {
                        eds_point[k]->son1= eds_box[i];
                        eds_box[i]->father= eds_point[k];
                        if((eds_point[k]->pm)&&
                        ((eds_point[k]->pm)!=(eds_box[i]->p1)))
                        MORE_THAN_ONE_POINT(eds_point[k],eds_box[i]->p1);
                        eds_point[k]->pm= eds_box[i]->p1;
                        
                        save_point= eds_box[i]->p1;
                        eds_box[i]->p1= eds_box[i]->p2;
                        eds_box[i]->p2= save_point;
                        
                        eds_point[k]->div_factor= lng2/lng1;
                        }
                    else
                    {
                        eds_box[i]->son2= eds_point[k];
                        eds_point[k]->father= eds_box[i];
                        if((eds_box[i]->pm)&&
                        ((eds_point[k]->pm)!=(eds_point[k]->p2)))
                        MORE_THAN_ONE_POINT(eds_point[k],eds_point[k]->p2);
                        eds_box[i]->pm= eds_point[k]->p2;
                        
                        save_point= eds_point[k]->p1;
                        eds_point[k]->p1= eds_point[k]->p2;
                        eds_point[k]->p2= save_point;
                        
                        eds_box[i]->div_factor= 1.0-lng1/lng2;
                        }
                    
                    /* :22 */
                    
                    break;
                    }
                if(k==4)TOO_MANY_BOXES(pts[(i+1)%4]->id);
                }
            
            /* :18 *//* 23: */
            
            
            second_x_class= x_class;
            while((*text!='\n')&&(*text!='\0'))
            {
                SKIP_SPACE;
                save_char= *text;
                text++;
                SKIP_SPACE;GET_UNIT;
                switch(save_char)
                {
                    case 'T':case 't':
                    x_class= 0;
                    sscanf(buffer,"%d",&x_class);
                    second_x_class= current_area_class= x_class;
                    break;
                    case 'F':case 'f':
                    c_type= 0;
                    sscanf(buffer,"%d",&c_type);
                    break;
                    case 'R':case 'r':
                    circle_type= 0;
                    sscanf(buffer,"%d",&circle_type);
                    if((circle_type<1)||(circle_type>4))
                    WRONG_MIDPOINT_NUMBER(circle_type);
                    if(SQUARE_P(b))NOT_A_SQUARE(b);
                    b->quarter_circle= circle_type;
                    c_type= ((circle_type==1)||(circle_type==3))?LTRB:LBRT;
                    break;
                    case 'A':case 'a':
                    second_x_class= x_class;
                    sscanf(buffer,"%d",&second_x_class);
                    if(second_x_class==-1)
                    {
                        (b->e3)->unvalid= true;
                        (b->e4)->unvalid= true;
                        (b->p4)->valid= false;;
                        }
                    break;
                    case 'D':case 'd':
                    e_no= 0;
                    sscanf(buffer,"%d",&e_no);
                    if((e_no<1)||(e_no>4))NO_EDGE_INDEX(e_no);
                    (&(b->e1))[e_no-1]->boundary_type= DIRICHLET;
                    break;
                    case 'N':case 'n':
                    e_no= 0;
                    sscanf(buffer,"%d",&e_no);
                    if((e_no<1)||(e_no>4))NO_EDGE_INDEX(e_no);
                    (&(b->e1))[e_no-1]->boundary_type= NEUMANN;
                    break;
                    case 'C':case 'c':
                    e_no= 0;
                    sscanf(buffer,"%d",&e_no);
                    if((e_no<1)||(e_no>4))NO_EDGE_INDEX(e_no);
                    (&(b->e1))[e_no-1]->boundary_type= CAUCHY;
                    break;
                    case 'B':case 'b':
                    e_no= 0;
                    sscanf(buffer,"%d",&e_no);
                    if((e_no<1)||(e_no>4))NO_EDGE_INDEX(e_no);
                    if((*text=='\n')||(*text=='\0'))MISSING_NUMBER('B','B');
                    SKIP_SPACE;GET_UNIT;
                    e_x_class= 0;
                    sscanf(buffer,"%d",&e_x_class);
                    (&(b->e1))[e_no-1]->edge_class= e_x_class;
                    break;
                    case '\n':case '\0':
                    break;
                    default:
                    UNKNOWN_PARAMETER('B');
                    }
                }
            b->area_class= x_class;
            b->second_area_class= second_x_class;
            b->coarse_type= c_type;
            
            /* :23 *//* 24: */
            
            
            do{
                xreal x21,x31,y21,y31,jac;
                
                x21= (b->p2)->x-(b->p1)->x;x31= (b->p3)->x-(b->p1)->x;
                y21= (b->p2)->y-(b->p1)->y;y31= (b->p3)->y-(b->p1)->y;
                jac= x21*y31-x31*y21;
                if(jac==ZERO)POINTS_ON_LINE(b->id,1,2,3);
                if(jac<ZERO)BOX_NOT_ORIENTED(b->id);
                
                x21= (b->p3)->x-(b->p2)->x;x31= (b->p4)->x-(b->p2)->x;
                y21= (b->p3)->y-(b->p2)->y;y31= (b->p4)->y-(b->p2)->y;
                jac= x21*y31-x31*y21;
                if(jac==ZERO)POINTS_ON_LINE(b->id,2,3,4);
                if(jac<ZERO)BOX_NOT_ORIENTED(b->id);
                
                x21= (b->p4)->x-(b->p3)->x;x31= (b->p1)->x-(b->p3)->x;
                y21= (b->p4)->y-(b->p3)->y;y31= (b->p1)->y-(b->p3)->y;
                jac= x21*y31-x31*y21;
                if(jac==ZERO)POINTS_ON_LINE(b->id,3,4,1);
                if(jac<ZERO)BOX_NOT_ORIENTED(b->id);
                
                x21= (b->p1)->x-(b->p4)->x;x31= (b->p2)->x-(b->p4)->x;
                y21= (b->p1)->y-(b->p4)->y;y31= (b->p2)->y-(b->p4)->y;
                jac= x21*y31-x31*y21;
                if(jac==ZERO)POINTS_ON_LINE(b->id,4,1,2);
                if(jac<ZERO)BOX_NOT_ORIENTED(b->id);
                }while(false);
            
            /* :24 */
            break;
            case 'T':case 't':
            /* 25: */
            
            text++;SKIP_SPACE;
            GET_UNIT;
            if(sscanf(buffer,"%d",&index)==0)ERROR_MISSING_NUMBER;
            LINE_END_ERROR;SKIP_SPACE;
            GET_UNIT;
            if(sscanf(buffer,"%d",&k1)==0)ERROR_MISSING_NUMBER;
            LINE_END_ERROR;SKIP_SPACE;
            GET_UNIT;
            if(sscanf(buffer,"%d",&k2)==0)ERROR_MISSING_NUMBER;
            LINE_END_ERROR;SKIP_SPACE;
            GET_UNIT;
            if(sscanf(buffer,"%d",&k3)==0)ERROR_MISSING_NUMBER;
            x_class= current_area_class;
            c_type= 0;
            
            /* :25 *//* 26: */
            
            
            if((index<0)||(index>max_user_box_index))WRONG_ID("triangle",index);
            if((k1<0)||(k1>max_user_box_index))WRONG_ID("Point",k1);
            if((k2<0)||(k2>max_user_box_index))WRONG_ID("Point",k2);
            if((k3<0)||(k3>max_user_box_index))WRONG_ID("Point",k3);
            if(user_points[k1]==nil)POINT_NOT_DEFINED(k1);
            if(user_points[k2]==nil)POINT_NOT_DEFINED(k2);
            if(user_points[k3]==nil)POINT_NOT_DEFINED(k3);
            
            t= GET_TRIANGLE;
            t->id= index;
            t->p1= user_points[k1];t->p2= user_points[k2];
            t->p3= user_points[k3];
            t->area_class= x_class;
            (t->p1)->valid= true;(t->p2)->valid= true;
            (t->p3)->valid= true;
            t_counter++;
            
            /* :26 *//* 27: */
            
            
            if(first_triangle==nil)
            {first_triangle= t;last_triangle= t;}
            else
            {
                t->last= last_triangle;
                last_triangle->next= t;
                last_triangle= t;
                }
            if(user_triangles[index]==nil)user_triangles[index]= t;
            else DOUBLE_DEFINED("triangle",index);
            
            /* :27 *//* 28: */
            
            
            e1= search_edge(t->p2,t->p3);
            if(e1==nil)
            {
                e1= GET_EDGE;
                e1->id= -(new_edge_counter++);
                e1->p1= t->p2;e1->p2= t->p3;
                if(first_edge==nil)
                {first_edge= e1;last_edge= e1;}
                else
                {
                    e1->last= last_edge;
                    last_edge->next= e1;
                    last_edge= e1;
                    }
                }
            t->e1= e1;
            if(e1->father)e1->boundary_type= INTERIOR;
            
            e2= search_edge(t->p3,t->p1);
            if(e2==nil)
            {
                e2= GET_EDGE;
                e2->id= -(new_edge_counter++);
                e2->p1= t->p3;e2->p2= t->p1;
                
                e2->last= last_edge;
                last_edge->next= e2;
                last_edge= e2;
                }
            t->e2= e2;
            if(e2->father)e2->boundary_type= INTERIOR;
            
            e3= search_edge(t->p1,t->p2);
            if(e3==nil)
            {
                e3= GET_EDGE;
                e3->id= -(new_edge_counter++);
                e3->p1= t->p1;e3->p2= t->p2;
                
                e3->last= last_edge;
                last_edge->next= e3;
                last_edge= e3;
                }
            t->e3= e3;
            if(e3->father)e3->boundary_type= INTERIOR;
            
            /* :28 *//* 29: */
            
            
            while((*text!='\n')&&(*text!='\0'))
            {
                SKIP_SPACE;
                save_char= *text;
                text++;
                SKIP_SPACE;GET_UNIT;
                switch(save_char)
                {
                    case 'T':case 't':
                    x_class= 0;
                    sscanf(buffer,"%d",&x_class);
                    second_x_class= current_area_class= x_class;
                    break;
                    case 'D':case 'd':
                    e_no= 0;
                    sscanf(buffer,"%d",&e_no);
                    if((e_no<1)||(e_no>3))NO_EDGE_INDEX(e_no);
                    (&(t->e1))[e_no-1]->boundary_type= DIRICHLET;
                    break;
                    case 'N':case 'n':
                    e_no= 0;
                    sscanf(buffer,"%d",&e_no);
                    if((e_no<1)||(e_no>3))NO_EDGE_INDEX(e_no);
                    (&(t->e1))[e_no-1]->boundary_type= NEUMANN;
                    break;
                    case 'C':case 'c':
                    e_no= 0;
                    sscanf(buffer,"%d",&e_no);
                    if((e_no<1)||(e_no>3))NO_EDGE_INDEX(e_no);
                    (&(t->e1))[e_no-1]->boundary_type= CAUCHY;
                    break;
                    case 'B':case 'b':
                    e_no= 0;
                    sscanf(buffer,"%d",&e_no);
                    if((e_no<1)||(e_no>3))NO_EDGE_INDEX(e_no);
                    if((*text=='\n')||(*text=='\0'))MISSING_NUMBER('B','B');
                    SKIP_SPACE;GET_UNIT;
                    e_x_class= 0;
                    sscanf(buffer,"%d",&e_x_class);
                    (&(t->e1))[e_no-1]->edge_class= e_x_class;
                    break;
                    case '\n':case '\0':
                    break;
                    default:
                    UNKNOWN_PARAMETER('T');
                    }
                }
            t->area_class= x_class;
            
            /* :29 */
            break;
            case '\n':
            case '%':case '#':
            break;
            default:
            GET_LINE;
            UNKNOWN_COMMAND;
	}
        SKIP_LINE;
    }
    
    
    ZIBFree(buffer);
    ZIBFree((char*) user_points);
    ZIBFree((char*) user_boxes);
    
    if(no_error_occured && infoBoxes)
    {
        cout << "\n\tBoxes: " << p_counter << " points, " << b_counter 
	<< " boxes, " << t_counter << " triangles read\n";
    }
    return no_error_occured;
}
