#usage "en:<qt><nobr>After initial export of P-CAD / Altium and Protel boards and schematics <br>"
       "to ACCEL ASCII format you can import your designs herewith into EAGLE.<br>"
       // Remove this when it goes into EAGLE "
       //"<author>Author: apl@cadsoft.de</author>"
       ,
       "de:<qt><nobr>Durch vorherigem Export von P-CAD-/Altium- und Protel-Boards und -Schaltplänen <br>"
       "in ACCEL-ASCII-Format können Sie Ihre Designs hiermit in EAGLE importieren.<br>"
       //"<author>Autor: apl@cadsoft.de</author>"
       ,
       "ru:<qt><nobr>Импорт из Altium / Protel и P-CAD топологии или схемы в ACCEL ASCII формат.<br>"
       "Сделайте экспорт в формат ACCEL ASCII и затем импортируйте этот файл в EAGLE.<br>"
       //"<author>Автор: apl@cadsoft.de</author>"

string Version = "1.1.2";

#require 6.0300

// Please keep to alpabetic ordering for maintainability !
string Dictionary[] = {
  "en\v"
  "de\v"
  "ru\v",
  "Cancel\v"
  "Abbrechen\v"
  "Отмена\v",
  "ACCEL - EAGLE layer mapping\v"
  "ACCEL - EAGLE - Layerzuordnung\v"
  "ACCEL - EAGLE - соответствие слоёв\v",
  "ACCEL\nType\tACCEL\nLayer\tACCEL\nNumber\tEAGLE\nNumber\tEAGLE\nName\v"
  "ACCEL\nTyp\tACCEL\nLayer\tACCEL\nNummer\tEAGLE\nNummer\tEAGLE\nName\v"
  "ACCEL\nТип\tACCEL\nСлой\tACCEL\nНомер\tEAGLE\nНомер\tEAGLE\nИмя\v",
  "Adjust layer mapping\v"
  "Layerzuordnung anpassen\v"
  "Настройка соответствия слоёв\v",
  "&Browse\v"
  "&Suchen\v"
  "&Обзор\v",
  " doesn't exist!\v"
  " existiert nicht!\v"
  " не существует!\v",
  "File \v"
  "Datei \v"
  "Файл\v",
  "Help\v"
  "Hilfe\v"
  "Помощь\v",
  "Import P-CAD/Altium/Protel (ACCEL ASCII)\v"
  "Import von P-CAD/Altium/Protel (ACCEL ASCII)\v"
  "Импорт из P-CAD/Altium/Protel (ACCEL ASCII)\v",
  "Import file:\v"
  "Import-Datei:\v"
  "Импортируемый файл:\v",
  "Load\v"
  "Laden\v"
  "Загрузить\v",
  "Mapping:\v"
  "Zuordnung:\v"
  "Соответствие:\v",
  "Please start from board or schematic editor !\v"
  "Bitte starten Sie vom Board- oder Schaltplan-Editor!\v"
  "Пожалуйста, начните с редактора топологии или схемы!\v",
  "Process sheet \v"
  "Bearbeite Sheet \v"
  "Обработка листа \v",
  "Save\v"
  "Speichern\v"
  "Сохранить\v",
  "Save layer mapping file\v"
  "Layerzuordnungs-Datei speichern\v"
  "Сохранить соответствие слоёв\v",
  "Select import file\v"
  "Import-Datei auswählen\v"
  "Выберите импортируемый файл\v",
  "Select layer mapping file\v"
  "Layerzuordnungs-Datei auswählen\v"
  "Выберите файл соответствия слоёв\v",
  "Start\v"
  "Start\v"
  "Старт\v",
  "Wrong file signature: \v"
  "Falsche Datei-Signatur: \v"
  "Неправильная сигнатура файла: \v",
  "Warnings log\v"
  "Warnungen log\v"
  "Предупреждения\v",
  "-Back\v"
  "-Zurück\v"
  "-Обратно\v",
  "Can't open default.dru !",
  "Kann nicht geöffnet werden default.dru !",
  "Ошибка при открытии файла default.dru !"
};

string DlgLang = language();
if (DlgLang != "de" && DlgLang != "ru") DlgLang = "en";
int LangIdx = strstr(Dictionary[0], DlgLang) / 3;

// Translate, based on dictionary
string TR(string s) {
  string t = lookup(Dictionary, s, LangIdx, '\v');
  return t ? t : s;
}
//-----------------------------------------------------------------------------

// merged string contains input file without comments
string MergedString;

// Header

string Tokens[];
int TokensNumber = 0;
int CurrentChar = 0;
int CurrentToken = 0;

string MajorVersion;
string MinorVersion;

string TimeStampYear;
string TimeStampMonth;
string TimeStampDay;
string TimeStampHour;
string TimeStampMinute;
string TimeStampSecond;

string ProgramName;
string ProgramVersion;

string Copyright;

string HeaderString;

string FileUnits;

string GuidString;

string FileAuthor;

// Library

string LibraryName;

// This is a collection of data for Pads shapes

int PadShapeStyleShapeType[];
string PadShapeStyleDefsWidth[];
string PadShapeStyleDefsHeight[];
int PadShapeStyleDefsPolygon[];
string PadShapeStyleDefsLayer[];
int NrPadShapeStyle = 0;

int PadStyleDefsArray[];
string PadStyleDefsScript[];
int PadShapeAddRotation[];
// Pointer and number of Pad shapes in collection
int PadShapePoiner[];
int NrPadShapes[];
int PadStyleDefsSkip[];
int IfSMD[];
int PadStyleDefsNumber = 0;

int ViaStyleDefsArray[];
string ViaStyleDefsScript[];
string ViaStyleDefsType[];
string ViaStyleDefsDiameter[];
int ViaStyleDefsSkip[];
int ViaStyleDefsNumber = 0;

int TextStyleDefsArray[];
string TextStyleDefFontHeight[];
string TextStyleDefFontStrokeWidth[];
int TextStyleDefsNumber = 0;

int PatternDefExtendedArray[];
int PatternGraphicsDefArray[];
int IfNameDefinedInPattern[];
int IfValueDefinedInPattern[];
int PatternAttributesIndex[];
int PatternNrAttributes[];
string PatternName[];
string PatternOriginalName[];
string PatternGraphicsDefName[];
string PatternDefaultVariantName[];
int PatternDefExtendedNumber = 0;

int NrPadPinMap = 0;
string PadPinMapNum[];
string PadPinMapPinRef[];

int CompDefsArray[];
int CompDefsNumber = 0;
int PadPinMapRef[];
int PadPinMapCount[];

int NrAttributes = 0;
string AttributesName[];
int AttributesIndex[];

int SymbolDefsArray[];
string SymbolsName[];
string OriginalSymbolsName[];
int IfNameDefinedInSymbol[];
int IfValueDefinedInSymbol[];
int SymbolAttributesIndex[];
int SymbolNrAttributes[];
int SymbolDefsNumber = 0;

string DevicesName[];
string SymbolDevicesName[];
int NrSymbolDevices = 0;

int NrPadsOnBoard = 0;
int PadOnBoardIndex[];
string PadOnBoardDefs[];

int NrDummyDevices = 0;
string DummyDevices[];

// Netlist

string NetlistName;

// PCBDesign

int PCBDesignToken = 0;
string PcbDesignName = "";

int LayerDefsArray[];
string LayersName[];
int LayersCode[];
string LayersType[];
int LayerDefsNumber = 0;

int PCBDesignMultiLayerToken = 0;

int PCBLayerContentsArray[];
int NrPCBLayerContents = 0;

// schematicDesign

int SchematicDesignToken = 0;
string SchematicDesignName = "";

int SchTitleSheet = 0;

int SheetsArray[];
int NrSheets = 0;

int CompInstances[];
int NrCompInstances = 0;
string CompInstancesName[];
string CompInstancesRef[];
string CompValue[];

int NrNodes = 0;
string NodeElementName[];
string NodePadName[];

int NrNets = 0;
string NetNames[];
int NodeRef[];
int NrNetNodes[];

int NrLabels = 0;
string XCoordLabels[];
string YCoordLabels[];
string TypeLabels[];
string NetNameRef[];
string IsLabelFlipped[];
string LabelRotation[];

// Misc

int DebugMessage = 1;

int IfPinText = 0;

string LabelTextHeight = "0.07inch";
string NameValueTextHeight = "0.05inch";

int IfUpdateLayersMap = 0;

string PCADfileName;
string SCRIPTfileName;
string WarningsLogFileName;

string ext[] = { "*.asc", "*.asc" };
enum   { PCB, SCH };
int    FileType  = PCB;
//string FileInfo = "Select a import file.";

int    Lines;
string PcadLines[];

string Status;  // = "First select a ACCEL_ASCII file, then click on Start.";

int SchematicWindow = 0;
int BoardWindow = 0;

real WiresPointX[];
real WiresPointY[];
string WiresNet[];
int NrWiresPoint = 0;

int UseExternalText = 0;
string ExternalText = "";

int BatchMode = 0;

string DEFAULT_WIRE_WIDTH_BOARD = "10mil";
string DEFAULT_WIRE_WIDTH_SCHEMATIC = "6mil";

real ROUNDNESS = 3.0;

string DRUFileName;

int Vers = 1;
int SubVers = 1;

string LogLines[];
int    NrLogLines;

void WriteLog( string message )
{
  if( DebugMessage ) {
    printf( "%s", message );
  }

  LogLines[ NrLogLines++ ] = message;
}

string GetFile(string fname)
{
  PCADfileName = fname;
  if (fname) PCADfileName = filesetext(fname,"/");
  string f[];
  int fcnt;

  if (fname) fcnt = fileglob(f, PCADfileName);  // 2008-10-21 check file name

  if( !fcnt ) {
    PCADfileName = dlgFileOpen(TR("Select import file"), fname,
  ext[FileType] + " *.pcb *.ASC *.PCB *.sch *.txt *.TXT;; (*.*)");
    if (!PCADfileName) return fname;
  }

  Lines = fileread(PcadLines, PCADfileName);
  if (Lines == -1) exit(-7113);
  SCRIPTfileName = filesetext(PCADfileName, ".scr");
  return PCADfileName;
}

string ShowRefLayer[];

int    CntlayerDef = -1;
string RefLayerDef[];
string RefLayerNum[];
string RefLayerType[];
string PcadEagleLayerRefName[];
string PcadEagleLayerRefNum[];

void LoadCrossRef( string CrossfileName )
{
  if (!CrossfileName) {
     CrossfileName = dlgFileOpen(TR("Select layer mapping file"), PCADfileName + ".lmp", "*.lmp");
     if (!CrossfileName) return;
  }

  CntlayerDef = fileread(ShowRefLayer, CrossfileName);

  if( CntlayerDef < 0 ) {
    if( DebugMessage ) {
      printf( "# info: CrossfileName %s not found\n", CrossfileName );
    }

    return;
  }

  string w[];
  for (int n = 0; n < CntlayerDef; n++) {
    strsplit(w, ShowRefLayer[n], '\t');
    RefLayerType[n] = w[0];
    RefLayerDef[n] = w[1];
    RefLayerNum[n] = w[2];
    PcadEagleLayerRefNum[n] = w[3];
    PcadEagleLayerRefName[n] = w[4];
  }

  if( DebugMessage ) {
    //printf( "# info: CrossfileName %s loaded\n", CrossfileName );
  }
}

void SaveCrossRef( void )
{
  string CrossfileName = dlgFileSave(TR("Save layer mapping file"), PCADfileName + ".lmp", "*.lmp");

  if (!CrossfileName) return;

  output(CrossfileName, "wt") {
    for (int n = 0; n < CntlayerDef; n++) {
      printf("%s\t%s\t%s\t%s\t%s\n",
            RefLayerType[n],
            RefLayerDef[n],
            RefLayerNum[n],
            PcadEagleLayerRefNum[n],
            PcadEagleLayerRefName[n]
            );
    }
  }
}

// This function updates dialog window to show progress

void UpdateProgress( string info )
{
  if( !BatchMode ) {
    sprintf( Status, info );
    dlgRedisplay();
  }
}

// This function replaces characters which have
// special meaning in Eagle. Returns updated string

string ReplaceNotSupportedCharacters( string InputStr )
{
  string OutputStr;

  int length = strlen( InputStr );

  for( int i = 0; i < length; i++ ) {
    switch( InputStr[ i ] ) {
      case '\\':
        OutputStr[ i ] = '/';
      break;
      case ' ':
        OutputStr[ i ] = '_';
      break;
      case '(':
        OutputStr[ i ] = '_';
      break;
      case ')':
        OutputStr[ i ] = '_';
      break;
      case '[':
        OutputStr[ i ] = '_';
      break;
      case ']':
        OutputStr[ i ] = '_';
      break;
      case '\'':
        OutputStr[ i ] = '_';
      break;
      default:
        OutputStr[ i ] = InputStr[ i ];
    }
  }

  return( OutputStr );
}

// This function replaces characters which have
// special meaning in Eagle for text string. Returns updated string

string ReplaceNotSupportedCharactersText( string InputStr )
{
  string OutputStr;

  int length = strlen( InputStr );

  int j = 0;

  for( int i = 0; i < length; i++ ) {
    switch( InputStr[ i ] ) {
      case '\'':
        OutputStr[ j ] = '\'';
        j++;
        OutputStr[ j ] = '\'';
      break;
      case '\\':
        if( ( InputStr[ i + 1 ] == 'n' ) ||
            ( InputStr[ i + 1 ] == '\\' ) ) {
          OutputStr[ j ] = InputStr[ i ];
          i++;
          j++;
          OutputStr[ j ] = InputStr[ i ];
        }
        else {
          i++;
          j--;
        }
      break;
      default:
        OutputStr[ j ] = InputStr[ i ];
    }

    j++;
  }

  return( OutputStr );
}

// This function merges all lines and removes comments
void MergeLines( void )
{
  for( int j = 0; j < Lines; j++ ) {
     if ( strchr( PcadLines[ j ], ';' ) >= 0 ) {
        string currentLine = PcadLines[ j ];
        int lineLength = strlen( currentLine );
        int flag = 0;
        for( int i = 0; i < lineLength; i++ ) {
           if ( currentLine[ i ] == '"' )
              flag = !flag;
           if ( currentLine[ i ] == ';' && !flag) {
              currentLine[ i ] = '\0';
              break;
           }
        }
        PcadLines[ j ] = currentLine;
     }
  }
  // Merge them all in one step !
  MergedString = strjoin(PcadLines, ' ');
}

// This function create token for string inside double quotas

void ProcessDoubleQuotas( int lineLength )
{
  string tmpString;
  int strLength = 0;

  tmpString[ strLength ] = MergedString[ CurrentChar ];
  strLength++;

  CurrentChar++;

  while( CurrentChar < lineLength ) {
    tmpString[ strLength ] = MergedString[ CurrentChar ];
    strLength++;

    if( MergedString[ CurrentChar ] == '"' ) {
      if( MergedString[ CurrentChar - 1 ] != '\\' ) {
        break;
      }
      else {
        tmpString[ strLength - 1 ] = '"';
      }
    }

    CurrentChar++;
  }

  tmpString[ strLength ] = 0;

  Tokens[ TokensNumber ] = tmpString;
  TokensNumber++;
}

// This function create token for keyword or variable name

void ProcessString( int lineLength )
{
  string tmpString;

  while( CurrentChar < lineLength ) {
    switch( MergedString[ CurrentChar ] ) {
      case ' ':
      case '(':
      case ')':
      case '"':
        CurrentChar--;
        Tokens[ TokensNumber ] = tmpString;
        TokensNumber++;
      return;
      default:
        tmpString = tmpString + MergedString[ CurrentChar ];
        CurrentChar++;
     }
  }

  Tokens[ TokensNumber ] = tmpString;
  TokensNumber++;
}

// This function creates array of strings from MergedString

void SplitToTokens( void )
{
  UpdateProgress( TR("Parsing") );

  int lineLength = strlen( MergedString );

  CurrentChar = 0;

  while( CurrentChar < lineLength ) {
    switch( MergedString[ CurrentChar ] ) {
      case ' ':
      break;
      case '(':
        Tokens[ TokensNumber ] = "(";
        TokensNumber++;
      break;
      case ')':
        Tokens[ TokensNumber ] = ")";
        TokensNumber++;
      break;
      case '"':
        ProcessDoubleQuotas( lineLength );

        //sprintf(Status, "Token %d:%s", TokensNumber, Tokens[ TokensNumber ] );
        //dlgRedisplay();

      break;
      default:
        ProcessString( lineLength );

        //sprintf(Status, "Token %d:%s", TokensNumber, Tokens[ TokensNumber ] );
        //dlgRedisplay();
    }

    CurrentChar++;
  }
}

// This function check if dbUnit equal to mil, mm or in.
// Returns 0 if dbUnit is correct
// otherwise returns 1

int checkDbUnits( string fileUnits )
{
  if( fileUnits == "mil") return( 0 );
  if( fileUnits == "mm") return( 0 );
  if( fileUnits == "in") return( 0 );

  return( 1 );
}

// Removes double quotas at the begining and
// the end of string if any. Return new string

string RemoveDoubleQuotas( string inputString )
{
  string outputString = "";

  int startPos = 0;
  int length =  strlen( inputString );

  if( length > 0 ) {
    if( inputString[ length - 1 ] == '"' ) {
      length--;
    }

    if( inputString[ 0 ] == '"' ) {
      startPos = 1;
      length--;
    }
  }

  for( int i = 0; i < length; i++ ) {
    outputString[ i ] = inputString[ startPos + i ];
  }

  return( outputString );
}

// This function check if first word is equal to PCAD_ASCII,
// ACCEL_ASCII or TangoPRO_ASCII. Returns 0 if signature correct
// otherwise returns 1

int CheckSignature( void )
{
  if( Tokens[ 0 ] == "PCAD_ASCII") return( 0 );
  if( Tokens[ 0 ] == "ACCEL_ASCII") return( 0 );
  if( Tokens[ 0 ] == "TangoPRO_ASCII") return( 0 );

  return( 1 );
}

// This function process header of file.
// If header processed successfully function returns 0
// otherwise returns 1

