//-----------------------------------------------------------------------------
// Purpose: returns the next index, or INVALID_STRING_INDEX if no more strings available
//-----------------------------------------------------------------------------
StringIndex_t CLocalizedStringTable::GetNextStringIndex(StringIndex_t index)
{
	StringIndex_t idx = m_Lookup.NextInorder(index);
	if (idx == m_Lookup.InvalidIndex())
		return INVALID_STRING_INDEX;
	return idx;
}
void CAI_GoalEntity::InputUpdateActors( inputdata_t &inputdata )
{
	int i;
	CUtlRBTree<CAI_BaseNPC *> prevActors;
	CUtlRBTree<CAI_BaseNPC *>::IndexType_t index;

	SetDefLessFunc( prevActors );
	
	PruneActors();
	
	for ( i = 0; i < m_actors.Count(); i++ )
	{
		prevActors.Insert( m_actors[i] );
	}
	
	ResolveNames();
	
	for ( i = 0; i < m_actors.Count(); i++ )
	{
		index = prevActors.Find( m_actors[i] );
		if ( index == prevActors.InvalidIndex() )
		{
			if ( m_flags & ACTIVE )
				EnableGoal( m_actors[i] );
		}
		else
			prevActors.Remove( m_actors[i] );
	}
	
	for ( index = prevActors.FirstInorder(); index != prevActors.InvalidIndex(); index = prevActors.NextInorder( index ) )
	{
		if ( m_flags & ACTIVE )
			DisableGoal( prevActors[ index ] );
	}
}
void BuildWhiteList()
{
	// Search for unusedcontent.cfg file
	if ( !g_pFileSystem->FileExists( WHITELIST_FILE ) )
	{
		vprint( 1, "Running with no whitelist.cfg file!!!\n" );
		return;
	}

	vprint( 1, "\nBuilding whitelist\n" );

	KeyValues *kv = new KeyValues( WHITELIST_FILE );
	if ( kv )
	{
		if ( kv->LoadFromFile( g_pFileSystem, WHITELIST_FILE, NULL ) )
		{
			for ( KeyValues *sub = kv->GetFirstSubKey(); sub; sub = sub->GetNextKey() )
			{
				if ( !Q_stricmp( sub->GetName(), "add" ) )
				{
					AddToWhiteList( sub->GetString() );
				}
				else if ( !Q_stricmp( sub->GetName(), "remove" ) )
				{
					RemoveFromWhiteList( sub->GetString() );
				}
				else
				{
					vprint( 1, "Unknown subkey '%s' in %s\n", sub->GetName(), WHITELIST_FILE );
				}
			}
		}

		kv->deleteThis();
	}

	if ( verbose || printwhitelist )
	{
		vprint( 1, "Whitelist:\n\n" );


		for ( int i = g_WhiteList.FirstInorder(); 
			i != g_WhiteList.InvalidIndex(); 
			i = g_WhiteList.NextInorder( i ) )
		{
			UnusedContent::CUtlSymbol& sym = g_WhiteList[ i ];

			char const *resolved = g_Analysis.symbols.String( sym );
			vprint( 2, "  %s\n", resolved );
		}
	}

	// dump the whitelist file list anyway
	{
		filesystem->RemoveFile( "whitelist_files.txt", "GAME" );
		for ( int i = g_WhiteList.FirstInorder(); 
			i != g_WhiteList.InvalidIndex(); 
			i = g_WhiteList.NextInorder( i ) )
		{
			UnusedContent::CUtlSymbol& sym = g_WhiteList[ i ];
			char const *resolved = g_Analysis.symbols.String( sym );
			logprint( "whitelist_files.txt", "\"%s\"\n", resolved );
		}
	}


	vprint( 1, "Whitelist resolves to %d files (added %i/removed %i)\n\n", g_WhiteList.Count(), wl_added, wl_removed );
}
//-----------------------------------------------------------------------------
//	ExcludePathsDlg_Populate
//
//	Generate a path table.
//-----------------------------------------------------------------------------
void ExcludePathsDlg_Populate( HWND hWnd, bool bRefresh )
{
	struct GamePath_t 
	{
		CUtlString	pathName;
		bool		bIsModPath;
	};

	CUtlVector< GamePath_t > gamePaths;		

	// can skip the time consuming directory scan, unless forced
	if ( bRefresh || !g_PathTable.Count() )
	{
		g_PathTable.Purge();

		for ( int i = 0; i < ARRAYSIZE( g_GameNames ); i++ )
		{
			char szTargetPath[MAX_PATH];
			V_strncpy( szTargetPath, g_localPath, sizeof( szTargetPath ) );
			V_AppendSlash( szTargetPath, sizeof( szTargetPath ) );
			V_strncat( szTargetPath, g_GameNames[i].pName, sizeof( szTargetPath ) );

			GamePath_t gamePath;
			gamePath.pathName = szTargetPath;
			gamePath.bIsModPath = g_GameNames[i].bIsModPath;
			gamePaths.AddToTail( gamePath );
		}

		// iterate all game paths
		for ( int i = 0; i < gamePaths.Count(); i++ )
		{
			CUtlVector< CUtlString > dirList;
			RecurseFileTree_r( g_localPath, gamePaths[i].pathName.String(), 0, dirList, gamePaths[i].bIsModPath );
		}
	}

	// reset the tree
	HWND hWndTree = GetDlgItem( hWnd, IDC_PATHS_TREE );
	TreeView_DeleteAllItems( hWndTree );

	// reset and add root
	// only the root is at depth 0
	AddItemToTree( hWndTree, ROOT_NAME, 0, false );

	// build the tree view
	for ( int iIndex = g_PathTable.FirstInorder(); iIndex != g_PathTable.InvalidIndex(); iIndex = g_PathTable.NextInorder( iIndex ) )
	{
		// due to sorting, number of slashes is depth
		const char *pString = g_PathTable[iIndex].pathName.String();
		int depth = 0;
		for ( int j = 0; j < (int)strlen( pString ); j++ )
		{
			if ( pString[j] == '\\' )
			{
				depth++;
			}
		}
		if ( !depth )
		{
			depth = 1;
		}

		char szPath[MAX_PATH];
		V_FileBase( pString, szPath, sizeof( szPath ) );
		AddItemToTree( hWndTree, szPath, depth, g_PathTable[iIndex].bIsModPath );
	}

	HTREEITEM hTreeRoot = TreeView_GetRoot( hWndTree );
	for ( int i = 0; i < g_ExcludePaths.Count(); i++ )
	{
		HTREEITEM hTree = ExcludePathsDlg_Find_r( hWndTree, hTreeRoot, 0, "", g_ExcludePaths[i].String() );
		if ( hTree )
		{
			ExcludePathsDlg_SetCheckState_r( hWndTree, hTree, 0, true );
		}
	}

	// expand the root node to show state
	ExcludePathsDlg_ExpandToShowState_r( hWndTree, hTreeRoot, 0 );
}