Example #1
0
/*!
    Returns TRUE if the property is scriptable for object \a o;
    otherwise returns FALSE.

    If no object \a o is given, the function returns a static
    approximation.
 */
bool QMetaProperty::scriptable( QObject* o ) const
{
    if ( o ) {
	int idx = _id >= 0 ? _id : (*meta)->indexOfProperty( this, TRUE );
	return idx >= 0 && o->qt_property( idx, 4, 0 );
    }
    if ( testFlags( ScriptableOverride ) ) {
	const QMetaObject* mo = (*meta);
	const QMetaProperty* parent = mo->resolveProperty( this );
	return parent ? parent->scriptable() : FALSE;
    }
    return !testFlags( NotScriptable );
}
Example #2
0
/*!
    Returns TRUE if the property shall be stored for object \a o;
    otherwise returns FALSE.

    If no object \a o is given, the function returns a static
    approximation.
 */
bool QMetaProperty::stored( QObject* o ) const
{
    if ( !isValid() || !writable() )
	return FALSE;
    if ( o ) {
	int idx = _id >= 0 ? _id : (*meta)->indexOfProperty( this, TRUE );
	return idx >= 0 && o->qt_property( idx, 5, 0 );
    }
    if ( testFlags( StoredOverride ) ) {
	const QMetaObject* mo = (*meta);
	const QMetaProperty* parent = mo->resolveProperty( this );
	return parent ? parent->stored() : FALSE;
    }
    return !testFlags( NotStored );
}
Example #3
0
HRESULT csMenu::QueryContextMenu(HMENU hmenu, UINT indexMenu, UINT idCmdFirst,
                                 UINT /*idCmdLast*/, UINT uFlags)
{
  if( uFlags & CMF_DEFAULTONLY ) {
    return MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, 0);
  }

  UINT uPos = 0;
  UINT uCmdID = idCmdFirst;

  const DWORD flags = regReadFlags();

  const csWString parallel  = regReadParallel();
  const DWORD parallelCount = regReadParallelCount();
  const bool hasParallel    = !parallel.empty()  &&  parallelCount > 1;

  HMENU submenu = CreatePopupMenu();
  insertMenuItem(submenu, uPos++, uCmdID++, L"List", !_files.empty());
  insertMenuItem(submenu, uPos++, uCmdID++, L"List (path)", !_files.empty());
  insertMenuItem(submenu, uPos++, uCmdID++, L"List (path, tabular)", !_files.empty());
  insertSeparatorMenuItem(submenu, uPos++);
  insertMenuItem(submenu, uPos++, uCmdID++, L"Create symbolic link...",
                 _files.size() == 1);
  insertSeparatorMenuItem(submenu, uPos++);
  insertCheckableMenuItem(submenu, uPos++, uCmdID++, L"Batch processing",
                          testFlags(flags, CMD_FLAG_BATCH));
  insertCheckableMenuItem(submenu, uPos++, uCmdID++, L"Parallel execution",
                          testFlags(flags, CMD_FLAG_PARALLEL), hasParallel);
  insertCheckableMenuItem(submenu, uPos++, uCmdID++, L"Resolve UNC paths",
                          testFlags(flags, CMD_FLAG_UNC));
  insertCheckableMenuItem(submenu, uPos++, uCmdID++, L"UN*X path separators",
                          testFlags(flags, CMD_FLAG_UNIX));

  insertSubMenuItem(hmenu, submenu, indexMenu, uCmdID++, L"CS::Menu", _menuBitmap);

  const csWStringList scripts = regReadScripts();
  if( !scripts.empty()  &&  !_files.empty() ) {
    insertSeparatorMenuItem(submenu, uPos++);
    for(csWStringList::const_iterator it = scripts.begin(); it != scripts.end(); it++) {
      insertMenuItem(submenu, uPos++, uCmdID++, it->c_str());
    }
  }

  return MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, uCmdID-idCmdFirst);
}
Example #4
0
void LiveSocket::sendNode(uint32_t clientId, QTreeNode* node, int32_t ndx, int32_t ndy, uint32_t floorMask)
{
	bool underground;
	if(floorMask & 0xFF00) {
		if(floorMask & 0x00FF) {
			underground = false;
		} else {
			underground = true;
		}
	} else {
		underground = false;
	}

	node->setVisible(clientId, underground, true);

	// Send message
	NetworkMessage message;
	message.write<uint8_t>(PACKET_NODE);
	message.write<uint32_t>((ndx << 18) | (ndy << 4) | ((floorMask & 0xFF00) ? 1 : 0));

	if(!node) {
		message.write<uint8_t>(0x00);
	} else {
		Floor** floors = node->getFloors();

		uint16_t sendMask = 0;
		for(uint32_t z = 0; z < 16; ++z) {
			uint32_t bit = 1 << z;
			if(floors[z] && testFlags(floorMask, bit)) {
				sendMask |= bit;
			}
		}

		message.write<uint16_t>(sendMask);
		for(uint32_t z = 0; z < 16; ++z) {
			if(testFlags(sendMask, 1 << z)) {
				sendFloor(message, floors[z]);
			}
		}
	}

	send(message);
}
/*!
  Returns whether the property shall be stored for object \a o or
  not.
 */