int ProcessAsciiHeader( void )
{
  UpdateProgress( TR("ProcessAsciiHeader") );

  CurrentToken++;

  while( CurrentToken < TokensNumber ) {
    if( Tokens[ CurrentToken ] == "(" ) {
      CurrentToken++;

      if( Tokens[ CurrentToken ] == "asciiVersion" ) {
        CurrentToken++;

        MajorVersion = Tokens[ CurrentToken ];

        CurrentToken++;

        MinorVersion = Tokens[ CurrentToken ];

        CurrentToken++;

        if( Tokens[ CurrentToken ] != ")" ) {
          dlgMessageBox( "Error in asciiVersion", "OK");
          return( 1 );
        }
      }
      else {
        if( Tokens[ CurrentToken ] == "timeStamp" ) {
          CurrentToken++;

          TimeStampYear = Tokens[ CurrentToken ];

          CurrentToken++;

          TimeStampMonth = Tokens[ CurrentToken ];

          CurrentToken++;

          TimeStampDay = Tokens[ CurrentToken ];

          CurrentToken++;

          TimeStampHour = Tokens[ CurrentToken ];

          CurrentToken++;

          TimeStampMinute = Tokens[ CurrentToken ];

          CurrentToken++;

          TimeStampSecond = Tokens[ CurrentToken ];

          CurrentToken++;

          if( Tokens[ CurrentToken ] != ")" ) {
            dlgMessageBox( "Error in timeStamp", "OK");
            return( 1 );
          }
        }
        else {
          if( Tokens[ CurrentToken ] == "program" ) {
            CurrentToken++;

            ProgramName = RemoveDoubleQuotas( Tokens[ CurrentToken ] );

            CurrentToken++;

            ProgramVersion = RemoveDoubleQuotas( Tokens[ CurrentToken ] );

            CurrentToken++;

            if( Tokens[ CurrentToken ] != ")" ) {
              dlgMessageBox( "Error in program keyword", "OK");
              return( 1 );
            }
          }
          else {
            if( Tokens[ CurrentToken ] == "copyright" ) {
              CurrentToken++;

              Copyright = RemoveDoubleQuotas( Tokens[ CurrentToken ] );

              CurrentToken++;

              if( Tokens[ CurrentToken ] != ")" ) {
                dlgMessageBox( "Error in copyright keyword", "OK");
                return( 1 );
              }
            }
            else {
              if( Tokens[ CurrentToken ] == "headerString" ) {
                CurrentToken++;

                HeaderString = RemoveDoubleQuotas( Tokens[ CurrentToken ] );

                CurrentToken++;

                if( Tokens[ CurrentToken ] != ")" ) {
                  dlgMessageBox( "Error in header string keyword", "OK");
                  return( 1 );
                }
              }
              else {
                if( Tokens[ CurrentToken ] == "fileUnits" ) {
                  CurrentToken++;

                  FileUnits = strlwr( Tokens[ CurrentToken ] );

                  if( checkDbUnits( FileUnits ) ) {
                    dlgMessageBox( "Unknown fileUnits " + FileUnits, "OK");
                    return( 1 );
                  }

                  CurrentToken++;

                  if( Tokens[ CurrentToken ] != ")" ) {
                    dlgMessageBox( "Error in fileUnits", "OK");
                    return( 1 );
                  }
                }
                else {
                  if( Tokens[ CurrentToken ] == "guidString" ) {
                    CurrentToken++;

                    GuidString = RemoveDoubleQuotas( Tokens[ CurrentToken ] );

                    CurrentToken++;

                    if( Tokens[ CurrentToken ] != ")" ) {
                      dlgMessageBox( "Error in header guidString keyword", "OK");
                      return( 1 );
                    }
                  }
                  else {
                    if( Tokens[ CurrentToken ] == "fileAuthor" ) {
                      CurrentToken++;

                      FileAuthor = RemoveDoubleQuotas( Tokens[ CurrentToken ] );

                      CurrentToken++;

                      if( Tokens[ CurrentToken ] != ")" ) {
                        dlgMessageBox( "Error in header fileAuthor keyword", "OK");
                        return( 1 );
                      }
                    }
                    else {
                      dlgMessageBox( "Unknown keyword in header " + Tokens[ CurrentToken ], "OK");
                      return( 1 );
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
    else {
      if( Tokens[ CurrentToken ] == ")" ) {
        return( 0 );
      }
      else {
        dlgMessageBox( "Unexpected keyword in header " + Tokens[ CurrentToken ], "OK");
        return( 1 );
      }
    }

    CurrentToken++;
  }

  return( 1 );
}

// This function process padStyleDef keyword.
// If padStyleDef processed successfully function returns 0
// oterwise returns 1

int ProcessPadStyleDef( void )
{
  int level = 1;

  CurrentToken++;

  PadStyleDefsArray[ PadStyleDefsNumber ] = CurrentToken;

  PadStyleDefsNumber++;

  while( CurrentToken < TokensNumber ) {
    if( Tokens[ CurrentToken ] == "(" ) {
      level++;
    }

    if( Tokens[ CurrentToken ] == ")" ) {
      level--;

      if( level == 0 ) {
        return( 0 );
      }
    }

    CurrentToken++;
  }

  return( 1 );
}

// This function process viaStyleDef keyword.
// If viaStyleDef processed successfully function returns 0
// oterwise returns 1

int ProcessViaStyleDef( void )
{
  int level = 1;

  CurrentToken++;

  ViaStyleDefsArray[ ViaStyleDefsNumber ] = CurrentToken;

  ViaStyleDefsNumber++;

  while( CurrentToken < TokensNumber ) {
    if( Tokens[ CurrentToken ] == "(" ) {
      level++;
    }

    if( Tokens[ CurrentToken ] == ")" ) {
      level--;

      if( level == 0 ) {
        return( 0 );
      }
    }

    CurrentToken++;
  }

  return( 1 );
}

// This function process textStyleDef keyword.
// If textStyleDef processed successfully function returns 0
// oterwise returns 1

int ProcessTextStyleDef( void )
{
  int level = 1;

  CurrentToken++;

  TextStyleDefsArray[ TextStyleDefsNumber ] = CurrentToken;

  TextStyleDefsNumber++;

  while( CurrentToken < TokensNumber ) {
    if( Tokens[ CurrentToken ] == "(" ) {
      level++;

      if( Tokens[ CurrentToken + 1 ] == "fontHeight" ) {
        TextStyleDefFontHeight[ TextStyleDefsNumber - 1 ] =  Tokens[ CurrentToken + 2 ];

        if( Tokens[ CurrentToken + 3 ] != ")" ) {
           TextStyleDefFontHeight[ TextStyleDefsNumber - 1 ] =
            TextStyleDefFontHeight[ TextStyleDefsNumber - 1 ] + Tokens[ CurrentToken + 3 ];
        }
      }
      else {
        if( Tokens[ CurrentToken + 1 ] == "strokeWidth" ) {
          TextStyleDefFontStrokeWidth[ TextStyleDefsNumber - 1 ] =  Tokens[ CurrentToken + 2 ];

          if( Tokens[ CurrentToken + 3 ] != ")" ) {
            TextStyleDefFontStrokeWidth[ TextStyleDefsNumber - 1 ] =
             TextStyleDefFontStrokeWidth[ TextStyleDefsNumber - 1 ] + Tokens[ CurrentToken + 3 ];
          }
        }
      }
    }

    if( Tokens[ CurrentToken ] == ")" ) {
      level--;

      if( level == 0 ) {
        return( 0 );
      }
    }

    CurrentToken++;
  }

  return( 1 );
}

// This function process patternDefExtended keyword.
// If patternDefExtended processed successfully function returns 0
// oterwise returns 1

int ProcessPatternDefExtended( void )
{
  int level = 1;

  CurrentToken++;

  int patternDefExtendedToken = CurrentToken;

  while( CurrentToken < TokensNumber ) {
    if( Tokens[ CurrentToken ] == "(" ) {
      level++;

      if( Tokens[ CurrentToken + 1 ] == "patternGraphicsDef" ) {
        PatternDefExtendedArray[ PatternDefExtendedNumber ] = patternDefExtendedToken;
        PatternGraphicsDefArray[ PatternDefExtendedNumber ] = CurrentToken + 1;

        PatternDefExtendedNumber++;
      }
    }

    if( Tokens[ CurrentToken ] == ")" ) {
      level--;

      if( level == 0 ) {
        return( 0 );
      }
    }

    CurrentToken++;
  }

  return( 1 );
}

// This function process compDef keyword.
// If compDef processed successfully function returns 0
// oterwise returns 1

int ProcessCompDef( void )
{
  int level = 1;

  CurrentToken++;

  CompDefsArray[ CompDefsNumber ] = CurrentToken;

  CompDefsNumber++;

  while( CurrentToken < TokensNumber ) {
    if( Tokens[ CurrentToken ] == "(" ) {
      level++;
    }

    if( Tokens[ CurrentToken ] == ")" ) {
      level--;

      if( level == 0 ) {
        return( 0 );
      }
    }

    CurrentToken++;
  }

  return( 1 );
}

// This function process patternDef keyword.
// If patternDef processed successfully function returns 0
// oterwise returns 1

int ProcessPatternDef( void )
{
  int level = 1;

  CurrentToken++;

  //PatternDefsArray[ PatternDefsNumber ] = CurrentToken;

  //PatternDefsNumber++;

  PatternDefExtendedArray[ PatternDefExtendedNumber ] = CurrentToken;
  PatternGraphicsDefArray[ PatternDefExtendedNumber ] = -1;
  PatternGraphicsDefName[ PatternDefExtendedNumber ] = "";

  PatternDefExtendedNumber++;

  while( CurrentToken < TokensNumber ) {
    if( Tokens[ CurrentToken ] == "(" ) {
      level++;
    }

    if( Tokens[ CurrentToken ] == ")" ) {
      level--;

      if( level == 0 ) {
        return( 0 );
      }
    }

    CurrentToken++;
  }

  return( 1 );
}

// This function process symbolDef keyword.
// If symbolDef processed successfully function returns 0
// oterwise returns 1

int ProcessSymbolDef( void )
{
  int level = 1;

  CurrentToken++;

  SymbolDefsArray[ SymbolDefsNumber ] = CurrentToken;

  SymbolDefsNumber++;

  while( CurrentToken < TokensNumber ) {
    if( Tokens[ CurrentToken ] == "(" ) {
      level++;
    }

    if( Tokens[ CurrentToken ] == ")" ) {
      level--;

      if( level == 0 ) {
        return( 0 );
      }
    }

    CurrentToken++;
  }

  return( 1 );
}

// This function process library keyword.
// If library processed successfully function returns 0
// oterwise returns 1

int ProcessLibrary( void )
{
  PadStyleDefsNumber = 0;
  ViaStyleDefsNumber = 0;
  TextStyleDefsNumber = 0;
  PatternDefExtendedNumber = 0;
  CompDefsNumber = 0;
  //PatternDefsNumber = 0;
  SymbolDefsNumber = 0;

  UpdateProgress( TR("ProcessLibrary") );

  CurrentToken++;

  LibraryName = RemoveDoubleQuotas( Tokens[ CurrentToken ] );

  CurrentToken++;

  while( CurrentToken < TokensNumber ) {
    if( Tokens[ CurrentToken ] == "(" ) {

      CurrentToken++;

      if( Tokens[ CurrentToken ] == "padStyleDef" ) {
        if( ProcessPadStyleDef() ) {
          dlgMessageBox( "Error in padStyleDef processing", "OK");
          return( 1 );
        }
      }
      else {
        if( Tokens[ CurrentToken ] == "viaStyleDef" ) {
          if( ProcessViaStyleDef() ) {
            dlgMessageBox( "Error in viaStyleDef processing", "OK");
            return( 1 );
          }
        }
        else {
          if( Tokens[ CurrentToken ] == "textStyleDef" ) {
            if( ProcessTextStyleDef() ) {
              dlgMessageBox( "Error in textStyleDef processing", "OK");
              return( 1 );
            }
          }
          else {
            if( Tokens[ CurrentToken ] == "patternDefExtended" ) {
              if( ProcessPatternDefExtended() ) {
                dlgMessageBox( "Error in patternDefExtended processing", "OK");
                return( 1 );
              }
            }
            else {
              if( Tokens[ CurrentToken ] == "compDef" ) {
                if( ProcessCompDef() ) {
                  dlgMessageBox( "Error in compDef processing", "OK");
                  return( 1 );
                }
              }
              else {
                if( Tokens[ CurrentToken ] == "patternDef" ) {
                  if( ProcessPatternDef() ) {
                    dlgMessageBox( "Error in patternDef processing", "OK");
                    return( 1 );
                  }
                }
                else {
                  if( Tokens[ CurrentToken ] == "symbolDef" ) {
                    if( ProcessSymbolDef() ) {
                      dlgMessageBox( "Error in symbolDef processing", "OK");
                      return( 1 );
                    }
                  }
                  else {
                    dlgMessageBox( "Unknown keyword in library " + Tokens[ CurrentToken ], "OK");
                    return( 1 );
                  }
                }
              }
            }
          }
        }
      }
    }
    else {
      if( Tokens[ CurrentToken ] == ")" ) {

        /*string info;

        sprintf( info, "PadStyleDefsNumber = %d ViaStyleDefsNumber = %d",
                        PadStyleDefsNumber, ViaStyleDefsNumber );
        dlgMessageBox( info, "OK");

        sprintf( info, "TextStyleDefsNumber = %d PatternDefExtendedNumber = %d",
                        TextStyleDefsNumber, PatternDefExtendedNumber );
        dlgMessageBox( info, "OK");

        sprintf( info, "CompDefsNumber = %d PatternDefsNumber = %d SymbolDefsNumber = %d",
                        CompDefsNumber, PatternDefsNumber, SymbolDefsNumber );
        dlgMessageBox( info, "OK");*/

        return( 0 );
      }
      else {
        dlgMessageBox( "Unexpected keyword in library " + Tokens[ CurrentToken ], "OK");
        return( 1 );
      }
    }

    CurrentToken++;
  }

  return( 1 );
}

// This function skip all internal data and return.

int SkipThisItem( void )
{
  int level = 1;

  CurrentToken++;

  while( CurrentToken < TokensNumber ) {
    if( Tokens[ CurrentToken ] == "(" ) {
      level++;
    }

    if( Tokens[ CurrentToken ] == ")" ) {
      level--;

      if( level == 0 ) {
        return( 0 );
      }
    }

    CurrentToken++;
  }

  return( 1 );
}

// This function process globalAttrs keyword.
// If globalAttrs processed successfully function returns 0
// oterwise returns 1

int ProcessGlobalAttrs( void )
{
  int level = 1;

  CurrentToken++;

  while( CurrentToken < TokensNumber ) {
    if( Tokens[ CurrentToken ] == "(" ) {
      level++;
    }

    if( Tokens[ CurrentToken ] == ")" ) {
      level--;

      if( level == 0 ) {
        return( 0 );
      }
    }

    CurrentToken++;
  }

  return( 1 );
}

// This function process compInst keyword.
// If compInst processed successfully function returns 0
// oterwise returns 1

int ProcessCompInst( void )
{
  int level = 1;

  CurrentToken++;

  CompInstances[ NrCompInstances ] = CurrentToken;

  CompInstancesName[ NrCompInstances ] = ReplaceNotSupportedCharacters( RemoveDoubleQuotas( Tokens[ CurrentToken ] ) );

  NrCompInstances++;

  while( CurrentToken < TokensNumber ) {
    if( Tokens[ CurrentToken ] == "(" ) {
      level++;

      if( Tokens[ CurrentToken + 1 ] == "compRef" ) {
        CompInstancesRef[ NrCompInstances - 1 ] = ReplaceNotSupportedCharacters( RemoveDoubleQuotas( Tokens[ CurrentToken + 2 ] ) );
      }
      else {
        if( Tokens[ CurrentToken + 1 ] == "compValue" ) {
          CompValue[ NrCompInstances - 1 ] = ReplaceNotSupportedCharacters( RemoveDoubleQuotas( Tokens[ CurrentToken + 2 ] ) );
        }
      }
    }

    if( Tokens[ CurrentToken ] == ")" ) {
      level--;

      if( level == 0 ) {
        return( 0 );
      }
    }

    CurrentToken++;
  }

  return( 1 );
}

// This function process net keyword.
// If net processed successfully function returns 0
// oterwise returns 1

int ProcessNet( void )
{
  int nodesCount = 0;
  int level = 1;

  CurrentToken++;

  NetNames[ NrNets ] = ReplaceNotSupportedCharacters( RemoveDoubleQuotas(  Tokens[ CurrentToken ] ) );
  NodeRef[ NrNets ] = NrNodes;

  CurrentToken++;

  while( CurrentToken < TokensNumber ) {
    if( Tokens[ CurrentToken ] == "(" ) {
      level++;

      CurrentToken++;

      if( Tokens[ CurrentToken ] == "node" ) {
        CurrentToken++;
        NodeElementName[ NrNodes ] = ReplaceNotSupportedCharacters( RemoveDoubleQuotas(  Tokens[ CurrentToken ] ) );
        CurrentToken++;
        NodePadName[ NrNodes ] = ReplaceNotSupportedCharacters( RemoveDoubleQuotas(  Tokens[ CurrentToken ] ) );
        CurrentToken++;
        NrNodes++;
        nodesCount++;
      }
    }

    if( Tokens[ CurrentToken ] == ")" ) {
      level--;

      if( level == 0 ) {
        if( nodesCount ) {
          NrNetNodes[ NrNets ] = nodesCount;
          NrNets++;
        }

        return( 0 );
      }
    }

    CurrentToken++;
  }

  return( 1 );
}

// This function process netClass keyword.
// If netClass processed successfully function returns 0
// oterwise returns 1

int ProcessNetClass( void )
{
  int level = 1;

  CurrentToken++;

  while( CurrentToken < TokensNumber ) {
    if( Tokens[ CurrentToken ] == "(" ) {
      level++;
    }

    if( Tokens[ CurrentToken ] == ")" ) {
      level--;

      if( level == 0 ) {
        return( 0 );
      }
    }

    CurrentToken++;
  }

  return( 1 );
}

// This function process netlist keyword.
// If netlist processed successfully function returns 0
// oterwise returns 1

int ProcessNetlist( void )
{
  UpdateProgress( TR("ProcessNetlist") );

  CurrentToken++;

  NetlistName = RemoveDoubleQuotas( Tokens[ CurrentToken ] );

  CurrentToken++;

  while( CurrentToken < TokensNumber ) {
    if( Tokens[ CurrentToken ] == "(" ) {

      CurrentToken++;

      if( Tokens[ CurrentToken ] == "globalAttrs" ) {
        if( ProcessGlobalAttrs() ) {
          dlgMessageBox( "Error in globalAttrs processing", "OK");
          return( 1 );
        }
      }
      else {
        if( Tokens[ CurrentToken ] == "compInst" ) {
          if( ProcessCompInst() ) {
            dlgMessageBox( "Error in compInst processing", "OK");
            return( 1 );
          }
        }
        else {
          if( Tokens[ CurrentToken ] == "net" ) {
            if( ProcessNet() ) {
              dlgMessageBox( "Error in net processing", "OK");
              return( 1 );
            }
          }
          else {
            if( Tokens[ CurrentToken ] == "netClass" ) {
              if( ProcessNetClass() ) {
                dlgMessageBox( "Error in net processing", "OK");
                return( 1 );
              }
            }
            else {
              dlgMessageBox( "Unknown keyword in netlist: " + Tokens[ CurrentToken ], "OK");
              return( 1 );
            }
          }
        }
      }
    }
    else {
      if( Tokens[ CurrentToken ] == ")" ) {
        return( 0 );
      }
      else {
        dlgMessageBox( "Unexpected keyword in netlist " + Tokens[ CurrentToken ], "OK");
        return( 1 );
      }
    }

    CurrentToken++;
  }

  return( 1 );
}

// This function process pcbDesignHeader keyword.
// If pcbDesignHeader processed successfully function returns 0
// oterwise returns 1

int ProcessPcbDesignHeader( void )
{
  int level = 1;

  CurrentToken++;

  while( CurrentToken < TokensNumber ) {
    if( Tokens[ CurrentToken ] == "(" ) {
      level++;
    }

    if( Tokens[ CurrentToken ] == ")" ) {
      level--;

      if( level == 0 ) {
        return( 0 );
      }
    }

    CurrentToken++;
  }

  return( 1 );
}

// This function process layerDef keyword.
// If layerDef processed successfully function returns 0
// oterwise returns 1

int ProcessLayerDef( void )
{
  CurrentToken++;

  LayersName[ LayerDefsNumber ] = RemoveDoubleQuotas( Tokens[ CurrentToken ] );

  CurrentToken++;

  while( CurrentToken < TokensNumber ) {
    if( Tokens[ CurrentToken ] == "(" ) {

      CurrentToken++;

      if( Tokens[ CurrentToken ] == "layerNum" ) {
        CurrentToken++;

        LayersCode[ LayerDefsNumber ] = strtol( Tokens[ CurrentToken ] );

        CurrentToken++;

        if( Tokens[ CurrentToken ] != ")" ) {
          dlgMessageBox( "Error in layerNum", "OK");
          return( 1 );
        }
      }
      else {
        if( Tokens[ CurrentToken ] == "layerType" ) {
          CurrentToken++;

          LayersType[ LayerDefsNumber ] = Tokens[ CurrentToken ];

          CurrentToken++;

          if( Tokens[ CurrentToken ] != ")" ) {
            dlgMessageBox( "Error in layerType", "OK");
            return( 1 );
          }
        }
        else {
          if( Tokens[ CurrentToken ] == "attr" ) {
            if( SkipThisItem() ) {
              dlgMessageBox( "Error in LayerDef attr processing", "OK");
              return( 1 );
            }
          }
          else {
            if( Tokens[ CurrentToken ] == "fieldSetRef" ) {
              if( SkipThisItem() ) {
                dlgMessageBox( "Error in LayerDef fieldSetRef processing", "OK");
                return( 1 );
              }
            }
            else {
              if( Tokens[ CurrentToken ] == "netNameRef" ) {
                if( SkipThisItem() ) {
                  dlgMessageBox( "Error in LayerDef netNameRef processing", "OK");
                  return( 1 );
                }
              }
              else {
                dlgMessageBox( "Unknown keyword in ProcessLayerDef: " + Tokens[ CurrentToken ], "OK");
                return( 1 );
              }
            }
          }
        }
      }
    }
    else {
      if( Tokens[ CurrentToken ] == ")" ) {
        LayerDefsArray[ LayerDefsNumber ] = CurrentToken;

        LayerDefsNumber++;

        return( 0 );
      }
      else {
        dlgMessageBox( "Unexpected keyword in ProcessLayerDef " + Tokens[ CurrentToken ], "OK");
        return( 1 );
      }
    }

    CurrentToken++;
  }

  return( 1 );
}

// This function process multiLayer keyword.
// If multiLayer processed successfully function returns 0
// oterwise returns 1

int ProcessMultiLayer( void )
{
  int level = 1;

  CurrentToken++;

  PCBDesignMultiLayerToken = CurrentToken;

  while( CurrentToken < TokensNumber ) {
    if( Tokens[ CurrentToken ] == "(" ) {
      level++;

      CurrentToken++;

      if( Tokens[ CurrentToken ] == "pad" ) {
        PadOnBoardIndex[ NrPadsOnBoard ] = CurrentToken;
        NrPadsOnBoard++;
        SkipThisItem();
      }
      else {
        if( SkipThisItem() ) {
          dlgMessageBox( "Error in ProcessMultiLayer processing", "OK");
          return( 1 );
        }
        level--;
      }
    }
    else {
      if( Tokens[ CurrentToken ] == ")" ) {
        return( 0 );

        /*level--;

        if( level == 0 ) {
          return( 0 );
        }*/
      }
      else {
        dlgMessageBox( "Unexpected keyword in ProcessMultiLayer " + Tokens[ CurrentToken ], "OK");
        return( 1 );
      }
    }

    CurrentToken++;
  }

  return( 1 );
}

// This function process layerContents keyword.
// If layerContents processed successfully function returns 0
// oterwise returns 1

int ProcessLayerContents( void )
{
  int level = 1;

  PCBLayerContentsArray[ NrPCBLayerContents ] = CurrentToken;

  NrPCBLayerContents++;

  CurrentToken++;

  while( CurrentToken < TokensNumber ) {
    if( Tokens[ CurrentToken ] == "(" ) {
      level++;
    }

    if( Tokens[ CurrentToken ] == ")" ) {
      level--;

      if( level == 0 ) {
        return( 0 );
      }
    }

    CurrentToken++;
  }

  return( 1 );
}

// This function process pcbDesign keyword.
// If pcbDesign processed successfully function returns 0
// oterwise returns 1

int ProcessPcbDesign( void )
{
  UpdateProgress( TR("ProcessPcbDesign") );

  PCBDesignToken = CurrentToken;

  CurrentToken++;

  PcbDesignName = RemoveDoubleQuotas( Tokens[ CurrentToken ] );

  CurrentToken++;

  while( CurrentToken < TokensNumber ) {
    if( Tokens[ CurrentToken ] == "(" ) {

      CurrentToken++;

      if( Tokens[ CurrentToken ] == "pcbDesignHeader" ) {
        if( ProcessPcbDesignHeader() ) {
          dlgMessageBox( "Error in ProcessPcbDesignHeader processing", "OK");
          return( 1 );
        }
      }
      else {
        if( Tokens[ CurrentToken ] == "layerDef" ) {
          if( ProcessLayerDef() ) {
            dlgMessageBox( "Error in ProcessLayerDef processing", "OK");
            return( 1 );
          }
        }
        else {
          if( Tokens[ CurrentToken ] == "multiLayer" ) {
            if( ProcessMultiLayer() ) {
              dlgMessageBox( "Error in ProcessMultiLayer processing", "OK");
              return( 1 );
            }
          }
          else {
            if( Tokens[ CurrentToken ] == "layerContents" ) {
              if( ProcessLayerContents() ) {
                dlgMessageBox( "Error in ProcessLayerContents processing", "OK");
                return( 1 );
              }
            }
            else {
              if( Tokens[ CurrentToken ] == "pcbPrintSettings" ) {
                if( SkipThisItem() ) {
                  dlgMessageBox( "Error in pcbPrintSettings processing", "OK");
                  return( 1 );
                }
              }
              else {
                if( Tokens[ CurrentToken ] == "drillSymSettings" ) {
                  if( SkipThisItem() ) {
                    dlgMessageBox( "Error in drillSymSettings processing", "OK");
                    return( 1 );
                  }
                }
                else {
                  if( Tokens[ CurrentToken ] == "gerberSettings" ) {
                    if( SkipThisItem() ) {
                      dlgMessageBox( "Error in gerberSettings processing", "OK");
                      return( 1 );
                    }
                  }
                  else {
                    if( Tokens[ CurrentToken ] == "ncDrillSettings" ) {
                      if( SkipThisItem() ) {
                        dlgMessageBox( "Error in ncDrillSettings processing", "OK");
                        return( 1 );
                      }
                    }
                    else {
                      if( Tokens[ CurrentToken ] == "programState" ) {
                        if( SkipThisItem() ) {
                          dlgMessageBox( "Error in programState processing", "OK");
                          return( 1 );
                        }
                      }
                      else {
                        if( Tokens[ CurrentToken ] == "layerSets" ) {
                          if( SkipThisItem() ) {
                            dlgMessageBox( "Error in layerSets processing", "OK");
                            return( 1 );
                          }
                        }
                        else {
                          if( Tokens[ CurrentToken ] == "layerPairs" ) {
                            if( SkipThisItem() ) {
                              dlgMessageBox( "Error in layerPairs processing", "OK");
                              return( 1 );
                            }
                          }
                          else {
                            if( Tokens[ CurrentToken ] == "displayDrawOrder" ) {
                              if( SkipThisItem() ) {
                                dlgMessageBox( "Error in displayDrawOrder processing", "OK");
                                return( 1 );
                              }
                            }
                            else {
                              if( Tokens[ CurrentToken ] == "reportSettings" ) {
                                if( SkipThisItem() ) {
                                  dlgMessageBox( "Error in reportSettings processing", "OK");
                                  return( 1 );
                                }
                              }
                              else {
                                if( Tokens[ CurrentToken ] == "odbSettings" ) {
                                  if( SkipThisItem() ) {
                                    dlgMessageBox( "Error in odbSettings processing", "OK");
                                    return( 1 );
                                  }
                                }
                                else {
                                  if( Tokens[ CurrentToken ] == "layersStackup" ) {
                                    if( SkipThisItem() ) {
                                      dlgMessageBox( "Error in layersStackup processing", "OK");
                                      return( 1 );
                                    }
                                  }
                                  else {
                                    dlgMessageBox( "Unknown keyword in ProcessPcbDesign: " + Tokens[ CurrentToken ], "OK");
                                    return( 1 );
                                  }
                                }
                              }
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
    else {
      if( Tokens[ CurrentToken ] == ")" ) {
        return( 0 );
      }
      else {
        dlgMessageBox( "Unexpected keyword in ProcessPcbDesign " + Tokens[ CurrentToken ], "OK");
        return( 1 );
      }
    }

    CurrentToken++;
  }

  return( 1 );
}

int ProcessSchDesignHeader( void )
{
  int level = 1;

  CurrentToken++;

  while( CurrentToken < TokensNumber ) {
    if( Tokens[ CurrentToken ] == "(" ) {
      level++;
    }

    if( Tokens[ CurrentToken ] == ")" ) {
      level--;

      if( level == 0 ) {
        return( 0 );
      }
    }

    CurrentToken++;
  }

  return( 1 );
}

int ProcessDesignInfo( void )
{
  int level = 1;

  CurrentToken++;

  while( CurrentToken < TokensNumber ) {
    if( Tokens[ CurrentToken ] == "(" ) {
      level++;
    }

    if( Tokens[ CurrentToken ] == ")" ) {
      level--;

      if( level == 0 ) {
        return( 0 );
      }
    }

    CurrentToken++;
  }

  return( 1 );
}

int ProcessSchTitleSheet( void )
{
  int level = 1;

  CurrentToken++;

  SchTitleSheet = CurrentToken;

  CurrentToken++;
  CurrentToken++;

  while( CurrentToken < TokensNumber ) {
    if( Tokens[ CurrentToken ] == "(" ) {
      level++;
    }

    if( Tokens[ CurrentToken ] == ")" ) {
      level--;

      if( level == 0 ) {
        return( 0 );
      }
    }

    CurrentToken++;
  }

  return( 1 );
}

int ProcessSheet( void )
{
  int level = 1;

  CurrentToken++;

  SheetsArray[ NrSheets ] = CurrentToken;

  NrSheets++;

  while( CurrentToken < TokensNumber ) {
    if( Tokens[ CurrentToken ] == "(" ) {
      level++;
    }

    if( Tokens[ CurrentToken ] == ")" ) {
      level--;

      if( level == 0 ) {
        return( 0 );
      }
    }

    CurrentToken++;
  }

  return( 1 );
}

// This function process schematicDesign keyword.
// If schematicDesign processed successfully function returns 0
// oterwise returns 1

int ProcessSchematicDesign( void )
{
  UpdateProgress( TR("ProcessSchematicDesign") );

  SchematicDesignToken = CurrentToken;

  CurrentToken++;

  SchematicDesignName = RemoveDoubleQuotas( Tokens[ CurrentToken ] );

  CurrentToken++;

  while( CurrentToken < TokensNumber ) {
    if( Tokens[ CurrentToken ] == "(" ) {

      CurrentToken++;

      if( Tokens[ CurrentToken ] == "schDesignHeader" ) {
        if( ProcessSchDesignHeader() ) {
          dlgMessageBox( "Error in ProcessSchDesignHeader processing", "OK");
          return( 1 );
        }
      }
      else {
        if( Tokens[ CurrentToken ] == "designInfo" ) {
          if( ProcessDesignInfo() ) {
            dlgMessageBox( "Error in ProcessDesignInfo processing", "OK");
            return( 1 );
          }
        }
        else {
          if( Tokens[ CurrentToken ] == "titleSheet" ) {
            if( ProcessSchTitleSheet() ) {
              dlgMessageBox( "Error in ProcessSchTitleSheet processing", "OK");
              return( 1 );
            }
          }
          else {
            if( Tokens[ CurrentToken ] == "sheet" ) {
              if( ProcessSheet() ) {
                dlgMessageBox( "Error in ProcessLayerContents processing", "OK");
                return( 1 );
              }
            }
            else {
              if( Tokens[ CurrentToken ] == "schematicPrintSettings" ) {
                if( SkipThisItem() ) {
                  dlgMessageBox( "Error in schematicPrintSettings processing", "OK");
                  return( 1 );
                }
              }
              else {
                if( Tokens[ CurrentToken ] == "programState" ) {
                  if( SkipThisItem() ) {
                    dlgMessageBox( "Error in programState processing", "OK");
                    return( 1 );
                  }
                }
                else {
                  if( Tokens[ CurrentToken ] == "reportSettings" ) {
                    if( SkipThisItem() ) {
                      dlgMessageBox( "Error in reportSettings processing", "OK");
                      return( 1 );
                    }
                  }
                  else {
                    dlgMessageBox( "Unknown keyword in ProcessSchematicDesign: " + Tokens[ CurrentToken ], "OK");
                    return( 1 );
                  }
                }
              }
            }
          }
        }
      }
    }
    else {
      if( Tokens[ CurrentToken ] == ")" ) {
        return( 0 );
      }
      else {
        dlgMessageBox( "Unexpected keyword in ProcessSchematicDesign " + Tokens[ CurrentToken ], "OK");
        return( 1 );
      }
    }

    CurrentToken++;
  }

  return( 1 );
}

// This function parse tree starting from
// top keywords. If processed seccesfully returns 0,
// if signature is wrong returns 1

int ParseTree( void )
{
  if( CheckSignature() ) {
    dlgMessageBox( TR("Wrong file signature: ") +  Tokens[ 0 ], "OK");
    return( 1 );
  }

  CurrentToken = 1;

  while( CurrentToken < TokensNumber ) {
    if( Tokens[ CurrentToken ] == "(" ) {
      CurrentToken++;

      if( Tokens[ CurrentToken ] == "asciiHeader" ) {
        if( ProcessAsciiHeader() ) {
          dlgMessageBox( "Error in file header processing", "OK");
        }
      }
      else {
        if( Tokens[ CurrentToken ] == "library" ) {
          if( ProcessLibrary() ) {
            dlgMessageBox( "Error in library processing", "OK");
            return( 1 );
          }
        }
        else {
          if( Tokens[ CurrentToken ] == "netlist" ) {
            if( ProcessNetlist() ) {
              dlgMessageBox( "Error in netlist processing", "OK");
              return( 1 );
            }
          }
          else {
            if( Tokens[ CurrentToken ] == "pcbDesign" ) {
              if( ProcessPcbDesign() ) {
                dlgMessageBox( "Error in pcbDesign processing", "OK");
                return( 1 );
              }
            }
            else {
              if( Tokens[ CurrentToken ] == "schematicDesign" ) {
                if( ProcessSchematicDesign() ) {
                  dlgMessageBox( "Error in schematicDesign processing", "OK");
                  return( 1 );
                }
              }
              else {
                if( Tokens[ CurrentToken ] == ")" ) {
                  break;
                }
                else {
                  dlgMessageBox( "Unexpected keyword: " + Tokens[ CurrentToken ], "OK");

                  if( 1 ) {
                    dlgMessageBox( "debug: " + Tokens[ CurrentToken - 2 ] +
                                               Tokens[ CurrentToken - 1 ] +
                                               Tokens[ CurrentToken ] +
                                               Tokens[ CurrentToken + 1 ] +
                                               Tokens[ CurrentToken + 2 ], "OK");
                  }

                  return( 1 );
                }
              }
            }
          }
        }
      }
    }

    CurrentToken++;
  }


  return( 0 );
}

string ConvertUnits( string textValue, string unitValue )
{
  if( unitValue == "" ) {
    if( FileUnits == "mil") {
      real rValue = strtod( textValue );
      string retValue;
      sprintf( retValue, "%f", round( rValue ) );
      return( retValue );
    }
    return( textValue );
  }

  if( unitValue == "mil") {
    if( FileUnits == "mil") {
      real rValue = strtod( textValue );
      string retValue;
      sprintf( retValue, "%f", round( rValue ) );
      return( retValue );
    }

    if( FileUnits == "mm") {
      real rValue = strtod( textValue );
      string retValue;
      sprintf( retValue, "%f", rValue * 25.4 / 1000.0 );
      return( retValue );
    }

    if( FileUnits == "in") {
      real rValue = strtod( textValue );
      string retValue;
      sprintf( retValue, "%f", rValue / 1000.0 );
      return( retValue );
    }
  }

  if( unitValue == "mm") {
    if( FileUnits == "mil") {
      real rValue = strtod( textValue );
      string retValue;
      sprintf( retValue, "%f", rValue * 1000.0 / 25.4 );
      return( retValue );
    }

    if( FileUnits == "mm") {
      return( textValue );
    }

    if( FileUnits == "in") {
      real rValue = strtod( textValue );
      string retValue;
      sprintf( retValue, "%f", rValue / 25.4 );
      return( retValue );
    }
  }

  if( unitValue == "in") {
    if( FileUnits == "mil") {
      real rValue = strtod( textValue );
      string retValue;
      sprintf( retValue, "%f", rValue * 1000.0 );
      return( retValue );
    }

    if( FileUnits == "mm") {
      real rValue = strtod( textValue );
      string retValue;
      sprintf( retValue, "%f", rValue * 25.4 );
      return( retValue );
    }

    if( FileUnits == "in") {
      return( textValue );
    }
  }

  string tmp;
  sprintf( tmp, "# ConvertUnits: unknown units: %s", unitValue );
  WriteLog( tmp );

  return( textValue );
}

int CheckForNull( string str )
{
  int length = strlen( str );

  for( int i = 0; i < length; i++ ) {
    switch( str[ i ] ) {
      case '1':
      case '2':
      case '3':
      case '4':
      case '5':
      case '6':
      case '7':
      case '8':
      case '9':
      return( 0 );
      default:;
    }
  }

  return( 1 );
}

string GetNumberValue( string str )
{
  string value = "";

  int length = strlen( str );

  for( int i = 0; i < length; i++ ) {
    switch( str[ i ] ) {
      case '+':
      case '-':
      case '0':
      case '1':
      case '2':
      case '3':
      case '4':
      case '5':
      case '6':
      case '7':
      case '8':
      case '9':
      case '.':
        value = value + str[ i ];
      break;
      default:
        return( value );
    }
  }

  return( value );
}

int IsNumberValue( string str )
{
  int length = strlen( str );

  for( int i = 0; i < length; i++ ) {
    switch( str[ i ] ) {
      case '+':
      case '-':
      case '0':
      case '1':
      case '2':
      case '3':
      case '4':
      case '5':
      case '6':
      case '7':
      case '8':
      case '9':
      case '.':
      break;
      default:
        return( 0 );
    }
  }

  return( 1 );
}

int IsASCIIValue( string str )
{
  if( strlen( str ) > 0 ) {
    switch( str[ 0 ] ) {
      case '0':
      case '1':
      case '2':
      case '3':
      case '4':
      case '5':
      case '6':
      case '7':
      case '8':
      case '9':
        return( 0 );
      case '.':
      case '+':
      case '-':
        if( strlen( str ) > 1 ) {
          switch( str[ 1 ] ) {
            case '0':
            case '1':
            case '2':
            case '3':
            case '4':
            case '5':
            case '6':
            case '7':
            case '8':
            case '9':
              return( 0 );
            default:;
          }
        }
      break;
      default:;
    }
  }

  return( 1 );
}

string GetUnitValue( string str )
{
  string value = "";

  int length = strlen( str );

  for( int i = 0; i < length; i++ ) {
    switch( str[ i ] ) {
      case '+':
      case '-':
      case '0':
      case '1':
      case '2':
      case '3':
      case '4':
      case '5':
      case '6':
      case '7':
      case '8':
      case '9':
      case '.':
      break;
      default:
        value = value + str[ i ];
    }
  }

  return( value );
}

string MinValue( string val1, string val2 )
{
  real rVal1 = strtod( ConvertUnits( GetNumberValue( val1 ), GetUnitValue( val1 ) ) );
  real rVal2 = strtod( ConvertUnits( GetNumberValue( val2 ), GetUnitValue( val2 ) ) );

  string tmp;

  if( rVal1 > rVal2 ) {
    sprintf( tmp, "%f", rVal2 );
  }
  else {
    sprintf( tmp, "%f", rVal1 );
  }

  return( tmp );
}

string MaxValue( string val1, string val2 )
{
  real rVal1 = strtod( ConvertUnits( GetNumberValue( val1 ), GetUnitValue( val1 ) ) );
  real rVal2 = strtod( ConvertUnits( GetNumberValue( val2 ), GetUnitValue( val2 ) ) );

  string tmp;

  if( rVal1 < rVal2 ) {
    sprintf( tmp, "%f", rVal2 );
  }
  else {
    sprintf( tmp, "%f", rVal1 );
  }

  return( tmp );
}

real GetValue( string val )
{
  real rVal = strtod( ConvertUnits( GetNumberValue( val ), GetUnitValue( val ) ) );

  return( rVal );
}

// Find token with a name.
// Returns token number if found,
// -1 if not found
// startToken should points to "("

int FindToken( int startToken, string name )
{
  int level = 1;
  CurrentToken = startToken;

  while( CurrentToken < TokensNumber ) {
    if( Tokens[ CurrentToken ] == "(" ) {
      level++;
      CurrentToken++;
      if( Tokens[ CurrentToken ] == name ) {
        return( CurrentToken );
      }
      else {
        if( SkipThisItem() ) {
          return( -1 );
        }
        level--;  // If an item is skipped, the level needs to be increased !
      }
    }
    else {
      if( Tokens[ CurrentToken ] == ")" ) {
        level--;

        if( level == 0 ) {
          return( -1 );
        }
      }
      else {
        /*dlgMessageBox( "Unexpected keyword in FindToken " + Tokens[ CurrentToken ], "OK");
        return( 1 );*/
      }
    }

    CurrentToken++;
  }

  return( -1 );
}

// This function write list of PCAD layer as comments to script

void PrintPCADLayers( void )
{
  printf( "# PCAD layers:\n");

  for( int i = 0; i < LayerDefsNumber; i++ ) {
    printf( "#Layer = '%s' %d %s\n", LayersName[ i ], LayersCode[ i ],
    LayersType[ i ] );
  }

  printf( "#\n" );
}

// This function returns index of found PadStyleDefinition
// in array or -1 if failed

int FindPadStyleDef( string name )
{
  for( int i = 0; i < PadStyleDefsNumber; i++ ) {
    int startToken = PadStyleDefsArray[ i ];

    if( Tokens[ startToken ] == name ) {
      return( i );
    }
  }

  return( -1 );
}

// This function returns index of found ViaStyleDefinition
// in array or -1 if failed

int FindViaStyleDef( string name )
{
  for( int i = 0; i < ViaStyleDefsNumber; i++ ) {
    int startToken = ViaStyleDefsArray[ i ];

    if( Tokens[ startToken ] == name ) {
      return( i );
    }
  }

  return( -1 );
}

// This function returns index of found TextStyleDefinition
// in array or -1 if failed

int FindTextStyleDef( string name )
{
  for( int i = 0; i < TextStyleDefsNumber; i++ ) {
    int startToken = TextStyleDefsArray[ i ];

    if( Tokens[ startToken ] == name ) {
      return( i );
    }
  }

  return( -1 );
}

int checkLayerType( int LayerNumPosition )
{
  for( int i = 0; i < LayerDefsNumber; i++ ) {
    if( LayersCode[ i ] == strtol( Tokens[ LayerNumPosition ] ) ) {
      if( LayersType[ i ] == "Signal" ) {
        return( 1 );
      }
    }
  }

  return( 0 );
}

real RotateXCoord( real x, real y, real rotationInRad )
{
  return( x * cos( rotationInRad ) - y * sin( rotationInRad ) );
}

real RotateYCoord( real x, real y, real rotationInRad )
{
  return( x * sin( rotationInRad ) + y * cos( rotationInRad ) );
}

void Ellipse( real a, real b, real xCoord, real yCoord, real rotationInDegree )
{
  if( a < 0.0 ) {
    dlgMessageBox( "a must be > 0", "OK");
    return;
  }

  if( b < 0.0 ) {
    dlgMessageBox( "b must be > 0", "OK");
    return;
  }

  if( b > a ) {
    dlgMessageBox( "a must be > b", "OK");
    return;
  }

  real phi = atan( b / a );

  real theta = PI / 2 - phi;

  real r1 = ( a * sin( theta ) + b * cos( theta ) - a ) /
            ( sin( theta ) + cos( theta ) - 1 );

  real r2 = ( a * sin( theta ) + b * cos( theta ) - b ) /
            ( sin( theta ) + cos( theta ) - 1 );

  real x = r2 * sin( phi );

  real y = b - r2 * ( 1.0 - cos( phi ) );

  real rotationInRad = rotationInDegree * PI / 180.0;

  printf( "ARC CW (%f %f) (%f %f) (%f %f);\n",
          xCoord + RotateXCoord( 0.0, b, rotationInRad ), yCoord + RotateYCoord( 0.0, b, rotationInRad ),
          xCoord + RotateXCoord( 0.0, b - 2.0 * r2, rotationInRad ), yCoord + RotateYCoord( 0.0, b - 2.0 * r2, rotationInRad ),
          xCoord + RotateXCoord( x, y, rotationInRad ), yCoord + RotateYCoord( x, y, rotationInRad ) );

  printf( "ARC CCW (%f %f) (%f %f) (%f %f);\n",
          xCoord + RotateXCoord( 0.0, b, rotationInRad ), yCoord + RotateYCoord( 0.0, b, rotationInRad ),
          xCoord + RotateXCoord( 0.0, b - 2.0 * r2, rotationInRad ), yCoord + RotateYCoord( 0.0, b - 2.0 * r2, rotationInRad ),
          xCoord + RotateXCoord( -x, y, rotationInRad ), yCoord + RotateYCoord( -x, y, rotationInRad ) );


  printf( "ARC CW (%f %f) (%f %f) (%f %f);\n",
          xCoord + RotateXCoord( 0.0, -b, rotationInRad ), yCoord + RotateYCoord( 0.0, -b, rotationInRad ),
          xCoord + RotateXCoord( 0.0, 2.0 * r2 - b, rotationInRad ), yCoord + RotateYCoord( 0.0, 2.0 * r2 - b, rotationInRad ),
          xCoord + RotateXCoord( -x, -y, rotationInRad ), yCoord + RotateYCoord( -x, -y, rotationInRad ) );

  printf( "ARC CCW (%f %f) (%f %f) (%f %f);\n",
          xCoord + RotateXCoord( 0.0, -b, rotationInRad ), yCoord + RotateYCoord( 0.0, -b, rotationInRad ),
          xCoord + RotateXCoord( 0.0, 2.0 * r2 - b, rotationInRad ), yCoord + RotateYCoord( 0.0, 2.0 * r2 - b, rotationInRad ),
          xCoord + RotateXCoord( x, -y, rotationInRad ), yCoord + RotateYCoord( x, -y, rotationInRad ) );


  printf( "ARC CW (%f %f) (%f %f) (%f %f);\n",
          xCoord + RotateXCoord( a, 0.0, rotationInRad ), yCoord + RotateYCoord( a, 0.0, rotationInRad ),
          xCoord + RotateXCoord( a - 2.0 * r1, 0.0, rotationInRad ), yCoord + RotateYCoord( a - 2.0 * r1, 0.0, rotationInRad ),
          xCoord + RotateXCoord( x, -y, rotationInRad ), yCoord + RotateYCoord( x, -y, rotationInRad ) );

  printf( "ARC CCW (%f %f) (%f %f) (%f %f);\n",
          xCoord + RotateXCoord( a, 0.0, rotationInRad ), yCoord + RotateYCoord( a, 0.0, rotationInRad ),
          xCoord + RotateXCoord( a - 2.0 * r1, 0.0, rotationInRad ), yCoord + RotateYCoord( a - 2.0 * r1, 0.0, rotationInRad ),
          xCoord + RotateXCoord( x, y, rotationInRad ), yCoord + RotateYCoord( x, y, rotationInRad ) );


  printf( "ARC CW (%f %f) (%f %f) (%f %f);\n",
          xCoord + RotateXCoord( -a, 0.0, rotationInRad ), yCoord + RotateYCoord( -a, 0.0, rotationInRad ),
          xCoord + RotateXCoord( 2.0 * r1 - a, 0.0, rotationInRad ), yCoord + RotateYCoord( 2.0 * r1 - a, 0.0, rotationInRad ),
          xCoord + RotateXCoord( -x, y, rotationInRad ), yCoord + RotateYCoord( -x, y, rotationInRad ) );

  printf( "ARC CCW (%f %f) (%f %f) (%f %f);\n",
          xCoord + RotateXCoord( -a, 0.0, rotationInRad ), yCoord + RotateYCoord( -a, 0.0, rotationInRad ),
          xCoord + RotateXCoord( 2.0 * r1 - a, 0.0, rotationInRad ), yCoord + RotateYCoord( 2.0 * r1 - a, 0.0, rotationInRad ),
          xCoord + RotateXCoord( -x, -y, rotationInRad ), yCoord + RotateYCoord( -x, -y, rotationInRad ) );
}

void FilledEllipse( real a, real b, real xCoord, real yCoord, real rotationInDegree )
{
  if( a < 0.0 ) {
    dlgMessageBox( "a must be > 0", "OK");
    return;
  }

  if( b < 0.0 ) {
    dlgMessageBox( "b must be > 0", "OK");
    return;
  }

  if( b > a ) {
    dlgMessageBox( "a must be > b", "OK");
    return;
  }

  real phi = atan( b / a );

  real theta = PI / 2 - phi;

  real r1 = ( a * sin( theta ) + b * cos( theta ) - a ) /
            ( sin( theta ) + cos( theta ) - 1 );

  real r2 = ( a * sin( theta ) + b * cos( theta ) - b ) /
            ( sin( theta ) + cos( theta ) - 1 );

  real x = r2 * sin( phi );

  real y = b - r2 * ( 1.0 - cos( phi ) );

  real rotationInRad = rotationInDegree * PI / 180.0;

  printf( "POLYGON 0\n");
  printf( "(%f %f) @-%f (%f %f)\n",
          xCoord + RotateXCoord( 0.0, b, rotationInRad ), yCoord + RotateYCoord( 0.0, b, rotationInRad ),
          r2,
          xCoord + RotateXCoord( x, y, rotationInRad ), yCoord + RotateYCoord( x, y, rotationInRad ) );

  printf( "@-%f (%f %f)\n",
          r1,
          xCoord + RotateXCoord( a, 0.0, rotationInRad ), yCoord + RotateYCoord( a, 0.0, rotationInRad ) );

  printf( "@-%f (%f %f)\n",
          r1,
          xCoord + RotateXCoord( x, -y, rotationInRad ), yCoord + RotateYCoord( x, -y, rotationInRad ) );


  printf( "@-%f (%f %f)\n",
          r2,
          xCoord + RotateXCoord( 0.0, -b, rotationInRad ), yCoord + RotateYCoord( 0.0, -b, rotationInRad ) );

  printf( "@-%f (%f %f)\n",
          r2,
          xCoord + RotateXCoord( -x, -y, rotationInRad ), yCoord + RotateYCoord( -x, -y, rotationInRad ) );

  printf( "@-%f (%f %f)\n",
          r1,
          xCoord + RotateXCoord( -a, 0.0, rotationInRad ), yCoord + RotateYCoord( -a, 0.0, rotationInRad ) );

  printf( "@-%f (%f %f)\n",
          r1,
          xCoord + RotateXCoord( -x, y, rotationInRad ), yCoord + RotateYCoord( -x, y, rotationInRad ) );

  printf( "@-%f (%f %f);\n",
          r2,
          xCoord + RotateXCoord( 0.0, b, rotationInRad ), yCoord + RotateYCoord( 0.0, b, rotationInRad ) );
}

int OnePadShapeCreated;

int ProcessOnePadShape( int Number, int startToken, string holeDiam )
{
  int layerNumRefPosition = FindToken( startToken + 1, "layerNumRef" );

  if( layerNumRefPosition >= 0 ) {
    if( checkLayerType( layerNumRefPosition + 1  ) ) {
      int padShapeTypePosition = FindToken( startToken + 1, "padShapeType" );

      if( padShapeTypePosition >= 0 ) {
        int shapeWidthPosition = FindToken( startToken + 1, "shapeWidth" );

        if( shapeWidthPosition >= 0 ) {
          string TokenText = Tokens[ shapeWidthPosition + 1 ];

          if( Tokens[ shapeWidthPosition + 2 ] != ")" ) {
            if( IsASCIIValue( Tokens[ shapeWidthPosition + 2 ] ) ) {
              TokenText = TokenText + Tokens[ shapeWidthPosition + 2 ];
            }
            else {
              WriteLog( "#warning: wrong description.\n" );
            }
          }

          string shapeWidth = ConvertUnits( GetNumberValue( TokenText ),
                                            GetUnitValue( TokenText ) );

          int shapeHeightPosition = FindToken( startToken + 1, "shapeHeight" );

          if( shapeHeightPosition >= 0 ) {

            string TokenText = Tokens[ shapeHeightPosition + 1 ];

            if( Tokens[ shapeHeightPosition + 2 ] != ")" ) {
              if( IsASCIIValue( Tokens[ shapeHeightPosition + 2 ] ) ) {
                TokenText = TokenText + Tokens[ shapeHeightPosition + 2 ];
              }
              else {
                WriteLog( "#warning: wrong description.\n" );
              }
            }

            string shapeHeight = ConvertUnits( GetNumberValue( TokenText ),
                                               GetUnitValue( TokenText ) );

            if( ( !CheckForNull( shapeWidth ) ) ||
                ( !CheckForNull( shapeHeight ) ) ) {

              printf("#  PadShape: layerNumRef = %s",
                Tokens[ layerNumRefPosition + 1 ] );
              printf(" padShapeType = %s",
                Tokens[ padShapeTypePosition + 1 ] );
              printf(" shapeWidth = %s",
                shapeWidth );
              printf(" shapeHeight = %s\n",
                shapeHeight );

              if( IfSMD[ Number ] ) { // SMD
                if( 1 /*OnePadShapeCreated == 0*/ ) {
                  if( Tokens[ padShapeTypePosition + 1 ] == "Oval" ) { // Oval
                    if( OnePadShapeCreated == 0 ) {
                      sprintf( PadStyleDefsScript[ Number ], "%sSMD %s %s -100",
                               PadStyleDefsScript[ Number ],
                               shapeWidth, shapeHeight );
                      OnePadShapeCreated = 1;
                    }
                  }
                  else {
                    if( Tokens[ padShapeTypePosition + 1 ] == "Rect" ) { // Rectangle
                      if( OnePadShapeCreated == 0 ) {
                        sprintf( PadStyleDefsScript[ Number ], "%sSMD %s %s -0",
                                 PadStyleDefsScript[ Number ],
                                 shapeWidth, shapeHeight );
                        OnePadShapeCreated = 1;
                      }
                    }
                    else {
                      if( Tokens[ padShapeTypePosition + 1 ] == "Ellipse" ) { // Ellipse
                        if( shapeWidth == shapeHeight ) {
                          if( OnePadShapeCreated == 0 ) {
                            sprintf( PadStyleDefsScript[ Number ], "%sSMD %s %s -100",
                                     PadStyleDefsScript[ Number ],
                                     shapeWidth, shapeHeight );
                            OnePadShapeCreated = 1;
                          }
                        }
                        else {
                          //if( DebugMessage ) {
                            WriteLog( "# warning: Ellipse with different width and height.\n");
                          //}

                          // Create circle here and ellipse later over it

                          //PadStyleShapeType[ Number ] = 1;

                          if( OnePadShapeCreated == 0 ) {
                            sprintf( PadStyleDefsScript[ Number ], "%sSMD %s %s -100",
                                     PadStyleDefsScript[ Number ],
                                     shapeWidth, shapeWidth );
                            OnePadShapeCreated = 1;
                          }
                        }
                      }
                      else {
                        if( Tokens[ padShapeTypePosition + 1 ] == "RndRect" ) { // RoundRectangle
                          if( OnePadShapeCreated == 0 ) {
                            sprintf( PadStyleDefsScript[ Number ], "%sSMD %s %s -25",
                                     PadStyleDefsScript[ Number ],
                                     shapeWidth, shapeHeight );
                            OnePadShapeCreated = 1;
                          }
                        }
                        else {
                          if( Tokens[ padShapeTypePosition + 1 ] == "Target" ) { // Make round
                            if( OnePadShapeCreated == 0 ) {
                              sprintf( PadStyleDefsScript[ Number ], "%sSMD %s %s -100",
                                 PadStyleDefsScript[ Number ],
                                 shapeWidth, shapeHeight );
                               OnePadShapeCreated = 1;
                            }
                          }
                          else {
                            string tmp;
                            sprintf( tmp, "# warning: SMDShape %s not supported yet\n",
                                           Tokens[ padShapeTypePosition + 1 ] );
                            WriteLog( tmp );
                          }
                        }
                      }
                    }
                  }
                }
              }
              else { // PAD
                if( 1 /*OnePadShapeCreated == 0*/ ) {
                  if( Tokens[ padShapeTypePosition + 1 ] == "Oval" ) { // Oval
                    if( shapeWidth == shapeHeight ) {
                      if( OnePadShapeCreated == 0 ) {
                        sprintf( PadStyleDefsScript[ Number ], "%sPAD %s ROUND",
                                 PadStyleDefsScript[ Number ],
                                 shapeWidth );
                        OnePadShapeCreated = 1;
                      }
                    }
                    else {
                      //PadStyleShapeType[ Number ] = 1;

                      if( OnePadShapeCreated == 0 ) {
                        real val1 = strtod( ConvertUnits( GetNumberValue( shapeHeight ),
                                                          GetUnitValue( shapeHeight ) ) );
                        real val2 = strtod( ConvertUnits( GetNumberValue( shapeWidth ),
                                                          GetUnitValue( shapeWidth ) ) );

                        real D = val1;

                        if( D > val2 ) {
                          D = val2;
                        }

                        sprintf( PadStyleDefsScript[ Number ], "%sPAD %f LONG",
                                 PadStyleDefsScript[ Number ], D );

                        /*sprintf( PadStyleDefsScript[ Number ], "%sPAD %s SQUARE",
                                 PadStyleDefsScript[ Number ],
                                 MinValue( shapeWidth, shapeHeight ) );*/

                        OnePadShapeCreated = 1;

                        if( val1 > val2 ) {
                          PadShapeAddRotation[ Number ] = 1;
                        }
                      }

                      /*PadShapeStyleShapeType[ NrPadShapeStyle ] = 2;
                      PadShapeStyleDefsWidth[ NrPadShapeStyle ] = shapeWidth;
                      PadShapeStyleDefsHeight[ NrPadShapeStyle ] = shapeHeight;
                      PadShapeStyleDefsLayer[ NrPadShapeStyle ] = Tokens[ layerNumRefPosition + 1 ];
                      NrPadShapeStyle++;

                      NrPadShapes[ Number ]++;*/
                    }
                  }
                  else {
                    if( Tokens[ padShapeTypePosition + 1 ] == "Rect" ) { // Rectangle
                      if( shapeWidth == shapeHeight ) {
                        if( OnePadShapeCreated == 0 ) {
                          sprintf( PadStyleDefsScript[ Number ], "%sPAD %s SQUARE",
                                   PadStyleDefsScript[ Number ],
                                   shapeWidth );
                          OnePadShapeCreated = 1;
                        }
                      }
                      else {
                        if( OnePadShapeCreated == 0 ) {
                          sprintf( PadStyleDefsScript[ Number ], "%sPAD %s SQUARE",
                                   PadStyleDefsScript[ Number ],
                                   MinValue( shapeWidth, shapeHeight ) );
                          OnePadShapeCreated = 1;
                        }

                        PadShapeStyleShapeType[ NrPadShapeStyle ] = 4;
                        PadShapeStyleDefsWidth[ NrPadShapeStyle ] = shapeWidth;
                        PadShapeStyleDefsHeight[ NrPadShapeStyle ] = shapeHeight;
                        PadShapeStyleDefsLayer[ NrPadShapeStyle ] = Tokens[ layerNumRefPosition + 1 ];
                        NrPadShapeStyle++;

                        NrPadShapes[ Number ]++;
                      }
                    }
                    else {
                      if( Tokens[ padShapeTypePosition + 1 ] == "Ellipse" ) { // Ellipse
                        if( shapeWidth == shapeHeight ) {
                          if( OnePadShapeCreated == 0 ) {
                            sprintf( PadStyleDefsScript[ Number ], "%sPAD %s ROUND",
                                     PadStyleDefsScript[ Number ],
                                     shapeWidth );
                            OnePadShapeCreated = 1;
                          }
                        }
                        else {
                          //if( DebugMessage ) {
                            WriteLog( "# warning: Ellipse with different width and height.\n");
                          //}

                          // Create circle here and ellipse later over it

                          PadShapeStyleShapeType[ NrPadShapeStyle ] = 1;
                          PadShapeStyleDefsWidth[ NrPadShapeStyle ] = shapeWidth;
                          PadShapeStyleDefsHeight[ NrPadShapeStyle ] = shapeHeight;
                          PadShapeStyleDefsLayer[ NrPadShapeStyle ] = Tokens[ layerNumRefPosition + 1 ];
                          NrPadShapeStyle++;

                          NrPadShapes[ Number ]++;

                          if( OnePadShapeCreated == 0 ) {
                            sprintf( PadStyleDefsScript[ Number ], "%sPAD %s ROUND",
                                     PadStyleDefsScript[ Number ],
                                     MinValue( shapeWidth, shapeHeight ) );
                            OnePadShapeCreated = 1;
                          }
                        }
                      }
                      else {
                        if( Tokens[ padShapeTypePosition + 1 ] == "MtHole" ) { // MountingHole
                          if( shapeWidth == shapeHeight ) {
                            if( OnePadShapeCreated == 0 ) {
                              sprintf( PadStyleDefsScript[ Number ], "%sHOLE %s",
                                       PadStyleDefsScript[ Number ],
                                       holeDiam );

                              OnePadShapeCreated = 1;
                            }
                          }
                          else {
                            //if( DebugMessage ) {
                              WriteLog( "# warning: MtHole with different width and height.\n");
                            //}
                          }
                        }
                        else {
                          if( Tokens[ padShapeTypePosition + 1 ] == "RndRect" ) { // RoundRectangle
                            if( OnePadShapeCreated == 0 ) {
                              real val1 = strtod( ConvertUnits( GetNumberValue( shapeHeight ),
                                                                GetUnitValue( shapeHeight ) ) );
                              real val2 = strtod( ConvertUnits( GetNumberValue( shapeWidth ),
                                                                GetUnitValue( shapeWidth ) ) );

                              real minVal = val1;
                              real maxVal = val1;

                              if( minVal > val2 ) {
                                minVal = val2;
                              }

                              if( maxVal < val2 ) {
                                maxVal = val2;
                              }

                              real d = maxVal * ( 1.0 - 0.7 / ROUNDNESS );

                              if( minVal > d ) {
                                minVal = d;
                              }

                              sprintf( PadStyleDefsScript[ Number ], "%sPAD %f SQUARE",
                                       PadStyleDefsScript[ Number ], minVal );
                              OnePadShapeCreated = 1;
                            }

                            PadShapeStyleShapeType[ NrPadShapeStyle ] = 2;
                            PadShapeStyleDefsWidth[ NrPadShapeStyle ] = shapeWidth;
                            PadShapeStyleDefsHeight[ NrPadShapeStyle ] = shapeHeight;
                            PadShapeStyleDefsLayer[ NrPadShapeStyle ] = Tokens[ layerNumRefPosition + 1 ];
                            NrPadShapeStyle++;

                            NrPadShapes[ Number ]++;
                          }
                          else {
                            if( Tokens[ padShapeTypePosition + 1 ] == "Target" ) { // Make it round
                              if( OnePadShapeCreated == 0 ) {
                                sprintf( PadStyleDefsScript[ Number ], "%sPAD %s ROUND",
                                         PadStyleDefsScript[ Number ],
                                         shapeWidth );
                                OnePadShapeCreated = 1;
                              }
                            }
                            else {
                              string tmp;
                              sprintf( tmp, "# warning: PadShape %s not supported yet\n",
                                       Tokens[ padShapeTypePosition + 1 ] );
                              WriteLog( tmp );
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }

              PadStyleDefsSkip[ Number ] = 0;
            }
            else {
              if( DebugMessage ) {
                printf( "# skips because of zero coordinates.\n");
              }
            }
          }
        }
        else { // No width
          if( Tokens[ padShapeTypePosition + 1 ] == "Polygon" ) {
            printf( "#polygonPad\n");

            string xLineCoord[];
            string yLineCoord[];
            int nrLines = 0;

            int shapeOutlinePosition = FindToken( startToken + 1, "shapeOutline" );

            if( shapeOutlinePosition >= 0 ) {
	      int currentToken = shapeOutlinePosition + 1;

              PadShapeStyleDefsPolygon[ NrPadShapeStyle ] = currentToken;

	      while( currentToken < TokensNumber ) {
		if( Tokens[ currentToken ] == "(" ) {
		  currentToken++;

		  if( Tokens[ currentToken ] == "pt" ) {
		    xLineCoord[ nrLines ] = Tokens[ currentToken + 1 ];
		    yLineCoord[ nrLines ] = Tokens[ currentToken + 2 ];
		    nrLines++;

		    currentToken = currentToken + 3;
		  }
		}
		else {
		  if( Tokens[ currentToken ] == ")" ) {
		    break;
		  }
	        }

  	        currentToken++;
	      }

	      string minX = xLineCoord[ 0 ];
	      string minY = yLineCoord[ 0 ];
              string maxX = xLineCoord[ 0 ];
	      string maxY = yLineCoord[ 0 ];

	      for( int i = 0; i < nrLines; i++ ) {
	        minX = MinValue( minX, xLineCoord[ i ] );
	        maxX = MaxValue( maxX, xLineCoord[ i ] );
	        minY = MinValue( minY, yLineCoord[ i ] );
	        maxY = MaxValue( maxY, yLineCoord[ i ] );
              }

              real rMinX = strtod( minX );
              real rMaxX = strtod( maxX );
              real rMinY = strtod( minY );
              real rMaxY = strtod( maxY );

              real rX = ( rMaxX - rMinX ) / 2.0;
              real rY = ( rMaxY - rMinY ) / 2.0;

              real r = rX;

              if( r > rY ) {
                r = rY;
              }

	      if( OnePadShapeCreated == 0 ) {
                if( IfSMD[ Number ] ) {
                  sprintf( PadStyleDefsScript[ Number ], "%sSMD %f %f -0",
                           PadStyleDefsScript[ Number ],
                           r,
                           r );
                }
                else {
	          sprintf( PadStyleDefsScript[ Number ], "%sPAD %f SQUARE",
	                   PadStyleDefsScript[ Number ],
	                   r );
                }

	        OnePadShapeCreated = 1;
	      }

	      PadShapeStyleShapeType[ NrPadShapeStyle ] = 3;
	      PadShapeStyleDefsWidth[ NrPadShapeStyle ] = maxX;
	      PadShapeStyleDefsHeight[ NrPadShapeStyle ] = maxY;
	      PadShapeStyleDefsLayer[ NrPadShapeStyle ] = Tokens[ layerNumRefPosition + 1 ];
	      NrPadShapeStyle++;

	      NrPadShapes[ Number ]++;

              PadStyleDefsSkip[ Number ] = 0;
            }
            else {
              WriteLog("# warning: can't find shapeOutline\n");
            }
          }
	}
      }
    }
  }
  else {
    if( DebugMessage ) {
      printf( "#skips because of layer.\n");
    }
  }

  return( 0 );
}

int ProcessPadShapes( int Number, int startToken, string holeDiam )
{
  OnePadShapeCreated = 0;

  CurrentToken = startToken + 1;

  while( CurrentToken < TokensNumber ) {
    if( Tokens[ CurrentToken ] == "(" ) {
      CurrentToken++;

      if( Tokens[ CurrentToken ] == "padShape" ) {
        int SavePosition = CurrentToken;

        ProcessOnePadShape( Number, SavePosition, holeDiam );

        CurrentToken = SavePosition;
      }

      SkipThisItem();
    }
    else {
      if( Tokens[ CurrentToken ] == ")" ) {
        break;
      }
      else {
        dlgMessageBox( "Unexpected keyword in ProcessPadShapes " + Tokens[
                        CurrentToken ], "OK");
        return( 1 );
      }
    }

    CurrentToken++;
  }

  return( 1 );
}

// This function converts PCAD layers to Eagle layers

string ConvertLayer( string PCADLayer )
{
  for (int n = 0; n <= CntlayerDef; n++) {
    if( PCADLayer == RefLayerNum[n] ) {
      if( DebugMessage ) {
        //printf( "# info: this layer was converted by using user file.\n");
      }

      return( PcadEagleLayerRefNum[n] );
    }
  }

  if( PCADLayer == "0" ) return( "48" ); // Unknown layer
  if( PCADLayer == "1" ) return( "1" ); // Top
  if( PCADLayer == "2" ) return( "16" ); // Bottom
  if( PCADLayer == "3" ) return( "20" ); // Dimension
  if( PCADLayer == "4" ) return( "29" ); // Top Mask
  if( PCADLayer == "5" ) return( "30" ); // Bot Mask
  if( PCADLayer == "6" ) return( "21" ); // Top Silk
  if( PCADLayer == "7" ) return( "22" ); // Bot Silk
  if( PCADLayer == "8" ) return( "31" ); // Top Paste
  if( PCADLayer == "9" ) return( "32" ); // Bot Paste
  if( PCADLayer == "10" ) return( "21" ); // Top Assy
  if( PCADLayer == "11" ) return( "22" ); // Bot Assy
  if( PCADLayer == "12" ) return( "2" ); // Int1
  if( PCADLayer == "13" ) return( "3" ); // Int2
  if( PCADLayer == "14" ) return( "4" ); // Int3
  if( PCADLayer == "15" ) return( "5" ); // Int4
  if( PCADLayer == "16" ) return( "6" ); // Int5
  if( PCADLayer == "17" ) return( "7" ); // Int6
  if( PCADLayer == "18" ) return( "8" ); // Int7
  if( PCADLayer == "19" ) return( "9" ); // Int8
  if( PCADLayer == "20" ) return( "48" ); // MECH
  if( PCADLayer == "21" ) return( "48" ); // MECH
  if( PCADLayer == "22" ) return( "48" ); // MESH
  if( PCADLayer == "23" ) return( "48" ); // MESH
  if( PCADLayer == "24" ) return( "48" ); // MESH
  if( PCADLayer == "25" ) return( "48" ); // TopStrMsk 48 ?
  if( PCADLayer == "26" ) return( "48" ); // BotStrMsk 48 ?
  if( PCADLayer == "27" ) return( "48" ); // TopCreep 48 ?
  if( PCADLayer == "28" ) return( "48" ); // BotCreep 48 ?
  if( PCADLayer == "29" ) return( "48" ); // Int1Creep 48 ?
  if( PCADLayer == "30" ) return( "48" ); // Int2Creep 48 ?
  if( PCADLayer == "31" ) return( "48" ); // Int3Creep 48 ?
  if( PCADLayer == "32" ) return( "48" ); // Int4Creep 48 ?
  if( PCADLayer == "33" ) return( "48" ); // Int5Creep 48 ?
  if( PCADLayer == "34" ) return( "48" ); // Int6Creep 48 ?
  if( PCADLayer == "35" ) return( "48" ); // Int7Creep 48 ?
  if( PCADLayer == "36" ) return( "48" ); // Int8Creep 48 ?
  if( PCADLayer == "37" ) return( "48" ); // Int9Creep 48 ?
  if( PCADLayer == "38" ) return( "48" ); // Int10Creep 48 ?
  if( PCADLayer == "39" ) return( "48" ); // Reserve ?
  if( PCADLayer == "40" ) return( "48" ); // TxtCreep 48 ?
  if( PCADLayer == "41" ) return( "48" ); // DrillHelp 48 ?
  if( PCADLayer == "42" ) return( "44" ); // Drill
  if( PCADLayer == "43" ) return( "48" ); // TopTxt 48 ?
  if( PCADLayer == "44" ) return( "48" ); // BotTxt 48 ?
  if( PCADLayer == "45" ) return( "48" ); // TopHelp 48 ?
  if( PCADLayer == "46" ) return( "48" ); // BotHelp 48 ?
  if( PCADLayer == "47" ) return( "48" ); // Int1Help 48 ?
  if( PCADLayer == "48" ) return( "48" ); // Int2Help 48 ?
  if( PCADLayer == "49" ) return( "48" ); // Int3Help 48 ?
  if( PCADLayer == "50" ) return( "48" ); // Int4Help 48 ?
  if( PCADLayer == "51" ) return( "48" ); // Int5Help 48 ?
  if( PCADLayer == "52" ) return( "48" ); // Int6Help 48 ?
  if( PCADLayer == "53" ) return( "48" ); // Int7Help 48 ?
  if( PCADLayer == "54" ) return( "48" ); // Int8Help 48 ?
  if( PCADLayer == "55" ) return( "48" ); // Int9Help 48 ?
  if( PCADLayer == "56" ) return( "48" ); // Int10Help 48 ?
  if( PCADLayer == "57" ) return( "48" ); // SilkscreenTop 48 ?
  if( PCADLayer == "58" ) return( "48" ); // SilkscreenBot 48 ?
  if( PCADLayer == "59" ) return( "48" ); // BoardHelp 48 ?
  if( PCADLayer == "60" ) return( "48" ); // A4H1T0 48 ?
  if( PCADLayer == "61" ) return( "48" ); // A4H1B0 48 ?
  if( PCADLayer == "62" ) return( "48" ); // A4H2T0 48 ?
  if( PCADLayer == "63" ) return( "48" ); // A4H2B0 48 ?
  if( PCADLayer == "64" ) return( "48" ); // A4H1-5T0 48 ?
  if( PCADLayer == "65" ) return( "48" ); // A4H1-5B0 48 ?
  if( PCADLayer == "66" ) return( "48" ); // A4H3T0 48 ?
  if( PCADLayer == "67" ) return( "48" ); // A4H3B0 48 ?
  if( PCADLayer == "68" ) return( "48" ); // A3H1T0 48 ?
  if( PCADLayer == "69" ) return( "48" ); // A3H1B0 48 ?
  if( PCADLayer == "70" ) return( "48" ); // TitleReserveT 48 ?
  if( PCADLayer == "71" ) return( "48" ); // TitleReserveB 48 ?
  if( PCADLayer == "72" ) return( "48" ); // TopDesRes 48 ?
  if( PCADLayer == "73" ) return( "48" ); // BotDesRes 48 ?
  if( PCADLayer == "74" ) return( "48" ); // TopLCover 48 ?
  if( PCADLayer == "75" ) return( "48" ); // BotLCover 48 ?
  if( PCADLayer == "76" ) return( "48" ); // TopTstPnt 48 ?
  if( PCADLayer == "77" ) return( "48" ); // BotTstPnt 48 ?
  // No Layers 78, 79
  if( PCADLayer == "80" ) return( "48" ); // Int1Txt 48 ?
  if( PCADLayer == "81" ) return( "48" ); // Int2Txt 48 ?
  if( PCADLayer == "82" ) return( "48" ); // Int3Txt 48 ?
  if( PCADLayer == "83" ) return( "48" ); // Int4Txt 48 ?
  if( PCADLayer == "84" ) return( "48" ); // Int5Txt 48 ?
  if( PCADLayer == "85" ) return( "48" ); // Int6Txt 48 ?
  if( PCADLayer == "86" ) return( "48" ); // Int7Txt 48 ?
  if( PCADLayer == "87" ) return( "48" ); // Int8Txt 48 ?
  if( PCADLayer == "88" ) return( "48" ); // Int9Txt 48 ?
  if( PCADLayer == "89" ) return( "48" ); // Int10Txt 48 ?
  if( PCADLayer == "90" ) return( "48" ); // TxtTopCreep 48 ?
  if( PCADLayer == "91" ) return( "48" ); // TxtBotCreep 48 ?
  if( PCADLayer == "92" ) return( "48" ); // TxtInt1Creep 48 ?
  if( PCADLayer == "93" ) return( "48" ); // TxtInt2Creep 48 ?
  if( PCADLayer == "94" ) return( "48" ); // TxtInt3Creep 48 ?
  if( PCADLayer == "95" ) return( "48" ); // TxtInt4Creep 48 ?
  if( PCADLayer == "96" ) return( "48" ); // TxtInt5Creep 48 ?
  if( PCADLayer == "97" ) return( "48" ); // TxtInt6Creep 48 ?
  if( PCADLayer == "98" ) return( "48" ); // TxtInt7Creep 48 ?
  if( PCADLayer == "99" ) return( "48" ); // TxtInt8Creep 48 ?
  if( PCADLayer == "100" ) return( "48" ); // TxtInt9Creep 48 ?
  if( PCADLayer == "101" ) return( "48" ); // TxtInt10Creep 48 ?
  if( PCADLayer == "102" ) return( "48" ); // Reserve1 48 ?
  if( PCADLayer == "103" ) return( "48" ); // TxtAssyTopCreep 48 ?
  if( PCADLayer == "104" ) return( "48" ); // TxtAssyBotCreep 48 ?
  if( PCADLayer == "105" ) return( "48" ); // TxtAssyTop 48 ?
  if( PCADLayer == "106" ) return( "48" ); // TxtAssyBot 48 ?
  if( PCADLayer == "107" ) return( "48" ); // TxtTopLCover 48 ?
  if( PCADLayer == "108" ) return( "48" ); // TxtBotLCover 48 ?
  if( PCADLayer == "109" ) return( "48" ); // TestPointTop 48 ?
  if( PCADLayer == "110" ) return( "48" ); // TestPointBot 48 ?
  if( PCADLayer == "111" ) return( "35" ); // TopGlue
  if( PCADLayer == "112" ) return( "36" ); // BotGlue
  if( PCADLayer == "113" ) return( "48" ); // Drill-Top-I1 48 ?
  if( PCADLayer == "123" ) return( "48" ); // Drill-Top-I4 48 ?

  string tmp;
  sprintf( tmp, "# warning: ConvertLayer: can't convert layer %s\n", PCADLayer );
  WriteLog( tmp );

  return( "" );
}

void GenerateOnePadDefinition( int Number, int startToken )
{
  //PadStyleDefsScript[ Number ] = "#PadStyleDef " + Tokens[ startToken ];
  printf( "#PadStyleDef %s\n", Tokens[ startToken ] );

    /*ReplaceNotSupportedCharacters( RemoveDoubleQuotas(
    Tokens[ startToken ] ) );*/

  PadStyleDefsSkip[ Number ] = 1;
  PadShapeAddRotation[ Number ] = 0;

  int holeDiamPosition = FindToken( startToken + 1, "holeDiam" );

  if( holeDiamPosition >= 0 ) {
    string TokenText = Tokens[ holeDiamPosition + 1 ];

    if( Tokens[ holeDiamPosition + 2 ] != ")" ) {
      if( IsASCIIValue( Tokens[ holeDiamPosition + 2 ] ) ) {
        TokenText = TokenText + Tokens[ holeDiamPosition + 2 ];
      }
      else {
        WriteLog( "#warning: wrong description.\n" );
      }
    }

    string holeDiam = ConvertUnits( GetNumberValue( TokenText ),
                                    GetUnitValue( TokenText ) );

    PadShapePoiner[ Number ] = NrPadShapeStyle;
    NrPadShapes[ Number ] = 0;

    if( CheckForNull( holeDiam ) ) {
      IfSMD[ Number ] = 1;
    }
    else {
      IfSMD[ Number ] = 0;
    }

    if( DebugMessage ) {
      printf( "#HoleDiameter = %s\n", holeDiam );
    }

    ProcessPadShapes( Number, startToken, holeDiam );

    if( PadStyleDefsSkip[ Number ] ) {
      if( DebugMessage ) {
        printf( "# this PadDefinition was skipped.\n");
      }
    }
    else {
      if( IfSMD[ Number ] ) {
      }
      else {
        sprintf( PadStyleDefsScript[ Number ], "CHANGE DRILL %s;\n%s",
                 holeDiam, PadStyleDefsScript[ Number ] );
      }

      //printf( "#%s\n", PadStyleDefsScript[ Number ] );
    }
  }
  else {
    if( DebugMessage ) {
      printf( "# skips because pad has no holeDiam.\n");
    }
  }
}

void GeneratePadDefinitions( void )
{
  for( int i = 0; i < PadStyleDefsNumber; i++ ) {
    int startToken = PadStyleDefsArray[ i ];

    string info;
    sprintf( info, "Process Pad Style definition %d (%d)", i, PadStyleDefsNumber );
    UpdateProgress( info );

    GenerateOnePadDefinition( i, startToken );
  }
}

// This function write library header to script

void GenerateLibraryHeader( void )
{
  string libraryName;
  string array[];

  libraryName = filesetext( PCADfileName, ".lbr");

  PrintPCADLayers();

  printf("# Library header:\n");

  if( fileglob( array, libraryName ) ) {
    printf("SET CONFIRM YES;\n");
    printf("REMOVE '%s';\n", libraryName );
    printf("SET CONFIRM OFF;\n");
  }

  printf("OPEN '%s';\n", libraryName);
  printf("SET WIRE_BEND 2;\n");
  printf("SET OPTIMIZING OFF;\n");

  printf("#\n");
}

// Returns originalName

string GetOriginalDeviceName( int startToken )
{
  string originalName = "";

  int token = FindToken( startToken, "originalName" );

  if( token > 0 ) {
    originalName = Tokens[ token + 1 ];
  }

  return( ReplaceNotSupportedCharacters( RemoveDoubleQuotas( originalName ) ) );
}

// This function generates one pad in device

void GeneratePad( int startToken, int zeroPosition )
{
  int tokenPosition = FindToken( startToken + 1, "padStyleRef" );

  if( tokenPosition >= 0 ) {
    printf("#padStyleRef = %s\n", Tokens[ tokenPosition + 1 ] );

    string info;
    sprintf( info, "Process pad %d %s", tokenPosition, Tokens[ tokenPosition + 1 ] );
    UpdateProgress( info );

    int PadStyleDefNum = FindPadStyleDef( Tokens[ tokenPosition + 1 ] );

    if( PadStyleDefNum >= 0 ) {
      if( PadStyleDefsSkip[ PadStyleDefNum ] == 0 ) {
        printf( "%s", PadStyleDefsScript[ PadStyleDefNum ] );

        int defaultPinDesPosition = FindToken( startToken + 1, "defaultPinDes" );

        int padNumPosition = FindToken( startToken + 1, "padNum" );

        if( padNumPosition >= 0 ) {
          int padCoordPosition = FindToken( startToken + 1, "pt" );

          if( padCoordPosition >= 0 ) {
            string rotation = "0";

            int rotationPosition = FindToken( startToken + 1, "rotation" );

            if( rotationPosition >= 0 ) {
              rotation = Tokens[ rotationPosition + 1 ];
            }

            if( PadShapeAddRotation[ PadStyleDefNum ] ) {
              real rot = strtod( rotation );

              rot = rot + 90.0;

              if( rot >= 360.0 ) {
                rot = rot - 360.0;
              }

              sprintf( rotation, "%f", rot );
            }

            string padName = "";

            padName = Tokens[ padNumPosition + 1 ];

            /*if( defaultPinDesPosition >= 0 ) {
              padName = ReplaceNotSupportedCharacters( RemoveDoubleQuotas( Tokens[ defaultPinDesPosition + 1 ] ) );
            }
            else {
              padName = Tokens[ padNumPosition + 1 ];
            }*/

            string xCoordPad = "";
            string yCoordPad = "";

            xCoordPad = Tokens[ padCoordPosition + 1 ];

            if( IsASCIIValue( Tokens[ padCoordPosition + 2 ] ) ) {
	      xCoordPad = xCoordPad + Tokens[ padCoordPosition + 2 ];

	      if( Tokens[ padCoordPosition + 3 ] != ")" ) {
	        yCoordPad = Tokens[ padCoordPosition + 3 ];

	        if( Tokens[ padCoordPosition + 4 ] != ")" ) {
	          yCoordPad = yCoordPad + Tokens[ padCoordPosition + 4 ];
	        }
	      }
	      else {
	        WriteLog( "#warning: wront point description.\n" );
	      }
            }
            else {
	      yCoordPad = Tokens[ padCoordPosition + 2 ];

	      if( Tokens[ padCoordPosition + 3 ] != ")" ) {
	        yCoordPad = yCoordPad + Tokens[ padCoordPosition + 3 ];
	      }
	    }

            string Val1 = ConvertUnits( GetNumberValue( xCoordPad ),
                                        GetUnitValue( xCoordPad ) );
            string Val2 = ConvertUnits( GetNumberValue( yCoordPad ),
                                        GetUnitValue( yCoordPad ) );

            if( zeroPosition ) {
              Val1 = "0.0";
              Val2 = "0.0";
            }

            if( IfSMD[ PadStyleDefNum ] ) {
              printf( " R%s '%s' (%s %s);\n",
                rotation,
                padName,
                Val1, Val2 );


            }
            else {
              int pos = strstr( PadStyleDefsScript[ PadStyleDefNum ], "HOLE" );

              if( padName == "0" ) {
                printf( " (%s %s);\n",
                          Val1, Val2 );
              }
              else {
                if( pos >= 0 ) {
                  printf( " '%s' (%s %s);\n",
                          padName,
                          Val1, Val2 );
                }
                else {
		  printf( " R%s '%s' (%s %s);\n",
		    rotation,
		    padName,
		    Val1, Val2 );
                 }
               }
            }

	    int PPointer = PadShapePoiner[ PadStyleDefNum ];
	    int PNumber = NrPadShapes[ PadStyleDefNum ];

	    for( int i = 0; i < PNumber; i++, PPointer++ ) {
	      if( PadShapeStyleShapeType[ PPointer ] == 1 ) {
		printf("CHANGE LAYER %s;\n", ConvertLayer( PadShapeStyleDefsLayer[ PPointer ] ) );

		real xCoord = GetValue( Tokens[ padCoordPosition + 1 ] );
		real yCoord = GetValue( Tokens[ padCoordPosition + 2 ] );
		real halfWidth = GetValue( PadShapeStyleDefsWidth[ PPointer ] ) / 2.0;
		real halfHeight = GetValue( PadShapeStyleDefsHeight[ PPointer ] ) / 2.0;

		if( halfWidth > halfHeight ) {
		  FilledEllipse( halfWidth, halfHeight, xCoord, yCoord, 0 );
		}
		else {
		  FilledEllipse( halfHeight, halfWidth, xCoord, yCoord, 90.0 );
		}
	      }

	      if( PadShapeStyleShapeType[ PPointer ] == 2 ) {
		printf("CHANGE LAYER %s;\n", ConvertLayer( PadShapeStyleDefsLayer[ PPointer ] ) );

		real xCoord = GetValue( Tokens[ padCoordPosition + 1 ] );
		real yCoord = GetValue( Tokens[ padCoordPosition + 2 ] );
		real halfWidth = GetValue( PadShapeStyleDefsWidth[ PPointer ] ) / 2.0;
		real halfHeight = GetValue( PadShapeStyleDefsHeight[ PPointer ] ) / 2.0;

                real rotationInRad = strtod( rotation ) * PI / 180.0;

                real radius;

                if( halfWidth < halfHeight ) {
                  radius = halfWidth / ROUNDNESS;
                }
                else {
                  radius = halfHeight / ROUNDNESS;
                }

                printf("# PadShapeStyleShapeType = 2 halfWidth = %f halfHeight = %f radius = %f\n", halfWidth, halfHeight, radius );

                real x_lo = -halfWidth + radius;
                real y_lo = -halfHeight + radius;
                real x_hi = halfWidth - radius;
                real y_hi = halfHeight - radius;

		printf("POLYGON %f (%f %f) (%f %f) (%f %f) (%f %f) (%f %f);\n", 2 * radius,
                               xCoord + RotateXCoord( x_lo, y_lo, rotationInRad ), yCoord + RotateYCoord( x_lo, y_lo, rotationInRad ),
			       xCoord + RotateXCoord( x_hi, y_lo, rotationInRad ), yCoord + RotateYCoord( x_hi, y_lo, rotationInRad ),
                               xCoord + RotateXCoord( x_hi, y_hi, rotationInRad ), yCoord + RotateYCoord( x_hi, y_hi, rotationInRad ),
			       xCoord + RotateXCoord( x_lo, y_hi, rotationInRad ), yCoord + RotateYCoord( x_lo, y_hi, rotationInRad ),
                               xCoord + RotateXCoord( x_lo, y_hi, rotationInRad ), yCoord + RotateYCoord( x_lo, y_hi, rotationInRad ) );

	        /*printf("POLYGON 0 (%f %f) (%f %f) @-%f (%f %f) (%f %f) @-%f (%f %f) (%f %f) @-%f (%f %f) (%f %f) @-%f (%f %f) ;\n",
		               xCoord + RotateXCoord( halfWidth - radius, -halfHeight, rotationInRad ), yCoord + RotateYCoord( halfWidth - radius, -halfHeight, rotationInRad ),
                               xCoord + RotateXCoord( -halfWidth + radius, -halfHeight, rotationInRad ), yCoord + RotateYCoord( -halfWidth + radius, -halfHeight, rotationInRad ),
                               radius,
			       xCoord + RotateXCoord( -halfWidth, -halfHeight + radius, rotationInRad ), yCoord + RotateYCoord( -halfWidth, -halfHeight + radius, rotationInRad ),
			       xCoord + RotateXCoord( -halfWidth, halfHeight - radius, rotationInRad ), yCoord + RotateYCoord( -halfWidth, halfHeight - radius, rotationInRad ),
			       radius,
			       xCoord + RotateXCoord( -halfWidth + radius, halfHeight, rotationInRad ), yCoord + RotateYCoord( -halfWidth + radius, halfHeight, rotationInRad ),
			       xCoord + RotateXCoord( halfWidth - radius, halfHeight, rotationInRad ), yCoord + RotateYCoord( halfWidth - radius, halfHeight, rotationInRad ),
			       radius,
			       xCoord + RotateXCoord( halfWidth, halfHeight - radius, rotationInRad ), yCoord + RotateYCoord( halfWidth, halfHeight - radius, rotationInRad ),
			       xCoord + RotateXCoord( halfWidth, -halfHeight + radius, rotationInRad ), yCoord + RotateYCoord( halfWidth, -halfHeight + radius, rotationInRad ),
                               radius,
			       xCoord + RotateXCoord( halfWidth - radius, -halfHeight, rotationInRad ), yCoord + RotateYCoord( halfWidth - radius, -halfHeight, rotationInRad ) );*/
	      }

	      if( PadShapeStyleShapeType[ PPointer ] == 3 ) {
	        string xPadCoord[];
	        string yPadCoord[];
	        int nrLines = 0;

		printf("CHANGE LAYER %s;\n", ConvertLayer( PadShapeStyleDefsLayer[ PPointer ] ) );

		int currentToken = PadShapeStyleDefsPolygon[ PPointer ];

		while( currentToken < TokensNumber ) {
		  if( Tokens[ currentToken ] == "(" ) {
		    currentToken++;

		    if( Tokens[ currentToken ] == "pt" ) {
		      xPadCoord[ nrLines ] = Tokens[ currentToken + 1 ];

		      if( IsASCIIValue( Tokens[ currentToken + 2 ] ) ) {
			xPadCoord[ nrLines ] = xPadCoord[ nrLines ] + Tokens[ currentToken + 2 ];

			if( Tokens[ currentToken + 3 ] != ")" ) {
			  yPadCoord[ nrLines ] = Tokens[ currentToken + 3 ];

			  if( Tokens[ currentToken + 4 ] != ")" ) {
			    yPadCoord[ nrLines ] = yPadCoord[ nrLines ] + Tokens[ currentToken + 4 ];
			  }
			}
			else {
			  WriteLog( "#warning: wront point description.\n" );
			}
		      }
		      else {
			yPadCoord[ nrLines ] = Tokens[ currentToken + 2 ];

			if( Tokens[ currentToken + 3 ] != ")" ) {
			  yPadCoord[ nrLines ] = yPadCoord[ nrLines ] + Tokens[ currentToken + 3 ];
			}
		      }

		      nrLines++;

		      currentToken = currentToken + 3;
		    }
		  }
		  else {
		    if( Tokens[ currentToken ] == ")" ) {
		      break;
		    }
		  }

		  currentToken++;
		} // while

		real xCoord = GetValue( Tokens[ padCoordPosition + 1 ] );
		real yCoord = GetValue( Tokens[ padCoordPosition + 2 ] );

		//printf("GRID 0.01 mil;\n" );

                real rotationInRad = strtod( rotation ) * PI / 180.0;

                printf("# PadShapeStyleShapeType == 3\n");

		printf("POLYGON 0\n");

		for( int i = 0; i < nrLines; i++ ) {
                  real xPolyCoord = strtod( ConvertUnits( GetNumberValue( xPadCoord[ i ] ), GetUnitValue( xPadCoord[ i ] ) ) );
                  real yPolyCoord = strtod( ConvertUnits( GetNumberValue( yPadCoord[ i ] ), GetUnitValue( yPadCoord[ i ] ) ) );

		  printf("  (%f %f)\n", xCoord + RotateXCoord( xPolyCoord, yPolyCoord, rotationInRad ), yCoord + RotateYCoord( xPolyCoord, yPolyCoord, rotationInRad ) );
		}

                real xPolyCoord = strtod( ConvertUnits( GetNumberValue( xPadCoord[ 0 ] ), GetUnitValue( xPadCoord[ 0 ] ) ) );
                real yPolyCoord = strtod( ConvertUnits( GetNumberValue( yPadCoord[ 0 ] ), GetUnitValue( yPadCoord[ 0 ] ) ) );

		printf("  (%f %f);\n", xCoord + RotateXCoord( xPolyCoord, yPolyCoord, rotationInRad ), yCoord + RotateYCoord( xPolyCoord, yPolyCoord, rotationInRad ) );
	      }

	      if( PadShapeStyleShapeType[ PPointer ] == 4 ) {
		printf("CHANGE LAYER %s;\n", ConvertLayer( PadShapeStyleDefsLayer[ PPointer ] ) );

		real xCoord = GetValue( Tokens[ padCoordPosition + 1 ] );
		real yCoord = GetValue( Tokens[ padCoordPosition + 2 ] );
		real halfWidth = GetValue( PadShapeStyleDefsWidth[ PPointer ] ) / 2.0;
		real halfHeight = GetValue( PadShapeStyleDefsHeight[ PPointer ] ) / 2.0;

                printf("# PadShapeStyleShapeType = 4\n");

                real rotationInRad = strtod( rotation ) * PI / 180.0;

		printf("POLYGON 0 (%f %f) (%f %f) (%f %f) (%f %f) (%f %f);\n",
                               xCoord + RotateXCoord( -halfWidth, -halfHeight, rotationInRad ), yCoord + RotateYCoord( -halfWidth, -halfHeight, rotationInRad ),
			       xCoord + RotateXCoord( halfWidth, -halfHeight, rotationInRad ), yCoord + RotateYCoord( halfWidth, -halfHeight, rotationInRad ),
                               xCoord + RotateXCoord( halfWidth, halfHeight, rotationInRad ), yCoord + RotateYCoord( halfWidth, halfHeight, rotationInRad ),
			       xCoord + RotateXCoord( -halfWidth, halfHeight, rotationInRad ), yCoord + RotateYCoord( -halfWidth, halfHeight, rotationInRad ),
                               xCoord + RotateXCoord( -halfWidth, -halfHeight, rotationInRad ), yCoord + RotateYCoord( -halfWidth, -halfHeight, rotationInRad ) );
              }
            }
          }
          else {
            string tmp;
            sprintf( tmp, "#WARNING: Can't find pt for pad %s\n",
                    Tokens[ startToken + 3 ] );
            WriteLog( tmp );
          }
        }
        else {
          string tmp;
          printf("#WARNING: Can't find padNum for pad %s\n",
                  Tokens[ startToken + 3 ] );
          WriteLog( tmp );
        }
      }
      else {
        printf("#skip this pad\n");
      }
    }
    else {
      string tmp;
      printf("#WARNING: Can't find padStyleDef for pad %s\n",
              Tokens[ startToken + 3 ] );
      WriteLog( tmp );
    }
  }
  else {
    string tmp;
    printf("#WARNING: Can't find padStyleRef for pad %s\n",
            Tokens[ startToken + 3 ] );
    WriteLog( tmp );
  }
}

void GenerateOneLine( int startToken, int ifNet, int ifBoard )
{
  string net = "";
  string width;
  string xLineCoord[];
  string yLineCoord[];
  int nrLines = 0;

  CurrentToken = FindToken( startToken + 1, "width" );


  if( CurrentToken > 0 ) {
    string TokenText = Tokens[ CurrentToken + 1 ];

    if( Tokens[ CurrentToken + 2 ] != ")" ) {
      if( IsASCIIValue( Tokens[ CurrentToken + 2 ] ) ) {
        TokenText = TokenText + Tokens[ CurrentToken + 2 ];
      }
      else {
        WriteLog( "#warning: wrong description.\n" );
      }
    }

    width = TokenText;
  }
  else {
    if( ifBoard ) {
      width = DEFAULT_WIRE_WIDTH_BOARD;
    }
    else {
      width = DEFAULT_WIRE_WIDTH_SCHEMATIC;
    }
  }

  if( 1 ) {
    CurrentToken = startToken + 1;

    while( CurrentToken < TokensNumber ) {
      if( Tokens[ CurrentToken ] == "(" ) {
        CurrentToken++;

        if( Tokens[ CurrentToken ] == "pt" ) {
          xLineCoord[ nrLines ] = Tokens[ CurrentToken + 1 ];

          if( IsASCIIValue( Tokens[ CurrentToken + 2 ] ) ) {
            xLineCoord[ nrLines ] = xLineCoord[ nrLines ] + Tokens[ CurrentToken + 2 ];

            if( Tokens[ CurrentToken + 3 ] != ")" ) {
              yLineCoord[ nrLines ] = Tokens[ CurrentToken + 3 ];

              if( Tokens[ CurrentToken + 4 ] != ")" ) {
                yLineCoord[ nrLines ] =  yLineCoord[ nrLines ] + Tokens[ CurrentToken + 4 ];
              }
            }
            else {
              WriteLog( "#warning: wront point description.\n" );
            }
          }
          else {
            yLineCoord[ nrLines ] = Tokens[ CurrentToken + 2 ];

            if( Tokens[ CurrentToken + 3 ] != ")" ) {
              yLineCoord[ nrLines ] = yLineCoord[ nrLines ] + Tokens[ CurrentToken + 3 ];
            }
          }

          nrLines++;

          SkipThisItem();
        }
        else {
          if( Tokens[ CurrentToken ] == "width" ) {
            SkipThisItem();
          }
          else {
            if( Tokens[ CurrentToken ] == "netNameRef" ) {
              net = ReplaceNotSupportedCharacters( RemoveDoubleQuotas( Tokens[ CurrentToken + 1 ] ) );
              SkipThisItem();
            }
            else {
              if( Tokens[ CurrentToken ] == "dimensionRef" ) {
                SkipThisItem();
              }
              else {
                if( Tokens[ CurrentToken ] == "endStyle" ) {
                  SkipThisItem();
                }
                else {
                  if( DebugMessage ) {
                    printf( "# GenerateOneLine ??????? %s\n",  Tokens[ CurrentToken ] );
                  }
                  SkipThisItem();
                }
              }
            }
          }
        }
      }
      else {
        if( Tokens[ CurrentToken ] == ")" ) {
          break;
        }
        else {
          dlgMessageBox( "Unexpected keyword in GenerateOneLine " + Tokens[ CurrentToken ], "OK");
          return;
        }
      }

      CurrentToken++;
    }

    if( ifNet ) {
      for( int i = 0; i < nrLines - 1; i++ ) {
        printf("NET '%s' (%s %s) (%s %s);\n", net, xLineCoord[ i ], yLineCoord[ i ],
                                                   xLineCoord[ i + 1 ], yLineCoord[ i + 1 ] );
      }

      for( int j = 0; j < nrLines; j++ ) {
        real xCoord = strtod( ConvertUnits( GetNumberValue( xLineCoord[ j ] ), GetUnitValue( xLineCoord[ j ] ) ) );
        real yCoord = strtod( ConvertUnits( GetNumberValue( yLineCoord[ j ] ), GetUnitValue( yLineCoord[ j ] ) ) );

        WiresPointX[ NrWiresPoint ] = xCoord;
        WiresPointY[ NrWiresPoint ] = yCoord;
        WiresNet[ NrWiresPoint ] = net;

        NrWiresPoint++;
      }

      return;
    }

    // Generate line or wire
    if( net == "" ) {
      for( int i = 0; i < nrLines - 1; i++ ) {
        string Val1 = ConvertUnits( GetNumberValue( xLineCoord[ i ] ),
                                    GetUnitValue( xLineCoord[ i ] ) );
        string Val2 = ConvertUnits( GetNumberValue( yLineCoord[ i ] ),
                                    GetUnitValue( yLineCoord[ i ] ) );

        string Val3 = ConvertUnits( GetNumberValue( xLineCoord[ i + 1 ] ),
                                    GetUnitValue( xLineCoord[ i + 1 ] ) );
        string Val4 = ConvertUnits( GetNumberValue( yLineCoord[ i + 1 ] ),
                                    GetUnitValue( yLineCoord[ i + 1 ] ) );

        printf("WIRE %s (%s %s) (%s %s);\n", width, Val1, Val2, Val3, Val4 );
      }
    }
    else {
      for( int i = 0; i < nrLines - 1; i++ ) {
        string Val1 = ConvertUnits( GetNumberValue( xLineCoord[ i ] ),
                                    GetUnitValue( xLineCoord[ i ] ) );
        string Val2 = ConvertUnits( GetNumberValue( yLineCoord[ i ] ),
                                    GetUnitValue( yLineCoord[ i ] ) );

        string Val3 = ConvertUnits( GetNumberValue( xLineCoord[ i + 1 ] ),
                                    GetUnitValue( xLineCoord[ i + 1 ] ) );
        string Val4 = ConvertUnits( GetNumberValue( yLineCoord[ i + 1 ] ),
                                    GetUnitValue( yLineCoord[ i + 1 ] ) );

        printf("WIRE '%s' %s (%s %s) (%s %s);\n", net, width, Val1, Val2, Val3, Val4 );
      }
    }
  }
  else {
    WriteLog("# warning: GenerateOneLine can't find width.\n");
  }
}

void GenerateOnePcbPoly( int startToken, int ifBoard, string width )
{
  string net = "";
  string xLineCoord[];
  string yLineCoord[];
  int nrLines = 0;

  CurrentToken = startToken + 1;

  while( CurrentToken < TokensNumber ) {
    if( Tokens[ CurrentToken ] == "(" ) {
      CurrentToken++;

      if( Tokens[ CurrentToken ] == "pt" ) {
        xLineCoord[ nrLines ] = Tokens[ CurrentToken + 1 ];

        if( IsASCIIValue( Tokens[ CurrentToken + 2 ] ) ) {
          xLineCoord[ nrLines ] = xLineCoord[ nrLines ] + Tokens[ CurrentToken + 2 ];

          if( Tokens[ CurrentToken + 3 ] != ")" ) {
            yLineCoord[ nrLines ] = Tokens[ CurrentToken + 3 ];

            if( Tokens[ CurrentToken + 4 ] != ")" ) {
              yLineCoord[ nrLines ] =  yLineCoord[ nrLines ] + Tokens[ CurrentToken + 4 ];
            }
          }
          else {
            WriteLog( "#warning: wront point description.\n" );
          }
        }
        else {
          yLineCoord[ nrLines ] = Tokens[ CurrentToken + 2 ];

          if( Tokens[ CurrentToken + 3 ] != ")" ) {
            yLineCoord[ nrLines ] = yLineCoord[ nrLines ] + Tokens[ CurrentToken + 3 ];
          }
        }

        nrLines++;

        SkipThisItem();
      }
      else {
        if( Tokens[ CurrentToken ] == "width" ) {
          string TokenText = Tokens[ CurrentToken + 1 ];

          if( Tokens[ CurrentToken + 2 ] != ")" ) {
            if( IsASCIIValue( Tokens[ CurrentToken + 2 ] ) ) {
              TokenText = TokenText + Tokens[ CurrentToken + 2 ];
            }
            else {
              WriteLog( "#warning: wrong description.\n" );
            }
          }

          width = TokenText;

          SkipThisItem();
        }
        else {
          if( Tokens[ CurrentToken ] == "netNameRef" ) {
            net = ReplaceNotSupportedCharacters( RemoveDoubleQuotas( Tokens[ CurrentToken + 1 ] ) );
            SkipThisItem();
          }
          else {
            if( Tokens[ CurrentToken ] == "fillets" ) {
              SkipThisItem();
            }
            else {
              if( DebugMessage ) {
                printf( "# GenerateOnePcbPoly ??????? %s\n",  Tokens[ CurrentToken ] );
              }
              SkipThisItem();
            }
          }
        }
      }
    }
    else {
      if( Tokens[ CurrentToken ] == ")" ) {
        break;
      }
      else {
        dlgMessageBox( "Unexpected keyword in GenerateOnePcbPoly " + Tokens[ CurrentToken ], "OK");
        return;
      }
    }

    CurrentToken++;
  }

  if( width == "" ) {
     width = "0";

    /*if( ifBoard ) {
      width = DEFAULT_WIRE_WIDTH_BOARD;
    }
    else {
      width = DEFAULT_WIRE_WIDTH_SCHEMATIC;
    }*/
  }

  // Generate line
  if( net == "" ) {
    printf("POLYGON");
  }
  else {
    printf("POLYGON '%s'", net );
  }

  if( width == "" ) {
  }
  else {
    printf(" %s", width );
  }

  printf("\n");

  for( int i = 0; i < nrLines; i++ ) {
    printf("  (%s %s)\n", xLineCoord[ i ], yLineCoord[ i ] );
  }

  printf("  (%s %s);\n", xLineCoord[ 0 ], yLineCoord[ 0 ] );
}

void GenerateOneText( int startToken )
{
  string text = "";
  string textStyleDef;
  string textRotation = "0";
  string xTextCoord;
  string yTextCoord;
  string justify = "";
  string xExtent = "";
  string yExtent = "";
  string mirrored = "";
  int    pointFound = 0;

  CurrentToken = FindToken( startToken + 1, "textStyleRef" );

  textStyleDef = Tokens[ CurrentToken + 1 ];

  if( CurrentToken > 0 ) {
    CurrentToken = startToken + 1;

    while( CurrentToken < TokensNumber ) {
      if( Tokens[ CurrentToken ] == "(" ) {
        CurrentToken++;

        if( Tokens[ CurrentToken ] == "pt" ) {
          pointFound = 1;

          xTextCoord = Tokens[ CurrentToken + 1 ];

          if( IsASCIIValue( Tokens[ CurrentToken + 2 ] ) ) {
            xTextCoord = xTextCoord + Tokens[ CurrentToken + 2 ];

            if( Tokens[ CurrentToken + 3 ] != ")" ) {
              yTextCoord = Tokens[ CurrentToken + 3 ];

              if( Tokens[ CurrentToken + 4 ] != ")" ) {
                yTextCoord = yTextCoord + Tokens[ CurrentToken + 4 ];
              }
            }
            else {
              WriteLog( "#warning: wront point description.\n" );
            }
          }
          else {
            yTextCoord = Tokens[ CurrentToken + 2 ];

            if( Tokens[ CurrentToken + 3 ] != ")" ) {
              yTextCoord = yTextCoord + Tokens[ CurrentToken + 3 ];
            }
          }

          SkipThisItem();
        }
        else {
          if( Tokens[ CurrentToken ] == "rotation" ) {
            textRotation = Tokens[ CurrentToken + 1 ];
            SkipThisItem();
          }
          else {
            if( Tokens[ CurrentToken ] == "textStyleRef" ) {
              SkipThisItem();
            }
            else {
              if( Tokens[ CurrentToken ] == "justify" ) {
                justify = Tokens[ CurrentToken + 1 ];
                SkipThisItem();
              }
              else {
                if( Tokens[ CurrentToken ] == "extent" ) {
                  //xExtent = Tokens[ CurrentToken + 1 ];
                  //yExtent = Tokens[ CurrentToken + 2 ];
                  SkipThisItem();
                }
                else {
                  if( Tokens[ CurrentToken ] == "isFlipped" ) {
                    if( Tokens[ CurrentToken + 1 ] == "True" ) {
                      mirrored = "M";
                    }
                    SkipThisItem();
                  }
                  else {
                    if( Tokens[ CurrentToken ] == "isVisible" ) {
                      SkipThisItem();
                    }
                    else {
                      if( DebugMessage ) {
                        printf( "# GenerateOneText ??????? %s\n",  Tokens[ CurrentToken ] );
                      }
                      SkipThisItem();
                    }
                  }
                }
              }
            }
          }
        }
      }
      else {
        if( Tokens[ CurrentToken ] == ")" ) {
          break;
        }
        else {
          if( UseExternalText ) {
            text = ExternalText;
          }
          else {
            sprintf( text, "'%s'", ReplaceNotSupportedCharactersText( RemoveDoubleQuotas( Tokens[ CurrentToken ] ) ) );

//printf("# IfPinText = %d text = %s\n", IfPinText, text );

            // It should be in all cases as we discussed
            //if( IfPinText ) {
              if( text[ 1 ] == '~' ) {
                text[ 1 ] = '!';
              }
            //}
          }
        }
      }

      CurrentToken++;
    }

    if( text == "''" ) {
      return;
    }

    if( !pointFound ) {
      return;
    }

    if( justify == "" ) { //LowerLeft
      printf("CHANGE ALIGN BOTTOM LEFT;\n");

      if( xExtent != "" ) {
	sprintf( xTextCoord, "%f", strtod( xTextCoord ) - strtod( xExtent ) / 2 );
      }

      if( yExtent != "" ) {
	sprintf( yTextCoord, "%f", strtod( yTextCoord ) - strtod( yExtent ) / 2 );
      }
    } else if( justify == "UpperLeft" ) {
      printf("CHANGE ALIGN TOP LEFT;\n");

      if( xExtent != "" ) {
	sprintf( xTextCoord, "%f", strtod( xTextCoord ) - strtod( xExtent ) / 2 );
      }

      if( yExtent != "" ) {
	sprintf( yTextCoord, "%f", strtod( yTextCoord ) + strtod( yExtent ) / 2 );
      }
    } else if( justify == "UpperCenter" ) {
      printf("CHANGE ALIGN TOP CENTER;\n");

      if( yExtent != "" ) {
	sprintf( yTextCoord, "%f", strtod( yTextCoord ) + strtod( yExtent ) / 2 );
      }
    } else if( justify == "UpperRight" ) {
      printf("CHANGE ALIGN TOP RIGHT;\n");

      if( xExtent != "" ) {
	sprintf( xTextCoord, "%f", strtod( xTextCoord ) + strtod( xExtent ) / 2 );
      }

      if( yExtent != "" ) {
	sprintf( yTextCoord, "%f", strtod( yTextCoord ) + strtod( yExtent ) / 2 );
      }
    } else if( justify == "Left" ) {
      printf("CHANGE ALIGN CENTER LEFT;\n");

      if( xExtent != "" ) {
	sprintf( xTextCoord, "%f", strtod( xTextCoord ) - strtod( xExtent ) / 2 );
      }
    } else if( justify == "Center" ) {
      printf("CHANGE ALIGN CENTER CENTER;\n");
    } else if( justify == "Right" ) {
      printf("CHANGE ALIGN CENTER RIGHT;\n");

      if( xExtent != "" ) {
	sprintf( xTextCoord, "%f", strtod( xTextCoord ) + strtod( xExtent ) / 2 );
      }
    } else if( justify == "LowerLeft" ) {
      printf("CHANGE ALIGN BOTTOM LEFT;\n");

      if( xExtent != "" ) {
	sprintf( xTextCoord, "%f", strtod( xTextCoord ) - strtod( xExtent ) / 2 );
      }

      if( yExtent != "" ) {
	sprintf( yTextCoord, "%f", strtod( yTextCoord ) - strtod( yExtent ) / 2 );
      }
    } else if( justify == "LowerCenter" ) {
      printf("CHANGE ALIGN BOTTOM CENTER;\n");

      if( yExtent != "" ) {
	sprintf( yTextCoord, "%f", strtod( yTextCoord ) - strtod( yExtent ) / 2 );
      }

    } else if( justify == "LowerRight" ) {
      printf("CHANGE ALIGN BOTTOM RIGHT;\n");

      if( xExtent != "" ) {
	sprintf( xTextCoord, "%f", strtod( xTextCoord ) + strtod( xExtent ) / 2 );
      }

      if( yExtent != "" ) {
	sprintf( yTextCoord, "%f", strtod( yTextCoord ) - strtod( yExtent ) / 2 );
      }
    }
    else {
      printf("# warning: unknown justify parameter value = %s\n", justify );
      printf("CHANGE ALIGN BOTTOM LEFT;\n");

      if( xExtent != "" ) {
	sprintf( xTextCoord, "%f", strtod( xTextCoord ) - strtod( xExtent ) / 2 );
      }

      if( yExtent != "" ) {
	sprintf( yTextCoord, "%f", strtod( yTextCoord ) - strtod( yExtent ) / 2 );
      }
    }

    // Generate text
    int textStyleDefPos = FindTextStyleDef( textStyleDef );

    if( textStyleDefPos >= 0 ) {
      real fontHeight = strtod( ConvertUnits( GetNumberValue( TextStyleDefFontHeight[ textStyleDefPos ] ), GetUnitValue(  TextStyleDefFontHeight[ textStyleDefPos ] ) ) );
      real fontWidth = strtod( ConvertUnits( GetNumberValue( TextStyleDefFontStrokeWidth[ textStyleDefPos ] ), GetUnitValue( TextStyleDefFontStrokeWidth[ textStyleDefPos ] ) ) );

      printf("CHANGE SIZE %s;\n", TextStyleDefFontHeight[ textStyleDefPos ] );

      if( fontHeight ) {
        int ratio = round( 100.0 * fontWidth / fontHeight );

        if( ratio > 31.0 ) {
          ratio = 31.0;
        }

        printf("CHANGE RATIO %d;\n", ratio );
      }

      printf("TEXT %s %sSR%s (%s %s);\n", text, mirrored, textRotation, xTextCoord, yTextCoord  );
    }
    else {
      WriteLog("# warning: GenerateOneText can't find textStyleDef.\n");
    }
  }
  else {
    WriteLog("# warning: GenerateOneText can't find textStyleRef.\n");
  }
}

void GenerateOneBus( int startToken )
{
  int    textToken;
  string dispName;
  string textX;
  string textY;
  string xLineCoord[];
  string yLineCoord[];
  int nrLines = 0;

  CurrentToken = startToken + 1;

  string name = RemoveDoubleQuotas( Tokens[ CurrentToken ] );

  CurrentToken++;

  while( CurrentToken < TokensNumber ) {
    if( Tokens[ CurrentToken ] == "(" ) {
      CurrentToken++;

      if( Tokens[ CurrentToken ] == "pt" ) {
        xLineCoord[ nrLines ] = Tokens[ CurrentToken + 1 ];

        if( IsASCIIValue( Tokens[ CurrentToken + 2 ] ) ) {
          xLineCoord[ nrLines ] = xLineCoord[ nrLines ] + Tokens[ CurrentToken + 2 ];

          if( Tokens[ CurrentToken + 3 ] != ")" ) {
            yLineCoord[ nrLines ] = Tokens[ CurrentToken + 3 ];

            if( Tokens[ CurrentToken + 4 ] != ")" ) {
              yLineCoord[ nrLines ] =  yLineCoord[ nrLines ] + Tokens[ CurrentToken + 4 ];
            }
          }
          else {
            WriteLog( "#warning: wront point description.\n" );
          }
        }
        else {
          yLineCoord[ nrLines ] = Tokens[ CurrentToken + 2 ];

          if( Tokens[ CurrentToken + 3 ] != ")" ) {
            yLineCoord[ nrLines ] = yLineCoord[ nrLines ] + Tokens[ CurrentToken + 3 ];
          }
        }

        nrLines++;

        SkipThisItem();
      }
      else {
        if( Tokens[ CurrentToken ] == "dispName" ) {
          dispName = Tokens[ CurrentToken + 1 ];
          SkipThisItem();
        }
        else {
          if( Tokens[ CurrentToken ] == "text" ) {
            textToken = CurrentToken;
            SkipThisItem();
          }
          else {
            if( DebugMessage ) {
              printf( "# GenerateOneBus ??????? %s\n",  Tokens[ CurrentToken ] );
            }
            SkipThisItem();
          }
        }
      }
    }
    else {
      if( Tokens[ CurrentToken ] == ")" ) {
        break;
      }
      else {
        dlgMessageBox( "Unexpected keyword in GenerateOneBus " + Tokens[ CurrentToken ], "OK");
        return;
      }
    }

    CurrentToken++;
  }

  int pos = strchr( name, '(' );

  if( pos >= 0 ) {
    int pos1 = strchr( name, ':' );

    if( pos1 >= 0 ) {
      if( pos1 > pos + 1 ) {
        int firstNumber = strtol( strsub( name, pos + 1, pos1 - pos - 1 ) );

        int pos2 = strchr( name, ')' );

        if( pos2 >= 0 ) {
          if( pos2 > pos1 + 1 ) {
            int secondNumber = strtol( strsub( name, pos1 + 1, pos2 - pos1 - 1 ) );

            string busName = ReplaceNotSupportedCharacters( strsub( name, 0, pos ) );

            for( int i = 0; i < nrLines - 1; i++ ) {
              printf("BUS '%s[%d..%d]' (%s %s) (%s %s);\n", busName, firstNumber, secondNumber,
                                                            xLineCoord[ i ], yLineCoord[ i ],
                                                            xLineCoord[ i + 1 ], yLineCoord[ i + 1 ] );
            }

            if( dispName == "True" ) {
              UseExternalText = 1;
              sprintf( ExternalText, "'%s[%d..%d]'", busName, firstNumber, secondNumber );
              GenerateOneText( textToken );
              UseExternalText = 0;
            }
          }
        }
        else {
          WriteLog( "#warning: GenerateOneBus cant find ')'\n");
        }
      }
      else {
        WriteLog( "#warning: GenerateOneBus wrong first number\n");
      }
    }
    else {
      WriteLog( "#warning: GenerateOneBus cant find ':'\n");
    }
  }
  else {
    string busName = ReplaceNotSupportedCharacters( name );

    for( int i = 0; i < nrLines - 1; i++ ) {
      printf("BUS '%s' (%s %s) (%s %s);\n", busName,
                                            xLineCoord[ i ], yLineCoord[ i ],
                                            xLineCoord[ i + 1 ], yLineCoord[ i + 1 ] );
    }

    if( dispName == "True" ) {
      UseExternalText = 1;
      sprintf( ExternalText, "'%s'", busName );
      GenerateOneText( textToken );
      UseExternalText = 0;
    }

    //printf( "# GenerateOneBus cant find '('\n");
  }
}

void ArcDraw( string width, real X, string xArcCoordUnit, real Y, string yArcCoordUnit,
              real Radius, string radiusUnit, real arcs, real arce )
{
   string as;
   real arcStart = 360 + (arcs);
   if (arcStart > 360) arcStart -= 360;
   real arcEnd = arcStart + (arce);
   if (arcEnd > 360) arcEnd -= 360;
   real xArcStart = Radius * cos(PI / 180 * arcStart);
   real yArcStart = Radius * sin(PI / 180 * arcStart);
   real xArcEnd   = Radius * cos(PI / 180 * arcEnd);
   real yArcEnd   = Radius * sin(PI / 180 * arcEnd);

   printf( "ARC CCW %s (%.8f%s %.8f%s) (%.8f%s %.8f%s) (%.8f%s %.8f%s);\n",
                  width,
                  X + xArcStart, xArcCoordUnit, Y + yArcStart, yArcCoordUnit,
                  X - xArcStart, xArcCoordUnit, Y - yArcStart, yArcCoordUnit,
                  X + xArcEnd, xArcCoordUnit, Y + yArcEnd, yArcCoordUnit );
}

void GenerateOneArc( int startToken )
{
  real   radius;
  string radiusUnit = "";
  real   startAngle;
  real   sweepAngle;
  string width;
  real   xArcCoord;
  string xArcCoordUnit = "";
  real   yArcCoord;
  string yArcCoordUnit = "";

  CurrentToken = startToken + 1;

  while( CurrentToken < TokensNumber ) {
    if( Tokens[ CurrentToken ] == "(" ) {
      CurrentToken++;

      if( Tokens[ CurrentToken ] == "pt" ) {
        string xArcCoordText = "";
        string yArcCoordText = "";

        xArcCoordText = Tokens[ CurrentToken + 1 ];

        if( IsASCIIValue( Tokens[ CurrentToken + 2 ] ) ) {
          xArcCoordText = xArcCoordText + Tokens[ CurrentToken + 2 ];

          if( Tokens[ CurrentToken + 3 ] != ")" ) {
            yArcCoordText = Tokens[ CurrentToken + 3 ];

            if( Tokens[ CurrentToken + 4 ] != ")" ) {
              yArcCoordText = yArcCoordText + Tokens[ CurrentToken + 4 ];
            }
          }
          else {
            WriteLog( "#warning: wront point description.\n" );
          }
        }
        else {
          yArcCoordText = Tokens[ CurrentToken + 2 ];

          if( Tokens[ CurrentToken + 3 ] != ")" ) {
            yArcCoordText = yArcCoordText + Tokens[ CurrentToken + 3 ];
          }
        }

        xArcCoord = strtod( ConvertUnits( GetNumberValue( xArcCoordText ), GetUnitValue( xArcCoordText ) ) );
        yArcCoord = strtod( ConvertUnits( GetNumberValue( yArcCoordText ), GetUnitValue( yArcCoordText ) ) );

        SkipThisItem();
      }
      else {
        if( Tokens[ CurrentToken ] == "radius" ) {
          string ArcRadiusText = Tokens[ CurrentToken + 1 ];

          if( Tokens[ CurrentToken + 2 ] != ")" ) {
            if( IsASCIIValue( Tokens[ CurrentToken + 2 ] ) ) {
              ArcRadiusText = ArcRadiusText + Tokens[ CurrentToken + 2 ];
            }
            else {
              WriteLog( "#warning: wront radius description.\n" );
            }
          }

          radius = strtod( ConvertUnits( GetNumberValue( ArcRadiusText ), GetUnitValue( ArcRadiusText ) ) );

          SkipThisItem();
        }
        else {
          if( Tokens[ CurrentToken ] == "startAngle" ) {
            startAngle = strtod( Tokens[ CurrentToken + 1 ] );
            SkipThisItem();
          }
          else {
            if( Tokens[ CurrentToken ] == "sweepAngle" ) {
              sweepAngle = strtod( Tokens[ CurrentToken + 1 ] );
              SkipThisItem();
            }
            else {
              if( Tokens[ CurrentToken ] == "width" ) {
                width = Tokens[ CurrentToken + 1 ];
                SkipThisItem();
              }
              else {
                if( DebugMessage ) {
                  printf( "# GenerateOneArc ??????? %s\n",  Tokens[ CurrentToken ] );
                }
                SkipThisItem();
              }
            }
          }
        }
      }
    }
    else {
      if( Tokens[ CurrentToken ] == ")" ) {
        break;
      }
    }

    CurrentToken++;
  }

  //if( ( sweepAngle - startAngle >= 360 ) || ( ( ( sweepAngle == 0 ) && ( startAngle == 0 ) ) ) ) {
  if( ( sweepAngle >= 360 ) || ( ( ( sweepAngle == 0 ) && ( startAngle == 0 ) ) ) ) {
    printf("CIRCLE %s (%.8f%s %.8f%s) (%.8f%s %.8f%s);\n",
            width, xArcCoord, xArcCoordUnit, yArcCoord, yArcCoordUnit,
            xArcCoord + radius, xArcCoordUnit, yArcCoord, yArcCoordUnit );
  }
  else {
    ArcDraw( width, xArcCoord, xArcCoordUnit, yArcCoord, yArcCoordUnit, radius, radiusUnit, startAngle, sweepAngle );
  }
}

void GenerateOneTripleArc( int startToken )
{
  string width;
  real   xPointCoord[];
  real   yPointCoord[];
  int    nrPoints = 0;

  CurrentToken = startToken + 1;

  while( CurrentToken < TokensNumber ) {
    if( Tokens[ CurrentToken ] == "(" ) {
      CurrentToken++;

      if( Tokens[ CurrentToken ] == "pt" ) {
        string xArcCoordText = "";
        string yArcCoordText = "";

        xArcCoordText = Tokens[ CurrentToken + 1 ];

        if( IsASCIIValue( Tokens[ CurrentToken + 2 ] ) ) {
          xArcCoordText = xArcCoordText + Tokens[ CurrentToken + 2 ];

          if( Tokens[ CurrentToken + 3 ] != ")" ) {
            yArcCoordText = Tokens[ CurrentToken + 3 ];

            if( Tokens[ CurrentToken + 4 ] != ")" ) {
              yArcCoordText = yArcCoordText + Tokens[ CurrentToken + 4 ];
            }
          }
          else {
            WriteLog( "#warning: wront point description.\n" );
          }
        }
        else {
          yArcCoordText = Tokens[ CurrentToken + 2 ];

          if( Tokens[ CurrentToken + 3 ] != ")" ) {
            yArcCoordText = yArcCoordText + Tokens[ CurrentToken + 3 ];
          }
        }

        xPointCoord[ nrPoints ] = strtod( ConvertUnits( GetNumberValue( xArcCoordText ), GetUnitValue( xArcCoordText ) ) );
        yPointCoord[ nrPoints ] = strtod( ConvertUnits( GetNumberValue( yArcCoordText ), GetUnitValue( yArcCoordText ) ) );

        //printf( "# coord = %f %f\n", xPointCoord[ nrPoints ], yPointCoord[ nrPoints ] );

        nrPoints++;

        SkipThisItem();
      }
      else {
        if( Tokens[ CurrentToken ] == "width" ) {
          width = Tokens[ CurrentToken + 1 ];
          SkipThisItem();
        }
        else {
          if( DebugMessage ) {
            printf( "# GenerateOneTripleArc ??????? %s\n",  Tokens[ CurrentToken ] );
          }
          SkipThisItem();
        }
      }
    }
    else {
      if( Tokens[ CurrentToken ] == ")" ) {
        break;
      }
    }

    CurrentToken++;
  }

  if( nrPoints == 3 ) {
    if( ( xPointCoord[ 1 ] == xPointCoord[ 2 ] ) && ( yPointCoord[ 1 ] == yPointCoord[ 2 ] ) ) {
      printf( "CIRCLE %s (%.8f %.8f) (%.8f %.8f); # triplePointArc\n", width,
              xPointCoord[ 0 ], yPointCoord[ 0 ],
              xPointCoord[ 1 ], yPointCoord[ 1 ] );
    }
    else {
      real pX = 2 * xPointCoord[ 0 ] - xPointCoord[ 1 ];
      real pY = 2 * yPointCoord[ 0 ] - yPointCoord[ 1 ];

      printf( "ARC CCW %s (%.8f %.8f) (%.8f %.8f) (%.8f %.8f); # triplePointArc\n", width,
             xPointCoord[ 1 ],
             yPointCoord[ 1 ],
             pX,
             pY,
             xPointCoord[ 2 ],
             yPointCoord[ 2 ] );
    }
  }
  else {
    string tmp;
    sprintf( tmp, "warning: GenerateOneTripleArc wrong number of points %d\n", nrPoints );
    WriteLog( tmp );
  }
}

void GenerateIslandCutouts( int startToken )
{
  CurrentToken = startToken + 1;

  while( CurrentToken < TokensNumber ) {
    if( Tokens[ CurrentToken ] == "(" ) {
      CurrentToken++;

      if( Tokens[ CurrentToken ] == "islandOutline" ) {
        SkipThisItem();
      }
      else {
        if( Tokens[ CurrentToken ] == "cutout" ) {
          printf("CHANGE Pour cutout;\n");
          int SavePosition = CurrentToken;
          CurrentToken++;
          CurrentToken++;
          printf( "CHANGE THERMALS OFF;\n");
          GenerateOnePcbPoly( CurrentToken, 1, "" );
          CurrentToken = SavePosition;
          printf("CHANGE Pour solid;\n");
          SkipThisItem();
        }
        else {
          printf( "# GenerateIslandCutouts ??????? %s\n",  Tokens[ CurrentToken ] );
          SkipThisItem();
        }
      }
    }
    else {
      if( Tokens[ CurrentToken ] == ")" ) {
        break;
      }
    }

    CurrentToken++;
  }
}

void GenerateOneCopperPour95( int startToken )
{
  int thermal = 0;
  int pourSolid = 1;
  string width = DEFAULT_WIRE_WIDTH_BOARD;
  string pourSpacing = "";

  CurrentToken = FindToken( startToken + 1, "pourSpacing" );

  if( CurrentToken > 0 ) {
    printf( "CHANGE SPACING %s;\n", Tokens[ CurrentToken + 1 ] );
  }

  CurrentToken = startToken + 1;

  while( CurrentToken < TokensNumber ) {
    if( Tokens[ CurrentToken ] == "(" ) {
      CurrentToken++;

      if( Tokens[ CurrentToken ] == "pourType" ) {
        if( Tokens[ CurrentToken + 1 ] != "SolidPour" ) {
          pourSolid = 0;
        }
        SkipThisItem();
      }
      else {
        if( Tokens[ CurrentToken ] == "netNameRef" ) {
          SkipThisItem();
        }
        else {
          if( Tokens[ CurrentToken ] == "pourSpacing" ) {
            string TokenText = Tokens[ CurrentToken + 1 ];

            if( Tokens[ CurrentToken + 2 ] != ")" ) {
              if( IsASCIIValue( Tokens[ CurrentToken + 2 ] ) ) {
                TokenText = TokenText + Tokens[ CurrentToken + 2 ];
              }
              else {
                WriteLog( "#warning: wrong description.\n" );
              }
            }

            pourSpacing = TokenText;

            SkipThisItem();
          }
          else {
            if( Tokens[ CurrentToken ] == "pourBackoff" ) {
              SkipThisItem();
            }
            else {
              if( Tokens[ CurrentToken ] == "pourSmoothness" ) {
                SkipThisItem();
              }
              else {
                if( Tokens[ CurrentToken ] == "islandRemoval" ) {
                  SkipThisItem();
                }
                else {
                  if( Tokens[ CurrentToken ] == "pcbPoly" ) {
                    int SavePosition = CurrentToken;

                    if( thermal ) {
                      printf( "CHANGE THERMALS ON;\n");
                    }
                    else {
                      printf( "CHANGE THERMALS OFF;\n");
                    }

                    if( pourSolid ) {
                      printf( "CHANGE POUR SOLID;\n");
                    }
                    else {
                      printf( "CHANGE POUR HATCH;\n");
                    }

                    if( pourSpacing != "" ) {
                      printf( "CHANGE SPACING %s;\n", pourSpacing );
                    }
                    else {
                      printf( "CHANGE SPACING 50mil;\n", pourSpacing );
                    }

                    printf("# CopperPour95\n");
                    GenerateOnePcbPoly( SavePosition, 1, width );

                    if( thermal ) {
                      printf( "CHANGE THERMALS OFF;\n");
                    }

                    CurrentToken = SavePosition;
                    SkipThisItem();
                  }
                  else {
                    if( Tokens[ CurrentToken ] == "width" ) {
                      string TokenText = Tokens[ CurrentToken + 1 ];

                      if( Tokens[ CurrentToken + 2 ] != ")" ) {
                        if( IsASCIIValue( Tokens[ CurrentToken + 2 ] ) ) {
                          TokenText = TokenText + Tokens[ CurrentToken + 2 ];
                        }
                        else {
                          WriteLog( "#warning: wrong description.\n" );
                        }
                      }

                      width = TokenText;

                      SkipThisItem();
                    }
                    else {
                      if( Tokens[ CurrentToken ] == "useDesignRules" ) {
                        SkipThisItem();
                      }
                      else {
                        if( Tokens[ CurrentToken ] == "thermalType" ) {
                          if( Tokens[ CurrentToken + 1 ] != "NoTherm" ) {
                            thermal = 1;
                          }
                          SkipThisItem();
                        }
                        else {
                          if( Tokens[ CurrentToken ] == "thermalWidth" ) {
                            SkipThisItem();
                          }
                          else {
                            if( Tokens[ CurrentToken ] == "thermalSpokes" ) {
                              SkipThisItem();
                            }
                            else {
                              if( Tokens[ CurrentToken ] == "viaThermalType" ) {
                                SkipThisItem();
                              }
                              else {
                                if( Tokens[ CurrentToken ] == "viaThermalWidth" ) {
                                  SkipThisItem();
                                }
                                else {
                                  if( Tokens[ CurrentToken ] == "viaThermalSpokes" ) {
                                    SkipThisItem();
                                  }
                                  else {
                                    if( Tokens[ CurrentToken ] == "island" ) {
                                      int SavePosition = CurrentToken;
                                      // Comment this line because Eagle doesn't use GND cutouts
                                      //GenerateIslandCutouts( CurrentToken );
                                      CurrentToken = SavePosition;
                                      SkipThisItem();
                                    }
                                    else {
                                      if( DebugMessage ) {
                                        printf( "# GenerateOneCopperPour95 ??????? %s\n",  Tokens[ CurrentToken ] );
                                      }
                                      SkipThisItem();
                                    }
                                  }
                                }
                              }
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
    else {
      if( Tokens[ CurrentToken ] == ")" ) {
        break;
      }
    }

    CurrentToken++;
  }
}

void GenerateOneDimension( int startToken )
{
  CurrentToken = FindToken( startToken + 1, "dimPoints" );

  if( CurrentToken > 0 ) {
    string xPointCoord[];
    string yPointCoord[];
    string xPointUnit[];
    string yPointUnit[];
    int    nrPoints = 0;

    CurrentToken = CurrentToken + 1;

    while( CurrentToken < TokensNumber ) {
      if( Tokens[ CurrentToken ] == "(" ) {
        CurrentToken++;

        if( Tokens[ CurrentToken ] == "pt" ) {
          string xCoord = "";
          string yCoord = "";

          xCoord = Tokens[ CurrentToken + 1 ];

          if( IsASCIIValue( Tokens[ CurrentToken + 2 ] ) ) {
            xCoord = xCoord + Tokens[ CurrentToken + 2 ];

            if( Tokens[ CurrentToken + 3 ] != ")" ) {
              yCoord = Tokens[ CurrentToken + 3 ];

              if( Tokens[ CurrentToken + 4 ] != ")" ) {
                yCoord = yCoord + Tokens[ CurrentToken + 4 ];
              }
            }
            else {
              WriteLog( "#warning: wront point description.\n" );
            }
          }
          else {
            yCoord = Tokens[ CurrentToken + 2 ];

            if( Tokens[ CurrentToken + 3 ] != ")" ) {
               yCoord = yCoord + Tokens[ CurrentToken + 3 ];
            }
          }

          xPointCoord[ nrPoints ] = GetNumberValue( xCoord );
          yPointCoord[ nrPoints ] = GetNumberValue( yCoord );
          xPointUnit[ nrPoints ]  = GetUnitValue( xCoord );
          yPointUnit[ nrPoints ]  = GetUnitValue( yCoord );

          nrPoints++;

          SkipThisItem();
        }
        else {
          if( DebugMessage ) {
            printf( "# GenerateOneDimension ??????? %s\n",  Tokens[ CurrentToken ] );
          }
          SkipThisItem();
        }
      }
      else {
        if( Tokens[ CurrentToken ] == ")" ) {
          break;
        }
      }

      CurrentToken++;
    }

    CurrentToken = FindToken( startToken + 1, "dimOrient" );

    string dimensionDirection = "PARALLEL";

    if( Tokens[ CurrentToken + 1 ] == "dim_vertical" ) {
      xPointCoord[ 1 ] = xPointCoord[ 0 ];
      xPointUnit[ 1 ] = xPointUnit[ 0 ];
      dimensionDirection = "Horizontal";
    }

    if( Tokens[ CurrentToken + 1 ] == "dim_horizontal" ) {
      yPointCoord[ 1 ] = yPointCoord[ 0 ];
      yPointUnit[ 1 ] = yPointUnit[ 0 ];
      dimensionDirection = "Vertical";
    }

    if( nrPoints == 3 ) {
      printf("GRID mm 0.0001;\n" );
      printf("CHANGE LAYER 47;\n");
      printf( "DIMENSION %s (C%s%s %s%s) (C%s%s %s%s) (C%s%s %s%s);\n",
             dimensionDirection,
             xPointCoord[ 0 ],
             xPointUnit[ 0 ],
             yPointCoord[ 0 ],
             yPointUnit[ 0 ],
             xPointCoord[ 1 ],
             xPointUnit[ 1 ],
             yPointCoord[ 1 ],
             yPointUnit[ 1 ],
             xPointCoord[ 2 ],
             xPointUnit[ 2 ],
             yPointCoord[ 2 ],
             yPointUnit[ 2 ] );
    }
    printf("GRID %s;\n", FileUnits );
  }
}

/*void GenerateOneAttribute( int startToken, string layer )
{
  CurrentToken = startToken + 1;

  string type = RemoveDoubleQuotas( Tokens[ CurrentToken ] );

  if( type == "Type" ) {
    while( CurrentToken < TokensNumber ) {
      if( Tokens[ CurrentToken ] == "(" ) {
        CurrentToken++;

        if( Tokens[ CurrentToken ] == "pt" ) {
          printf("CHANGE ALIGN CENTER;\n");
          printf("CHANGE LAYER 27;\n");

          string xCoord = Tokens[ CurrentToken + 1 ];
          string yCoord = "";

          if( IsASCIIValue( Tokens[ CurrentToken + 2 ] ) ) {
            xCoord = xCoord + Tokens[ CurrentToken + 2 ];

            if( Tokens[ CurrentToken + 3 ] != ")" ) {
              yCoord = Tokens[ CurrentToken + 3 ];

              if( Tokens[ CurrentToken + 4 ] != ")" ) {
                yCoord = yCoord + Tokens[ CurrentToken + 4 ];
              }
            }
            else {
              WriteLog( "#warning: wront point description.\n" );
            }
          }
          else {
            yCoord = Tokens[ CurrentToken + 2 ];

            if( Tokens[ CurrentToken + 3 ] != ")" ) {
              yCoord = yCoord + Tokens[ CurrentToken + 3 ];
            }
          }

          printf("TEXT '>VALUE' (%s %s);\n",
                  ConvertUnits( GetNumberValue( xCoord ), GetUnitValue( xCoord ) ),
                  ConvertUnits( GetNumberValue( yCoord ), GetUnitValue( yCoord ) ) );

          printf("CHANGE LAYER 25;\n");
          printf("TEXT '>NAME' (0.0 0.0);\n");

          if( layer != "" ) {
            printf( "CHANGE LAYER %s;\n", layer );
          }
        }
        else {
          SkipThisItem();
        }
      }
      else {
        if( Tokens[ CurrentToken ] == ")" ) {
          break;
       }
      }

      CurrentToken++;
    }
  }
}*/

/*void GenerateNameAndValue( int startToken, string layer )
{
  CurrentToken = startToken + 1;

  int textToken = startToken + 1;

  string type = RemoveDoubleQuotas( Tokens[ CurrentToken ] );

  string xCoord = "0.0";
  string yCoord = "0.0";
  string isVisible = "True";
  string textStyleRef = "";
  int ifPoint = 0;

  while( CurrentToken < TokensNumber ) {
    if( Tokens[ CurrentToken ] == "(" ) {
      CurrentToken++;

      if( Tokens[ CurrentToken ] == "pt" ) {
        ifPoint = 1;

	xCoord = Tokens[ CurrentToken + 1 ];
	yCoord = "";

	if( IsASCIIValue( Tokens[ CurrentToken + 2 ] ) ) {
	  xCoord = xCoord + Tokens[ CurrentToken + 2 ];

	  if( Tokens[ CurrentToken + 3 ] != ")" ) {
	    yCoord = Tokens[ CurrentToken + 3 ];

	    if( Tokens[ CurrentToken + 4 ] != ")" ) {
	      yCoord = yCoord + Tokens[ CurrentToken + 4 ];
	    }
	  }
	  else {
	    WriteLog( "#warning: wront point description.\n" );
	  }
	}
	else {
	  yCoord = Tokens[ CurrentToken + 2 ];

	  if( Tokens[ CurrentToken + 3 ] != ")" ) {
	    yCoord = yCoord + Tokens[ CurrentToken + 3 ];
	  }
	}

	SkipThisItem();
      }
      else {
	if( Tokens[ CurrentToken ] == "isVisible" ) {
	  if( Tokens[ CurrentToken + 1 ] == "False" ) {
	    isVisible = "False";
	  }

	  SkipThisItem();
	}
	else {
	  if( Tokens[ CurrentToken ] == "textStyleRef" ) {
	    textStyleRef = RemoveDoubleQuotas( Tokens[ CurrentToken + 1 ] );

	    SkipThisItem();
	  }
	  else {
	    SkipThisItem();
	  }
	}
      }
    }
    else {
      if( Tokens[ CurrentToken ] == ")" ) {
	break;
     }
   }

    CurrentToken++;
  }

  if( type == "Value" ) {
    if( isVisible == "True" ) {
      printf("CHANGE ALIGN CENTER;\n");
      printf("CHANGE LAYER 27;\n");

      if( ifPoint ) {
        UseExternalText = 1;
        ExternalText = "'>VALUE'";
        GenerateOneText( textToken );
        UseExternalText = 0;
      }
      else {
        printf("TEXT '>VALUE' (0.0 0.0);\n");
      }

      if( layer != "" ) {
        printf( "CHANGE LAYER %s;\n", layer );
      }
    }
  }

  if( type == "RefDes" ) {
    if( isVisible == "True" ) {
      printf("CHANGE ALIGN CENTER;\n");
      printf("CHANGE LAYER 25;\n");

      if( ifPoint ) {
        UseExternalText = 1;
        ExternalText = "'>NAME'";
        GenerateOneText( textToken );
        UseExternalText = 0;
      }
      else {
        printf("TEXT '>NAME' (0.0 0.0);\n");
      }

      if( layer != "" ) {
        printf( "CHANGE LAYER %s;\n", layer );
      }
    }
  }
}*/

void GenerateNameAndValue( int startToken, string layer, int patternIndex )
{
  CurrentToken = startToken + 1;

  int textToken = startToken + 1;

  string type = ReplaceNotSupportedCharacters( RemoveDoubleQuotas( Tokens[ CurrentToken ] ) );

  string xCoord = "0.0";
  string yCoord = "0.0";
  string isVisible = "False";
  string textStyleRef = "";
  int ifPoint = 0;

  while( CurrentToken < TokensNumber ) {
    if( Tokens[ CurrentToken ] == "(" ) {
      CurrentToken++;

      if( Tokens[ CurrentToken ] == "pt" ) {
        ifPoint = 1;

	xCoord = Tokens[ CurrentToken + 1 ];
	yCoord = "";

	if( IsASCIIValue( Tokens[ CurrentToken + 2 ] ) ) {
	  xCoord = xCoord + Tokens[ CurrentToken + 2 ];

	  if( Tokens[ CurrentToken + 3 ] != ")" ) {
	    yCoord = Tokens[ CurrentToken + 3 ];

	    if( Tokens[ CurrentToken + 4 ] != ")" ) {
	      yCoord = yCoord + Tokens[ CurrentToken + 4 ];
	    }
	  }
	  else {
	    WriteLog( "#warning: wront point description.\n" );
	  }
	}
	else {
	  yCoord = Tokens[ CurrentToken + 2 ];

	  if( Tokens[ CurrentToken + 3 ] != ")" ) {
	    yCoord = yCoord + Tokens[ CurrentToken + 3 ];
	  }
	}

	SkipThisItem();
      }
      else {
	if( Tokens[ CurrentToken ] == "isVisible" ) {
	  if( Tokens[ CurrentToken + 1 ] == "True" ) {
	    isVisible = "True";
	  }

	  SkipThisItem();
	}
	else {
	  if( Tokens[ CurrentToken ] == "textStyleRef" ) {
	    textStyleRef = RemoveDoubleQuotas( Tokens[ CurrentToken + 1 ] );

	    SkipThisItem();
	  }
	  else {
	    SkipThisItem();
	  }
	}
      }
    }
    else {
      if( Tokens[ CurrentToken ] == ")" ) {
	break;
     }
   }

    CurrentToken++;
  }

  if( type == "Value" ) {
    printf("CHANGE ALIGN CENTER;\n");
    printf("CHANGE LAYER 27;\n");

    if( ifPoint ) {
      UseExternalText = 1;
      ExternalText = "'>VALUE'";
      GenerateOneText( textToken );
      UseExternalText = 0;
    }
    else {
      printf("TEXT '>VALUE' (0.0 0.0);\n");
    }

    if( layer != "" ) {
      printf( "CHANGE LAYER %s;\n", layer );
    }

    if( isVisible != "True" ) {
      IfValueDefinedInPattern[ patternIndex ] = 1;
    }
  }

  if( type == "RefDes" ) {
    printf("CHANGE ALIGN CENTER;\n");
    printf("CHANGE LAYER 25;\n");

    if( ifPoint ) {
      UseExternalText = 1;
      ExternalText = "'>NAME'";
      GenerateOneText( textToken );
      UseExternalText = 0;
    }
    else {
      printf("TEXT '>NAME' (0.0 0.0);\n");
    }

    if( layer != "" ) {
      printf( "CHANGE LAYER %s;\n", layer );
    }

    if( isVisible != "True" ) {
      IfNameDefinedInPattern[ patternIndex ] = 1;
    }
  }

  AttributesName[ NrAttributes ] = type;
  AttributesIndex[ NrAttributes ] = startToken;
  NrAttributes++;

  PatternNrAttributes[ patternIndex ]++;
}

void GenerateNameAndValueSchematics( int startToken, int symbolIndex )
{
  CurrentToken = startToken + 1;

  int textToken = startToken + 1;

  string type =  ReplaceNotSupportedCharacters( RemoveDoubleQuotas( Tokens[ CurrentToken ] ) );

  string xCoord = "0.0";
  string yCoord = "0.0";
  string isVisible = "False";
  string textStyleRef = "";
  int ifPoint = 0;

  while( CurrentToken < TokensNumber ) {
    if( Tokens[ CurrentToken ] == "(" ) {
      CurrentToken++;

      if( Tokens[ CurrentToken ] == "pt" ) {
        ifPoint = 1;

	xCoord = Tokens[ CurrentToken + 1 ];
	yCoord = "";

	if( IsASCIIValue( Tokens[ CurrentToken + 2 ] ) ) {
	  xCoord = xCoord + Tokens[ CurrentToken + 2 ];

	  if( Tokens[ CurrentToken + 3 ] != ")" ) {
	    yCoord = Tokens[ CurrentToken + 3 ];

	    if( Tokens[ CurrentToken + 4 ] != ")" ) {
	      yCoord = yCoord + Tokens[ CurrentToken + 4 ];
	    }
	  }
	  else {
	    WriteLog( "#warning: wront point description.\n" );
	  }
	}
	else {
	  yCoord = Tokens[ CurrentToken + 2 ];

	  if( Tokens[ CurrentToken + 3 ] != ")" ) {
	    yCoord = yCoord + Tokens[ CurrentToken + 3 ];
	  }
	}

	SkipThisItem();
      }
      else {
	if( Tokens[ CurrentToken ] == "isVisible" ) {
	  if( Tokens[ CurrentToken + 1 ] == "True" ) {
	    isVisible = "True";
	  }

	  SkipThisItem();
	}
	else {
	  if( Tokens[ CurrentToken ] == "textStyleRef" ) {
	    textStyleRef = RemoveDoubleQuotas( Tokens[ CurrentToken + 1 ] );

	    SkipThisItem();
	  }
	  else {
	    SkipThisItem();
	  }
	}
      }
    }
    else {
      if( Tokens[ CurrentToken ] == ")" ) {
	break;
     }
   }

    CurrentToken++;
  }

  if( type == "Value" ) {
    printf("CHANGE ALIGN CENTER;\n");
    printf("CHANGE LAYER 96;\n");

    if( ifPoint ) {
      UseExternalText = 1;
      ExternalText = "'>VALUE'";
      GenerateOneText( textToken );
      UseExternalText = 0;
    }
    else {
      printf("TEXT '>VALUE' (0.0 0.0);\n");
    }

    if( isVisible != "True" ) {
      IfValueDefinedInSymbol[ symbolIndex ] = 1;
    }
  }

  if( type == "RefDes" ) {
    printf("CHANGE ALIGN CENTER;\n");
    printf("CHANGE LAYER 95;\n");

    if( ifPoint ) {
      UseExternalText = 1;
      ExternalText = "'>NAME'";
      GenerateOneText( textToken );
      UseExternalText = 0;
    }
    else {
      printf("TEXT '>NAME' (0.0 0.0);\n");
    }

    if( isVisible != "True" ) {
      IfNameDefinedInSymbol[ symbolIndex ] = 1;
    }
  }

  AttributesName[ NrAttributes ] = type;
  AttributesIndex[ NrAttributes ] = startToken;
  NrAttributes++;

  SymbolNrAttributes[ symbolIndex ]++;
}

void GenerateLayerContents( int startToken, int patternIndex )
{
  printf("# LayerContents\n");

  CurrentToken = FindToken( startToken + 1, "layerNumRef" );

  if( CurrentToken > 0 ) {
    string layer = ConvertLayer( Tokens[ CurrentToken + 1 ] );

    printf( "# layerNumRef = %s\n", Tokens[ CurrentToken + 1 ] );
    printf( "CHANGE LAYER %s;\n", layer );

    CurrentToken = startToken + 1;

    while( CurrentToken < TokensNumber ) {
      if( Tokens[ CurrentToken ] == "(" ) {
        CurrentToken++;

        if( Tokens[ CurrentToken ] == "line" ) {
          int SavePosition = CurrentToken;
          GenerateOneLine( SavePosition, 0, 1 );
          CurrentToken = SavePosition;
          SkipThisItem();
        }
        else {
          if( Tokens[ CurrentToken ] == "arc" ) {
            int SavePosition = CurrentToken;
            GenerateOneArc( SavePosition );
            CurrentToken = SavePosition;
            SkipThisItem();
          }
          else {
            if( Tokens[ CurrentToken ] == "text" ) {
              int SavePosition = CurrentToken;
              GenerateOneText( SavePosition );
              CurrentToken = SavePosition;
              SkipThisItem();
            }
            else {
              if( Tokens[ CurrentToken ] == "attr" ) {
                int SavePosition = CurrentToken;

                if( patternIndex >= 0 ) {
                  GenerateNameAndValue( SavePosition, layer, patternIndex );
                }

                CurrentToken = SavePosition;
                SkipThisItem();
              }
              else {
                if( Tokens[ CurrentToken ] == "triplePointArc" ) {
                  int SavePosition = CurrentToken;
                  GenerateOneTripleArc( SavePosition );
                  CurrentToken = SavePosition;
                  SkipThisItem();
                }
                else {
                  if( Tokens[ CurrentToken ] == "testpoint" ) {
                    SkipThisItem();
                  }
                  else {
                    if( Tokens[ CurrentToken ] == "layerNumRef" ) {
                      SkipThisItem();
                    }
                    else {
                      if( Tokens[ CurrentToken ] == "pcbPoly" ) {
                        int SavePosition = CurrentToken;
                        printf( "CHANGE THERMALS OFF;\n");
                        GenerateOnePcbPoly( SavePosition, 1, DEFAULT_WIRE_WIDTH_BOARD );
                        CurrentToken = SavePosition;
                        SkipThisItem();
                      }
                      else {
                        if( Tokens[ CurrentToken ] == "polyCutOut" ) {
                          printf("CHANGE Pour cutout;\n");
                          int SavePosition = CurrentToken;
                          CurrentToken++;
                          CurrentToken++;
                          printf( "CHANGE THERMALS OFF;\n");
                          GenerateOnePcbPoly( CurrentToken, 1, DEFAULT_WIRE_WIDTH_BOARD );
                          CurrentToken = SavePosition;
                          printf("CHANGE Pour solid;\n");
                          SkipThisItem();
                        }
                        else {
                          if( Tokens[ CurrentToken ] == "copperPour95" ) {
                            int SavePosition = CurrentToken;
                            GenerateOneCopperPour95( SavePosition );
                            CurrentToken = SavePosition;
                            SkipThisItem();
                          }
                          else {
                            if( Tokens[ CurrentToken ] == "field" ) {
                              SkipThisItem();
                            }
                            else {
                              if( Tokens[ CurrentToken ] == "boardOutlineObj" ) {
                                SkipThisItem();
                              }
                              else {
                                if( Tokens[ CurrentToken ] == "dimension" ) {
                                  int SavePosition = CurrentToken;
                                  GenerateOneDimension( SavePosition );
                                  CurrentToken = SavePosition;
                                  SkipThisItem();
                                }
                                else {
                                  if( Tokens[ CurrentToken ] == "table" ) {
                                    SkipThisItem();
                                  }
                                  else {
                                    if( DebugMessage ) {
                                      printf( "# GenerateLayerContents ??????? %s\n",  Tokens[ CurrentToken ] );
                                    }
                                    SkipThisItem();
                                  }
                                }
                              }
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
      else {
        if( Tokens[ CurrentToken ] == ")" ) {
          break;
        }
        else {
          dlgMessageBox( TR("Unexpected keyword in LayerContents: ") + Tokens[ CurrentToken ], "OK");
          return;
        }
      }

      CurrentToken++;
    }
  }
  else {
    WriteLog("# warning: GenerateLayerContents can't find layerNumRef.\n");
  }
}

// Generate devices from patternDef and patternDefExtended

void GeneratePackages( void )
{
  printf("# Packages:\n");

  for( int i = 0; i < PatternDefExtendedNumber; i++ ) {
    int startToken = PatternDefExtendedArray[ i ];

    string DeviceName = ReplaceNotSupportedCharacters( RemoveDoubleQuotas(
                                                       Tokens[ startToken ] )
                                                       );

    string OriginalDeviceName = GetOriginalDeviceName( startToken + 1 );

    IfNameDefinedInPattern[ i ] = 0;
    IfValueDefinedInPattern[ i ] = 0;
    PatternAttributesIndex[ i ] = NrAttributes;
    PatternNrAttributes[ i ] = 0;
    PatternName[ i ] = DeviceName;
    PatternOriginalName[ i ] = OriginalDeviceName;

    int patternGraphicsNameRefToken = FindToken( startToken + 1, "patternGraphicsNameRef" );

    if( patternGraphicsNameRefToken >= 0 ) {
      PatternDefaultVariantName[ i ] = ReplaceNotSupportedCharacters( RemoveDoubleQuotas( Tokens[ patternGraphicsNameRefToken + 1 ] ) );
    }
    else {
      PatternDefaultVariantName[ i ] = "";
    }

    int patternGraphicsDefToken = PatternGraphicsDefArray[ i ];

    if( patternGraphicsDefToken < 0 ) {
      patternGraphicsDefToken = startToken;
      PatternGraphicsDefName[ i ] = "";
    }
    else {
      int patternGraphicsNameDefToken = FindToken( patternGraphicsDefToken + 1, "patternGraphicsNameDef" );

      if( patternGraphicsNameDefToken >= 0 ) {
        PatternGraphicsDefName[ i ] = ReplaceNotSupportedCharacters( RemoveDoubleQuotas( Tokens[ patternGraphicsNameDefToken + 1 ] ) );
      }
      else {
        PatternGraphicsDefName[ i ] = "";
        WriteLog( "# warning: no patternGraphicsNameDef\n");
      }
    }

    printf("#\n");
    printf("# Package: %s OriginalName = %s VariantName = %s PatternDefaultVariantName = %s\n", DeviceName, OriginalDeviceName,
              PatternGraphicsDefName[ i ], PatternDefaultVariantName[ i ] );

    printf("EDIT '%s%s.PAC';\n", DeviceName, PatternGraphicsDefName[ i ] );
    printf("DESCRIPTION 'Original name <b>%s</b><p>';\n", OriginalDeviceName );
    printf("GRID %s;\n", FileUnits );
    printf("CHANGE FONT VECTOR;\n");

    if( patternGraphicsDefToken >= 0 ) {
      CurrentToken = FindToken( patternGraphicsDefToken + 1, "multiLayer" );

      if( CurrentToken > 0 ) {
        CurrentToken++;

        while( CurrentToken < TokensNumber ) {
          if( Tokens[ CurrentToken ] == "(" ) {
            CurrentToken++;

            if( Tokens[ CurrentToken ] == "pad" ) {
              int SavePosition = CurrentToken;

              GeneratePad( SavePosition, 0 );

              CurrentToken = SavePosition;
            }

            SkipThisItem();
          }
          else {
            if( Tokens[ CurrentToken ] == ")" ) {
              break;
            }
            else {
              dlgMessageBox( "Unexpected keyword in multiLayer " + Tokens[ CurrentToken ], "OK");
              return;
            }
          }

          CurrentToken++;
        }
      }

      CurrentToken = patternGraphicsDefToken;

      CurrentToken++;

      while( CurrentToken < TokensNumber ) {
        if( Tokens[ CurrentToken ] == "(" ) {
          CurrentToken++;

          if( Tokens[ CurrentToken ] == "layerContents" ) {
            int SavePosition = CurrentToken;

            GenerateLayerContents( SavePosition, i );

            CurrentToken = SavePosition;
          }

          SkipThisItem();
        }
        else {
          if( Tokens[ CurrentToken ] == ")" ) {
            break;
          }
          else {
            dlgMessageBox( "Unexpected keyword in layerContents " + Tokens[ CurrentToken ], "OK");
            return;
          }
        }

        CurrentToken++;
      }
    }
  }
}

int OneViaShapeCreated;

int ProcessOneViaShape( int Number, int startToken, string holeDiam )
{
  int layerNumRefPosition = FindToken( startToken + 1, "layerNumRef" );

  if( layerNumRefPosition >= 0 ) {
    if( checkLayerType( layerNumRefPosition + 1  ) ) {
      int viaShapeTypePosition = FindToken( startToken + 1, "viaShapeType" );

      if( viaShapeTypePosition >= 0 ) {
        int shapeWidthPosition = FindToken( startToken + 1, "shapeWidth" );

        if( shapeWidthPosition >= 0 ) {
          string TokenText = Tokens[ shapeWidthPosition + 1 ];

          if( Tokens[ shapeWidthPosition + 2 ] != ")" ) {
            if( IsASCIIValue( Tokens[ shapeWidthPosition + 2 ] ) ) {
              TokenText = TokenText + Tokens[ shapeWidthPosition + 2 ];
            }
            else {
              WriteLog( "#warning: wrong description.\n" );
            }
          }

          string shapeWidth = ConvertUnits( GetNumberValue( TokenText ),
                                            GetUnitValue( TokenText ) );

          int shapeHeightPosition = FindToken( startToken + 1, "shapeHeight" );

          if( shapeHeightPosition >= 0 ) {

            string TokenText = Tokens[ shapeHeightPosition + 1 ];

            if( Tokens[ shapeHeightPosition + 2 ] != ")" ) {
              if( IsASCIIValue( Tokens[ shapeHeightPosition + 2 ] ) ) {
                TokenText = TokenText + Tokens[ shapeHeightPosition + 2 ];
              }
              else {
                WriteLog( "#warning: wrong description.\n" );
              }
            }

            string shapeHeight = ConvertUnits( GetNumberValue( TokenText ),
                                               GetUnitValue( TokenText ) );

            if( ( !CheckForNull( shapeWidth ) ) ||
                ( !CheckForNull( shapeHeight ) ) ) {

              printf("#  ViaShape: layerNumRef = %s",
                Tokens[ layerNumRefPosition + 1 ] );
              printf(" viaShapeType = %s",
                Tokens[ viaShapeTypePosition + 1 ] );
              printf(" shapeWidth = %s", shapeWidth );
              printf(" shapeHeight = %s\n", shapeHeight );

              if( OneViaShapeCreated == 0 ) {
                if( Tokens[ viaShapeTypePosition + 1 ] == "Oval" ) { // Oval
                  if( shapeWidth == shapeHeight ) {
                      ViaStyleDefsType[ Number ] = "ROUND";
                      ViaStyleDefsDiameter[ Number ] = shapeWidth;
                      OneViaShapeCreated = 1;
                      ViaStyleDefsSkip[ Number ] = 0;
                  }
                  else {
                    ViaStyleDefsType[ Number ] = "ROUND";
                    ViaStyleDefsDiameter[ Number ] = shapeWidth;
                    OneViaShapeCreated = 1;
                    ViaStyleDefsSkip[ Number ] = 0;

                    //if( DebugMessage ) {
                      WriteLog("#warning: ViaShape: oval. Create round via\n");
                    //}
                  }
                }
                else {
                  if( Tokens[ viaShapeTypePosition + 1 ] == "Rect" ) { // Rectangle
                    if( shapeWidth == shapeHeight ) {
                      ViaStyleDefsType[ Number ] = "SQUARE";
                      ViaStyleDefsDiameter[ Number ] = shapeWidth;
                      OneViaShapeCreated = 1;
                      ViaStyleDefsSkip[ Number ] = 0;
                    }
                    else {
                      ViaStyleDefsType[ Number ] = "SQUARE";
                      ViaStyleDefsDiameter[ Number ] = shapeWidth;
                      OneViaShapeCreated = 1;
                      ViaStyleDefsSkip[ Number ] = 0;

                      //if( DebugMessage ) {
                        WriteLog("#warning: ViaShape: rectangle. Create square via.\n");
                      //}
                    }
                  }
                  else {
                    if( Tokens[ viaShapeTypePosition + 1 ] == "Ellipse" ) { // Ellipse
                      if( shapeWidth == shapeHeight ) {
                        ViaStyleDefsType[ Number ] = "ROUND";
                        ViaStyleDefsDiameter[ Number ] = shapeWidth;
                        OneViaShapeCreated = 1;
                        ViaStyleDefsSkip[ Number ] = 0;
                      }
                      else {
                        ViaStyleDefsType[ Number ] = "ROUND";
                        ViaStyleDefsDiameter[ Number ] = shapeWidth;
                        OneViaShapeCreated = 1;
                        ViaStyleDefsSkip[ Number ] = 0;

                        //if( DebugMessage ) {
                          WriteLog( "# warning: ViaShape: Ellips with different width and height. Create round via.\n");
                        //}
                      }
                    }
                    else {
                      if( Tokens[ viaShapeTypePosition + 1 ] == "MtHole" ) { // MountingHole
                        //if( DebugMessage ) {
                          WriteLog("#warning: ViaShape:MtHole \n");
                        //}
                      }
                      else {
                        if( Tokens[ viaShapeTypePosition + 1 ] == "RndRect" ) { // RoundRectangle
                          ViaStyleDefsType[ Number ] = "SQUARE";
                          real width = strtod( shapeWidth );
                          width = width * ( 1.0 - 0.7 / ROUNDNESS );

                          string newWidth;

                          sprintf( newWidth, "%f", width );

                          ViaStyleDefsDiameter[ Number ] = newWidth;
                          OneViaShapeCreated = 1;
                          ViaStyleDefsSkip[ Number ] = 0;

                          //if( DebugMessage ) {
                            WriteLog("#warning: ViaShape: RndRect. Create shrinked square via.\n");
                          //}
                        }
                        else {
                          if( Tokens[ viaShapeTypePosition + 1 ] == "Target" ) { // Make it round
                            //if( DebugMessage ) {
                              WriteLog("#warning: ViaShape: Target. Do not supported.\n");
                            //}
                          }
                          else {
                            string tmp;
                            sprintf( tmp, "# warning: ViaShape %s not supported yet\n",
                                       Tokens[ viaShapeTypePosition + 1 ] );
                            WriteLog( tmp );
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
            else {
              if( DebugMessage ) {
                printf( "# via's shape skips because of zero width and height.\n");
              }
            }
          }
        }
      }
    }
    else {
      if( DebugMessage ) {
        printf( "# via's shape skips because of layer.\n");
      }
    }
  }

  return( 0 );
}

int ProcessViaShapes( int Number, int startToken, string holeDiam )
{
  OneViaShapeCreated = 0;

  CurrentToken = startToken + 1;

  while( CurrentToken < TokensNumber ) {
    if( Tokens[ CurrentToken ] == "(" ) {
      CurrentToken++;

      if( Tokens[ CurrentToken ] == "viaShape" ) {
        int SavePosition = CurrentToken;

        ProcessOneViaShape( Number, SavePosition, holeDiam );

        CurrentToken = SavePosition;
      }

      SkipThisItem();
    }
    else {
      if( Tokens[ CurrentToken ] == ")" ) {
        break;
      }
      else {
        dlgMessageBox( TR("Unexpected keyword in ProcessViaShapes: ") + Tokens[
                        CurrentToken ], "OK");
        return( 1 );
      }
    }

    CurrentToken++;
  }

  return( 1 );
}

void GenerateOneViaDefinition( int Number, int startToken )
{
  printf( "#ViaStyleDef %s\n", Tokens[ startToken ] );

  ViaStyleDefsSkip[ Number ] = 1;

  int holeDiamPosition = FindToken( startToken + 1, "holeDiam" );

  if( holeDiamPosition >= 0 ) {
    string holeDiam = Tokens[ holeDiamPosition + 1 ];

    if( CheckForNull( holeDiam ) ) {
      WriteLog("# warning: zero hole in via\n");
    }

    if( DebugMessage ) {
      printf( "#HoleDiameter = %s\n", holeDiam );
    }

    ProcessViaShapes( Number, startToken, holeDiam );

    if( ViaStyleDefsSkip[ Number ] ) {
      if( DebugMessage ) {
        printf( "# this ViaDefinition was skipped.\n");
      }
    }
    else {
      sprintf( ViaStyleDefsScript[ Number ], "CHANGE DRILL %s;\n%s",
               holeDiam, ViaStyleDefsScript[ Number ] );
    }
  }
  else {
    if( DebugMessage ) {
      printf( "# skips because via has no holeDiam.\n");
    }
  }
}

void GenerateViaDefinitions( void )
{
  for( int i = 0; i < ViaStyleDefsNumber; i++ ) {
    int startToken = ViaStyleDefsArray[ i ];

    string info;
    sprintf( info, TR("Process Via Style definition") + " %d (%d)", i, ViaStyleDefsNumber );
    UpdateProgress( info );

    GenerateOneViaDefinition( i, startToken );
  }
}

string FindSymbolNameByOriginal( string originalSymbolName )
{
  for( int i = 0; i < SymbolDefsNumber; i++ ) {
    if( originalSymbolName == OriginalSymbolsName[ i ] ) {
      return( SymbolsName[ i ] );
    }
  }

  return( "" );
}

int FindSymbolIndexByName( string symbolName )
{
  for( int i = 0; i < SymbolDefsNumber; i++ ) {
    if( symbolName == SymbolsName[ i ] ) {
      return( i );
    }
  }

  return( -1 );
}

int FindPatternDefIndexByName( string patternName, string variantName )
{
  for( int i = 0; i < PatternDefExtendedNumber; i++ ) {
    if( patternName == PatternName[ i ] ) {
      if( variantName == PatternGraphicsDefName[ i ] ) {
        return( i );
      }
    }
  }

  return( -1 );
}

string FindPatternNameByOrigin( string originalPatternName )
{
  for( int i = 0; i < PatternDefExtendedNumber; i++ ) {
    if( originalPatternName == PatternOriginalName[ i ] ) {
      return( PatternName[ i ] );
    }
  }

  return( "" );
}

string FindPatternDefaultVariantByOrigin( string originalPatternName )
{
  for( int i = 0; i < PatternDefExtendedNumber; i++ ) {
    if( originalPatternName == PatternOriginalName[ i ] ) {
      if( PatternDefaultVariantName[ i ] == PatternGraphicsDefName[ i ] ) {
        return( PatternDefaultVariantName[ i ] );
      }
    }
  }

  return( "" );
}

string FindSymbolDeviceName( string compName )
{
  for( int i = 0; i < NrCompInstances; i++ ) {
    if( compName == CompInstancesName[ i ] ) {
      return( CompInstancesRef[ i ] );
    }
  }

  return( "" );
}

string FindCompValue( string compName )
{
  for( int i = 0; i < NrCompInstances; i++ ) {
    if( compName == CompInstancesName[ i ] ) {
      return( CompValue[ i ] );
    }
  }

  return( "" );
}

string FindText( int startToken )
{
  CurrentToken = startToken + 1;

  while( CurrentToken < TokensNumber ) {
    if( Tokens[ CurrentToken ] == "(" ) {
      CurrentToken++;

      SkipThisItem();
    }
    else {
      if( Tokens[ CurrentToken ] == ")" ) {
        break;
      }

      return( ReplaceNotSupportedCharacters( RemoveDoubleQuotas( Tokens[ CurrentToken ] ) ) );
    }

    CurrentToken++;
  }

  return( "" );
}

string ConvertPinType( string pinType )
{
  if( pinType == "Unknown" ) {
    return( "IO" );
  } else if( pinType == "Passive" ) {
    return( "Pas" );
  } else if( pinType == "Input" ) {
    return( "In" );
  } else if( pinType == "Output" ) {
    return( "Out" );
  } else if( pinType == "Bidirectional" ) {
    return( "IO" );
  } else if( pinType == "OpenH" ) {
    return( "OC" );
  } else if( pinType == "OpenL" ) {
    return( "OC" );
  } else if( pinType == "PassiveH" ) {
    return( "Pas" );
  } else if( pinType == "PassiveL" ) {
    return( "Pas" );
  } else if( pinType == "ThreeState" ) {
    return( "Hiz" );
  } else if( pinType == "Power" ) {
    return( "Pwr" );
  }

  string tmp;
  sprintf( tmp, "# warning: unknown pinType = %s\n", pinType );
  WriteLog( tmp );

  return( "IO" );
}

int IfFitToSymbolName( int startToken, string OriginalSymbolName )
{
  int level = 1;
  CurrentToken = startToken;

  while( CurrentToken < TokensNumber ) {
    if( Tokens[ CurrentToken ] == "(" ) {
      level++;
      CurrentToken++;
      if( Tokens[ CurrentToken ] == "attachedSymbol" ) {
        int SavePosition = CurrentToken;

        CurrentToken = FindToken( SavePosition + 1, "symbolName" );

        if( CurrentToken >= 0 ) {
          string OriginalDeviceName = ReplaceNotSupportedCharacters( RemoveDoubleQuotas( Tokens[ CurrentToken + 1 ] ) );

          if( OriginalSymbolName == OriginalDeviceName ) {
            return( 1 );
          }
        }

        CurrentToken = SavePosition;
      }

      SkipThisItem();
    }
    else {
      if( Tokens[ CurrentToken ] == ")" ) {
        level--;

        if( level == 0 ) {
          return( 0 );
        }
      }
    }

    CurrentToken++;
  }

  return( 0 );
}

string FindPinDirection( string OriginalSymbolName, string pinNum )
{
  for( int i = 0; i < CompDefsNumber; i++ ) {
    int startToken = CompDefsArray[ i ];

    if( IfFitToSymbolName( startToken, OriginalSymbolName ) ) {
      CurrentToken = startToken + 1;

      while( CurrentToken < TokensNumber ) {
        if( Tokens[ CurrentToken ] == "(" ) {
          CurrentToken++;

          if( Tokens[ CurrentToken ] == "compPin" ) {
            int SavePosition = CurrentToken;
            string currentPinNum = FindText( SavePosition );

            if( currentPinNum == pinNum ) {
              int tokenPosition = FindToken( SavePosition + 1, "pinType" );

              if( tokenPosition >= 0 ) {
                string pinType = Tokens[ tokenPosition + 1 ];

                string pinTypeEagle = ConvertPinType( pinType );

                return( pinTypeEagle );
              }
            }

            CurrentToken = SavePosition;
          }

          SkipThisItem();
        }
        else {
          if( Tokens[ CurrentToken ] == ")" ) {
          }
        }

        CurrentToken++;
      }
    }
  }

  return( "IO" );
}

string PinNamesTable[];
int NrOfThisPinName[];
int CurrentPinIndex[];
int NrPinNames;

int FindPinName( string pinName )
{
  for( int i = 0; i < NrPinNames; i++ ) {
    if( PinNamesTable[ i ] == pinName ) {
      return( i );
    }
  }

  return( -1 );
}

void FillOnePinName( int startToken )
{
  CurrentToken = startToken + 1;

  while( CurrentToken < TokensNumber ) {
    if( Tokens[ CurrentToken ] == "(" ) {
      CurrentToken++;

      if( Tokens[ CurrentToken ] == "pinName" ) {
	int pinNameToken = CurrentToken + 1;

        string pinName = FindText( pinNameToken + 1 );

        if( pinName != "" ) {
          int index = FindPinName( pinName );

          if( index >= 0 ) {
            NrOfThisPinName[ index ]++;
          }
          else {
            PinNamesTable[ NrPinNames ] = pinName;
            NrOfThisPinName[ NrPinNames ] = 1;
            CurrentPinIndex[ NrPinNames ] = 1;
            NrPinNames++;
          }
        }

	return;
      }
      else {
        SkipThisItem();
      }
    }
    else {
      if( Tokens[ CurrentToken ] == ")" ) {
        break;
      }
    }

    CurrentToken++;
  }
}

void FillPinNameTable( int startToken )
{
  NrPinNames = 0;

  CurrentToken = startToken + 1;

  while( CurrentToken < TokensNumber ) {
    if( Tokens[ CurrentToken ] == "(" ) {
      CurrentToken++;

      if( Tokens[ CurrentToken ] == "pin" ) {
	int SavePosition = CurrentToken;
        FillOnePinName( SavePosition );
	CurrentToken = SavePosition;
	SkipThisItem();
      }
      else {
        SkipThisItem();
      }
    }
    else {
      if( Tokens[ CurrentToken ] == ")" ) {
	break;
      }
    }

    CurrentToken++;
  }
}

void GeneratePin( int startToken, string OriginalSymbolName )
{
  string pinNum;
  string xPointCoord;
  string yPointCoord;
  string rotation     = "0";
  string pinLength    = "0";
  int    isPinLength  = 0;
  string dispPinDes = "True";
  int    pinDesToken  = 0;
  string pinDes = "";
  string pinVisibility = "Off";
  int    pinNameToken = 0;
  string defaultPinDes;
  string insideStyle;
  int    isFlipped = 0;

  CurrentToken = startToken + 1;

  while( CurrentToken < TokensNumber ) {
    if( Tokens[ CurrentToken ] == "(" ) {
      CurrentToken++;

      if( Tokens[ CurrentToken ] == "pt" ) {
        xPointCoord = Tokens[ CurrentToken + 1 ];

        if( IsASCIIValue( Tokens[ CurrentToken + 2 ] ) ) {
          xPointCoord = xPointCoord + Tokens[ CurrentToken + 2 ];

          if( Tokens[ CurrentToken + 3 ] != ")" ) {
            yPointCoord = Tokens[ CurrentToken + 3 ];

            if( Tokens[ CurrentToken + 4 ] != ")" ) {
              yPointCoord = yPointCoord + Tokens[ CurrentToken + 4 ];
            }
          }
          else {
            WriteLog( "#warning: wront point description.\n" );
          }
        }
        else {
          yPointCoord = Tokens[ CurrentToken + 2 ];

          if( Tokens[ CurrentToken + 3 ] != ")" ) {
            yPointCoord = yPointCoord + Tokens[ CurrentToken + 3 ];
          }
        }

        SkipThisItem();
      }
      else {
        if( Tokens[ CurrentToken ] == "pinNum" ) {
          pinNum = Tokens[ CurrentToken + 1 ];
          SkipThisItem();
        }
        else {
          if( Tokens[ CurrentToken ] == "rotation" ) {
            rotation = Tokens[ CurrentToken + 1 ];
            SkipThisItem();
          }
          else {
            if( Tokens[ CurrentToken ] == "pinLength" ) {
              pinLength = Tokens[ CurrentToken + 1 ];
              isPinLength = 1;
              SkipThisItem();
            }
            else {
              if( Tokens[ CurrentToken ] == "pinDisplay" ) {
                if( Tokens[ CurrentToken + 2 ] == "dispPinDes" ) {
                  dispPinDes =  Tokens[ CurrentToken + 3 ];
                }

                if( Tokens[ CurrentToken + 2 ] == "dispPinName" ) {
                  if( Tokens[ CurrentToken + 3 ] == "True" ) {
                    pinVisibility = "";
                  }
                }

                SkipThisItem();
              }
              else {
                if( Tokens[ CurrentToken ] == "pinDes" ) {
                  int SavePosition = CurrentToken;
                  pinDesToken = SavePosition + 1;
                  pinDes = FindText( SavePosition + 2 );
                  CurrentToken = SavePosition;
                  SkipThisItem();
                }
                else {
                  if( Tokens[ CurrentToken ] == "pinName" ) {
                    pinNameToken = CurrentToken + 1;
                    SkipThisItem();
                  }
                  else {
                    if( Tokens[ CurrentToken ] == "defaultPinDes" ) {
                      defaultPinDes = Tokens[ CurrentToken + 1 ];
                      SkipThisItem();
                    }
                    else {
                      if( Tokens[ CurrentToken ] == "insideStyle" ) {
                        insideStyle = Tokens[ CurrentToken + 1 ];
                        SkipThisItem();
                      }
                      else {
                        if( Tokens[ CurrentToken ] == "isFlipped" ) {
		          if( Tokens[ CurrentToken + 1 ] == "True" ) {
		            isFlipped = 1;
		          }
                          SkipThisItem();
                        }
                        else {
                          if( DebugMessage ) {
                            printf( "# GeneratePin ??????? %s\n",  Tokens[ CurrentToken ] );
                          }
                          SkipThisItem();
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
    else {
      if( Tokens[ CurrentToken ] == ")" ) {
        break;
      }
    }

    CurrentToken++;
  }

  if( pinDesToken ) {
    if( dispPinDes == "True" ) {
      IfPinText = 1;
      GenerateOneText( pinDesToken + 1 );
      IfPinText = 0;
    }
  }

  /*if( pinNameToken ) {
    GenerateOneText( pinNameToken + 1 );
  }*/

  real pinLengthValue = strtod( GetNumberValue( pinLength ) );
  real rotationValue = strtod( GetNumberValue( rotation ) );

  real pinX = strtod( ConvertUnits( GetNumberValue( xPointCoord ), GetUnitValue( xPointCoord ) ) );
  real pinY = strtod( ConvertUnits( GetNumberValue( yPointCoord ), GetUnitValue( yPointCoord ) ) );

  if( !pinLengthValue ) {
    printf( "CHANGE LENGTH POINT;\n");
  } else if( pinLengthValue == 100 ) {
    printf( "CHANGE LENGTH SHORT;\n");
  } else if( pinLengthValue == 200 ) {
    printf( "CHANGE LENGTH MIDDLE;\n");
  } else if ( pinLengthValue == 300) {
    printf( "CHANGE LENGTH LONG;\n");
  }

  if( !isPinLength ) {
    printf( "CHANGE LENGTH LONG;\n");
    pinLengthValue = 300;
  }

  if( rotationValue >= 270 ) {
    pinY -= pinLengthValue;
  }
  else if( rotationValue  >= 180 ) {
    pinX -= pinLengthValue;
  }
  else if( rotationValue >=  90 ) {
    pinY += pinLengthValue;
  }
  else {
    pinX += pinLengthValue;
  }

  string mirrored = "";

// Mirrored (flipped) is not use here because it supported by above code

  /*if( isFlipped ) {
     mirrored = "M";
  }*/

  /*if( isFlipped ) {
    if( rotationValue >= 270 ) {
      pinY = pinY - 2 * pinLengthValue;
    }
    else if( rotationValue  >= 180 ) {
      pinX = pinX - 2 * pinLengthValue;
    }
    else if( rotationValue >=  90 ) {
      pinY = pinY + 2 * pinLengthValue;
    }
    else {
      pinX = pinX - 2 * pinLengthValue;
    }
  }*/

  string pinDirection = FindPinDirection( OriginalSymbolName, pinDes );

  string pinName = FindText( pinNameToken + 1 );

  if( pinName != "" ) {
    int index = FindPinName( pinName );

    if( index >= 0 ) {
      if( NrOfThisPinName[ index ] > 1 ) {
        sprintf( pinName, "%s@%d", pinName, CurrentPinIndex[ index ] );
        CurrentPinIndex[ index ]++;
      }
    }
    else {
      string tmp;
      printf( tmp, "# warning: can't find pin %s in table\n", pinName );
      WriteLog( tmp );
    }

    if( pinName[ 0 ] == '~' ) {
      pinName[ 0 ] = '!';
    }

    printf( "PIN '%s' %s %sR%f %s (%f %f);\n", pinName, pinDirection, mirrored, rotationValue + 180.0,
            pinVisibility, pinX, pinY );
  }
  else {
    printf( "PIN %s %sR%f %s (%f %f);\n", pinDirection, mirrored, rotationValue + 180.0,
            pinVisibility, pinX, pinY );
  }
}

void GenerateSymbols( void )
{
  printf("# Symbols:\n");

  for( int i = 0; i < SymbolDefsNumber; i++ ) {
    int startToken =  SymbolDefsArray[ i ];

    string info;
    sprintf( info, "Process symbol %d (%d)", i, SymbolDefsNumber + 1 );
    UpdateProgress( info );

    string SymbolName = ReplaceNotSupportedCharacters( RemoveDoubleQuotas(
                                                       Tokens[ startToken ] )
                                                       );

    string OriginalSymbolName = GetOriginalDeviceName( startToken + 1 );

    SymbolsName[ i ] = SymbolName;
    OriginalSymbolsName[ i ] = OriginalSymbolName;

    printf("#\n");
    printf("# Symbol: %s OriginalName = %s\n", SymbolName, OriginalSymbolName );

    printf("EDIT '%s.SYM';\n", SymbolName );
    printf("DESCRIPTION 'Original name <b>%s</b><p>';\n", OriginalSymbolName );
    printf("GRID %s;\n", FileUnits );
    printf("CHANGE FONT VECTOR;\n");

    FillPinNameTable( startToken );

    printf( "CHANGE LAYER 94;\n" );

    IfNameDefinedInSymbol[ i ] = 0;
    IfValueDefinedInSymbol[ i ] = 0;
    SymbolAttributesIndex[ i ] = NrAttributes;
    SymbolNrAttributes[ i ] = 0;

    CurrentToken = startToken + 1;

    while( CurrentToken < TokensNumber ) {
      if( Tokens[ CurrentToken ] == "(" ) {
        CurrentToken++;

        if( Tokens[ CurrentToken ] == "originalName" ) {
          SkipThisItem();
        }
        else {
          if( Tokens[ CurrentToken ] == "pin" ) {
            int SavePosition = CurrentToken;

            GeneratePin( SavePosition, OriginalSymbolName );

            CurrentToken = SavePosition;

            SkipThisItem();
          }
          else {
            if( Tokens[ CurrentToken ] == "line" ) {
              int SavePosition = CurrentToken;

              GenerateOneLine( SavePosition, 0, 0 );

              CurrentToken = SavePosition;

              SkipThisItem();
            }
            else {
              if( Tokens[ CurrentToken ] == "attr" ) {
                int SavePosition = CurrentToken;
                GenerateNameAndValueSchematics( SavePosition, i );
                CurrentToken = SavePosition;
                SkipThisItem();
              }
              else {
                if( Tokens[ CurrentToken ] == "poly" ) {
                  int SavePosition = CurrentToken;

                  GenerateOnePcbPoly( SavePosition, 0, DEFAULT_WIRE_WIDTH_BOARD );

                  CurrentToken = SavePosition;

                  SkipThisItem();
                }
                else {
                  if( Tokens[ CurrentToken ] == "text" ) {
                    int SavePosition = CurrentToken;
                    IfPinText = 1;
                    GenerateOneText( SavePosition );
                    IfPinText = 0;
                    CurrentToken = SavePosition;

                    SkipThisItem();
                  }
                  else {
                    if( Tokens[ CurrentToken ] == "triplePointArc" ) {
                      int SavePosition = CurrentToken;

                      GenerateOneTripleArc( SavePosition );

                      CurrentToken = SavePosition;

                      SkipThisItem();
                    }
                    else {
                      if( Tokens[ CurrentToken ] == "arc" ) {
                        int SavePosition = CurrentToken;
                        GenerateOneArc( SavePosition );
                        CurrentToken = SavePosition;
                        SkipThisItem();
                      }
                      else {
                        if( DebugMessage ) {
                          printf( "# GenerateSymbols ??????? %s\n",  Tokens[ CurrentToken ] );
                        }
                        SkipThisItem();
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
      else {
        if( Tokens[ CurrentToken ] == ")" ) {
          break;
        }
      }

      CurrentToken++;
    }
  }
}

int FindAttributeByNameInSymbol( int symbolIndex, string attributeName )
{
  for( int i = SymbolAttributesIndex[ symbolIndex ]; i < SymbolNrAttributes[ symbolIndex ]; i++ ) {
    if( attributeName == AttributesName[ i ] ) {
      return( AttributesIndex[ i ] );
    }
  }

  return( -1 );
}

int FindAttributeByNameInPattern( int patternIndex, string attributeName )
{
  for( int i = PatternAttributesIndex[ patternIndex ]; i < PatternNrAttributes[ patternIndex ]; i++ ) {
    if( attributeName == AttributesName[ i ] ) {
      return( AttributesIndex[ i ] );
    }
  }

  return( -1 );
}

void AddOneAttributes( int ifSymbol, int symbolIndex, string elemName, string attributeName, string attributeValue, int startToken, string xCoord, string yCoord )
{
  string xCoordText = "0.0";
  string yCoordText = "0.0";
  string rotation = "0";
  string isVisible = "False";
  string textStyleRef = "";
  string justify = "";
  int isFlipped = 0;

  if( symbolIndex >= 0 ) {
    int attrIndex;

    if( ifSymbol ) {
      attrIndex = FindAttributeByNameInSymbol( symbolIndex, attributeName );
    }
    else {
      attrIndex = FindAttributeByNameInPattern( symbolIndex, attributeName );
    }

//printf("# index attr name = %s\n", attributeName );
    if( attrIndex >= 0 ) {
//printf("# attr name = %s\n", Tokens[ attrIndex + 1 ] );

      CurrentToken = attrIndex + 3;

      while( CurrentToken < TokensNumber ) {
	if( Tokens[ CurrentToken ] == "(" ) {
	  CurrentToken++;

	  if( Tokens[ CurrentToken ] == "rotation" ) {
	    rotation = Tokens[ CurrentToken + 1 ];
	    SkipThisItem();
	  }
	  else {
	    if( Tokens[ CurrentToken ] == "isVisible" ) {
	      isVisible = Tokens[ CurrentToken + 1 ];
	      SkipThisItem();
	    }
	    else {
	      if( Tokens[ CurrentToken ] == "textStyleRef" ) {
		textStyleRef = Tokens[ CurrentToken + 1 ];
		SkipThisItem();
	      }
	      else {
		if( Tokens[ CurrentToken ] == "isFlipped" ) {
		  if( Tokens[ CurrentToken + 1 ] == "True" ) {
		    isFlipped = 1;
		  }
		  SkipThisItem();
		}
		else {
		  if( Tokens[ CurrentToken ] == "justify" ) {
		    justify = Tokens[ CurrentToken + 1 ];
		    SkipThisItem();
		  }
		  else {
		    SkipThisItem();
		  }
		}
	      }
	    }
	  }
	}
	else {
	  if( Tokens[ CurrentToken ] == ")" ) {
	    break;
	  }
	}

	CurrentToken++;
      }
    }
  }

  CurrentToken = startToken;

  while( CurrentToken < TokensNumber ) {
    if( Tokens[ CurrentToken ] == "(" ) {
      CurrentToken++;

      if( Tokens[ CurrentToken ] == "pt" ) {
        xCoordText = Tokens[ CurrentToken + 1 ];

        if( IsASCIIValue( Tokens[ CurrentToken + 2 ] ) ) {
          xCoordText = xCoordText + Tokens[ CurrentToken + 2 ];

          if( Tokens[ CurrentToken + 3 ] != ")" ) {
            yCoordText = Tokens[ CurrentToken + 3 ];

            if( Tokens[ CurrentToken + 4 ] != ")" ) {
              yCoordText = yCoordText + Tokens[ CurrentToken + 4 ];
            }
          }
          else {
            WriteLog( "#warning: wront point description.\n" );
          }
        }
        else {
          yCoordText = Tokens[ CurrentToken + 2 ];

          if( Tokens[ CurrentToken + 3 ] != ")" ) {
            yCoordText = yCoordText + Tokens[ CurrentToken + 3 ];
          }
        }

        SkipThisItem();
      }
      else {
        if( Tokens[ CurrentToken ] == "rotation" ) {
          rotation = Tokens[ CurrentToken + 1 ];
          SkipThisItem();
        }
        else {
          if( Tokens[ CurrentToken ] == "isVisible" ) {
            isVisible = Tokens[ CurrentToken + 1 ];
            SkipThisItem();
          }
          else {
            if( Tokens[ CurrentToken ] == "textStyleRef" ) {
              textStyleRef = Tokens[ CurrentToken + 1 ];
              SkipThisItem();
            }
            else {
              if( Tokens[ CurrentToken ] == "isFlipped" ) {
                if( Tokens[ CurrentToken + 1 ] == "True" ) {
                  isFlipped = 1;
                }
                SkipThisItem();
              }
              else {
                if( Tokens[ CurrentToken ] == "justify" ) {
                  justify = Tokens[ CurrentToken + 1 ];
                  SkipThisItem();
                }
                else {
                  SkipThisItem();
                }
              }
            }
          }
        }
      }
    }
    else {
      if( Tokens[ CurrentToken ] == ")" ) {
        break;
      }
    }

    CurrentToken++;
  }

  real newXCoord = strtod( ConvertUnits( GetNumberValue( xCoord ), GetUnitValue( xCoord ) ) ) +
		   strtod( ConvertUnits( GetNumberValue( xCoordText ), GetUnitValue( xCoordText ) ) );

  real newYCoord = strtod( ConvertUnits( GetNumberValue( yCoord ), GetUnitValue( yCoord ) ) ) +
		   strtod( ConvertUnits( GetNumberValue( yCoordText ), GetUnitValue( yCoordText ) ) );

  string mirrored = "";

  if( isFlipped ) {
     mirrored = "M";
  }

  if( attributeValue == "" ) {
    attributeValue = "''";
  }
  else {
    attributeValue = ReplaceNotSupportedCharactersText( attributeValue );
  }

  if( isVisible != "True" ) {
    if( elemName != "" ) {
      printf( "CHANGE DISPLAY OFF;\n" );
    }
  }
  else {
    if( elemName != "" ) {
      printf( "CHANGE DISPLAY VALUE;\n" );
    }
  }

  if( justify == "" ) { //LowerLeft
    printf("CHANGE ALIGN BOTTOM LEFT;\n");
  } else if( justify == "UpperLeft" ) {
    printf("CHANGE ALIGN TOP LEFT;\n");
  } else if( justify == "UpperCenter" ) {
    printf("CHANGE ALIGN TOP CENTER;\n");
  } else if( justify == "UpperRight" ) {
    printf("CHANGE ALIGN TOP RIGHT;\n");
  } else if( justify == "Left" ) {
    printf("CHANGE ALIGN CENTER LEFT;\n");
  } else if( justify == "Center" ) {
    printf("CHANGE ALIGN CENTER CENTER;\n");
  } else if( justify == "Right" ) {
    printf("CHANGE ALIGN CENTER RIGHT;\n");
  } else if( justify == "LowerLeft" ) {
    printf("CHANGE ALIGN BOTTOM LEFT;\n");
  } else if( justify == "LowerCenter" ) {
    printf("CHANGE ALIGN BOTTOM CENTER;\n");
  } else if( justify == "LowerRight" ) {
    printf("CHANGE ALIGN BOTTOM RIGHT;\n");
  }
  else {
    printf("# warning: unknown justify parameter value = %s\n", justify );
    printf("CHANGE ALIGN BOTTOM LEFT;\n");
  }

  int textStyleDefPos = FindTextStyleDef( textStyleRef );

  if( textStyleDefPos >= 0 ) {
    real fontHeight = strtod( ConvertUnits( GetNumberValue( TextStyleDefFontHeight[ textStyleDefPos ] ), GetUnitValue(  TextStyleDefFontHeight[ textStyleDefPos ] ) ) );
    real fontWidth = strtod( ConvertUnits( GetNumberValue( TextStyleDefFontStrokeWidth[ textStyleDefPos ] ), GetUnitValue( TextStyleDefFontStrokeWidth[ textStyleDefPos ] ) ) );

    printf("CHANGE SIZE %s;\n", TextStyleDefFontHeight[ textStyleDefPos ] );

    if( fontHeight ) {
      int ratio = round( 100.0 * fontWidth / fontHeight );

      if( ratio > 31.0 ) {
        ratio = 31.0;
      }

      printf("CHANGE RATIO %d;\n", ratio );
    }
  }

  if( elemName != "" ) {
    printf( "ATTRIBUTE '%s' '%s' '%s' %sSR%s (%f %f);\n", elemName, attributeName, attributeValue,  mirrored, rotation, newXCoord, newYCoord );
  }
  else {
    printf( "ATTRIBUTE '%s' '%s';\n", attributeName, attributeValue );
  }
}

void AddAttributes( int ifSymbol, int symbolIndex, string elemName, int patternGraphicsRef, string xCoord, string yCoord )
{
  CurrentToken = patternGraphicsRef + 1;

  while( CurrentToken < TokensNumber ) {
    if( Tokens[ CurrentToken ] == "(" ) {
      CurrentToken++;

      if( Tokens[ CurrentToken ] == "attr" ) {
        string attrName = ReplaceNotSupportedCharacters( RemoveDoubleQuotas( Tokens[ CurrentToken + 1 ] ) );

        if( attrName == "Name" ) {
          attrName = "Name_";
        }

        if( ( strlwr( attrName ) != "value" ) && ( strlwr( attrName ) != "name" ) && ( strlwr( attrName ) != "refdes" ) ) {
          int SavePosition = CurrentToken;
          AddOneAttributes( ifSymbol, symbolIndex, elemName, attrName, ReplaceNotSupportedCharacters( RemoveDoubleQuotas( Tokens[ CurrentToken + 2 ] ) ),
                            CurrentToken, xCoord, yCoord );
          CurrentToken = SavePosition;
        }

        SkipThisItem();
      }
      else {
        SkipThisItem();
      }
    }
    else {
      if( Tokens[ CurrentToken ] == ")" ) {
        break;
      }
    }

    CurrentToken++;
  }
}

void GenerateDevices( void )
{
  printf("# Devices:\n");

  for( int i = 0; i < CompDefsNumber; i++ ) {
    int startToken = CompDefsArray[ i ];

    string DeviceName = ReplaceNotSupportedCharacters( RemoveDoubleQuotas(
                                                       Tokens[ startToken ] )
                                                       );

    string OriginalDeviceName = GetOriginalDeviceName( startToken + 1 );

    printf("#\n");
    printf("# Device: %s OriginalName = %s\n", DeviceName, OriginalDeviceName );

    printf("EDIT '%s.DEV';\n", DeviceName );
    printf("GRID %s;\n", FileUnits );

    //AddAttributes( 0, -1, "", startToken, "0.0", "0.0" );

    int packageExists = 0;

    int attachedPatternToken = FindToken( startToken + 1, "attachedPattern" );

    if( attachedPatternToken > 0 ) {
      CurrentToken = FindToken( attachedPatternToken + 1, "patternName" );

      if( CurrentToken >= 0 ) {
        string originPatternName = ReplaceNotSupportedCharacters( RemoveDoubleQuotas( Tokens[ CurrentToken + 1 ] ) );

        string patternName = FindPatternNameByOrigin( originPatternName );

        if( patternName != "" ) {
          string patternDefaultVariant = FindPatternDefaultVariantByOrigin( originPatternName );

          printf( "PACKAGE '%s%s';\n", patternName, patternDefaultVariant );

          packageExists = 1;

          CurrentToken = FindToken( attachedPatternToken + 1, "padPinMap" );

          if( CurrentToken > 0 ) {
            PadPinMapRef[ i ] = NrPadPinMap;
            PadPinMapCount[ i ] = 0;

            CurrentToken++;

            while( Tokens[ CurrentToken ] != ")" ) {
              PadPinMapNum[ NrPadPinMap ] = Tokens[ CurrentToken + 2 ];
              PadPinMapPinRef[ NrPadPinMap ] =  ReplaceNotSupportedCharacters( RemoveDoubleQuotas( Tokens[ CurrentToken + 6 ] ) );

              //printf( "# PadMap: num = %s ref = %s\n", PadPinMapNum[ NrPadPinMap ], PadPinMapPinRef[ NrPadPinMap ] );

              NrPadPinMap++;
              PadPinMapCount[ i ]++;

              CurrentToken = CurrentToken + 8;
            }
          }
        }
        else {
          string tmp;
          sprintf( tmp, "# warning: no package exists for attachedPattern in device %s \n", DeviceName );
          WriteLog( tmp );
        }
      }
      else {
        string tmp;
        sprintf( tmp, "# warning: no pattern name in device %s \n", DeviceName );
        WriteLog( tmp );
      }
    }
    else {
      string tmp;
      sprintf( tmp, "# warning: no package for device %s \n", DeviceName );
      WriteLog( tmp );
    }

    if( !packageExists ) {
      printf("ATTRIBUTE '_EXTERNAL_';\n");
    }

    int symbolNum = 0;

    CurrentToken = startToken + 1;

    while( CurrentToken < TokensNumber ) {
      if( Tokens[ CurrentToken ] == "(" ) {
        CurrentToken++;

        if( Tokens[ CurrentToken ] == "attachedSymbol" ) {
          int SavePosition = CurrentToken;

          CurrentToken = FindToken( SavePosition + 1, "symbolName" );

          if( CurrentToken > 0 ) {
            string symbolName = ReplaceNotSupportedCharacters( RemoveDoubleQuotas( Tokens[ CurrentToken + 1 ] ) );

            string symbolNameByOriginal = FindSymbolNameByOriginal( symbolName );

            string partNum = "";

            int partNumPosition = FindToken( SavePosition + 1, "partNum" );

            if( partNumPosition >= 0 ) {
              partNum = Tokens[ partNumPosition + 1 ];
            }

            if( symbolNameByOriginal != "" ) {
              printf( "ADD '%s' 'G%s'(%.8f%s %.8f%s);\n", symbolNameByOriginal, partNum,
                                                   0.0, FileUnits, symbolNum * -100.0, FileUnits );

              DevicesName[ NrSymbolDevices ] = DeviceName;
              SymbolDevicesName[ NrSymbolDevices ] = symbolNameByOriginal;
              NrSymbolDevices++;

              symbolNum++;
            }
            else {
              string tmp;
              sprintf( tmp, "# warning: no SymbolNameByOriginal was found for symbol %s\n", symbolName );
              WriteLog( tmp );
            }
          }
          else {
            string tmp;
            sprintf( tmp, "# warning: no symbol name in device %s\n", DeviceName );
            WriteLog( tmp );
          }

          CurrentToken = SavePosition;
        }

        SkipThisItem();
      }
      else {
        if( Tokens[ CurrentToken ] == ")" ) {
          break;
        }
        else {
          dlgMessageBox( "Unexpected keyword in GenerateDevices " + Tokens[ CurrentToken ], "OK");
          return;
        }
      }

      CurrentToken++;
    }
  }
}

int FindDummyDeviceName( string DeviceName )
{
  for( int i = 0; i < NrDummyDevices; i++ ) {
    if( DummyDevices[ i ] == DeviceName ) {
      return( 1 );
    }
  }

  return( 0 );
}

void GenerateDummyDevices( void )
{
  NrDummyDevices = 0;

  printf("# Dummy devices: %d\n", NrPadsOnBoard );

  for( int i = 0; i < NrPadsOnBoard; i++ ) {
    int startToken = PadOnBoardIndex[ i ];

    int padStyleRefPosition = FindToken( startToken + 1, "padStyleRef" );

    if( padStyleRefPosition >= 0 ) {
      string DeviceName = ReplaceNotSupportedCharacters( RemoveDoubleQuotas(
                                                         Tokens[ padStyleRefPosition + 1 ] )
                                                         );

      PadOnBoardDefs[ i ] = DeviceName;

      if( FindDummyDeviceName( DeviceName ) == 0 ) {
        DummyDevices[ NrDummyDevices ] = DeviceName;
        NrDummyDevices++;

        printf("#\n");
        printf("# Dummy package: %s\n", DeviceName );

        printf("EDIT '%s.PAC';\n", DeviceName );
        printf("GRID %s;\n", FileUnits );

        GeneratePad( startToken, 1 );

        printf("#\n");
        printf("# Device: %s\n", DeviceName );

        printf("EDIT '%s.DEV';\n", DeviceName );
        printf("GRID %s;\n", FileUnits );
        printf("ATTRIBUTE '_EXTERNAL_';\n");
      }
    }
    else {
      WriteLog("# warning: can't find padStyleRef in dummy device.\n");
    }
  }
}

// Generate library from 'library' keyword

void GenerateLibrary( void )
{
  GenerateLibraryHeader();

  GeneratePadDefinitions();

  GenerateViaDefinitions();

  GeneratePackages();

  GenerateSymbols();

  GenerateDevices();

  GenerateDummyDevices();

  printf("WRITE;\n");
  printf("CLOSE;\n");
}

void GeneratePCBHeader( void )
{
  string libraryName;

  printf("# ***** Board *****\n");

  string eagleFileName;
  string array[];

  sprintf( eagleFileName, "%s.brd", PCADfileName);

  if( fileglob( array, eagleFileName ) ) {
    printf("SET CONFIRM YES;\n");
    printf("REMOVE '%s';\n", eagleFileName );
    printf("SET CONFIRM OFF;\n");
  }

  printf("EDIT '%s';\n", eagleFileName );
  printf("DRC LOAD '%s';\n", DRUFileName );
  printf("SET WIRE_BEND 2;\n");

  libraryName = filesetext( PCADfileName, ".lbr");

  printf("USE -* '%s';\n", libraryName);
  printf("GRID %s;\n", FileUnits );
  printf("SET OPTIMIZING ON;\n");
  printf("SET CONFIRM YES;\n");
  printf("CHANGE FONT VECTOR;\n");
}

// This function generates one via

void GenerateVia( int startToken )
{
  int tokenPosition = FindToken( startToken + 1, "viaStyleRef" );

  if( tokenPosition >= 0 ) {
    printf("#viaStyleRef = %s\n", Tokens[ tokenPosition + 1 ] );

    string info;
    sprintf( info, "Process via %d %s", tokenPosition, Tokens[ tokenPosition + 1 ] );
    UpdateProgress( info );

    int ViaStyleDefNum = FindViaStyleDef( Tokens[ tokenPosition + 1 ] );

    if( ViaStyleDefNum >= 0 ) {
      if( ViaStyleDefsSkip[ ViaStyleDefNum ] == 0 ) {
        printf( "%s", ViaStyleDefsScript[ ViaStyleDefNum ] );

        int viaNetPosition = FindToken( startToken + 1, "netNameRef" );

        int ifSignalName = 0;

        if( viaNetPosition >= 0 ) {
          ifSignalName = 1;
        }

        int viaCoordPosition = FindToken( startToken + 1, "pt" );

        if( viaCoordPosition >= 0 ) {
          string xCoordVia = "";
          string yCoordVia = "";

          xCoordVia = Tokens[ viaCoordPosition + 1 ];

          if( IsASCIIValue( Tokens[ viaCoordPosition + 2 ] ) ) {
	    xCoordVia = xCoordVia + Tokens[ viaCoordPosition + 2 ];

	    if( Tokens[ viaCoordPosition + 3 ] != ")" ) {
	      yCoordVia = Tokens[ viaCoordPosition + 3 ];

	      if( Tokens[ viaCoordPosition + 4 ] != ")" ) {
	        yCoordVia = yCoordVia + Tokens[ viaCoordPosition + 4 ];
	      }
	    }
	    else {
	      WriteLog( "#warning: wront point description.\n" );
	    }
          }
          else {
	    yCoordVia = Tokens[ viaCoordPosition + 2 ];

	    if( Tokens[ viaCoordPosition + 3 ] != ")" ) {
	      yCoordVia = yCoordVia + Tokens[ viaCoordPosition + 3 ];
	    }
	  }

          string Val1 = ConvertUnits( GetNumberValue( xCoordVia ),
                                      GetUnitValue( xCoordVia ) );
          string Val2 = ConvertUnits( GetNumberValue( yCoordVia ),
                                      GetUnitValue( yCoordVia ) );

          if( ifSignalName ) {
            printf( "VIA '%s' %s %s (%s %s);\n",
              ReplaceNotSupportedCharacters( RemoveDoubleQuotas( Tokens[ viaNetPosition + 1 ] ) ),
              ViaStyleDefsDiameter[ ViaStyleDefNum ],
              ViaStyleDefsType[ ViaStyleDefNum ],
              Val1, Val2 );
          }
          else {
            printf( "VIA %s %s (%s %s);\n",
              ViaStyleDefsDiameter[ ViaStyleDefNum ],
              ViaStyleDefsType[ ViaStyleDefNum ],
              Val1, Val2 );
          }
        }
        else {
          string tmp;
          sprintf( tmp, "#WARNING: Can't find pt for via %s\n",
                   Tokens[ startToken + 3 ] );
          WriteLog( tmp );
        }
      }
      else {
        if( DebugMessage ) {
          printf("#skip this via\n");
        }
      }
    }
    else {
      string tmp;
      sprintf( tmp, "#WARNING: Can't find viaStyleDef for via %s\n",
              Tokens[ startToken + 3 ] );
      WriteLog( tmp );
    }
  }
  else {
    string tmp;
    sprintf( tmp, "#WARNING: Can't find viaStyleRef for via %s\n",
            Tokens[ startToken + 3 ] );
    WriteLog( tmp );
  }
}

int IfNameChanged = 0;
int IfValueChanged = 0;

void ChangeOneNameAndValue( string elemName, string attributeName, int startToken, string xCoord, string yCoord, string pureRotation )
{
  string xCoordText = "0.0";
  string yCoordText = "0.0";
  string rotation = "0";
  string isVisible = "False";
  string textStyleRef = "";
  string justify = "";
  int isFlipped = 0;

  CurrentToken = startToken;

  while( CurrentToken < TokensNumber ) {
    if( Tokens[ CurrentToken ] == "(" ) {
      CurrentToken++;

      if( Tokens[ CurrentToken ] == "pt" ) {
        xCoordText = Tokens[ CurrentToken + 1 ];

        if( IsASCIIValue( Tokens[ CurrentToken + 2 ] ) ) {
          xCoordText = xCoordText + Tokens[ CurrentToken + 2 ];

          if( Tokens[ CurrentToken + 3 ] != ")" ) {
            yCoordText = Tokens[ CurrentToken + 3 ];

            if( Tokens[ CurrentToken + 4 ] != ")" ) {
              yCoordText = yCoordText + Tokens[ CurrentToken + 4 ];
            }
          }
          else {
            WriteLog( "#warning: wront point description.\n" );
          }
        }
        else {
          yCoordText = Tokens[ CurrentToken + 2 ];

          if( Tokens[ CurrentToken + 3 ] != ")" ) {
            yCoordText = yCoordText + Tokens[ CurrentToken + 3 ];
          }
        }

        SkipThisItem();
      }
      else {
        if( Tokens[ CurrentToken ] == "rotation" ) {
          rotation = Tokens[ CurrentToken + 1 ];
          SkipThisItem();
        }
        else {
          if( Tokens[ CurrentToken ] == "isVisible" ) {
            isVisible = Tokens[ CurrentToken + 1 ];
            SkipThisItem();
          }
          else {
            if( Tokens[ CurrentToken ] == "textStyleRef" ) {
              textStyleRef = Tokens[ CurrentToken + 1 ];
              SkipThisItem();
            }
            else {
              if( Tokens[ CurrentToken ] == "isFlipped" ) {
                if( Tokens[ CurrentToken + 1 ] == "True" ) {
                  isFlipped = 1;
                }
                SkipThisItem();
              }
              else {
                if( Tokens[ CurrentToken ] == "justify" ) {
                  justify = Tokens[ CurrentToken + 1 ];
                  SkipThisItem();
                }
                else {
                  SkipThisItem();
                }
              }
            }
          }
        }
      }
    }
    else {
      if( Tokens[ CurrentToken ] == ")" ) {
        break;
      }
    }

    CurrentToken++;
  }


  real newXCoord = strtod( ConvertUnits( GetNumberValue( xCoord ), GetUnitValue( xCoord ) ) ) +
		   strtod( ConvertUnits( GetNumberValue( xCoordText ), GetUnitValue( xCoordText ) ) );

  real newYCoord = strtod( ConvertUnits( GetNumberValue( yCoord ), GetUnitValue( yCoord ) ) ) +
		   strtod( ConvertUnits( GetNumberValue( yCoordText ), GetUnitValue( yCoordText ) ) );

  printf( "MOVE '%s>%s' (%f %f);\n", elemName, attributeName, newXCoord, newYCoord );

  real finalRotation = strtod( pureRotation );

  string mirrored = "";

  if( isFlipped ) {
     mirrored = "M";
  }

  printf( "ROTATE =S%sR%s '%s>%s';\n", mirrored, rotation, elemName, attributeName );

  if( justify == "" ) { //LowerLeft
    printf("CHANGE ALIGN BOTTOM LEFT;\n");
  } else if( justify == "UpperLeft" ) {
    printf("CHANGE ALIGN TOP LEFT;\n");
  } else if( justify == "UpperCenter" ) {
    printf("CHANGE ALIGN TOP CENTER;\n");
  } else if( justify == "UpperRight" ) {
    printf("CHANGE ALIGN TOP RIGHT;\n");
  } else if( justify == "Left" ) {
    printf("CHANGE ALIGN CENTER LEFT;\n");
  } else if( justify == "Center" ) {
    printf("CHANGE ALIGN CENTER CENTER;\n");
  } else if( justify == "Right" ) {
    printf("CHANGE ALIGN CENTER RIGHT;\n");
  } else if( justify == "LowerLeft" ) {
    printf("CHANGE ALIGN BOTTOM LEFT;\n");
  } else if( justify == "LowerCenter" ) {
    printf("CHANGE ALIGN BOTTOM CENTER;\n");
  } else if( justify == "LowerRight" ) {
    printf("CHANGE ALIGN BOTTOM RIGHT;\n");
  }
  else {
    string tmp;
    printf( tmp, "# warning: unknown justify parameter value = %s\n", justify );
    WriteLog( tmp );

    printf("CHANGE ALIGN BOTTOM LEFT;\n");
  }

  int textStyleDefPos = FindTextStyleDef( textStyleRef );

  if( textStyleDefPos >= 0 ) {
    real fontHeight = strtod( ConvertUnits( GetNumberValue( TextStyleDefFontHeight[ textStyleDefPos ] ), GetUnitValue(  TextStyleDefFontHeight[ textStyleDefPos ] ) ) );
    real fontWidth = strtod( ConvertUnits( GetNumberValue( TextStyleDefFontStrokeWidth[ textStyleDefPos ] ), GetUnitValue( TextStyleDefFontStrokeWidth[ textStyleDefPos ] ) ) );

    printf("CHANGE SIZE %s (%f %f);\n", TextStyleDefFontHeight[ textStyleDefPos ], newXCoord, newYCoord );

    if( fontHeight ) {
      int ratio = round( 100.0 * fontWidth / fontHeight );

      if( ratio > 31.0 ) {
	ratio = 31.0;
      }

      printf("CHANGE RATIO %d (%f %f);\n", ratio, newXCoord, newYCoord );
    }
  }

  if( isVisible != "True" ) {
    printf( "CHANGE DISPLAY OFF (%f %f);\n", newXCoord, newYCoord );
  }
  else {
    printf( "CHANGE DISPLAY VALUE (%f %f);\n", newXCoord, newYCoord );
  }
}

void ChangeNameAndValuePosition( string elemName, int patternGraphicsRef, string xCoord, string yCoord, string pureRotation )
{
  //printf("SMASH '%s';\n", elemName );

  CurrentToken = patternGraphicsRef + 1;

  while( CurrentToken < TokensNumber ) {
    if( Tokens[ CurrentToken ] == "(" ) {
      CurrentToken++;

      if( Tokens[ CurrentToken ] == "attr" ) {
        if( Tokens[ CurrentToken + 1 ] == "\"RefDes\"" ) {
          int SavePosition = CurrentToken;
          ChangeOneNameAndValue( elemName, "NAME", CurrentToken + 3, xCoord, yCoord, pureRotation );
          IfNameChanged = 1;
          CurrentToken = SavePosition;
        }

        if( Tokens[ CurrentToken + 1 ] == "\"Value\"" ) {
          int SavePosition = CurrentToken;
          ChangeOneNameAndValue( elemName, "VALUE", CurrentToken + 3, xCoord, yCoord, pureRotation );
          IfValueChanged = 1;
          CurrentToken = SavePosition;
        }

        SkipThisItem();
      }
      else {
        SkipThisItem();
      }
    }
    else {
      if( Tokens[ CurrentToken ] == ")" ) {
        break;
      }
    }

    CurrentToken++;
  }
}

int FindPatternGraphisRef( int startToken )
{
  int patternGraphicsNameRefToken = FindToken( startToken + 1, "patternGraphicsNameRef" );

  if( patternGraphicsNameRefToken >= 0 ) {
    string patternGraphicsNameRef = RemoveDoubleQuotas( Tokens[ patternGraphicsNameRefToken + 1 ] );

    CurrentToken = startToken + 1;

    while( CurrentToken < TokensNumber ) {
      if( Tokens[ CurrentToken ] == "(" ) {
        CurrentToken++;

        if( Tokens[ CurrentToken ] == "patternGraphicsRef" ) {
          int SavePosition = CurrentToken;
          int nameRefToken = FindToken( CurrentToken + 1, "patternGraphicsNameRef" );
          CurrentToken = SavePosition;

          if( nameRefToken >= 0 ) {
            string name = RemoveDoubleQuotas( Tokens[ nameRefToken + 1 ] );

            if( name == patternGraphicsNameRef ) {
              return( SavePosition );
            }
          }

          SkipThisItem();
        }
        else {
          SkipThisItem();
        }
      }
      else {
        if( Tokens[ CurrentToken ] == ")" ) {
          return( -1 );
        }
      }

      CurrentToken++;
    }
  }

  return( FindToken( startToken + 1, "patternGraphicsRef" ) );
}

// This function generates one component

void GeneratePattern( int startToken )
{
  int patternRefPosition = FindToken( startToken + 1, "patternRef" );

  if( patternRefPosition >= 0 ) {
    printf("#patternRef = %s\n", Tokens[ patternRefPosition + 1 ] );

    string info;
    sprintf( info, "Process pattern %d %s", patternRefPosition, Tokens[ patternRefPosition + 1 ] );
    UpdateProgress( info );

    int refDesRefPosition = FindToken( startToken + 1, "refDesRef" );

    if( refDesRefPosition >= 0 ) {
      string RotationMirrored = "";

      int mirrored = FindToken( startToken + 1, "isFlipped" );

      if( mirrored >= 0 ) {
        RotationMirrored = "M";
      }

      int rotationPosition = FindToken( startToken + 1, "rotation" );

      string pureRotation = "0.0";

      if( rotationPosition >= 0 ) {
        pureRotation =  Tokens[ rotationPosition + 1 ];
        RotationMirrored = RotationMirrored + "R" + Tokens[ rotationPosition + 1 ];
      }
      else {
        RotationMirrored = RotationMirrored + "R0";
      }

      int patternPosition = FindToken( startToken + 1, "pt" );

      if( patternPosition >= 0 ) {
        string xCoordPattern = "";
        string yCoordPattern = "";

        xCoordPattern = Tokens[ patternPosition + 1 ];

        if( IsASCIIValue( Tokens[ patternPosition + 2 ] ) ) {
	  xCoordPattern = xCoordPattern + Tokens[ patternPosition + 2 ];

	  if( Tokens[ patternPosition + 3 ] != ")" ) {
	    yCoordPattern = Tokens[ patternPosition + 3 ];

	    if( Tokens[ patternPosition + 4 ] != ")" ) {
	      yCoordPattern = yCoordPattern + Tokens[ patternPosition + 4 ];
	    }
	  }
	  else {
	    WriteLog( "#warning: wront point description.\n" );
	  }
        }
        else {
	  yCoordPattern = Tokens[ patternPosition + 2 ];

	  if( Tokens[ patternPosition + 3 ] != ")" ) {
	    yCoordPattern = yCoordPattern + Tokens[ patternPosition + 3 ];
	  }
        }

        string Val1 = ConvertUnits( GetNumberValue( xCoordPattern ),
                                    GetUnitValue( xCoordPattern ) );
        string Val2 = ConvertUnits( GetNumberValue( yCoordPattern ),
                                    GetUnitValue( yCoordPattern ) );

        string patternDefName = ReplaceNotSupportedCharacters( RemoveDoubleQuotas( Tokens[ patternRefPosition + 1 ] ) );
        string elemName = ReplaceNotSupportedCharacters( RemoveDoubleQuotas( Tokens[ refDesRefPosition + 1 ] ) );

        int patternGraphicsNameRefToken = FindToken( startToken + 1, "patternGraphicsNameRef" );

        string variantName = "";

        if( patternGraphicsNameRefToken >= 0 ) {
          variantName = ReplaceNotSupportedCharacters( RemoveDoubleQuotas( Tokens[ patternGraphicsNameRefToken + 1 ] ) );
        }

        if( RotationMirrored != "" ) {
          printf( "ADD '%s%s' '%s' %s (%s %s);\n",
                patternDefName,
                variantName,
                elemName,
                RotationMirrored,
                Val1, Val2 );
        }
        else {
          printf( "ADD '%s%s' '%s' (%s %s);\n",
                patternDefName,
                variantName,
                elemName,
                Val1, Val2 );
        }

        string value = FindCompValue( elemName );

        if( value != "" ) {
          printf( "VALUE '%s' '%s';\n", elemName, value );
        }

        int patternGraphicsRef = FindPatternGraphisRef( startToken );

        if( patternGraphicsRef >= 0 ) {
          int SavePosition = CurrentToken;

          int index = FindPatternDefIndexByName( patternDefName, variantName );

          AddAttributes( 0, index, elemName, patternGraphicsRef, Val1, Val2 );
          CurrentToken = SavePosition;
          printf("SMASH '%s';\n", elemName );

          IfNameChanged = 0;
          IfValueChanged = 0;

          ChangeNameAndValuePosition( elemName, patternGraphicsRef, Val1, Val2, pureRotation );

          if( index >= 0 ) {
            if( IfNameDefinedInPattern[ index ] ) {
              if( !IfNameChanged ) {
                printf( "DELETE '%s>NAME';\n", elemName );
              }
            }

            if( IfValueDefinedInPattern[ index ] ) {
              if( !IfValueChanged ) {
                printf( "DELETE '%s>VALUE';\n", elemName );
              }
            }
          }
          else {
            string tmp;
            sprintf( tmp, "# warning: can't find index for pattern %s\n", patternDefName );
            WriteLog( tmp );
          }

          CurrentToken = SavePosition;
        }
        else {
          int SavePosition = CurrentToken;

          int index = FindPatternDefIndexByName( patternDefName, "" );

          AddAttributes( 0, index, elemName, startToken, Val1, Val2 );
          CurrentToken = SavePosition;
          printf("SMASH '%s';\n", elemName );

          ChangeNameAndValuePosition( elemName, startToken, Val1, Val2, pureRotation );

          if( index >= 0 ) {
            if( IfNameDefinedInPattern[ index ] ) {
              if( !IfNameChanged ) {
                printf( "DELETE '%s>NAME';\n", elemName );
              }
            }

            if( IfValueDefinedInPattern[ index ] ) {
              if( !IfValueChanged ) {
                printf( "DELETE '%s>VALUE';\n", elemName );
              }
            }
          }
          else {
            string tmp;
            sprintf( tmp, "# warning: can't find index for pattern %s\n", patternDefName );
            WriteLog( tmp );
          }

          CurrentToken = SavePosition;
        }
      }
      else {
        string tmp;
        printf( tmp, "#warning: Can't find pattern coordinates %s\n",
                Tokens[ patternRefPosition + 1 ] );
        WriteLog( tmp );
      }
    }
    else {
      WriteLog("#warning: can't find pattern design name\n");
    }
  }
  else {
    WriteLog("#warning: Can't find pattern reference.\n");
  }
}

string FindNodePadName( string nodeElementName, string nodePadName )
{
  string compDefName = FindSymbolDeviceName( nodeElementName );

  if( compDefName != "" ) {
    for( int i = 0; i < CompDefsNumber; i++ ) {
      int startToken = CompDefsArray[ i ];

      string DeviceName = ReplaceNotSupportedCharacters( RemoveDoubleQuotas(
                                                         Tokens[ startToken ] )
                                                         );

      if( DeviceName == compDefName ) {
        int padMapIndex = PadPinMapRef[ i ];

        for( int j = 0; j < PadPinMapCount[ i ]; j++ ) {
          if( nodePadName == PadPinMapPinRef[ padMapIndex ] ) {
            return( PadPinMapNum[ padMapIndex ] );
          }

          padMapIndex++;
        }
      }
    }
  }

  return( "" );
}

void GenerateSignals( void )
{
  for( int i = 0; i < NrNets; i++ ) {
    int node = NodeRef[ i ];

    for( int j = 0; j < NrNetNodes[ i ]; j++ ) {
      string nodePadName = FindNodePadName( NodeElementName[ node ], NodePadName[ node ] );

      if( nodePadName != "" ) {
        printf( "SIGNAL %s %s %s;\n", NetNames[ i ], NodeElementName[ node ], nodePadName );
        node++;
      }
      else {
        string tmp;
        sprintf( tmp, "# warning: NodePadName not found %s %s\n", NodeElementName[ node ], NodePadName[ node ] );
        WriteLog( tmp );
      }
    }
  }
}

void GenerateOneDummyPattern( int startToken, int dummyPatternCount )
{
    int padStyleRefPosition = FindToken( startToken + 1, "padStyleRef" );

    if( padStyleRefPosition >= 0 ) {
      string DeviceName = ReplaceNotSupportedCharacters( RemoveDoubleQuotas(
                                                         Tokens[ padStyleRefPosition + 1 ] )
                                                         );

      CurrentToken = FindToken( startToken + 1, "pt" );

      if( CurrentToken >= 0 ) {
        string xCoordText;
        string yCoordText;

        xCoordText = Tokens[ CurrentToken + 1 ];

        if( IsASCIIValue( Tokens[ CurrentToken + 2 ] ) ) {
          xCoordText = xCoordText + Tokens[ CurrentToken + 2 ];

          if( Tokens[ CurrentToken + 3 ] != ")" ) {
            yCoordText = Tokens[ CurrentToken + 3 ];

            if( Tokens[ CurrentToken + 4 ] != ")" ) {
              yCoordText = yCoordText + Tokens[ CurrentToken + 4 ];
            }
          }
          else {
            WriteLog( "#warning: wront point description.\n" );
          }
        }
        else {
          yCoordText = Tokens[ CurrentToken + 2 ];

          if( Tokens[ CurrentToken + 3 ] != ")" ) {
            yCoordText = yCoordText + Tokens[ CurrentToken + 3 ];
          }
        }

        printf( "ADD '%s' 'DUMMY%d' (%s %s);\n",
                 ReplaceNotSupportedCharacters( RemoveDoubleQuotas( Tokens[ padStyleRefPosition + 1 ] ) ),
                 dummyPatternCount,
                 xCoordText, yCoordText );
      }
      else {
        WriteLog("# warning: GenerateOneDummyPattern: can't find point in dummy device.\n");
      }
    }
    else {
      WriteLog("# warning: GenerateOneDummyPattern: can't find padStyleRef in dummy device.\n");
    }

}

void GeneratePCBMultilayer( void )
{
  int dummyPatternCount = 1;

  if( PCBDesignMultiLayerToken ) {
    CurrentToken = PCBDesignMultiLayerToken;

    while( CurrentToken < TokensNumber ) {
      if( Tokens[ CurrentToken ] == "(" ) {
        CurrentToken++;

        if( Tokens[ CurrentToken ] == "pad" ) {
          int SavePosition = CurrentToken;
          GenerateOneDummyPattern( SavePosition, dummyPatternCount );
          CurrentToken = SavePosition;
          dummyPatternCount++;
          SkipThisItem();
        }
        else {
          if( Tokens[ CurrentToken ] == "via" ) {
            int SavePosition = CurrentToken;

            GenerateVia( SavePosition );

            CurrentToken = SavePosition;

            SkipThisItem();
          }
          else {
            if( Tokens[ CurrentToken ] == "pattern" ) {
              int SavePosition = CurrentToken;

              GeneratePattern( SavePosition );

              CurrentToken = SavePosition;

              SkipThisItem();
            }
            else {
              if( Tokens[ CurrentToken ] == "fromTo" ) {
                SkipThisItem();
              }
              else {
                string tmp;
                sprintf( tmp, "# warning: GeneratePCBMultilayer unknown keyword: %s\n",  Tokens[ CurrentToken ] );
                WriteLog( tmp );
                SkipThisItem();
              }
            }
          }
        }
      }
      else {
        if( Tokens[ CurrentToken ] == ")" ) {
          break;
        }
        else {
          dlgMessageBox( "Unexpected keyword in pcbDesign multiLayer " + Tokens[ CurrentToken ], "OK");
          return;
        }
      }

      CurrentToken++;
    }
  }
  else {
    WriteLog( "# warning: no multilayer token in pcbDesign\n");
  }

  GenerateSignals();
}

void GeneratePCBLayerContents( void )
{
  for( int i = 0; i < NrPCBLayerContents; i++ ) {
    int startToken = PCBLayerContentsArray[ i ];

    GenerateLayerContents( startToken, -1 );
  }
}

// Generate PCB from 'pcbDesign' keyword

void GeneratePCB( void )
{
  GeneratePCBHeader();

  GeneratePCBMultilayer();

  GeneratePCBLayerContents();

  printf("WINDOW FIT;\n");
  printf("SET CONFIRM OFF;\n");
}

void GenerateSchematicHeader( void )
{
  string libraryName;

  printf("# ***** Schematic *****\n");

  string eagleFileName;
  string array[];

  sprintf( eagleFileName, "%s.eagle.sch", PCADfileName);

  if( fileglob( array, eagleFileName ) ) {
    printf("SET CONFIRM YES;\n");
    printf("REMOVE '%s';\n", eagleFileName );
    printf("SET CONFIRM OFF;\n");
  }

  printf("EDIT '%s';\n", eagleFileName );

  libraryName = filesetext( PCADfileName, ".lbr");

  printf("USE -* '%s';\n", libraryName);
  printf("GRID %s;\n", FileUnits );
  //printf("SET OPTIMIZING ON;\n");
  printf("SET CONFIRM YES;\n");
  printf("SET AUTO_JUNCTION OFF;\n");
  printf("SET CHECK_CONNECTS OFF;\n");
  printf("SET WIRE_BEND 2;\n");
  printf("CHANGE FONT VECTOR;\n");
}

void GenerateOneSheetSymbol( int startToken )
{
  int symbolRefPosition = FindToken( startToken + 1, "symbolRef" );

  if( symbolRefPosition >= 0 ) {
    //printf("#symbolRef = %s\n", Tokens[ symbolRefPosition + 1 ] );

    string info;
    sprintf( info, TR("Process symbolref ")  + " %d %s", symbolRefPosition, Tokens[ symbolRefPosition + 1 ] );
    UpdateProgress( info );

    int refDesRefPosition = FindToken( startToken + 1, "refDesRef" );

    if( refDesRefPosition >= 0 ) {
      string refDesRef = ReplaceNotSupportedCharacters( RemoveDoubleQuotas( Tokens[ refDesRefPosition + 1 ] ) );

      printf("#refDesRef = %s\n", Tokens[ refDesRefPosition + 1 ] );

      string RotationMirrored = "";

      int mirrored = FindToken( startToken + 1, "isFlipped" );

      if( mirrored >= 0 ) {
        RotationMirrored = "M";
      }

      int rotationPosition = FindToken( startToken + 1, "rotation" );

      if( rotationPosition >= 0 ) {
        RotationMirrored = RotationMirrored + "R" + Tokens[ rotationPosition + 1 ];
      }
      else {
        RotationMirrored = RotationMirrored + "R0";
      }

      string partNum = "";

      int partNumPosition = FindToken( startToken + 1, "partNum" );

      if( partNumPosition >= 0 ) {
        partNum = Tokens[ partNumPosition + 1 ];
      }

      int patternPosition = FindToken( startToken + 1, "pt" );

      if( patternPosition >= 0 ) {
        string DeviceName = FindSymbolDeviceName( refDesRef );

        if( DeviceName != "" ) {
          string vtText = "";

          CurrentToken = startToken + 1;

          while( CurrentToken < TokensNumber ) {
            if( Tokens[ CurrentToken ] == "(" ) {
              CurrentToken++;

              if( Tokens[ CurrentToken ] == "attr" ) {
                string type = RemoveDoubleQuotas( Tokens[ CurrentToken + 1 ] );

                if( ( type == "VT" ) || ( type == "Vt" ) ) {
                  vtText = FindText( CurrentToken + 1 );

                  break;
                }

  	        SkipThisItem();
              }
              else {
                SkipThisItem();
              }
            }
            else {
              if( Tokens[ CurrentToken ] == ")" ) {
	        break;
              }
            }

            CurrentToken++;
          }

	  string xCoordPattern = "";
	  string yCoordPattern = "";

	  xCoordPattern = Tokens[ patternPosition + 1 ];

	  if( IsASCIIValue( Tokens[ patternPosition + 2 ] ) ) {
	    xCoordPattern = xCoordPattern + Tokens[ patternPosition + 2 ];

	    if( Tokens[ patternPosition + 3 ] != ")" ) {
	      yCoordPattern = Tokens[ patternPosition + 3 ];

	      if( Tokens[ patternPosition + 4 ] != ")" ) {
		yCoordPattern = yCoordPattern + Tokens[ patternPosition + 4 ];
	      }
	    }
	    else {
	      WriteLog( "#warning: wront point description.\n" );
	    }
	  }
	  else {
	    yCoordPattern = Tokens[ patternPosition + 2 ];

	    if( Tokens[ patternPosition + 3 ] != ")" ) {
	      yCoordPattern = yCoordPattern + Tokens[ patternPosition + 3 ];
	    }
	  }

	  string Val1 = ConvertUnits( GetNumberValue( xCoordPattern ),
				      GetUnitValue( xCoordPattern ) );
	  string Val2 = ConvertUnits( GetNumberValue( yCoordPattern ),
				      GetUnitValue( yCoordPattern ) );

          if( strtol( partNum ) > 1 ) {
            printf( "ADD '%s' '%sG%s' 'G%s' %s (%s %s);\n",
                  DeviceName,
                  refDesRef,
                  partNum,
                  partNum,
                  RotationMirrored,
                  Val1, Val2 );

            string tmp;

            sprintf( tmp, "%sG%sG%s", refDesRef, partNum, partNum );

            int SavePosition = CurrentToken;

            string symbolDefName = ReplaceNotSupportedCharacters( RemoveDoubleQuotas( Tokens[ symbolRefPosition + 1 ] ) );

            int index = FindSymbolIndexByName( symbolDefName );

            AddAttributes( 1, index, tmp, startToken, Val1, Val2 );
            CurrentToken = SavePosition;
            printf("SMASH (%s %s);\n", Val1, Val2 );

            IfNameChanged = 0;
            IfValueChanged = 0;

            ChangeNameAndValuePosition( tmp, startToken, Val1, Val2, Tokens[ rotationPosition + 1 ] );

            if( index >= 0 ) {
              if( IfNameDefinedInSymbol[ index ] ) {
                if( !IfNameChanged ) {
                  printf( "DELETE '%s>NAME';\n", tmp );
                }
              }

              if( IfValueDefinedInSymbol[ index ] ) {
                if( !IfValueChanged ) {
                  printf( "DELETE '%s>VALUE';\n", tmp );
                }
              }
            }
            else {
              string tmp;
              sprintf( tmp, "# warning: can't find index for symbol %s\n", symbolDefName );
              WriteLog( tmp );
            }

            CurrentToken = SavePosition;
          }
          else {
            printf( "ADD '%s' '%s' 'G%s' %s (%s %s);\n",
                  DeviceName,
                  refDesRef,
                  partNum,
                  RotationMirrored,
                  Val1, Val2 );

            string tmp;

            sprintf( tmp, "%sG%s", refDesRef, partNum );

            int SavePosition = CurrentToken;

            string symbolDefName = ReplaceNotSupportedCharacters( RemoveDoubleQuotas( Tokens[ symbolRefPosition + 1 ] ) );

            int index = FindSymbolIndexByName( symbolDefName );

            AddAttributes( 1, index, tmp, startToken, Val1, Val2 );
            CurrentToken = SavePosition;
            printf("SMASH (%s %s);\n", Val1, Val2 );

            IfNameChanged = 0;
            IfValueChanged = 0;

            ChangeNameAndValuePosition( tmp, startToken, Val1, Val2, Tokens[ rotationPosition + 1 ] );

            if( index >= 0 ) {
              if( IfNameDefinedInSymbol[ index ] ) {
                if( !IfNameChanged ) {
                  printf( "DELETE '%s>NAME';\n", tmp );
                }
              }

              if( IfValueDefinedInSymbol[ index ] ) {
                if( !IfValueChanged ) {
                  printf( "DELETE '%s>VALUE';\n", tmp );
                }
              }
            }
            else {
              string tmp;
              sprintf( tmp, "# warning: can't find index for symbol %s\n", symbolDefName );
              WriteLog( tmp );
            }

            CurrentToken = SavePosition;
          }
        }
        else {
          WriteLog("#warning: no DeviceName found.\n" );
        }
      }
      else {
        string tmp;
        printf( tmp, "#warning: Can't find pattern coordinates %s\n",
                Tokens[ symbolRefPosition + 1 ] );
        WriteLog( tmp );
      }
    }
    else {
      WriteLog("#warning: can't find symbol design name\n");
    }
  }
  else {
    WriteLog("#warning: Can't find symbol reference.\n");
  }
}

void GenerateTitleSheet( void )
{
  if( SchTitleSheet ) {
    CurrentToken = SchTitleSheet;

    CurrentToken++;
    CurrentToken++;

    while( CurrentToken < TokensNumber ) {
      if( Tokens[ CurrentToken ] == "(" ) {
        CurrentToken++;

        if( Tokens[ CurrentToken ] == "isVisible" ) {
          SkipThisItem();
        }
        else {
          if( Tokens[ CurrentToken ] == "border" ) {
            int SavePosition = CurrentToken;
            //GenerateBorder( SavePosition );
            CurrentToken = SavePosition;
            SkipThisItem();
          }
          else {
            if( Tokens[ CurrentToken ] == "zones" ) {
              int SavePosition = CurrentToken;
              //GenerateZones( SavePosition ); FixMe
              CurrentToken = SavePosition;
              SkipThisItem();
            }
            else {
              if( Tokens[ CurrentToken ] == "offset" ) {
                SkipThisItem();
              }
              else {
                if( Tokens[ CurrentToken ] == "line" ) {
                  int SavePosition = CurrentToken;
                  GenerateOneLine( SavePosition, 0, 0 );
                  CurrentToken = SavePosition;
                  SkipThisItem();
                }
                else {
                  if( Tokens[ CurrentToken ] == "field" ) {
                    SkipThisItem();
                  }
                  else {
                    if( Tokens[ CurrentToken ] == "poly" ) {
                      int SavePosition = CurrentToken;
                      GenerateOnePcbPoly( SavePosition, 0, DEFAULT_WIRE_WIDTH_BOARD );
                      CurrentToken = SavePosition;
                      SkipThisItem();
                    }
                    else {
                      if( Tokens[ CurrentToken ] == "text" ) {
                        int SavePosition = CurrentToken;
                        GenerateOneText( SavePosition );
                        CurrentToken = SavePosition;
                        SkipThisItem();
                      }
                      else {
                        if( Tokens[ CurrentToken ] == "triplePointArc" ) {
                          int SavePosition = CurrentToken;
                          GenerateOneTripleArc( SavePosition );
                          CurrentToken = SavePosition;
                          SkipThisItem();
                        }
                        else {
                          if( DebugMessage ) {
                            printf( "# ????? GenerateTitleSheet unknown keyword: %s\n",  Tokens[ CurrentToken ] );
                          }
                          SkipThisItem();
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
      else {
        if( Tokens[ CurrentToken ] == ")" ) {
          break;
        }
        else {
          dlgMessageBox( TR("Unexpected keyword in GenerateTitleSheet: ") + Tokens[ CurrentToken ], "OK");
          return;
        }
      }

      CurrentToken++;
    }
  }
  else {
    WriteLog( "# warning: no titleSheet token in schematicDesign\n");
  }
}

void GenerateOnePort( int startToken )
{
  string type;
  string netNameRef;
  string isFlipped;
  string xCoordText;
  string yCoordText;
  string rotation = "0";

  CurrentToken = startToken + 1;

  while( CurrentToken < TokensNumber ) {
    if( Tokens[ CurrentToken ] == "(" ) {
      CurrentToken++;

      if( Tokens[ CurrentToken ] == "pt" ) {
        xCoordText = Tokens[ CurrentToken + 1 ];

        if( IsASCIIValue( Tokens[ CurrentToken + 2 ] ) ) {
          xCoordText = xCoordText + Tokens[ CurrentToken + 2 ];

          if( Tokens[ CurrentToken + 3 ] != ")" ) {
            yCoordText = Tokens[ CurrentToken + 3 ];

            if( Tokens[ CurrentToken + 4 ] != ")" ) {
              yCoordText = yCoordText + Tokens[ CurrentToken + 4 ];
            }
          }
          else {
            WriteLog( "#warning: wront point description.\n" );
          }
        }
        else {
          yCoordText = Tokens[ CurrentToken + 2 ];

          if( Tokens[ CurrentToken + 3 ] != ")" ) {
            yCoordText = yCoordText + Tokens[ CurrentToken + 3 ];
          }
        }

        SkipThisItem();
      }
      else {
        if( Tokens[ CurrentToken ] == "portType" ) {
          type = Tokens[ CurrentToken + 1 ];
          SkipThisItem();
        }
        else {
          if( Tokens[ CurrentToken ] == "netNameRef" ) {
            netNameRef = ReplaceNotSupportedCharacters( RemoveDoubleQuotas( Tokens[ CurrentToken + 1 ] ) );
            SkipThisItem();
          }
          else {
            if( Tokens[ CurrentToken ] == "isFlipped" ) {
              isFlipped = Tokens[ CurrentToken + 1 ];
              SkipThisItem();
            }
            else {
              if( Tokens[ CurrentToken ] == "portPinLength" ) {
                isFlipped = Tokens[ CurrentToken + 1 ];
                SkipThisItem();
              }
              else {
                if( Tokens[ CurrentToken ] == "rotation" ) {
                  rotation = Tokens[ CurrentToken + 1 ];
                  SkipThisItem();
                }
                else {
                  if( DebugMessage ) {
                    printf( "# GenerateOnePort ??????? %s\n",  Tokens[ CurrentToken ] );
                  }
                  SkipThisItem();
                }
              }
            }
          }
        }
      }
    }
    else {
      if( Tokens[ CurrentToken ] == ")" ) {
        break;
      }
    }

    CurrentToken++;
  }

  XCoordLabels[ NrLabels ] = xCoordText;
  YCoordLabels[ NrLabels ] = yCoordText;
  TypeLabels[ NrLabels ] = type;
  NetNameRef[ NrLabels ] = netNameRef;
  IsLabelFlipped[ NrLabels ] = isFlipped;
  LabelRotation[ NrLabels ] = rotation;

  NrLabels++;
}

void GenerateSheets( void )
{
  printf("# Sheets:\n");

  for( int i = 0; i < NrSheets; i++ ) {
    int startToken = SheetsArray[ i ];

    int junctions[];
    int NrJunctions = 0;

    NrLabels = 0;
    NrWiresPoint = 0;

    int buses[];
    int NrBuses = 0;

    string info;
    sprintf( info, TR("Process sheet ") + " %d (%d)", i, NrSheets );
    UpdateProgress( info );

    string sheetName = ReplaceNotSupportedCharacters( RemoveDoubleQuotas(
                                                     Tokens[ startToken ] )
                                                    );

    int sheetNumberToken = FindToken( startToken + 1, "sheetNum" );

    string sheetNumber;

    sprintf( sheetNumber, "%d", i + 1 );

    if( sheetNumberToken >= 0 ) {
      sheetNumber = Tokens[ sheetNumberToken + 1 ];
    }
    else {
      WriteLog( "# warning: no sheet number.\n" );
    }

    printf("#\n");
    printf("# sheet: %s %s\n", sheetName, sheetNumber );

    printf("EDIT '.S%s'\n", sheetNumber );
    printf("GRID %s;\n", FileUnits );

    GenerateTitleSheet();

    printf( "CHANGE LAYER 91;\n" );

    CurrentToken = startToken + 1;

    while( CurrentToken < TokensNumber ) {
      if( Tokens[ CurrentToken ] == "(" ) {
        CurrentToken++;

        if( Tokens[ CurrentToken ] == "sheetNum" ) {
          SkipThisItem();
        }
        else {
          if( Tokens[ CurrentToken ] == "fieldSetRef" ) {
            SkipThisItem();
          }
          else {
            if( Tokens[ CurrentToken ] == "junction" ) {
              junctions[ NrJunctions ] = CurrentToken + 1;
              NrJunctions++;
              SkipThisItem();
            }
            else {
              if( Tokens[ CurrentToken ] == "symbol" ) {
                int SavePosition = CurrentToken;
                GenerateOneSheetSymbol( SavePosition );
                CurrentToken = SavePosition;
                SkipThisItem();
              }
              else {
                if( Tokens[ CurrentToken ] == "wire" ) {
                  int SavePosition = CurrentToken;
                  GenerateOneLine( SavePosition + 2, 1, 0 );
                  CurrentToken = SavePosition;
                  SkipThisItem();
                }
                else {
                  if( Tokens[ CurrentToken ] == "text" ) {
                    int SavePosition = CurrentToken;
                    GenerateOneText( SavePosition );
                    CurrentToken = SavePosition;
                    SkipThisItem();
                  }
                  else {
                    if( Tokens[ CurrentToken ] == "triplePointArc" ) {
                      int SavePosition = CurrentToken;
                      GenerateOneTripleArc( SavePosition );
                      CurrentToken = SavePosition;
                      SkipThisItem();
                    }
                    else {
                      if( Tokens[ CurrentToken ] == "port" ) {
                        int SavePosition = CurrentToken;
                        GenerateOnePort( SavePosition );
                        CurrentToken = SavePosition;
                        SkipThisItem();
                      }
                      else {
                        if( Tokens[ CurrentToken ] == "line" ) {
                          int SavePosition = CurrentToken;
                          GenerateOneLine( SavePosition, 0, 0 );
                          CurrentToken = SavePosition;
                          SkipThisItem();
                        }
                        else {
                          if( Tokens[ CurrentToken ] == "bus" ) {
                            //int SavePosition = CurrentToken;
                            //GenerateOneBus( SavePosition );
                            buses[ NrBuses ] = CurrentToken;
                            NrBuses++;
                            //CurrentToken = SavePosition;
                            SkipThisItem();
                          }
                          else {
                            if( Tokens[ CurrentToken ] == "drawBorder" ) {
                              SkipThisItem();
                            }
                            else {
                              if( Tokens[ CurrentToken ] == "EntireDesign" ) {
                                SkipThisItem();
                              }
                              else {
                                if( Tokens[ CurrentToken ] == "isRotated" ) {
                                  SkipThisItem();
                                }
                                else {
                                  if( Tokens[ CurrentToken ] == "pageSize" ) {
                                    SkipThisItem();
                                  }
                                  else {
                                    if( Tokens[ CurrentToken ] == "scaleFactor" ) {
                                      SkipThisItem();
                                    }
                                    else {
                                      if( Tokens[ CurrentToken ] == "offset" ) {
                                        SkipThisItem();
                                      }
                                      else {
                                        if( Tokens[ CurrentToken ] == "PrintRegion" ) {
                                          SkipThisItem();
                                        }
                                        else {
                                          if( Tokens[ CurrentToken ] == "sheetOrderNum" ) {
                                            SkipThisItem();
                                          }
                                          else {
                                            if( Tokens[ CurrentToken ] == "busEntry" ) {
                                              SkipThisItem();
                                            }
                                            else {
                                              if( DebugMessage ) {
                                                printf( "# GenerateSheets ??????? %s\n",  Tokens[ CurrentToken ] );
                                              }
                                              SkipThisItem();
                                            }
                                          }
                                        }
                                      }
                                    }
                                  }
                                }
                              }
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
      else {
        if( Tokens[ CurrentToken ] == ")" ) {
          for( int j = 0; j < NrJunctions; j++ ) {
            int CurrentToken = junctions[ j ];

            int junctionPt = FindToken( CurrentToken, "pt" );

            if( junctionPt >= 0 ) {
	      string xCoordPattern = "";
	      string yCoordPattern = "";

	      xCoordPattern = Tokens[ junctionPt + 1 ];

	      if( IsASCIIValue( Tokens[ junctionPt + 2 ] ) ) {
		xCoordPattern = xCoordPattern + Tokens[ junctionPt + 2 ];

		if( Tokens[ junctionPt + 3 ] != ")" ) {
		  yCoordPattern = Tokens[ junctionPt + 3 ];

		  if( Tokens[ junctionPt + 4 ] != ")" ) {
		    yCoordPattern = yCoordPattern + Tokens[ junctionPt + 4 ];
		  }
		}
		else {
		  WriteLog( "#warning: wront point description.\n" );
		}
	      }
	      else {
		yCoordPattern = Tokens[ junctionPt + 2 ];

		if( Tokens[ junctionPt + 3 ] != ")" ) {
		  yCoordPattern = yCoordPattern + Tokens[ junctionPt + 3 ];
		}
	      }

	      string Val1 = ConvertUnits( GetNumberValue( xCoordPattern ),
					  GetUnitValue( xCoordPattern ) );
	      string Val2 = ConvertUnits( GetNumberValue( yCoordPattern ),
					  GetUnitValue( yCoordPattern ) );

              printf( "JUNCTION (%s %s);\n", Val1, Val2 );
            }
            else {
              WriteLog( "# warning: no junction position.\n" );
            }
          }

          printf("CHANGE SIZE %s;\n", LabelTextHeight );

          for( int k = 0; k < NrLabels; k++ ) {
            string mirrored = "";

            if( IsLabelFlipped[ k ] ) {
              mirrored = "M";
            }

            printf("LABEL %sR%s (%s %s) (%s %s);\n", mirrored, LabelRotation[ k ],
                                                  XCoordLabels[ k ],
                                                  YCoordLabels[ k ],
                                                  XCoordLabels[ k ],
                                                  YCoordLabels[ k ] );

            // Generate wires to fill gaps in ports

            real xLabelCoord = strtod( XCoordLabels[ k ] );
            real yLabelCoord = strtod( YCoordLabels[ k ] );

            int toLeft  = ( TypeLabels[ k ] == "LeftAngle_Sgl_Horz" ) ||
                          ( TypeLabels[ k ] == "LeftAngle_Dbl_Horz" ) ||
                          ( TypeLabels[ k ] == "BothAngle_Dbl_Horz" );
            int toRight = ( TypeLabels[ k ] == "RightAngle_Sgl_Horz" ) ||
                          ( TypeLabels[ k ] == "RightAngle_Dbl_Horz" ) ||
                          ( TypeLabels[ k ] == "BothAngle_Dbl_Horz" );

            if( IsLabelFlipped[ k ] ) {
              int tmp = toLeft;
              toLeft = toRight;
              toRight = tmp;
            }

            if( 1 /*toRight*/ ) {
              for( int l = 0; l < NrWiresPoint; l++ ) {
                int right = 1000000;
                int index = -1;

                if( ( yLabelCoord == WiresPointY[ l ] ) && ( WiresNet[ l ] == NetNameRef[ k ] ) ) {
                  if( xLabelCoord < WiresPointX[ l ] ) {
                    if( right > WiresPointX[ l ] ) {
                      right = WiresPointX[ l ];
                      index = l;
                    }
                  }
                }

                if( index >= 0 ) {
                  printf("NET '%s' (%s %s) (%f %f);\n", NetNameRef[ k ], XCoordLabels[ k ], YCoordLabels[ k ],
                                                        WiresPointX[ index ], WiresPointY[ index ] );
                }
                else {
                  //printf( "#info: wires point %s %s to the right not found.\n", XCoordLabels[ k ], YCoordLabels[ k ] );
                }
              }
            }

            if( 1 /*toLeft*/ ) {
              for( int l = 0; l < NrWiresPoint; l++ ) {
                int left = -1000000;
                int index = -1;

                if( ( yLabelCoord == WiresPointY[ l ] ) && ( WiresNet[ l ] == NetNameRef[ k ] ) ) {
                  if( xLabelCoord > WiresPointX[ l ] ) {
                    if( left < WiresPointX[ l ] ) {
                      left = WiresPointX[ l ];
                      index = l;
                    }
                  }
                }

                if( index >= 0 ) {
                  printf("NET '%s' (%s %s) (%f %f);\n", NetNameRef[ k ], XCoordLabels[ k ], YCoordLabels[ k ],
                                                        WiresPointX[ index ], WiresPointY[ index ] );
                }
                else {
                  //printf( "#info: wires point %s %s to the left not found.\n", XCoordLabels[ k ], YCoordLabels[ k ] );
                }
              }
            }
          }

          for( int l = 0; l < NrBuses; l++ ) {
            int busToken = buses[ l ];

            GenerateOneBus( busToken );
          }

          break;
        }
      }

      CurrentToken++;
    }
  }
}

void GenerateSchematic( void )
{
  GenerateSchematicHeader();

  GenerateSheets();

  printf("WINDOW FIT;\n");
  printf("SET CONFIRM OFF;\n");
}

// This function generate script based on parsed data.
// If processed seccesfully returns 0,
// otherwise returns 1

int GenerateScript( void )
{
  output(SCRIPTfileName, "wt") {
    GenerateLibrary();

    if( PCBDesignToken ) {
      GeneratePCB();
    }

    if( SchematicDesignToken ) {
      GenerateSchematic();
    }
  }

  return( 0 );
}

int    Cntelayer = 0;
string EagleLayerName[];
int    EagleLayerNum[];

string SaveRefLayerDef[];
string SaveRefLayerNum[];
string SaveRefLayerType[];
string SavePcadEagleLayerRefName[];
string SavePcadEagleLayerRefNum[];

string PrevRefLayerDef[];
string PrevRefLayerNum[];
string PrevRefLayerType[];
string PrevPcadEagleLayerRefName[];
string PrevPcadEagleLayerRefNum[];

string PrevShowRefLayer[];

int UpdateRefLayers( void )
{
  int selref = 0;

  for( int i = 0; i < LayerDefsNumber; i++ ) {
    string pcadLayerStrNum;

    sprintf( pcadLayerStrNum, "%d", LayersCode[ i ] );

    int eagleFromPcadLayerNum = strtol( ConvertLayer( pcadLayerStrNum ) );

    int found = 0;

    for( int j = 0; j < Cntelayer; j++ ) {
      if( eagleFromPcadLayerNum == EagleLayerNum[ j ] ) {
        SaveRefLayerType[ i ] = LayersType[ i ];
        SaveRefLayerDef[ i ] = LayersName[ i ];
        SaveRefLayerNum[ i ] = pcadLayerStrNum;
        string tmp;
        sprintf( tmp, "%d", EagleLayerNum[ j ] );
        SavePcadEagleLayerRefNum[ i ] = tmp;
        SavePcadEagleLayerRefName[ i ] = EagleLayerName[ j ];

        selref++;

        found = 1;

        break;
      }
    }

    if( !found ) {
      sprintf( ShowRefLayer[selref], "%s\t%s\t%s\t%s\t%s",
               RefLayerType[ i ],
               RefLayerDef[ i ],
               RefLayerNum[ i ],
               0,
               "unknown" );

      selref++;
    }
  }

  for( i = 0; i < selref; i++ ) {
    RefLayerType[ i ] = SaveRefLayerType[ i ];
    RefLayerDef[ i ] = SaveRefLayerDef[ i ];
    RefLayerNum[ i ] = SaveRefLayerNum[ i ];
    PcadEagleLayerRefNum[ i ] = SavePcadEagleLayerRefNum[ i ];
    PcadEagleLayerRefName[ i ] = SavePcadEagleLayerRefName[ i ];

    sprintf( ShowRefLayer[ i ], "%s\t%s\t%s\t%s\t%s",
             SaveRefLayerType[ i ],
             SaveRefLayerDef[ i ],
             SaveRefLayerNum[ i ],
             SavePcadEagleLayerRefNum[ i ],
             SavePcadEagleLayerRefName[ i ] );
  }

  RefLayerType[ selref ] = "";
  RefLayerDef[ selref ] = "";
  RefLayerNum[ selref ] = "";
  PcadEagleLayerRefNum[ selref ] = "";
  PcadEagleLayerRefName[ selref ] = "";

  CntlayerDef = selref;

  return( selref );
}

void ProcessLayersMap( void )
{
  if( schematic ) {
    schematic(S) {
      S.layers(L) {
        EagleLayerName[Cntelayer] = L.name;
        EagleLayerNum[Cntelayer] = L.number;
        Cntelayer++;
      }
    }
  }
  else {
    if( board ) {
      board(B) {
        B.layers(L) {
          EagleLayerName[Cntelayer] = L.name;
          EagleLayerNum[Cntelayer] = L.number;
          Cntelayer++;
        }
      }
    }
  }

  int selPCAD = LayerDefsNumber;
  int selUlay = LayerDefsNumber;
  int selEAGLE = Cntelayer;

  int selref = 0;

  for( int i = 0; i < CntlayerDef; i++ ) {
    PrevRefLayerType[ i ] = RefLayerType[ i ];
    PrevRefLayerDef[ i ] = RefLayerDef[ i ];
    PrevRefLayerNum[ i ] = RefLayerNum[ i ];
    PrevPcadEagleLayerRefNum[ i ] = PcadEagleLayerRefNum[ i ];
    PrevPcadEagleLayerRefName[ i ] = PcadEagleLayerRefName[ i ];

    sprintf( PrevShowRefLayer[ i ], "%s\t%s\t%s\t%s\t%s",
             RefLayerType[ i ],
             RefLayerDef[ i ],
             RefLayerNum[ i ],
             PcadEagleLayerRefNum[ i ],
             SavePcadEagleLayerRefName[ i ] );
  }

  dlgDialog(TR("ACCEL - EAGLE layer mapping")) {

    selref = UpdateRefLayers();

    dlgHBoxLayout {
      dlgVBoxLayout dlgSpacing(350);

      dlgVBoxLayout {
        dlgLabel("ACCEL\nLayer\n--->>");
        dlgListBox( LayersName, selPCAD );
      }

      dlgVBoxLayout {
        dlgLabel("EAGLE\nLayer\n<<---");
        dlgListBox( PcadEagleLayerRefName, selUlay );
      }

      dlgVBoxLayout {
        dlgLabel("EAGLE\nLayer\n");
        dlgListBox( EagleLayerName, selEAGLE ) {
          // set Reference layer name
          PcadEagleLayerRefName[selPCAD] = EagleLayerName[selEAGLE];

          // set Reference layer number
          string tmp;
          sprintf( tmp, "%d", EagleLayerNum[selEAGLE] );
          PcadEagleLayerRefNum[selPCAD] = tmp;

          sprintf( ShowRefLayer[ selPCAD ], "%s\t%s\t%s\t%s\t%s",
                   RefLayerType[ selPCAD ],
                   RefLayerDef[ selPCAD ],
                   RefLayerNum[ selPCAD ],
                   PcadEagleLayerRefNum[ selPCAD ],
                   PcadEagleLayerRefName[ selPCAD ] );
        }
      }
    }

    dlgSpacing(10);

    dlgVBoxLayout {
      dlgLabel(TR("Mapping:"));
      dlgListView(TR("ACCEL\nType\tACCEL\nLayer\tACCEL\nNumber\tEAGLE\nNumber\tEAGLE\nName"), ShowRefLayer, selref );
    }

    dlgHBoxLayout {
    	dlgStretch(1);
      dlgPushButton("&" + TR("Load")) { LoadCrossRef(""); selref = UpdateRefLayers(); }
      dlgPushButton("&" + TR("Save")) SaveCrossRef();
      dlgPushButton("+OK")
        dlgAccept();

      dlgPushButton("-" + TR("Cancel")) {
        for( int i = 0; i < CntlayerDef; i++ ) {
          RefLayerType[ i ] = PrevRefLayerType[ i ];
          RefLayerDef[ i ] = PrevRefLayerDef[ i ];
          RefLayerNum[ i ] = PrevRefLayerNum[ i ];
          PcadEagleLayerRefNum[ i ] = PrevPcadEagleLayerRefNum[ i ];
          PcadEagleLayerRefName[ i ] = PrevPcadEagleLayerRefName[ i ];
          ShowRefLayer[ i ] = PrevShowRefLayer[ i ];
        }
        dlgReject();
      }
    }
  };
}

void OutputWarningsLogFile( void )
{
  string fullLog = "";

  WarningsLogFileName = PCADfileName + ".err";

  sprintf( fullLog, "Number of messages = %d\n\n",  NrLogLines );

  for( int n = 0; n < NrLogLines; n++ ) {
    fullLog = fullLog + LogLines[ n ];
  }

  output( WarningsLogFileName, "wt" ) {
    printf("%s", fullLog );
  }

  if( !BatchMode ) {
    if( NrLogLines ) {
      dlgDialog( TR( "Warnings log" ) ) {
        dlgHBoxLayout dlgSpacing (400);

        dlgHBoxLayout {
          dlgVBoxLayout dlgSpacing (300);
          dlgTextView ( fullLog );
        }

        dlgHBoxLayout {
          dlgStretch( 1 );
          dlgPushButton( TR("-Back")) dlgReject ();
          dlgStretch(1);
        }
      };
    }
  }
}

void ChangeDRU( void )
{
  string drufile = path_dru[ 0 ] + "/" + "default.dru";

  string f[];
  int fcnt = fileglob( f, drufile );

  if( fcnt ) {
    string DRUvalues[];

    int DRUlcnt = fileread( DRUvalues, drufile );

    string s[];
    int n;
    string outputString[];

    for( int line = 0; line < DRUlcnt; line++ ) {
      n = strsplit( s, DRUvalues[ line ], ' ');

      if( s[ 0 ] == "rvPadTop" ) {
        outputString[ line ] = "rvPadTop = 0";
      } else if( s[ 0 ] == "rvPadInner" ) {
        outputString[ line ] = "rvPadInner = 0";
      } else if( s[ 0 ] == "rvPadBottom" ) {
        outputString[ line ] = "rvPadBottom = 0";
      } else if( s[ 0 ] == "rvViaOuter" ) {
        outputString[ line ] = "rvViaOuter = 0";
      } else if( s[ 0 ] == "rvViaInner" ) {
        outputString[ line ] = "rvViaInner = 0";
      } else if( s[ 0 ] == "rvMicroViaOuter" ) {
        outputString[ line ] = "rvMicroViaOuter = 0";
      } else if( s[ 0 ] == "rvMicroViaInner" ) {
        outputString[ line ] = "rvMicroViaInner = 0";
      } else if( s[ 0 ] == "rlMinPadTop" ) {
        outputString[ line ] = "rlMinPadTop = 0mil";
      } else if( s[ 0 ] == "rlMaxPadTop" ) {
        outputString[ line ] = "rlMaxPadTop = 0mil";
      } else if( s[ 0 ] == "rlMinPadInner" ) {
        outputString[ line ] = "rlMinPadInner = 0mil";
      } else if( s[ 0 ] == "rlMaxPadInner" ) {
        outputString[ line ] = "rlMaxPadInner = 0mil";
      } else if( s[ 0 ] == "rlMinPadBottom" ) {
        outputString[ line ] = "rlMinPadBottom = 0mil";
      } else if( s[ 0 ] == "rlMaxPadBottom" ) {
        outputString[ line ] = "rlMaxPadBottom = 0mil";
      } else if( s[ 0 ] == "rlMinViaOuter" ) {
        outputString[ line ] = "rlMinViaOuter = 0mil";
      } else if( s[ 0 ] == "rlMaxViaOuter" ) {
        outputString[ line ] = "rlMaxViaOuter = 0mil";
      } else if( s[ 0 ] == "rlMinViaInner" ) {
        outputString[ line ] = "rlMinViaInner = 0mil";
      } else if( s[ 0 ] == "rlMaxViaInner" ) {
        outputString[ line ] = "rlMaxViaInner = 0mil";
      } else if( s[ 0 ] == "rlMinMicroViaOuter" ) {
        outputString[ line ] = "rlMinMicroViaOuter = 0mil";
      } else if( s[ 0 ] == "rlMaxMicroViaOuter" ) {
        outputString[ line ] = "rlMaxMicroViaOuter = 0mil";
      } else if( s[ 0 ] == "rlMinMicroViaInner" ) {
        outputString[ line ] = "rlMinMicroViaInner = 0mil";
      } else if( s[ 0 ] == "rlMaxMicroViaInner" ) {
        outputString[ line ] = "rlMaxMicroViaInner = 0mil";
      } else if( s[ 0 ] == "srRoundness" ) {
        outputString[ line ] = "srRoundness = 0.0";
      } else if( s[ 0 ] == "srMinRoundness" ) {
        outputString[ line ] = "srMinRoundness = 0mil";
      } else {
        outputString[ line ] = DRUvalues[ line ];
      }
    }

    output( DRUFileName, "wt") {
      for( int line = 0; line < DRUlcnt; line++ ) {
        printf("%s\n", outputString[ line ] );
      }
    }
  }
  else {
    dlgMessageBox(TR("Can't open default.dru !"), "OK");
  }
}

// This is the main parsing procedure
// This procedure do the following:
//
// 1. Merge all lines to one string and
//    remove all comments (comments may be added by inserting
//    a semicolon; the comment continues from the semicolon
//    to the end of the line.
// 2. Split merged string to array of tokens
// 3. Parse tree
// 4. Generate script

int Parsing( void )
{
  string a[];

  int fileExist = fileglob( a, PCADfileName );

  if( !fileExist ) {
    dlgMessageBox( TR("File ")  + PCADfileName + TR(" doesn't exist!"), "OK" );
    return( 1 );
  }

  DebugMessage = 1;
  MergedString = "";
  TokensNumber = 0;

  MergeLines();

  SplitToTokens();

  if( ParseTree() ) {
    return( 1 );
  }

  if( PCBDesignToken ) {
    DRUFileName = filesetext( PCADfileName, ".dru" );

    ChangeDRU();
  }

  string CrossfileName = PCADfileName + ".lmp";
  string f[];
  int crossfileExist = fileglob(f, CrossfileName);
  if( crossfileExist ) LoadCrossRef(CrossfileName);

  if( IfUpdateLayersMap ) {
    ProcessLayersMap();
  }

  if( GenerateScript() ) {
    return( 1 );
  }

  OutputWarningsLogFile();

  return( 0 );
}

// *********** Show and creat Reference ****************
int Execute(string fname) {
  // APL make parsing
  Parsing();
  return 1;
}

// ***** Main *****
void main( void )
{
  // Keep help here for it's too big to stuff into dictionary.
  string help[] = {
    "<b>General</b><br>"
    "ACCEL ASCII is also known as TangoPRO ASCII or P-CAD ASCII. "
    "It can be exported from <b>P-CAD</b>, <b>Altium Designer</b> and <b>PROTEL</b> and therefore allows conversion of "
    "designs in these formats to EAGLE."
    "The conversion to EAGLE works following:<br>"
    "First, in the directory of the input file, an EAGLE library with same name is generated. "
    "It contains the devices that are used. With this an EAGLE schematic or board with same name is generated. <br>"
    "For ACCEL ASCII schematic files partly end with \".sch\", EAGLE schematics get ending \".eagle.sch\". "
    "The conversion of a schematic without board doesn't make much sense because the package information is "
    "missing which is necessary for creation of a board.<br>"
    "Because of different data models and powerfulness of the foreign systems and EAGLE the conversion has limits. "
    "Ideally certain cases should already be avoided in the original data. "
    "Otherwise certain post processing steps may be necessary. In any case we recommend to perform a DRC after "
    "import in order to find and eliminate potential weaknesses of the design. "
    "<p>"
    "<b>Layer assignment</b><br>"
    "Depending on the source system, signal, solder and other layer types have different names. "
    "For conversion a default assignment is used which may not always be correct. "
    "For this case you can change this individually with the option \"Adjust layer mapping\"."
    "<p>"
    "<b>Conversion details:</b><br>"
    "<ul><li><i>Names: </i><br>"
              "To follow EAGLE's naming conventions for different types of entities certain characters are replaced "
              "by '_', in particular '(', ')', '[', ']', ''' and space. '\\\\' is replaced by '/'. "  // 4 backslashes here ? Insane. Seems to be a bug in EAGLE.
              "Control characters like '\\\\r' are not processed in a special way.</li>"
         "<li><i>Texts:</i><br>"
              "All texts are converted to vectorfont in EAGLE. This allows a system independent "
              "representation for polygon calculation and CAM processing. The font can be changed to fixed or "
              "proportional where needed. All other text properties are taken over from ACCEL ASCII.</li>"
         "<li><i>Pads and SMDs: </i><br>"
              "For pad and SMD types following conversion agreement is used:<br>"
              "Square pad/SMD      -> SQUARE pad/SMD,<br>"
              "Rectangle pad       -> SQUARE pad with additional rectangle polygon,<br>"
              "Oval pad            -> LONG pad in EAGLE (size and shape of original and converted pads are slightly "
              "different in this case),<br>"
              "Ellipse pad         -> ROUND pad with additional approximation polygon consisting of four arcs,<br>"
              "Polygon pad         -> SQUARE pad with additional polygon,<br>"
              "Round rectangle pad -> SQUARE pad and additional polygon with rounded corners,<br>"
              "Target pad          -> ROUND pad,<br>"
              "Rectangle SMD       -> rectangle SMD,<br>"
              "Oval SMD            -> SMD with 100% roundness,<br>"
              "Ellipse SMD         -> round SMD with additional approximation polygon consisting of four arcs,<br>"
              "Polygon SMD         -> square SMD with additional polygon,<br>"
              "Round rectangle     -> SMD with 25% roundness,<br>"
              "Target SMD          -> SMD with 100% roundness.</li>"
         "<li><i>Standalone pads (Free pads): </i><br>"
              "For standalone pads an appropriate library package is created in EAGLE.</li>"
         "<li><i>Vias:</i><br>"
              "Vias are converted the following way to EAGLE:<br>"
              "Oval -> ROUND, Rectangle -> SQUARE, Ellipse -> ROUND, Round rectangle -> SQUARE and Target -> ROUND.<br>"
              "The sizes of the EAGLE vias are adjusted to fit within the shape of the ACCEL vias to avoid clearance issues.</li>"
         "<li><i>Contacts / Routing: </i><br>"
              "In EAGLE coordinates of traces, pads, vias etc. have to match exactly in order to be properly routed. "
              "Otherwise airwires are generated. In some other systems certain deviations are allowed."
              "In other systems it's possible that a longer trace crosses a pad without connecting point. "
              "In EAGLE this leads to an airwire to the next connecting point. In this case the trace needs to be splitted with "
              "SPLIT command in order to create an additional connecting point at the pad position. </li>"
         "<li><i>Copper polygons general: </i><br>"
              "In EAGLE there's only one type for hatched polygons (horizontal and vertical stripes)."
              "The different possible hatch types in ACCEL ASCII like diagonal style for example, are all "
              "converted to this.<br>"
              "Thermals within polygons are also always horizontal and vertical. There's no specific thermal spoke width "
              "for each polygon, but a general value in the EAGLE design rules.<br>"
              "The removal of orphan property is converted to EAGLE but without threshold value (only on/off).</li>"
         "<li><i>Copper polygons in poured state: </i><br>"
              "In EAGLE polygons are saved always in unpoured state. The pour state is calculated dynamically "
              "by RATSNEST and depends on the parameters currently set.</li>"
         "<li><i>Dimensions: </i><br>"
              "As the data model for dimensions in EAGLE is much simpler than in ACCEL ASCII some details are not mapped to EAGLE.</li>"
         "<li><i>Labels:</i><br>"
              "Input, output and bidirectional labels are all converted to Xref labels in EAGLE.</li>"
         "<li><i>Attributes for layers: </i><br>"
              "In EAGLE layers can't have attributes. This is skipped.</li>"
         "<li><i>'zones' (in ACCEL schematic): </i><br>"
              "'zones' are not supported and skipped.</li>"
    "</ul>"
    ,
    "<b>Allgemeines</b><br>"
    "ACCEL ASCII ist auch unter dem Namen TangoPRO ASCII, oder P-CAD ASCII bekannt. "
    "Es kann von <b>P-CAD</b>, <b>Altium Designer</b> und <b>PROTEL</b> aus exportiert werden und ermöglicht so die "
    "Konvertierung von Designs in diesen Formaten in EAGLE-Format. "
    "Für die Konvertierung in EAGLE ist Folgendes zu beachten:<br>"
    "Zunächst wird im Verzeichnis der Inputdatei eine EAGLE-Bibliothek gleichen Namens generiert, "
    "die die verwendeten Bauteile enthält. Damit wird dann der gleichnamige EAGLE-Schaltplan oder das Board erstellt. "
    "Da ACCEL-ASCII-Schaltpläne wie EAGLE teilweise die Endung \".sch\" haben, erhalten die EAGLE-Schaltpläne "
    "die Endung \".eagle.sch\". "
    "Die Konvertierung eines Schaltplans alleine macht wenig Sinn, da die Package-Information fehlt, "
    "die für die Generierung eines Boards erforderlich wäre. "
    "Aufgrund der verschiedenen Datenmodelle und der Mächtigkeit der Fremdsysteme und EAGLE sind der Konvertierung "
    "Grenzen gesetzt. Idealerweise sollten bestimmte Fälle in den Originaldaten bereits vermieden werden. "
    "Ansonsten sind gewisse Nachbearbeitungsschritte erforderlich. In jedem Fall sollten Sie nach dem Import einen "
    "DRC durchführen, um eventuelle Schachstellen des Designs zu finden und zu beseitigen."
    "<p>"
    "<b>Zuordnung der Layer</b><br>"
    "Je nach Herkunftssystem haben die Signal- Beschriftungs- und sonstigen Layerarten verschiedene Namen. "
    "Für die Konvertierung wird eine gewisse Standard-Zuordnung angenommen, die jedoch nicht immer richtig sein muss. "
    "Für diesen Fall können Sie über die Option \"Manuelle Layer-Zuordnung\" dies individuell einstellen."
    "<p>"
    "<b>Details zur Konvertierung:</b><br>"
    "<ul><li><i>Namen: </i><br>"
              "Um EAGLE's Namenskonventionen für verschiedene Objekttypen zu entsprechen, werden verschiedene Zeichen "
              "durch '_' ersetzt, insbesondere '(', ')', '[', ']', ''' und Leerzeichen. '\\\\' wird ersetzt durch '/'. "
              "Kontrollzeichen wie '\\\\r' werden nicht speziell behandelt.</li>"
         "<li><i>Texte:</i><br>"
              "Alle Texte werden in Vektorfont konvertiert. Dies ermöglicht eine systemunabhängige "
              "Darstellung für das Polygon-Freirechnen und die CAM-Verarbeitung. Die Schriftart kann auf Fixed oder "
              "Proportional geändert werden wo nötig. Alle anderen Texteigenschaften werden aus ACCEL ASCII übernommen."
         "<li><i>Pads und SMDs: </i><br>"
              "Für Pads und SMDs werden folgende Konvertierungsregeln verwendet:<br>"
              "Square Pad/SMD      -> SQUARE Pad/SMD,<br>"
              "Rectangle Pad       -> SQUARE Pad mit umgebendem rechteckigem Polygon,<br>"
              "Oval Pad            -> LONG Pad (Größe und Form weichen leicht voneinander ab),<br>"
              "Ellipse Pad         -> ROUND Pad mit umgebendem Approximation-Polygon aus 4 Kreisbögen,<br>"
              "Polygon Pad         -> SQUARE Pad mit umgebendem Polygon,<br>"
              "Round rectangle Pad -> SQUARE Pad mit umgebendem Polygon mit Verrundungen,<br>"
              "Target Pad          -> ROUND Pad,<br>"
              "Rectangle SMD       -> rechteckiges SMD,<br>"
              "Oval SMD            -> SMD mit 100% Roundness,<br>"
              "Ellipse SMD         -> rundes SMD mit umgebendem Approximation-Polygon aus 4 Kreisbögen,<br>"
              "Polygon SMD         -> quadratisches SMD with umgebendem Polygon,<br>"
              "Round rectangle     -> SMD with 25% Roundness,<br>"
              "Target SMD          -> SMD with 100% Roundness.</li>"
         "<li><i>Standalone-Pads (Freie Pads): </i><br>"
              "Für Standalone-Pads wird ein entsprechendes Package in EAGLE erzeugt und verwendet.</li>"
         "<li><i>Vias:</i><br>"
              "Vias werden folgendermaßen zu EAGLE konvertiert:<br>"
              "Oval -> ROUND, Rectangle -> SQUARE, Ellipse -> ROUND, Round rectangle -> SQUARE and Target -> ROUND.<br>"
              "Die Größen der EAGLE-Vias werden so gesetzt, dass sie in die Form der ACCEL-Vias hineinpassen, um Abstände einzuhalten.</li>"
         "<li><i>Kontaktierung / Routen: </i><br>"
              "In EAGLE müssen die Koordinaten von Leiterbahnen, Pads, Vias etc. exakt aufeinander treffen, um als richtig geroutet "
              "zu gelten, sonst entstehen Luftlinien. In manchen anderen Systemen sind gewisse Abweichungen zulässig. "
              "Es kann in anderen Systemen vorkommen, daß eine längere Leiterbahn über einen Pad gelegt ist ohne einen Absetzpunkt. "
              "Das erzeugt in EAGLE eine Luftlinie bis zum nächsten Absetzpunkt. In diesem Fall muß mit SPLIT die Leiterbahn gesplittet "
              "werden, um einen zusätzlichen Absetzpunkt an der Pad-Position zu erzeugen.</li>"
         "<li><i>Kupfer-Polygone allgemein: </i><br>"
              "In EAGLE gibt es nur einen Typ für schraffierte Polygone (horizontale und vertikale Streifen). "
              "Die verschiedenen möglichen Schraffiertypen in ACCEL ASCII wie z.B. diagonale Schraffur werden alle "
              "dazu konvertiert.<br>"
              "Thermalstege in den Polygonen verlaufen immer horizontal und vertikal. Es gibt keine spezifische "
              "Thermalbreite für jedes Polygon, aber einen allgemeinen Wert in den Designregeln.<br>"
              "Die Orphan-Eigenschaft wird nach EAGLE konvertiert aber ohne Schwellwert (nur Orphans behalten/nicht behalten).</li>"
         "<li><i>Kupfer-Polygone in freigerechnetem Zustand: </i><br>"
              "In EAGLE werden Polygone immer im Definitions-Zustand gespeichert (nicht freigerechnet). Das Freirechnen erfolgt "
              "dynamisch durch RATSNEST und hängt von den aktuellen Parametern ab.</li>"
         "<li><i>Bemaßungen: </i><br>"
              "Da das Datenmodell für Bemaßungen in EAGLE wesentlich einfacher ist als in ACCEL ASCII, werden einige Details "
              "nicht in EAGLE abgebildet.</li>"
         "<li><i>Labels:</i><br>"
              "Input- Output- und bidirektionale Labels werden alle in Xref-Labels in EAGLE konvertiert.</li>"
         "<li><i>Attributes für Layer: </i><br>"
              "In EAGLE können Layer keine Attribute haben. Dies wird weggelassen.</li>"
         "<li><i>'zones' (in ACCEL-Schaltplänen): </i><br>"
              "'zones' werden nicht unterstützt und daher weggelassen.</li>"
    "</ul>"
    ,
    "<b>Общие замечания</b><br>"
  	"ACCEL ASCII также известен как TangoPRO ASCII или P-CAD ASCII. "
  	"Он может быть экспортирован из <b>Altium Designer</b>, <b>P-CAD</b> и <b>PROTEL</b>. "
  	"Трансляция в EAGLE работает следующим образом:<br>"
  	"В начале, в каталоге входного файла, создаётся библиотека EAGLE с тем же именем. "
  	"Она содержит компоненты, которые будут использованы в дальнейшем. Затем создаётся файл EAGLE с тем же именем, содержащий схему или топологию. <br>"
	"Для ACCEL ASCII файла схемы \".sch\", создаётся файл EAGLE \".eagle.sch\". "
	"Преобразование схемы без платы не имеет смысла, так как отсутствует информация,"
        "необходимая для создания платы."
	"<p>"
    "<b>Присвоение значений слоям</b><br>"
	"В зависимости от исходной системы, типы сигналов, припой и другие слои имеют разные названия. "
	"Соответствие слоёв, заданное по умолчанию, может быть изменено. "
	"Для этого воспользуйтесь опцией \"Настройка соответствия слоёв\"."
	"<p>"
    "<b>Различия и ограничения, возникающие при преобразовании</b><br>"
	"В связи с различными моделями данных и систем, преобразование имеет ограничения.  "
	"В идеале некоторые конфигурации следует избегать в исходных данных. "
	"В противном случае потребуется постобработка. Это включает в себя, в частности: "
    "<ul><li><i>Имена: </i><br>"
              "Следуя соглашениям о именах в EAGLE следующие символы будут преобразованы "
              "в '_': '(', ')', '[', ']', ''' и пробел. '\\\\' заменяется на '/'. "  // 4 backslashes here ? Insane. Seems to be a bug in EAGLE.
              "Управляющие символы, такие как '\\\\r' в строках не обрабатываются.</li>"
         "<li><i>Текстовые строки:</i><br>"
              "Все текстовые строки преобразуются в векторный шрифт в EAGLE. Это даёт возможность "
              "представить текст и использовать его для CAM обработки. Шрифт может быть изменен на фиксированный или "
              "пропорциональный где это необходимо. Все остальные свойства шрифта сохраняются из ACCEL ASCII.</li>"
         "<li><i>Pad и SMD: </i><br>"
              "Pad и SMD преобразуются следующим образом:<br>"
              "Square pad/SMD      -> SQUARE pad/SMD,<br>"
              "Rectangle pad       -> SQUARE pad с дополнительным прямоугольным полигоном,<br>"
              "Oval pad            -> LONG pad в EAGLE (размер и форма отличаются в этом случае),"
              "<br>"
              "Ellipse pad         -> ROUND pad с дополнительным полигоном, аппроксимированным четыремя дугам,<br>"
              "Polygon pad         -> SQUARE pad с дополнительным полигоном,<br>"
              "Round rectangle pad -> SQUARE pad с дополнительным полигоном с закругленными углами,<br>"
              "Target pad          -> ROUND pad,<br>"
              "Rectangle SMD       -> прямоугольный SMD,<br>"
              "Oval SMD            -> SMD с 100% закругленностью,<br>"
              "Ellipse SMD         -> ROUND SMD с дополнительным полигоном, аппроксимированным четыремя дугами,<br>"
              "Polygon SMD         -> SQUARE SMD с дополнительным полигоном,<br>"
              "Round rectangle     -> SMD с 25% закругленностью,<br>"
              "Target SMD          -> SMD с 100% закругленностью.</li>"
         "<li><i>Одиночные контактные площадки: </i><br>"
              "Для автономных контактных площадок в EAGLE создаются соответствующие библиотечные элементы.</li>"
         "<li><i>Переходы:</i><br>"
              "Переходы преобразуются следующим образом:<br>"
              "Oval -> ROUND, Rectangle -> SQUARE, Ellipse -> ROUND, Round rectangle -> SQUARE and Target -> ROUND.<br>"
              "Размер перехода в EAGLE подбирается таким образом, чтобы исключить нарушение минимального технологического допуска.</li>"
         "<li><i>Контакты / трассировка: </i><br>"
              "В EAGLE координаты проводов, контактных площадок, переходов и т.д. должны в точности совпадать с тем, чтобы быть правильно соединенными. "
	      "В противном случае создаются неподключенные соединения. В некоторых других системах допускаются отклонения.</li>"
	      "В других системах допускается если провод пересекает контактную площадку без подключения. "
	      "В EAGLE это приводит к созданию airwire к следующей точке цепи. В этом случае соединение должно быть разделено с помощью команды SPLIT "
	      "чтобы создать дополнительные соединительные точки.  </li>"
         "<li><i>Преобразование заливки: </i><br>"
               "В EAGLE есть только один тип заливки (горизонтальных и вертикальных полос штриховки). "
               "Различные возможные типы заливки в ACCEL ASCII, как, например, диагональный стиль, "
               "преобразуется в этот. <br>"
               "Thermals в пределах полигона также всегда горизонтальные и вертикальные. Там нет конкретных тепловых ширин "
               "для каждого полигона. Это значение задано в общих настройках EAGLE. <br>"
               "Удаление одиночных полигонов также преобразуется в EAGLE, но без порогового значения (только вкл / выкл). </ Li>"
         "<li><i>>Преобразование полигонов заливки: </i><br>"
              "В EAGLE полигоны заливки всегда сохраняются в незалитом состоянии. Состояние заливки всегда вычисляется динамически  "
              "с помощью RATSNEST и зависит от текущих установленных параметров.</li>"
         "<li><i>Линейки: </i><br>"
              "Поскольку модель данных в EAGLE существенно проще, чем в ACCEL ASCII некоторые детали линеек не преобразуются в EAGLE.</li>"
         "<li><i>Знаки подключения:</i><br>"
              "Входные, выходные и двунаправленные знаки подключения преобразуются в знак Xref в EAGLE.</li>"
         "<li><i>Атрибуты слоёв: </i><br>"
              "В EAGLE атрибуты слоёв не преобразуются.</li>"
         "<li><i>'зоны' (в ACCEL принципиальной схеме): </i><br>"
              "'зоны' в принципиальной схеме не преобразуются</li>"
    "</ul>"
	"В любом случае мы рекомендуем выполнить DRC после импорта для того, чтобы найти и устранить потенциальные проблемы."
  };

  BatchMode = 0;

  if( argc > 1 ) {
    BatchMode = 1;

    PCADfileName = argv[ 1 ];

    Lines = fileread( PcadLines, PCADfileName );

    if (Lines == -1) exit(-7113);

    SCRIPTfileName = filesetext(PCADfileName, ".scr");

    if( Parsing() ) {
      exit( 1 );
    }

    if( PCBDesignToken ) {
      exit ("SCRIPT '" + SCRIPTfileName + "'; RATSNEST; WRITE;");
    }

    exit ("SCRIPT '" + SCRIPTfileName +"' WRITE;");
  }

  SchematicWindow = 0;
  BoardWindow = 0;

  if (schematic) {
    schematic(S) {
      SchematicWindow = 1;
    }
  }
  else if (board) {
    board(B) {
      BoardWindow = 1;
    }
  }
  else {
    dlgMessageBox(TR("Please start from board or schematic editor !"), "OK");
    exit(0);
  }


  string fname = "";
  int nowstart = 0;
  dlgDialog(TR("Import P-CAD/Altium/Protel (ACCEL ASCII)")) {
    dlgLabel(usage);
    // www: Remove this when integrated into EAGLE
    //dlgLabel("Version " + Version);
    dlgLabel(Status, 1);
    dlgHBoxLayout {
      dlgLabel(TR("Import file:"));
      dlgStringEdit(fname);
      dlgPushButton(TR("&Browse") + "...") {
        fname = GetFile(fname);
      }
    }
    dlgHBoxLayout {
      dlgCheckBox(TR("Adjust layer mapping"), IfUpdateLayersMap );
      dlgStretch(1);
      dlgPushButton("-" + TR("Help") + "...")
        dlgDialog(TR("Import P-CAD/Altium/Protel (ACCEL ASCII)") + " - " + TR("Help")) {
          dlgHBoxLayout dlgSpacing(900);

          dlgHBoxLayout {
            dlgVBoxLayout dlgSpacing (500);
            dlgTextView( help[LangIdx] );
          }

          //dlgLabel(help[LangIdx]);

          dlgHBoxLayout {
            dlgStretch(1);
            dlgPushButton("+" + TR("OK"))
              dlgAccept();
            dlgStretch(1);
          }
        };
      dlgPushButton("+" + TR("Start")) {
        nowstart = Execute(fname);
        if (nowstart == 1) dlgAccept();
      }
      dlgPushButton("-" + TR("Cancel")) { dlgReject(); exit(-1); }
    }
  };

  if( PCBDesignToken )
    exit ("SCRIPT '" + SCRIPTfileName + "'; RATSNEST");
  exit ("SCRIPT '" + SCRIPTfileName +"';");
}

