void HippoUI_RenderD3D9::Init()
{
	
	//create sprite
	HRESULT hr = D3DXCreateSprite( m_pd3dDevice, &m_pSprite );
	if( FAILED( hr ) )
	{
		m_pSprite=0;
		ReportErr("D3DXCreateSprite Failed");
	}
	const int default_font_h=10;
	hr = D3DXCreateFont( m_pd3dDevice,
		16,					// Height
		0,                     // Width
		FW_NORMAL,               // Weight
		1,                     // MipLevels, 0 = autogen mipmaps
		FALSE,                 // Italic
		DEFAULT_CHARSET,       // CharSet
		OUT_DEFAULT_PRECIS,    // OutputPrecision
		DEFAULT_QUALITY,       // Quality
		DEFAULT_PITCH | FF_DONTCARE, // PitchAndFamily
		"Arial",              // pFaceName
		&m_pFont );              // ppFont
	if( FAILED( hr ) )
	{
		m_pFont=0;
		ReportErr("D3DXCreateFont Failed");
	}
}
Beispiel #2
0
void TerrainBorderRenderable::MakeIndexBuffer()
{
	auto device = Globals::GetDevice()->GetDeviceD3D9();
	IDirect3DIndexBuffer9* pIb = 0;
	HRESULT res = device->CreateIndexBuffer(24 * sizeof(WORD), D3DUSAGE_WRITEONLY, D3DFMT_INDEX16, D3DPOOL_MANAGED, &pIb, 0);
	if (res != S_OK)
		ReportErr("TerrainBorder CreateIB Failed");
	m_pIB.reset(pIb, [&](IDirect3DIndexBuffer9* p){p->Release(); });
	WORD* g_Indices = 0;
	m_pIB->Lock(0, 0, (void**)&g_Indices, 0);
	// positive x
	g_Indices[0] = 0; g_Indices[1] = 1; g_Indices[2] = 2;
	g_Indices[3] = 0; g_Indices[4] = 2; g_Indices[5] = 3;
	// negative x
	g_Indices[6] = 4; g_Indices[7] = 5; g_Indices[8] = 6;
	g_Indices[9] = 4; g_Indices[10] = 6; g_Indices[11] = 7;
	// positive z
	g_Indices[12] = 8; g_Indices[13] = 9; g_Indices[14] = 10;
	g_Indices[15] = 8; g_Indices[16] = 10; g_Indices[17] = 11;
	// negative z
	g_Indices[18] = 12; g_Indices[19] = 13; g_Indices[20] = 14;
	g_Indices[21] = 12; g_Indices[22] = 14; g_Indices[23] = 15;

	m_pIB->Unlock();
}
Beispiel #3
0
void TerrainRenderable::MakeIndexBuffer()
{
	auto device = Globals::GetDevice()->GetDeviceD3D9();

	HRESULT res = device->CreateIndexBuffer(GetIndexNum() * sizeof(WORD), D3DUSAGE_WRITEONLY, D3DFMT_INDEX16, D3DPOOL_MANAGED, &m_pIB, 0);
	if (res != S_OK)
		ReportErr("Terrain CreateIB Failed");

	WORD* g_Indices = 0;
	res = m_pIB->Lock(0, 0, (void**)&g_Indices, 0);
	for (int y = 0; y < terrain_h-1; ++y)
	{
		for (int x = 0; x < terrain_w-1; ++x)
		{
			m_IndexData.push_back((x + 0) + (y + 0)*terrain_w);
			m_IndexData.push_back((x + 0) + (y + 1)*terrain_w);
			m_IndexData.push_back((x + 1) + (y + 1)*terrain_w);

			m_IndexData.push_back((x + 0) + (y + 0)*terrain_w);
			m_IndexData.push_back((x + 1) + (y + 1)*terrain_w);
			m_IndexData.push_back((x + 1) + (y + 0)*terrain_w);
		}
	}
	WORD* first=&(m_IndexData[0]);
	memcpy_s(g_Indices,GetIndexNum() * sizeof(WORD),first,GetIndexNum() * sizeof(WORD));
	res = m_pIB->Unlock();
}
Beispiel #4
0
void TerrainRenderable::MakeVertexBuffer()
{
	auto device = Globals::GetDevice()->GetDeviceD3D9();
	int n=GetVertexNum();
	HRESULT res = device->CreateVertexBuffer(n * sizeof(TerrainVertex), D3DUSAGE_WRITEONLY, 0, D3DPOOL_MANAGED, &m_pVB, 0);
	if (res != S_OK)
		ReportErr("Terrain CreateVB Failed");
	TerrainVertex* v = 0;
	int idx=0;
	m_pVB->Lock(0, 0, (void**)&v, 0);

	for (int y = 0; y < terrain_h; ++y)
	{
		for (int x = 0; x < terrain_w; ++x)
		{
			float posx=x;
			float posz=y;
			ConvertPos(posx,posz);
			m_VertexData.push_back(TerrainVertex(posx, m_pHeightField->GetHeight(x,y), posz, (float)x / terrain_w, (float)y / terrain_h));
			//v[idx++]=TerrainVertex(x*vertex_stride - orgX_Offset, GetTerrainHeight(x,y), y*vertex_stride - orgY_Offset, (float)x / terrain_w, (float)y / terrain_h);
		}
	}
	TerrainVertex* first=&(m_VertexData[0]);
	memcpy_s(v,n*sizeof(TerrainVertex),first,n*sizeof(TerrainVertex));
	m_pVB->Unlock();
}
Beispiel #5
0
void TerrainPatch::CalcIndexBuffer()
{
	std::vector<WORD> tmp;
	//遍历地形中的索引,找到在圆圈内的三角形
	auto itr = m_parent->m_IndexData.begin();
	while (itr != m_parent->m_IndexData.end())
	{
		WORD idx0 = *itr;
		TerrainVertex* v0 = &m_parent->m_VertexData.at(idx0);
		++itr;

		WORD idx1 = *itr;
		TerrainVertex* v1 = &m_parent->m_VertexData.at(idx1);
		++itr;

		WORD idx2 = *itr;
		TerrainVertex* v2 = &m_parent->m_VertexData.at(idx2);
		++itr;

		if (IsTriangleInCircle2D(&m_Pos, m_r, v0, v1, v2))
		{
			tmp.push_back(idx0);
			tmp.push_back(idx1);
			tmp.push_back(idx2);
		}
	}

	if (tmp.size() > m_IndexData.size())
	{
		//删除硬件buffer
		if (m_pIB)
			m_pIB->Release();
		m_pIB = 0;
	}
	m_IndexData.swap(tmp);
	tmp.clear();

	//创建硬件buffer
	unsigned int indexsize = m_IndexData.size() * sizeof(WORD);
	if (!m_pIB)
	{
		auto device=Globals::GetDevice()->GetDeviceD3D9();
		HRESULT res = device->CreateIndexBuffer(indexsize, D3DUSAGE_DYNAMIC, D3DFMT_INDEX16, D3DPOOL_DEFAULT, &m_pIB, 0);
		if (res != S_OK)
			ReportErr("Terrain Patch CreateIB Failed");
	}
	//fill buffer
	WORD* g_Indices = 0;
	HRESULT res = m_pIB->Lock(0, 0, (void**)&g_Indices, D3DLOCK_DISCARD);
	WORD* first = &(m_IndexData[0]);
	memcpy_s(g_Indices, indexsize, first, indexsize);
	res = m_pIB->Unlock();
}
Beispiel #6
0
void WarningHeaderWithImplementation(const Tokenizer &tokenizer, OutputFormat outputFormat, std::ostream &errout)
{
    for (const Token *tok = tokenizer.tokens; tok; tok = tok->next)
    {
        // Only interested in included file
        if (tok->FileIndex == 0)
            continue;

        if (Match(tok, ") {"))
        {
            std::ostringstream ostr;
            ostr << "Found implementation in header";
            ReportErr(tokenizer, outputFormat, tok, "HeaderWithImplementation", ostr.str(), errout);
        }
    }
}
Beispiel #7
0
void TerrainBorderRenderable::MakeVertexBuffer(float left, float top, float right, float bottom)
{
	auto device = Globals::GetDevice()->GetDeviceD3D9();
	IDirect3DVertexBuffer9* pVb = 0;
	HRESULT res = device->CreateVertexBuffer(16 * sizeof(TerrainVertex), D3DUSAGE_WRITEONLY, 0, D3DPOOL_MANAGED, &pVb, 0);
	if (res != S_OK)
		ReportErr("SkyBox CreateVB Failed");
	m_pVB.reset(pVb, [&](IDirect3DVertexBuffer9* p){p->Release(); });

	TerrainVertex* v = 0;
	float scale = 500.0f;
	m_pVB->Lock(0, 0, (void**)&v, 0);
	float height = (top - bottom)*0.5f;
	float width = (right - left)*0.5f;

	// positive x
	v[0] = TerrainVertex(1.0f*right, -1.0f*height, 1.0f*width, 0.0f, 1.0f);
	v[1] = TerrainVertex(1.0f*right, 1.0f*height, 1.0f*width, 0.0f, 0.0f);
	v[2] = TerrainVertex(1.0f*right, 1.0f*height, -1.0f*width, 1.0f, 0.0f);
	v[3] = TerrainVertex(1.0f*right, -1.0f*height, -1.0f*width, 1.0f, 1.0f);
	D3DXPlaneFromPoints(&m_border_planes[POSITIVE_X], &v[0].m_pos, &v[1].m_pos, &v[2].m_pos);

	// negative x
	v[4] = TerrainVertex(1.0f*left, -1.0f*height, -1.0f*width, 0.0f, 1.0f);
	v[5] = TerrainVertex(1.0f*left, 1.0f*height, -1.0f*width, 0.0f, 0.0f);
	v[6] = TerrainVertex(1.0f*left, 1.0f*height, 1.0f*width, 1.0f, 0.0f);
	v[7] = TerrainVertex(1.0f*left, -1.0f*height, 1.0f*width, 1.0f, 1.0f);
	D3DXPlaneFromPoints(&m_border_planes[NEGATIVE_X], &v[4].m_pos, &v[5].m_pos, &v[6].m_pos);

	// positive z
	v[8] = TerrainVertex(-1.0f*width, -1.0f*height, 1.0f*top, 0.0f, 1.0f);
	v[9] = TerrainVertex(-1.0f*width, 1.0f*height, 1.0f*top, 0.0f, 0.0f);
	v[10] = TerrainVertex(1.0f*width, 1.0f*height, 1.0f*top, 1.0f, 0.0f);
	v[11] = TerrainVertex(1.0f*width, -1.0f*height, 1.0f*top, 1.0f, 1.0f);
	D3DXPlaneFromPoints(&m_border_planes[POSITIVE_Y], &v[8].m_pos, &v[9].m_pos, &v[10].m_pos);

	// negative z
	v[12] = TerrainVertex(1.0f*width, -1.0f*height, 1.0f*bottom, 0.0f, 1.0f);
	v[13] = TerrainVertex(1.0f*width, 1.0f*height, 1.0f*bottom, 0.0f, 0.0f);
	v[14] = TerrainVertex(-1.0f*width, 1.0f*height, 1.0f*bottom, 1.0f, 0.0f);
	v[15] = TerrainVertex(-1.0f*width, -1.0f*height, 1.0f*bottom, 1.0f, 1.0f);
	D3DXPlaneFromPoints(&m_border_planes[NEGATIVE_Y], &v[12].m_pos, &v[13].m_pos, &v[14].m_pos);

	m_pVB->Unlock();
}
void HippoUI_RenderD3D9::DrawString(HippoUI_Rect& rect,const WCHAR* str,HippoUi_Color& color,TEXT_AG ag)
{
	D3DXMATRIX matTransform;
	D3DXMatrixIdentity( &matTransform );
	m_pSprite->SetTransform( &matTransform );

	HRESULT res = m_pFont->DrawTextW(
		m_pSprite, 
		str, 
		-1, 
		&rect, //rect
		ConvertTextAG2D3dxFont(ag),//Format
		D3DXCOLOR( color.r, color.g, color.b, color.a ) );

	if(FAILED(res))
	{
		ReportErr("DrawString draw failed");
	}
}
Beispiel #9
0
void TerrainRenderablePlane::MakeVertexBuffer()
{
	auto device = Globals::GetDevice()->GetDeviceD3D9();
	int n = GetVertexNum();
	HRESULT res = device->CreateVertexBuffer(n * sizeof(TerrainVertex), D3DUSAGE_WRITEONLY, 0, D3DPOOL_MANAGED, &m_pVB, 0);
	if (res != S_OK)
		ReportErr("Terrain CreateVB Failed");
	TerrainVertex* v = 0;
	int idx = 0;
	m_pVB->Lock(0, 0, (void**)&v, 0);

	m_VertexData.push_back(TerrainVertex(0 - w / 2, 0 , 0 - h / 2, 0, 0));
	m_VertexData.push_back(TerrainVertex(0 - w / 2, 0 , h - h / 2, 0, 1));
	m_VertexData.push_back(TerrainVertex(w - w / 2, 0 , h - h / 2, 1, 1));
	m_VertexData.push_back(TerrainVertex(w - w / 2, 0 , 0 - h / 2, 1, 0));

	TerrainVertex* first = &(m_VertexData[0]);
	memcpy_s(v, n*sizeof(TerrainVertex), first, n*sizeof(TerrainVertex));
	m_pVB->Unlock();
}
Beispiel #10
0
void TerrainRenderablePlane::MakeIndexBuffer()
{
	auto device = Globals::GetDevice()->GetDeviceD3D9();

	HRESULT res = device->CreateIndexBuffer(GetIndexNum() * sizeof(WORD), D3DUSAGE_WRITEONLY, D3DFMT_INDEX16, D3DPOOL_MANAGED, &m_pIB, 0);
	if (res != S_OK)
		ReportErr("Terrain CreateIB Failed");

	WORD* g_Indices = 0;
	res = m_pIB->Lock(0, 0, (void**)&g_Indices, 0);

	m_IndexData.push_back(0);
	m_IndexData.push_back(1);
	m_IndexData.push_back(2);

	m_IndexData.push_back(0);
	m_IndexData.push_back(2);
	m_IndexData.push_back(3);

	WORD* first = &(m_IndexData[0]);
	memcpy_s(g_Indices, GetIndexNum() * sizeof(WORD), first, GetIndexNum() * sizeof(WORD));
	res = m_pIB->Unlock();
}
void HippoUI_RenderD3D9::DrawSprite(HippoUI_Rect& rect,HippoUI_TextureProxy* pTexProxy,HippoUi_Color& color)
{
	//return;
	IDirect3DTexture9* pTex=(IDirect3DTexture9*)(pTexProxy->GetHardwareTexturePtr());
	//calc scale
	D3DXMATRIXA16 matTransform;
	D3DXMatrixIdentity(&matTransform);

	float scale_x=( float )rect.GetWidth()/pTexProxy->GetRect().GetWidth();
	float scale_y=( float )rect.GetHeight()/pTexProxy->GetRect().GetHeight();
	D3DXMatrixScaling( &matTransform, scale_x, scale_y, 1.0f );
	m_pSprite->SetTransform(&matTransform);
	
	D3DXVECTOR3 vPos( ( float )rect.left, ( float )rect.top, 0.0f );
	vPos.x /= scale_x;
	vPos.y /= scale_y;

	HRESULT res=m_pSprite->Draw(pTex,pTexProxy->GetRect().GetRECT(),0,&vPos,D3DXCOLOR( color.r, color.g, color.b, color.a ));
	if(FAILED(res))
	{
		ReportErr("sprite draw failed");
	}
}
Beispiel #12
0
QTSS_Error FilterRequest(QTSS_Filter_Params* inParams)
{
    if (NULL == inParams || NULL == inParams->inRTSPSession || NULL == inParams->inRTSPRequest)
    {   Assert(0);
        return QTSS_NoErr;
    }

    OSMutexLocker locker(sAdminMutex);
    //check to see if we should handle this request. Invokation is triggered
    //by a "GET /" request
    
    QTSS_Error err = QTSS_NoErr;
    QTSS_RTSPRequestObject theRequest = inParams->inRTSPRequest;

    UInt32 paramLen = sizeof(sSessID);
    err = QTSS_GetValue(inParams->inRTSPSession, qtssRTSPSesID, 0, (void*)&sSessID, &paramLen);     
    if (err != QTSS_NoErr) 
        return QTSS_NoErr;

    StrPtrLen theFullRequest;
    err = QTSS_GetValuePtr(theRequest, qtssRTSPReqFullRequest, 0, (void**)&theFullRequest.Ptr, &theFullRequest.Len);
    if (err != QTSS_NoErr) 
        return QTSS_NoErr;
        
    
    StringParser fullRequest(&theFullRequest);
        
    if ( !IsAdminRequest(&fullRequest) ) 
        return QTSS_NoErr;
        
    if ( !AcceptSession(inParams->inRTSPSession) )
    {   (void)QTSS_Write(inParams->inRTSPRequest, sPermissionDeniedHeader, ::strlen(sPermissionDeniedHeader), NULL, 0);     
        (void)QTSS_Write(inParams->inRTSPRequest, sHTMLBody, ::strlen(sHTMLBody), NULL, 0);
        KeepSession(theRequest,false);
        return QTSS_NoErr;
    }
    
    if(!GetRequestAuthenticatedState(inParams)) // must authenticate before handling
    {
        if(QTSS_IsGlobalLocked()) // must NOT be global locked
            return QTSS_RequestFailed;
            
        if (!IsAuthentic(inParams,&fullRequest)) 
        {  
            (void)QTSS_Write(inParams->inRTSPRequest, sUnauthorizedResponseHeader, ::strlen(sUnauthorizedResponseHeader), NULL, 0);     
            (void)QTSS_Write(inParams->inRTSPRequest, sHTMLBody, ::strlen(sHTMLBody), NULL, 0);
            KeepSession(theRequest,false);
            return QTSS_NoErr;
        }
        
    }
    
    if (GetRequestFlushState(inParams)) 
    {   StillFlushing(inParams,true);
        return QTSS_NoErr;
    }
        
    if (!QTSS_IsGlobalLocked())
    {       
        if (InWaitInterval(inParams)) 
            return QTSS_NoErr; 

        //qtss_printf("New Request Wait for GlobalLock session=%"_U32BITARG_"\n",sSessID);
        (void)QTSS_RequestGlobalLock();
        KeepSession(theRequest,true);
        return QTSS_NoErr; 
    }
    
    //qtss_printf("Handle request session=%"_U32BITARG_"\n",sSessID);
    APITests_DEBUG();
    
    if (sQueryPtr != NULL) 
    {   delete sQueryPtr;
        sQueryPtr = NULL;   
    }
    sQueryPtr = NEW QueryURI(&theFullRequest);
    if (sQueryPtr == NULL) return QTSS_NoErr;
    
    ShowQuery_DEBUG();
    
    if (sAdminPtr != NULL) 
    {   delete sAdminPtr;
        sAdminPtr = NULL;
    }
    UInt32 result = sQueryPtr->EvalQuery(NULL, NULL);
    if (result == 0) do
    {
        if( ElementNode_CountPtrs() > 0)
        {   ElementNode_ShowPtrs();
            Assert(0);
        }
            
        GetQueryData(theRequest);
        
        SendResult(theRequest); 
        delete sAdminPtr;
        sAdminPtr = NULL;
        
        if (sQueryPtr && !sQueryPtr->QueryHasReponse())
        {   UInt32 err = 404;
            (void) sQueryPtr->EvalQuery(&err,NULL);
            ReportErr(inParams, err);
            break;
        }

        if (sQueryPtr && sQueryPtr->QueryHasReponse())
        {   ReportErr(inParams, sQueryPtr->GetEvaluResult());
        }
        
        if (sQueryPtr->fIsPref && sQueryPtr->GetEvaluResult() == 0)
        {   QTSS_ServiceID id;
            (void) QTSS_IDForService(QTSS_REREAD_PREFS_SERVICE, &id);           
            (void) QTSS_DoService(id, NULL);
        }
    } while(false);
    else
    {
        SendHeader(theRequest);         
        ReportErr(inParams, sQueryPtr->GetEvaluResult());
    }
    
    if (sQueryPtr != NULL) 
    {   delete sQueryPtr;
        sQueryPtr = NULL;
    }
    
    (void) StillFlushing(inParams,true);
    return QTSS_NoErr;

}
Beispiel #13
0
int main( int argc, char *argv[] )
{
    int wrank, wsize, rank, size, color;
    int j, tmp;
    int err, toterrs, errs = 0;
    MPI_Comm newcomm;

    MPI_Init( &argc, &argv );

    MPI_Comm_size( MPI_COMM_WORLD, &wsize );
    MPI_Comm_rank( MPI_COMM_WORLD, &wrank );

    /* Color is 0 or 1; 1 will be the processes that "fault" */
    /* process 0 and wsize/2+1...wsize-1 are in non-faulting group */
    color = (wrank > 0) && (wrank <= wsize/2);
    MPI_Comm_split( MPI_COMM_WORLD, color, wrank, &newcomm );

    MPI_Comm_size( newcomm, &size );
    MPI_Comm_rank( newcomm, &rank );

    /* Set errors return on COMM_WORLD and the new comm */
    MPI_Comm_set_errhandler( MPI_ERRORS_RETURN, MPI_COMM_WORLD );
    MPI_Comm_set_errhandler( MPI_ERRORS_RETURN, newcomm );

    err = MPI_Barrier( MPI_COMM_WORLD );
    if (err) errs += ReportErr( err, "Barrier" );
    if (color) {
	/* Simulate a fault on some processes */
	exit(1);
    }
    else {
	/* To improve the chance that the "faulted" processes will have
	   exited, wait for 1 second */
	sleep( 1 );
    }
    
    /* Can we still use newcomm? */
    for (j=0; j<rank; j++) {
	err = MPI_Recv( &tmp, 1, MPI_INT, j, 0, newcomm, MPI_STATUS_IGNORE );
	if (err) errs += ReportErr( err, "Recv" );
    }
    for (j=rank+1; j<size; j++) {
	err = MPI_Send( &rank, 1, MPI_INT, j, 0, newcomm );
	if (err) errs += ReportErr( err, "Recv" );
    }

    /* Now, try sending in MPI_COMM_WORLD on dead processes */
    /* There is a race condition here - we don't know for sure that the faulted
       processes have exited.  However, we can ensure a failure by using 
       synchronous sends - the sender will wait until the reciever handles 
       receives the message, which will not happen (the process will exit 
       without matching the message, even if it has not yet exited). */
    for (j=1; j<=wsize/2; j++) {
	err = MPI_Ssend( &rank, 1, MPI_INT, j, 0, MPI_COMM_WORLD );
	if (!err) {
	    errs++;
	    fprintf( stderr, "Ssend succeeded to dead process %d\n", j );
	}
    }

    err = MPI_Allreduce( &errs, &toterrs, 1, MPI_INT, MPI_SUM, newcomm );
    if (err) errs += ReportErr( err, "Allreduce" );
    MPI_Comm_free( &newcomm );

    MPI_Finalize();

    if (wrank == 0) {
	if (toterrs > 0) {
	    printf( " Found %d errors\n", toterrs );
	}
	else {
	    printf( " No Errors\n" );
	}
    }

    return 0;
}
Beispiel #14
0
void WarningIncludeHeader(const Tokenizer &tokenizer, bool Progress, OutputFormat outputFormat, std::ostream &errout)
{
    // A header is needed if:
    // * It contains some needed class declaration
    // * It contains some needed function declaration
    // * It contains some needed constant value
    // * It contains some needed variable
    // * It contains some needed enum


    // Extract all includes..
    std::vector< std::list<IncludeInfo> > includes(tokenizer.ShortFileNames.size(), std::list< IncludeInfo >());
    for (const Token *tok = tokenizer.tokens; tok; tok = tok->next)
    {
        if (strncmp(tok->str, "#include", 8) == 0)
        {
            // Get index of included file:
            unsigned int hfile;
            const char *includefile = tok->next->str;
            for (hfile = 0; hfile < tokenizer.ShortFileNames.size(); ++hfile)
            {
                if (SameFileName(tokenizer.ShortFileNames[hfile].c_str(), includefile))
                    break;
            }
            includes[tok->FileIndex].push_back(IncludeInfo(tok, hfile));
        }
    }

    // System headers are checked differently..
    std::vector<unsigned int> SystemHeaders(tokenizer.ShortFileNames.size(), 0);
    for (const Token *tok = tokenizer.tokens; tok; tok = tok->next)
    {
        if (strcmp(tok->str, "#include<>") == 0 ||
            (SystemHeaders[tok->FileIndex] && strcmp(tok->str, "#include") == 0))
        {
            // Get index of included file:
            const char *includefile = tok->next->str;
            for (unsigned int hfile = 0; hfile < tokenizer.ShortFileNames.size(); ++hfile)
            {
                if (SameFileName(tokenizer.ShortFileNames[hfile].c_str(), includefile))
                {
                    SystemHeaders[hfile] = 1;
                    break;
                }
            }
        }
    }


    // extracted class names..
    std::vector< std::set<std::string> > classes(tokenizer.ShortFileNames.size(), std::set<std::string>());

    // extracted symbol names..
    std::vector< std::set<std::string> > names(tokenizer.ShortFileNames.size(), std::set<std::string>());

    // needed symbol/type names
    std::vector< std::set<std::string> > needed(tokenizer.ShortFileNames.size(), std::set<std::string>());

    // symbol/type names that need at least a forward declaration
    std::vector< std::set<std::string> > needDeclaration(tokenizer.ShortFileNames.size(), std::set<std::string>());

    // Extract symbols from the files..
    {
        unsigned int indentlevel = 0;
        for (const Token *tok = tokenizer.tokens; tok; tok = tok->next)
        {
            // Don't extract symbols in the main source file
            if (tok->FileIndex == 0)
                continue;

            if (tok->next && tok->FileIndex != tok->next->FileIndex)
                indentlevel = 0;

            if (tok->str[0] == '{')
                indentlevel++;

            else if (indentlevel > 0 && tok->str[0] == '}')
                indentlevel--;

            if (indentlevel != 0)
                continue;

            // Class or namespace declaration..
            // --------------------------------------
            if (Match(tok,"class %var% {") || Match(tok,"class %var% :") || Match(tok,"struct %var% {"))
                classes[tok->FileIndex].insert(getstr(tok, 1));

            else if (Match(tok, "namespace %var% {") || Match(tok, "extern %str% {"))
            {
                tok = gettok(tok,2);
                continue;
            }

            else if (Match(tok, "struct %var% ;") || Match(tok, "class %var% ;"))
            {
                // This type name is probably needed in any files that includes this file
                const std::string name(tok->next->str);
                for (unsigned int i = 0; i < tokenizer.ShortFileNames.size(); ++i)
                {
                    if (i == tok->FileIndex)
                        continue;
                    for (std::list<IncludeInfo>::const_iterator it = includes[i].begin(); it != includes[i].end(); ++it)
                    {
                        if (it->hfile == tok->FileIndex)
                        {
                            needed[it->tok->FileIndex].insert(name);
                        }
                    }
                }
                continue;
            }

            // Variable declaration..
            // --------------------------------------
            else if (Match(tok, "%type% %var% ;") || Match(tok, "%type% %var% [") || Match(tok, "%type% %var% ="))
                names[tok->FileIndex].insert(getstr(tok, 1));

            else if (Match(tok, "%type% * %var% ;") || Match(tok, "%type% * %var% [") || Match(tok, "%type% * %var% ="))
                names[tok->FileIndex].insert(getstr(tok, 2));

            // enum..
            // --------------------------------------
            else if (strcmp(tok->str, "enum") == 0)
            {
                tok = tok->next;
                while (tok->next && tok->str[0]!=';')
                {
                    if (IsName(tok->str))
                        names[tok->FileIndex].insert(tok->str);
                    tok = tok->next;
                }
            }

            // function..
            // --------------------------------------
            else if (Match(tok,"%type% %var% (") ||
                     Match(tok,"%type% * %var% ("))
            {
                tok = tok->next;
                if (tok->str[0] == '*')
                    tok = tok->next;
                names[tok->FileIndex].insert(tok->str);
                while (tok->next && tok->str[0] != ')')
                    tok = tok->next;
            }

            // typedef..
            // --------------------------------------
            else if (strcmp(tok->str,"typedef")==0)
            {
                if (strcmp(getstr(tok,1),"enum")==0)
                    continue;
                while (tok->str[0] != ';' && tok->next)
                {
                    if (Match(tok, "%var% ;"))
                        names[tok->FileIndex].insert(tok->str);

                    tok = tok->next;
                }
            }

            // #define..
            // --------------------------------------
            else if (Match(tok, "#define %var%"))
                names[tok->FileIndex].insert(tok->next->str);
        }
    }

    // Get all needed symbols..
    {
        // Which files contain implementation?
        std::vector<unsigned int> HasImplementation(tokenizer.ShortFileNames.size(), 0);

        int indentlevel = 0;
        for (const Token *tok1 = tokenizer.tokens; tok1; tok1 = tok1->next)
        {
            if (strncmp(tok1->str, "#include", 8) == 0)
            {
                tok1 = tok1->next;
                continue;
            }

            if (tok1->next && tok1->FileIndex != tok1->next->FileIndex)
                indentlevel = 0;

            // implementation begins..
            else if (indentlevel == 0 && Match(tok1, ") {"))
            {
                // Go to the "{"
                while (tok1->str[0] != '{')
                    tok1 = tok1->next;
                indentlevel = 1;
                HasImplementation[tok1->FileIndex] = 1;
            }
            else if (indentlevel >= 1)
            {
                if (tok1->str[0] == '{')
                    ++indentlevel;
                else if (tok1->str[0] == '}')
                    --indentlevel;
            }

            if (Match(tok1, ": %var% {") || Match(tok1, ": %type% %var% {"))
            {
                const std::string classname(getstr(tok1, (strcmp(getstr(tok1,2),"{")) ? 2 : 1));
                needed[tok1->FileIndex].insert(classname);
            }

            if (indentlevel == 0 && Match(tok1, "%type% * %var%"))
            {
                if (Match(gettok(tok1,3), "[,;()[]"))
                {
                    needDeclaration[tok1->FileIndex].insert(tok1->str);
                    tok1 = gettok(tok1, 2);
                    continue;
                }
            }

            if (Match(tok1, "struct") || Match(tok1, "class"))
            {
                continue;
            }

            if (IsName(tok1->str) && !Match(tok1->next, "{"))
                needed[tok1->FileIndex].insert(tok1->str);
        }

        // Move needDeclaration symbols to needed for all files that has
        // implementation..
        for (unsigned int i = 0; i < HasImplementation.size(); ++i)
        {
            if (HasImplementation[i])
            {
                needed[i].insert(needDeclaration[i].begin(), needDeclaration[i].end());
            }
        }
    }

    // Remove keywords..
    for (unsigned int i = 0; i < tokenizer.ShortFileNames.size(); ++i)
    {
        const char *keywords[] = { "defined", // preprocessor
                                   "void",
                                   "bool",
                                   "char",
                                   "short",
                                   "int",
                                   "long",
                                   "float",
                                   "double",
                                   "false",
                                   "true",
                                   "std",
                                   "if",
                                   "for",
                                   "while",
                                   NULL
                                 };

        for (unsigned int k = 0; keywords[k]; ++k)
        {
            needed[i].erase(keywords[k]);
            needDeclaration[i].erase(keywords[k]);
        }
    }

    // Check if there are redundant includes..
    for (unsigned int fileIndex = 0; fileIndex < tokenizer.ShortFileNames.size(); ++fileIndex)
    {
        // Is the current file a system header? If so don't check it.
        if (SystemHeaders[fileIndex])
            continue;

        // Check if each include is needed..
        for (std::list<IncludeInfo>::const_iterator include = includes[fileIndex].begin(); include != includes[fileIndex].end(); ++include)
        {
            // include not found
            if (include->hfile >= tokenizer.ShortFileNames.size())
                continue;

            if (Progress)
            {
                std::cout << "progress: file " << tokenizer.ShortFileNames[fileIndex] << " checking include " << tokenizer.ShortFileNames[include->hfile] << std::endl;
            }

            // Get all includes
            std::set<unsigned int> AllIncludes;
            bool notfound = false;
            AllIncludes.insert(include->hfile);
            if (SystemHeaders[include->hfile])
                getincludes(includes, include->hfile, AllIncludes, notfound);

            // match symbols: needed
            bool Needed(false);
            for (std::set<unsigned int>::const_iterator it = AllIncludes.begin(); it != AllIncludes.end(); ++it)
            {
                const std::string sym = matchSymbols(needed[fileIndex], classes[*it], names[*it]);
                if (!sym.empty())
                {
                    if (Progress)
                        std::cout << "progress: needed symbol '" << sym << "'" << std::endl;
                    Needed = true;
                    break;
                }
            }

            // Check if local header is needed indirectly..
            if (!Needed && !SystemHeaders[include->hfile])
            {
                std::string needed_header;

                getincludes(includes, include->hfile, AllIncludes, notfound);
                for (std::set<unsigned int>::const_iterator it = AllIncludes.begin(); it != AllIncludes.end(); ++it)
                {
                    const std::string sym = matchSymbols(needed[fileIndex], classes[*it], names[*it]);
                    if (!sym.empty())
                    {
                        needed_header = tokenizer.ShortFileNames[*it];

                        if (Progress)
                            std::cout << "progress: needed symbol '" << sym << "'" << std::endl;
                        Needed = true;
                        break;
                    }
                }

                if (Needed)
                {
                    std::ostringstream errmsg;
                    errmsg << "Inconclusive results: The included header '"
                           << include->tok->next->str
                           << "' is not needed. However it is needed indirectly because it includes '"
                           << needed_header
                           << "'. If it is included by intention use '--skip "
                           << include->tok->next->str
                           << "' to remove false positives.";
                    ReportErr(tokenizer, outputFormat, include->tok, "HeaderNotNeeded", errmsg.str(), errout);
                }
            }

            if (!Needed)
            {
                if (!notfound)
                {
                    bool NeedDeclaration(false);
                    for (std::set<unsigned int>::const_iterator it = AllIncludes.begin(); it != AllIncludes.end(); ++it)
                    {
                        std::set<std::string> empty;
                        const std::string sym = matchSymbols(needDeclaration[fileIndex], classes[*it], empty);
                        if (!sym.empty())
                        {
                            NeedDeclaration = true;
                            break;
                        }
                    }

                    std::ostringstream errmsg;
                    errmsg << "The included header '" << include->tok->next->str << "' is not needed";
                    if (NeedDeclaration)
                        errmsg << " (but forward declaration is needed)";

                    ReportErr(tokenizer, outputFormat, include->tok, "HeaderNotNeeded", errmsg.str(), errout);
                }
                else if (Progress)
                    std::cout << "progress: bail out (header not found)" << std::endl;
            }
        }
    }
}