bool QMetaProperty::stored( QObject* o ) const
{
    if ( !isValid() || set == 0 || testFlags( NotStored | UnresolvedStored ) )
	return FALSE;

    if ( store == 0 )
	return TRUE;

    typedef bool (QObject::*ProtoBool)() const;
    ProtoBool m = (ProtoBool)store;

    return (o->*m)();
}
Example #6
0
int main(void){
    wchar_t dest[11];
    
    plan(31);

    ok(SUCCEEDED(StringCbPrintfExW(dest, 11 * sizeof(wchar_t),
                    NULL, NULL, 0, L"test")),
            "Print short string without any extended functionality.");
    is_wstring(L"test", dest,
            "Result of printing short string.");

    testDestEnd();
    testRemaining();
    testFlags();

    return 0;
}
Example #7
0
void LiveSocket::receiveNode(NetworkMessage& message, Editor& editor, Action* action, int32_t ndx, int32_t ndy, bool underground)
{
	QTreeNode* node = editor.map.getLeaf(ndx * 4, ndy * 4);
	if(!node) {
		log->Message(wxT("Warning: Received update for unknown tile (") + std::to_string(ndx * 4) + wxT("/") + std::to_string(ndy * 4) + wxT("/") + (underground ? "true" : "false") + wxT(")"));
		return;
	}

	node->setRequested(underground, false);
	node->setVisible(underground, true);

	uint16_t floorBits = message.read<uint16_t>();
	if(floorBits == 0) {
		return;
	}

	for(uint_fast8_t z = 0; z < 16; ++z) {
		if(testFlags(floorBits, 1 << z)) {
			receiveFloor(message, editor, action, ndx, ndy, z, node, node->getFloor(z));
		}
	}
}
Example #8
0
void LiveSocket::receiveFloor(NetworkMessage& message, Editor& editor, Action* action, int32_t ndx, int32_t ndy, int32_t z, QTreeNode* node, Floor* floor)
{
	Map& map = editor.map;

	uint16_t tileBits = message.read<uint16_t>();
	if(tileBits == 0) {
		for(uint_fast8_t x = 0; x < 4; ++x) {
			for(uint_fast8_t y = 0; y < 4; ++y) {
				action->addChange(new Change(map.allocator(node->createTile(ndx * 4 + x, ndy * 4 + y, z))));
			}
		}
		return;
	}
	
	// -1 on address since we skip the first START_NODE when sending
	const std::string& data = message.read<std::string>();
	mapReader.assign(reinterpret_cast<const uint8_t*>(data.c_str() - 1), data.size());

	BinaryNode* rootNode = mapReader.getRootNode();
	BinaryNode* tileNode = rootNode->getChild();

	Position position(0, 0, z);
	for(uint_fast8_t x = 0; x < 4; ++x) {
		for(uint_fast8_t y = 0; y < 4; ++y) {
			position.x = (ndx * 4) + x;
			position.y = (ndy * 4) + y;

			if(testFlags(tileBits, 1 << ((x * 4) + y))) {
				receiveTile(tileNode, editor, action, &position);
				tileNode->advance();
			} else {
				action->addChange(new Change(map.allocator(node->createTile(position.x, position.y, z))));
			}
		}
	}
	mapReader.close();
}
Example #9
0
void LiveSocket::sendFloor(NetworkMessage& message, Floor* floor)
{
	uint16_t tileBits = 0;
	for(uint_fast8_t x = 0; x < 4; ++x) {
		for(uint_fast8_t y = 0; y < 4; ++y) {
			uint_fast8_t index = (x * 4) + y;

			Tile* tile = floor->locs[index].get();
			if(tile && tile->size() > 0) {
				tileBits |= (1 << index);
			}
		}
	}

	message.write<uint16_t>(tileBits);
	if(tileBits == 0) {
		return;
	}

	mapWriter.reset();
	for(uint_fast8_t x = 0; x < 4; ++x) {
		for(uint_fast8_t y = 0; y < 4; ++y) {
			uint_fast8_t index = (x * 4) + y;
			if(testFlags(tileBits, 1 << index)) {
				sendTile(mapWriter, floor->locs[index].get(), nullptr);
			}
		}
	}
	mapWriter.endNode();

	std::string stream(
		reinterpret_cast<char*>(mapWriter.getMemory()),
		mapWriter.getSize()
	);
	message.write<std::string>(stream);
}
Example #10
0
void LinearScaleY::changeDiapason (double dataDiapason, double plotDiapason)
{ 
	Mx = -plotDiapason/(testFlags(Scale::ManualDiapason) ? fabs(max-min) : dataDiapason);
	x0 = (int)( plotDiapason - min*Mx );
};
Example #11
0
bool QMetaProperty::isEnumType() const
{
    return testFlags( EnumOrSet );
}
Example #12
0
bool NLS::Item::hasSlipPrevention() const {
	return testFlags(Items::Flags::Spikes);
}
Example #13
0
bool NLS::Item::hasTradeBlock() const {
	return testFlags(Items::Flags::TradeUnavailable);
}
Example #14
0
bool NLS::Item::hasKarma() const {
	return testFlags(Items::Flags::KarmaScissors);
}
Example #15
0
bool NLS::Item::hasLock() const {
	return testFlags(Items::Flags::Lock);
}
Example #16
0
bool NLS::Item::hasWarmSupport() const {
	return testFlags(Items::Flags::ColdProtection);
}
Example #17
0
bool executeCommand(const UINT cmd, const csWStringList& files)
{
  const csWString parallel  = regReadParallel();
  const DWORD parallelCount = regReadParallelCount();
  const bool    hasParallel = !parallel.empty()  &&  parallelCount > 1;

  const DWORD flags      = regReadFlags();
  const bool  isBatch    = testFlags(flags, CMD_FLAG_BATCH);
  const bool  isParallel = testFlags(flags, CMD_FLAG_PARALLEL)  &&  hasParallel;
  const bool  isUnc      = testFlags(flags, CMD_FLAG_UNC)  &&  cmd != Cmd_List;
  const bool  isUnix     = testFlags(flags, CMD_FLAG_UNIX);

  const csWString  scriptPath = regReadScriptsPath();
  const csWStringList scripts = regReadScripts();

  if(        cmd == Cmd_List                ||
             cmd == Cmd_ListWithPath        ||
             cmd == Cmd_ListWithPathTabular ) {
    int size = 0;
    for(csWStringList::const_iterator it = files.begin(); it != files.end(); it++) {
      wchar_t *uncName = 0;
      if( isUnc  &&  (uncName = resolveUNC(it->c_str())) != 0 ) {
        size += lenFN(csWString(uncName), cmd);
        delete[] uncName;
      } else {
        size += lenFN(*it, cmd);
      }
    }

    wchar_t *text = new wchar_t[size+1];
    if( text == 0 ) {
      return false;
    }

    int pos = 0;
    for(csWStringList::const_iterator it = files.begin(); it != files.end(); it++) {
      wchar_t *uncName = 0;
      if( isUnc  &&  (uncName = resolveUNC(it->c_str())) != 0 ) {
        catFN(text, pos, csWString(uncName), cmd);
        delete[] uncName;
      } else {
        catFN(text, pos, *it, cmd);
      }
    }
    text[size] = L'\0';

    if( files.size() == 1 ) {
      // Overwrite trailing <CR><LF>
      text[size-1] = text[size-2] = L'\0';
    }

    if( isUnix ) {
      replace(text, size, L'\\', L'/');
    }

    setClipboardText(text);
    delete[] text;

    return true;

  } else if( cmd == Cmd_CreateSymbolicLink ) {

    csWString symLink;

    IFileSaveDialog *saveDialog = NULL;
    HRESULT hr = CoCreateInstance(CLSID_FileSaveDialog, NULL, CLSCTX_INPROC_SERVER,
                                  IID_IFileSaveDialog, (LPVOID*)&saveDialog);
    if( hr == S_OK ) {
      saveDialog->SetTitle(L"Create symbolic link");

      const int index = files.front().lastIndexOf(L'\\');
      if( index >= 0 ) {
        const csWString path = files.front().mid(0, index);
        const csWString name = files.front().mid(index+1);

        PIDLIST_ABSOLUTE pidl = NULL;
        SHParseDisplayName(path.c_str(), NULL, &pidl, 0, NULL);
        if( pidl != NULL ) {
          IShellItem *item = NULL;
          SHCreateItemFromIDList(pidl, IID_IShellItem, (LPVOID*)&item);
          if( item != NULL ) {
            saveDialog->SetFolder(item);
            item->Release();
          }
          CoTaskMemFree(pidl);
        }

        saveDialog->SetFileName(name.c_str());
      }

      const COMDLG_FILTERSPEC filterSpec = {
        L"All files", L"*.*"
      };
      saveDialog->SetFileTypes(1, &filterSpec);

      const FILEOPENDIALOGOPTIONS opts
          = FOS_OVERWRITEPROMPT
          | FOS_FORCEFILESYSTEM
          | FOS_PATHMUSTEXIST
          | FOS_CREATEPROMPT
          | FOS_NOREADONLYRETURN
          | FOS_NODEREFERENCELINKS
          | FOS_DONTADDTORECENT;
      saveDialog->SetOptions(opts);

      if( saveDialog->Show(NULL) == S_OK ) {
        IShellItem *item = NULL;
        if( saveDialog->GetResult(&item) == S_OK ) {
          wchar_t *filename = NULL;
          if( item->GetDisplayName(SIGDN_FILESYSPATH, &filename) == S_OK ) {
            symLink = filename;
            CoTaskMemFree(filename);
          }

          item->Release();
        }
      }

      saveDialog->Release();
    }

    if( !symLink.empty() ) {
      if( csFileExists(symLink.c_str()) ) {
        MessageBoxW(NULL, L"Symbolic link target already exists!",
                    L"Error", MB_OK | MB_ICONERROR);
        return false;
      }

      const DWORD linkFlags = csIsDirectory(files.front().c_str())
          ? SYMBOLIC_LINK_FLAG_DIRECTORY
          : 0;

      if( CreateSymbolicLinkW(symLink.c_str(),
                              files.front().c_str(),
                              linkFlags) == 0 ) {
        const DWORD lastError = GetLastError();

        csWString msg(L"ERROR(0x");
        msg += csWString::number(lastError, 16);
        msg += L"): ";
        msg += formatError(lastError);

        MessageBoxW(NULL, msg.c_str(),
                    L"Error", MB_OK | MB_ICONERROR);
        return false;
      }
    }

    return true;

  } else if( cmd == Cmd_CheckBatchProcessing ) {
    regWriteFlags(flags ^ CMD_FLAG_BATCH);
    return true;

  } else if( cmd == Cmd_CheckParallelExecution ) {
    regWriteFlags(flags ^ CMD_FLAG_PARALLEL);
    return true;

  } else if( cmd == Cmd_CheckResolveUncPaths ) {
    regWriteFlags(flags ^ CMD_FLAG_UNC);
    return true;

  } else if( cmd == Cmd_CheckUnixPathSeparators ) {
    regWriteFlags(flags ^ CMD_FLAG_UNIX);
    return true;

  } else if( Cmd_ExecuteScripts <= cmd  &&  cmd < Cmd_ExecuteScripts+scripts.size() ) {
    csWString script(scriptPath + L"\\");
    UINT i = 0;
    for(csWStringList::const_iterator it = scripts.begin(); it != scripts.end(); it++) {
      if( i == cmd-Cmd_ExecuteScripts ) {
        script += *it;
        break;
      }
      i++;
    }

    if( isParallel ) {
      csWStringList args(files);
      args.push_front(script);
      args.push_front(csWString::number(parallelCount));
      ShellExecuteW(NULL, L"open", parallel.c_str(), joinFileNames(args).c_str(),
                    NULL, SW_SHOWNORMAL);
    } else { // DO NOT use parallelizer
      if( isBatch ) {
        const csWString args = joinFileNames(files);
        ShellExecuteW(NULL, L"open", script.c_str(), args.c_str(), NULL, SW_SHOWNORMAL);
      } else { // NO batch processing
        for(csWStringList::const_iterator it = files.begin();
            it != files.end(); it++) {
          ShellExecuteW(NULL, L"open", script.c_str(), quoteFileName(*it).c_str(),
                        NULL, SW_SHOWNORMAL);
        }
      }
    }
    return true;

  }

  return false;
}
MODULE* GPCB_FPL_CACHE::parseMODULE( LINE_READER* aLineReader ) throw( IO_ERROR, PARSE_ERROR )
{
    #define TEXT_DEFAULT_SIZE  ( 40*IU_PER_MILS )
    #define OLD_GPCB_UNIT_CONV IU_PER_MILS

    // Old version unit = 1 mil, so conv_unit is 10 or 0.1
    #define NEW_GPCB_UNIT_CONV ( 0.01*IU_PER_MILS )

    int                   paramCnt;
    double                conv_unit = NEW_GPCB_UNIT_CONV; // GPCB unit = 0.01 mils and Pcbnew 0.1
    wxPoint               textPos;
    wxString              msg;
    wxArrayString         parameters;
    std::auto_ptr<MODULE> module( new MODULE( NULL ) );


    if( aLineReader->ReadLine() == NULL )
        THROW_IO_ERROR( "unexpected end of file" );

    parameters.Clear();
    parseParameters( parameters, aLineReader );
    paramCnt = parameters.GetCount();

    /* From the Geda PCB documentation, valid Element definitions:
     *   Element [SFlags "Desc" "Name" "Value" MX MY TX TY TDir TScale TSFlags]
     *   Element (NFlags "Desc" "Name" "Value" MX MY TX TY TDir TScale TNFlags)
     *   Element (NFlags "Desc" "Name" "Value" TX TY TDir TScale TNFlags)
     *   Element (NFlags "Desc" "Name" TX TY TDir TScale TNFlags)
     *   Element ("Desc" "Name" TX TY TDir TScale TNFlags)
     */

    if( parameters[0].CmpNoCase( wxT( "Element" ) ) != 0 )
    {
        msg.Printf( _( "unknown token \"%s\"" ), GetChars( parameters[0] ) );
        THROW_PARSE_ERROR( msg, aLineReader->GetSource(), (const char *)aLineReader,
                           aLineReader->LineNumber(), 0 );
    }

    if( paramCnt < 10 || paramCnt > 14 )
    {
        msg.Printf( _( "Element token contains %d parameters." ), paramCnt );
        THROW_PARSE_ERROR( msg, aLineReader->GetSource(), (const char *)aLineReader,
                           aLineReader->LineNumber(), 0 );
    }

    // Test symbol after "Element": if [ units = 0.01 mils, and if ( units = 1 mil
    if( parameters[1] == wxT( "(" ) )
        conv_unit = OLD_GPCB_UNIT_CONV;

    if( paramCnt > 10 )
    {
        module->SetDescription( parameters[3] );
        module->SetReference( parameters[4] );
    }
    else
    {
        module->SetDescription( parameters[2] );
        module->SetReference( parameters[3] );
    }

    // Read value
    if( paramCnt > 10 )
        module->SetValue( parameters[5] );
    // With gEDA/pcb, value is meaningful after instantiation, only, so it's
    // often empty in bare footprints.
    if( module->Value().GetText().IsEmpty() )
        module->Value().SetText( wxT( "Val**" ) );


    if( paramCnt == 14 )
    {
        textPos = wxPoint( parseInt( parameters[8], conv_unit ),
                           parseInt( parameters[9], conv_unit ) );
    }
    else
    {
        textPos = wxPoint( parseInt( parameters[6], conv_unit ),
                           parseInt( parameters[7], conv_unit ) );
    }

    int orientation = parseInt( parameters[paramCnt-4], 1.0 );
    module->Reference().SetOrientation( (orientation % 2) ? 900 : 0 );

    // Calculate size: default height is 40 mils, width 30 mil.
    // real size is:  default * ibuf[idx+3] / 100 (size in gpcb is given in percent of default size
    int thsize = parseInt( parameters[paramCnt-3], TEXT_DEFAULT_SIZE ) / 100;
    thsize = std::max( (int)( 5 * IU_PER_MILS ), thsize ); // Ensure a minimal size = 5 mils
    int twsize = thsize * 30 / 40;
    int thickness = thsize / 8;

    // gEDA/pcb aligns top/left, not pcbnew's default, center/center.
    // Compensate for this by shifting the insertion point instead of the
    // aligment, because alignment isn't changeable in the GUI.
    textPos.x = textPos.x + twsize * module->GetReference().Len() / 2;
    textPos.y += thsize / 2;

    // gEDA/pcb draws a bit too low/left, while pcbnew draws a bit too
    // high/right. Compensate for similar appearance.
    textPos.x -= thsize / 10;
    textPos.y += thsize / 2;

    module->Reference().SetTextPosition( textPos );
    module->Reference().SetPos0( textPos );
    module->Reference().SetSize( wxSize( twsize, thsize ) );
    module->Reference().SetThickness( thickness );

    // gEDA/pcb shows only one of value/reference/description at a time. Which
    // one is selectable by a global menu setting. pcbnew needs reference as
    // well as value visible, so place the value right below the reference.
    module->Value().SetOrientation( module->Reference().GetOrientation() );
    module->Value().SetSize( module->Reference().GetSize() );
    module->Value().SetThickness( module->Reference().GetThickness() );
    textPos.y += thsize * 13 / 10;  // 130% line height
    module->Value().SetTextPosition( textPos );
    module->Value().SetPos0( textPos );

    while( aLineReader->ReadLine() )
    {
        parameters.Clear();
        parseParameters( parameters, aLineReader );

        if( parameters.IsEmpty() || parameters[0] == wxT( "(" ) )
            continue;

        if( parameters[0] == wxT( ")" ) )
            break;

        paramCnt = parameters.GetCount();

        // Test units value for a string line param (more than 3 parameters : ident [ xx ] )
        if( paramCnt > 3 )
        {
            if( parameters[1] == wxT( "(" ) )
                conv_unit = OLD_GPCB_UNIT_CONV;
            else
                conv_unit = NEW_GPCB_UNIT_CONV;
        }

        wxLogTrace( traceFootprintLibrary, wxT( "%s parameter count = %d." ),
                    GetChars( parameters[0] ), paramCnt );

        // Parse a line with format: ElementLine [X1 Y1 X2 Y2 Thickness]
        if( parameters[0].CmpNoCase( wxT( "ElementLine" ) ) == 0 )
        {
            if( paramCnt != 8 )
            {
                msg.Printf( wxT( "ElementLine token contains %d parameters." ), paramCnt );
                THROW_PARSE_ERROR( msg, aLineReader->GetSource(), (const char *)aLineReader,
                                   aLineReader->LineNumber(), 0 );
            }

            EDGE_MODULE* drawSeg = new EDGE_MODULE( module.get() );
            drawSeg->SetLayer( F_SilkS );
            drawSeg->SetShape( S_SEGMENT );
            drawSeg->SetStart0( wxPoint( parseInt( parameters[2], conv_unit ),
                                         parseInt( parameters[3], conv_unit ) ) );
            drawSeg->SetEnd0( wxPoint( parseInt( parameters[4], conv_unit ),
                                       parseInt( parameters[5], conv_unit ) ) );
            drawSeg->SetWidth( parseInt( parameters[6], conv_unit ) );
            drawSeg->SetDrawCoord();
            module->GraphicalItems().PushBack( drawSeg );
            continue;
        }

        // Parse an arc with format: ElementArc [X Y Width Height StartAngle DeltaAngle Thickness]
        if( parameters[0].CmpNoCase( wxT( "ElementArc" ) ) == 0 )
        {
            if( paramCnt != 10 )
            {
                msg.Printf( wxT( "ElementArc token contains %d parameters." ), paramCnt );
                THROW_PARSE_ERROR( msg, aLineReader->GetSource(), (const char *)aLineReader,
                                   aLineReader->LineNumber(), 0 );
            }

            // Pcbnew does know ellipse so we must have Width = Height
            EDGE_MODULE* drawSeg = new EDGE_MODULE( module.get() );
            drawSeg->SetLayer( F_SilkS );
            drawSeg->SetShape( S_ARC );
            module->GraphicalItems().PushBack( drawSeg );

            // for and arc: ibuf[3] = ibuf[4]. Pcbnew does not know ellipses
            int     radius = ( parseInt( parameters[4], conv_unit ) +
                               parseInt( parameters[5], conv_unit ) ) / 2;

            wxPoint centre( parseInt( parameters[2], conv_unit ),
                            parseInt( parameters[3], conv_unit ) );

            drawSeg->SetStart0( centre );

            // Pcbnew start angles are inverted and 180 degrees from Geda PCB angles.
            double start_angle = parseInt( parameters[6], -10.0 ) + 1800.0;

            // Pcbnew delta angle direction is the opposite of Geda PCB delta angles.
            double sweep_angle = parseInt( parameters[7], -10.0 );

            // Geda PCB does not support circles.
            if( sweep_angle == -3600.0 )
                drawSeg->SetShape( S_CIRCLE );

            // Angle value is clockwise in gpcb and Pcbnew.
            drawSeg->SetAngle( sweep_angle );
            drawSeg->SetEnd0( wxPoint( radius, 0 ) );

            // Calculate start point coordinate of arc
            wxPoint arcStart( drawSeg->GetEnd0() );
            RotatePoint( &arcStart, -start_angle );
            drawSeg->SetEnd0( centre + arcStart );
            drawSeg->SetWidth( parseInt( parameters[8], conv_unit ) );
            drawSeg->SetDrawCoord();
            continue;
        }

        // Parse a Pad with no hole with format:
        //   Pad [rX1 rY1 rX2 rY2 Thickness Clearance Mask "Name" "Number" SFlags]
        //   Pad (rX1 rY1 rX2 rY2 Thickness Clearance Mask "Name" "Number" NFlags)
        //   Pad (aX1 aY1 aX2 aY2 Thickness "Name" "Number" NFlags)
        //   Pad (aX1 aY1 aX2 aY2 Thickness "Name" NFlags)
        if( parameters[0].CmpNoCase( wxT( "Pad" ) ) == 0 )
        {
            if( paramCnt < 10 || paramCnt > 13 )
            {
                msg.Printf( wxT( "Pad token contains %d parameters." ), paramCnt );
                THROW_PARSE_ERROR( msg, aLineReader->GetSource(), (const char *)aLineReader,
                                   aLineReader->LineNumber(), 0 );
            }

            D_PAD* pad = new D_PAD( module.get() );

            static const LSET pad_front( 3, F_Cu, F_Mask, F_Paste );
            static const LSET pad_back(  3, B_Cu, B_Mask, B_Paste );

            pad->SetShape( PAD_SHAPE_RECT );
            pad->SetAttribute( PAD_ATTRIB_SMD );
            pad->SetLayerSet( pad_front );

            if( testFlags( parameters[paramCnt-2], 0x0080, wxT( "onsolder" ) ) )
                pad->SetLayerSet( pad_back );

            // Set the pad name:
            // Pcbnew pad name is used for electrical connection calculations.
            // Accordingly it should be mapped to gEDA's pin/pad number,
            // which is used for the same purpose.
            // gEDA also features a pin/pad "name", which is an arbitrary string
            // and set to the pin name of the netlist on instantiation. Many gEDA
            // bare footprints use identical strings for name and number, so this
            // can be a bit confusing.
            pad->SetPadName( parameters[paramCnt-3] );

            int x1 = parseInt( parameters[2], conv_unit );
            int x2 = parseInt( parameters[4], conv_unit );
            int y1 = parseInt( parameters[3], conv_unit );
            int y2 = parseInt( parameters[5], conv_unit );
            int width = parseInt( parameters[6], conv_unit );
            wxPoint delta( x2 - x1, y2 - y1 );
            double angle = atan2( (double)delta.y, (double)delta.x );

            // Get the pad clearance and the solder mask clearance.
            if( paramCnt == 13 )
            {
                int clearance = parseInt( parameters[7], conv_unit );
                // One of gEDA's oddities is that clearance between pad and polygon
                // is given as the gap on both sides of the pad together, so for
                // KiCad it has to halfed.
                pad->SetLocalClearance( clearance / 2 );

                // In GEDA, the mask value is the size of the hole in this
                // solder mask. In Pcbnew, it is a margin, therefore the distance
                // between the copper and the mask
                int maskMargin = parseInt( parameters[8], conv_unit );
                maskMargin = ( maskMargin - width ) / 2;
                pad->SetLocalSolderMaskMargin( maskMargin );
            }

            // Negate angle (due to Y reversed axis) and convert it to internal units
            angle = - RAD2DECIDEG( angle );
            pad->SetOrientation( KiROUND( angle ) );

            wxPoint padPos( (x1 + x2) / 2, (y1 + y2) / 2 );

            pad->SetSize( wxSize( KiROUND( EuclideanNorm( delta ) ) + width,
                                  width ) );

            padPos += module->GetPosition();
            pad->SetPos0( padPos );
            pad->SetPosition( padPos );

            if( !testFlags( parameters[paramCnt-2], 0x0100, wxT( "square" ) ) )
            {
                if( pad->GetSize().x == pad->GetSize().y )
                    pad->SetShape( PAD_SHAPE_CIRCLE );
                else
                    pad->SetShape( PAD_SHAPE_OVAL );
            }

            module->Add( pad );
            continue;
        }

        // Parse a Pin with through hole with format:
        //    Pin [rX rY Thickness Clearance Mask Drill "Name" "Number" SFlags]
        //    Pin (rX rY Thickness Clearance Mask Drill "Name" "Number" NFlags)
        //    Pin (aX aY Thickness Drill "Name" "Number" NFlags)
        //    Pin (aX aY Thickness Drill "Name" NFlags)
        //    Pin (aX aY Thickness "Name" NFlags)
        if( parameters[0].CmpNoCase( wxT( "Pin" ) ) == 0 )
        {
            if( paramCnt < 8 || paramCnt > 12 )
            {
                msg.Printf( wxT( "Pin token contains %d parameters." ), paramCnt );
                THROW_PARSE_ERROR( msg, aLineReader->GetSource(), (const char *)aLineReader,
                                   aLineReader->LineNumber(), 0 );
            }

            D_PAD* pad = new D_PAD( module.get() );

            pad->SetShape( PAD_SHAPE_CIRCLE );

            static const LSET pad_set = LSET::AllCuMask() | LSET( 3, F_SilkS, F_Mask, B_Mask );

            pad->SetLayerSet( pad_set );

            if( testFlags( parameters[paramCnt-2], 0x0100, wxT( "square" ) ) )
                pad->SetShape( PAD_SHAPE_RECT );

            // Set the pad name:
            // Pcbnew pad name is used for electrical connection calculations.
            // Accordingly it should be mapped to gEDA's pin/pad number,
            // which is used for the same purpose.
            pad->SetPadName( parameters[paramCnt-3] );

            wxPoint padPos( parseInt( parameters[2], conv_unit ),
                            parseInt( parameters[3], conv_unit ) );

            int padSize = parseInt( parameters[4], conv_unit );

            pad->SetSize( wxSize( padSize, padSize ) );

            int drillSize = 0;

            // Get the pad clearance, solder mask clearance, and drill size.
            if( paramCnt == 12 )
            {
                int clearance = parseInt( parameters[5], conv_unit );
                // One of gEDA's oddities is that clearance between pad and polygon
                // is given as the gap on both sides of the pad together, so for
                // KiCad it has to halfed.
                pad->SetLocalClearance( clearance / 2 );

                // In GEDA, the mask value is the size of the hole in this
                // solder mask. In Pcbnew, it is a margin, therefore the distance
                // between the copper and the mask
                int maskMargin = parseInt( parameters[6], conv_unit );
                maskMargin = ( maskMargin - padSize ) / 2;
                pad->SetLocalSolderMaskMargin( maskMargin );

                drillSize = parseInt( parameters[7], conv_unit );
            }
            else
            {
                drillSize = parseInt( parameters[5], conv_unit );
            }

            pad->SetDrillSize( wxSize( drillSize, drillSize ) );
            padPos += module->GetPosition();
            pad->SetPos0( padPos );
            pad->SetPosition( padPos );

            if( pad->GetShape() == PAD_SHAPE_CIRCLE  &&  pad->GetSize().x != pad->GetSize().y )
                pad->SetShape( PAD_SHAPE_OVAL );

            module->Add( pad );
            continue;
        }
    }

    // Recalculate the bounding box
    module->CalculateBoundingBox();
    return module.release();
}