Click here to Skip to main content
15,895,786 members
Articles / Desktop Programming / MFC

WWhizInterface: Enhancements to the Visual C++ Automation Interface

Rate me:
Please Sign up or sign in to vote.
4.50/5 (5 votes)
28 Jul 2001 150K   2.6K   47  
A C++ interface with a number of Visual C++ automation enhancements, allowing for more robust add-in programming.
///////////////////////////////////////////////////////////////////////////////
// $Workfile: WorkspaceInfo.cpp $
// $Archive: /WorkspaceWhiz/Src/WWhizInterface/WorkspaceInfo.cpp $
// $Date:: 1/03/01 12:13a  $ $Revision:: 39   $ $Author: Jjensen $
///////////////////////////////////////////////////////////////////////////////
// This source file is part of the Workspace Whiz! source distribution and
// is Copyright 1997-2001 by Joshua C. Jensen.  (http://workspacewhiz.com/)
//
// The code presented in this file may be freely used and modified for all
// non-commercial and commercial purposes so long as due credit is given and
// this header is left intact.
///////////////////////////////////////////////////////////////////////////////
#include "WorkspaceInfo.h"
#include "WorkspaceTags.h"
#include "TagList.h"
#include <ObjModel\addguid.h>
#include <ObjModel\appguid.h>
#include <ObjModel\bldguid.h>
#include <ObjModel\textguid.h>
#include <ObjModel\dbgguid.h>
#include "CompilerFiles.h"
#include "XmlData.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

static CString s_workspacePath;
static CString s_workspaceFullPath;
static CString s_extraFilename;
CTime g_lastFileRefresh;

static ProjectList s_projects;
static FileList s_fileList;
static FileList s_activeFileList;

int g_numRefs;

extern CMap<CString, LPCTSTR, int, int> g_filesChangedFileMap;

///////////////////////////////////////////////////////////////////////////////
ProjectList& WorkspaceInfo::GetProjectList(void)
{
	return s_projects;
}


FileList& WorkspaceInfo::GetFileList(void)
{
	return s_fileList;
}


FileList& WorkspaceInfo::GetActiveFileList(void)
{
	return s_activeFileList;
}


const CString& WorkspaceInfo::GetWorkspaceLocation(void)
{
	return s_workspacePath;
}


const CString& WorkspaceInfo::GetWorkspaceFullPath(void)
{
	return s_workspaceFullPath;
}


const CString& WorkspaceInfo::GetExtraFilename(void)
{
	return s_extraFilename;
}


void WorkspaceInfo::ResolveFilename(const CString& rootDir, CString& filename)
{
	// Initially resolve all environment variables.
	int position = -1;
	while (1)
	{
		// Search for $ symbols, denoting an environment variable.
		position = CStringFind(filename, '$', position + 1);
		if (position == -1)
			break;

		// Okay, there is an environment variable in there... resolve it.
		if (filename[position + 1] == '(')
		{
			int lastpos = filename.Find(')');
			CString env = filename.Mid(position + 2, lastpos - (position + 2));

			// See if we can resolve it.  If not, then exit.
			char buffer[_MAX_PATH];
			if (::GetEnvironmentVariable(env, buffer, _MAX_PATH) == 0)
				continue;

			// Okay, rebuild the string.
			filename = filename.Left(position) + buffer +
						filename.Right(filename.GetLength() - lastpos - 1);
		}
	}

	// Now resolve relative paths.
	if (filename[0] == '.'  ||
		((filename[0] != '\\'  &&  filename[0] != '/')  &&  filename[1] != ':')
		)
	{
		filename = rootDir + filename;
	}
	CFileStatus fileStatus;
	CFile::GetStatus(filename, fileStatus);
	filename = fileStatus.m_szFullName;
}


void WorkspaceInfo::SetWorkspaceLocation(void)
{
	// Retrieve the workspace name.
	s_workspaceFullPath = g_wwhizInterface->GetWorkspaceName();

	// Is it empty?
	if (s_workspaceFullPath.IsEmpty())
	{
		// If so, then there is no workspace open.
		// Call the OS for the current directory.
		::GetCurrentDirectory(_MAX_PATH, s_workspaceFullPath.GetBuffer(_MAX_PATH));
		s_workspaceFullPath.ReleaseBuffer();

		// Make sure it ends in a closing backslash.
		s_workspaceFullPath.TrimRight('\\');
		s_workspaceFullPath += "\\!!!WWhizVirtualWorkspace!!!.dsw";
	}

	int slashPos = s_workspaceFullPath.ReverseFind('\\');
	if (slashPos != -1)
	{
		s_workspacePath = s_workspaceFullPath.Left(slashPos + 1);
	}

	// Assign the extra filename.
	CString pathNoExt = s_workspaceFullPath;
	int dotPos = pathNoExt.ReverseFind('.');
	if (dotPos != -1)
		pathNoExt = pathNoExt.Left(dotPos);
	s_extraFilename = pathNoExt + ".ExtraFiles.WW";
}


bool WorkspaceInfo::GetCurrentFilename(CString& filename)
{
	// Is there an application?
	if (!g_pApplication)
	{
		filename.Empty();
		return false;
	}

	ObjModelHelper objModel;
	if (objModel.GetActiveDocument())
	{
		filename = objModel.GetFilename();
		return !filename.IsEmpty();
	}

	filename.Empty();
	return false;
}


Project* WorkspaceInfo::GetCurrentProject()
{
	if (!g_pApplication)
	{
		return NULL;
	}

	// Get the current project
	CComPtr<IDispatch> pActiveProject;
	g_pApplication->get_ActiveProject(&pActiveProject);
	if (pActiveProject)
	{
		CComQIPtr<IGenericProject, &IID_IGenericProject> pProject(pActiveProject);
		if (pProject)
		{
			CComBSTR bstrProjectName;
			pProject->get_FullName(&bstrProjectName);
			CString projectName = bstrProjectName;

			ProjectList& projectList = WorkspaceInfo::GetProjectList();
			POSITION pos = projectList.GetHeadPosition();
			while (pos)
			{
				Project* project = projectList.GetNext(pos);
				if (project->GetName().CompareNoCase(projectName) == 0)
				{
					return project;
				}
			}
		}
	}

	return NULL;
}


bool g_filesRefreshed;


// Clean the projects and filenames lists.
void WorkspaceInfo::RemoveAll(void)
{
	// Clean the projects list.
	s_projects.RemoveAll();

	// Clean the filenames list.
	s_fileList.RemoveAll();

	WorkspaceInfo::GetGlobalFileMap().RemoveAll();

	g_filesRefreshed = true;
}


static void WriteString(CFile& file, UINT numSpaces, LPCTSTR msg, ...)
{
	va_list args;
	char textBuffer[1024];

	va_start(args, msg);
	_vsnprintf(textBuffer, 1023, msg, args);
	va_end(args);

	// Write out indentation.
	char spaces[500];
	memset(spaces, ' ', numSpaces);
	file.Write(spaces, numSpaces);
	file.Write(textBuffer, strlen(textBuffer));
}


void WorkspaceInfo::ReadDSPFile(Project& prj)
{
	// Open the .dsp file.
	CStdioFile file;
	if (!file.Open(prj.GetName(), CFile::modeRead))
	{
		// Huh?
		return;
	}

	enum ParseState
	{
		FINDTARGET,
		PARSETARGET,
	};

	ParseState state = FINDTARGET;

	CMemFile xmlMemFile;
	WriteString(xmlMemFile, 0, "<VisualStudioProject\n  ProjectType=\"Visual C++\"\n"
		"  Version=\"6.00\"\n  Name = \"Test\">\n");
	
	// Begin reading the file.
	bool localListRefreshed = false;
	CString line;
	UINT numSpaces = 4;
	while (true)
	{
		// Read in a line from the file.
		if (!file.ReadString(line))
			break;

		if (line.IsEmpty())
			continue;

		// Check the state.
		if (state == FINDTARGET)
		{
			if (line.CompareNoCase("# Begin Target") == 0)
			{
				WriteString(xmlMemFile, 2, "<Files>\n");

				state = PARSETARGET;				
			}
		}

		else if (state == PARSETARGET)
		{
			enum Types
			{
				NONE,
				BEGIN_GROUP,
				END_GROUP,
				END_TARGET,
				SOURCE,
			};

			Types type = NONE;
			
			// Check for # Begin Group lines.
			if (line.GetLength() > 13  &&  _tcsncmp(line, "# Begin Group", 13) == 0)
			{
				type = BEGIN_GROUP;
				line = line.Mid(14);
			}

			// Check for # End Group lines
			else if (line.GetLength() >= 11  &&  _tcsncmp(line, "# End Group", 11) == 0)
			{
				type = END_GROUP;
				line = line.Mid(11);
			}

			// Check for SOURCE= lines.  (Do _tcsncmp() for speed)
			else if (line.GetLength() > 7  &&  _tcsncmp(line, "SOURCE=", 7) == 0)
			{
				type = SOURCE;
				line = line.Mid(7);
			}

			// Check for # End Group lines
			else if (line.GetLength() >= 12  &&  _tcsncmp(line, "# End Target", 12) == 0)
			{
				type = END_TARGET;
				line = line.Mid(12);
			}

			if (type == NONE)
				continue;
			if (type == END_GROUP)
			{
				numSpaces -= 2;
				WriteString(xmlMemFile, numSpaces, "</Filter>\n");
				continue;
			}
			else if (type == END_TARGET)
			{
				WriteString(xmlMemFile, 2, "</Files>\n");
				state = FINDTARGET;
				continue;
			}

			///////////////////////////////////////////////////////////////////////
			// Start the pointer just after the SOURCE=, but strip the beginning
			// and end quotes if they exist.
			int startPos = 0;
			if (line[0] == '"')
				startPos = 1;

			int endPos = line.GetLength();
			if (line[endPos - 1] == '"')
				endPos--;

			// Strip spaces, just in case.
			while (startPos < endPos  &&  line[startPos] == ' ')
				startPos++;

			// Create and resolve the filename.
			CString text = line.Mid(startPos, endPos - startPos);
			if (type == BEGIN_GROUP)
			{
				WriteString(xmlMemFile, numSpaces, "<Filter Name=\"%s\">\n", text);
				numSpaces += 2;
			}

			if (type == SOURCE)
			{
				WriteString(xmlMemFile, numSpaces, "<File RelativePath=\"%s\">\n", text);
				WriteString(xmlMemFile, numSpaces, "</File>\n", text);
			}
		}
	} //while(1)

	WriteString(xmlMemFile, 0, "</VisualStudioProject>\n");

#ifdef DUMP_FILE
	FILE* textFile = fopen("c:\\test.dsp", "wt");
	DWORD size = xmlMemFile.GetLength();
	char* buffer = new char[size + 1];
	xmlMemFile.SeekToBegin();
	xmlMemFile.Read(buffer, size);
	buffer[size]  = 0;

	fputs(buffer, textFile);
	fclose(textFile);
	delete [] buffer;
#endif DUMP_FILE
	
	// Close the .dsp file.
	file.Close();

	xmlMemFile.SeekToBegin();
	ReadVCProjFile(prj, &xmlMemFile);
}


void WorkspaceInfo::RecurseVCProjNode(
		XmlNode* parentNode, const CString& rootPath, FileList& fileList,
		bool& localListRefreshed, CList<CString, CString&>& projectsToAdd)
{
	if (!parentNode)
		return;

    XmlNode* node = (XmlNode*)parentNode->GetFirstChildNode();
    while (node)
    {
		// Is it a File node?
		if (node->GetName() == "File")
		{
			// Create and resolve the filename.
			XmlNode::Attribute* attr = node->FindAttribute("RelativePath");
			if (attr)
			{
				CString filename = attr->GetValue();
				WorkspaceInfo::ResolveFilename(rootPath, filename);

				File* file = File::Create(filename);

				// Insert it into the current project.
				if (fileList.Add(file))
				{
					g_filesRefreshed = true;
					localListRefreshed = true;
				}
				file->m_touched = true;

				// Test the file to see if it is a project or workspace.
				int dotPos = filename.ReverseFind('.');
				if (dotPos != -1)
				{
					CString ext = filename.Mid(dotPos + 1);
					ext.MakeLower();
					if (ext == "dsp"  ||  ext == "dsw"  ||  ext == "vcp"  ||  ext == "vcw"  ||  ext == "vcproj")
						projectsToAdd.AddTail(filename);
				}
			}
		}
		else if (node->GetName() == "Filter")
		{
			XmlNode::Attribute* attr = node->FindAttribute("Filter");
        	RecurseVCProjNode(node, rootPath, fileList, localListRefreshed, projectsToAdd);
		}

		node = (XmlNode*)node->GetNextSiblingNode();
	}
}


void WorkspaceInfo::ReadVCProjFile(Project& prj, CFile* inFile)
{
	if (!inFile)
	{
		// Parse the .vcproj file.
		if (!prj.GetXmlData().ParseXmlFile(prj.GetName()))
			return;
	}
	else
	{
		// Parse the .vcproj file.
		if (!prj.GetXmlData().ParseXmlFile(*inFile))
			return;
	}

	FileList& fileList = (FileList&)prj.GetFileList();

	// Build the root path to resolve filenames from.
	CString rootPath = prj.GetName().Left(prj.GetName().ReverseFind('\\') + 1);

	// Build the projectsToAdd list.
	CList<CString, CString&> projectsToAdd;
	bool prjIsExtraFiles = false;
	if (prj.GetName().CompareNoCase(GetExtraFilename() + ".dsp") != 0)
		projectsToAdd.AddTail(const_cast<CString&>(prj.GetName()));
	else
		prjIsExtraFiles = true;


	// Make sure no files have been touched yet.
	int fileListCount = fileList.GetCount();
	for (int i = 0; i < fileListCount; i++)
	{
		File* file = (File*)fileList.Get(i);
		file->m_touched = false;
	}

	bool localListRefreshed = false;
	XmlNode* filesNode = prj.GetXmlData().Find("Files");
	RecurseVCProjNode(filesNode, rootPath, fileList, localListRefreshed, projectsToAdd);

	// Remove unused files.
	fileListCount = fileList.GetCount();
	for (i = 0; i < fileListCount; i++)
	{
		File* file = (File*)fileList.Get(i);
		if (!file->m_touched)
		{
			// The file doesn't exist in the project anymore.
			fileList.Remove(i);
			i--;
			fileListCount--;
			g_filesRefreshed = true;
			localListRefreshed = true;
		}
	}

	if (localListRefreshed)
	{
		// Sort it.
		fileList.Sort();
	}

	// Add the .dsp and .dsw files.
	POSITION pos = projectsToAdd.GetHeadPosition();
	if (!prjIsExtraFiles)
		projectsToAdd.GetNext(pos);
	while (pos)
	{
		const CString& projectFilename = projectsToAdd.GetNext(pos);
		AddProject(projectFilename, prj.IsActive());
	}
}





// Read in a .dsw file.
void WorkspaceInfo::ReadDSWFile(Project& prj)
{
	// Open the .dsw file.
	CStdioFile file;
	if (!file.Open(prj.GetName(), CFile::modeRead))
	{
		// Huh?
		return;
	}

	// Build the root path to resolve filenames from.
	CString rootPath = prj.GetName().Left(prj.GetName().ReverseFind('\\') + 1);

	// Begin reading the file.
	CString line;
	while (1)
	{
		// Read in a line from the file.
		if (!file.ReadString(line))
			break;

		// Look for something that looks like this.
		// Project: "!MyLib"=".\Prj\!MyLib.dsp" - Package Owner=<4>
		// Project: "Gfx"=.\Prj\Gfx.dsp - Package Owner=<4>
		if (line.GetLength() <= 8  ||  strncmp(line, "Project:", 8) != 0)
			continue;

		// Search for the =.
		int endPos;		// Will be one past the last letter.
		int startPos = line.Find('=');
		if (startPos == -1)
			continue;
		startPos++;		// Move to the beginning of the name.

		// See if the name is quoted.
		if (line[startPos] == '"')
		{
			// Move past the quote.
			startPos++;
			
			// Find the closing quote.
			endPos = CStringFind(line, '"', startPos);
			if (endPos == -1)
				continue;
		}
		else //if (line[namePos] == '"')
		{
			// Find a space, since that should denote the end of the filename.
			endPos = CStringFind(line, ' ', startPos);
		}

		// Got the name isolated.  Add it.
		CString projectPath = line.Mid(startPos, endPos - startPos);
		ResolveFilename(rootPath, projectPath);
		Project* newlyAddedProject = AddHelper(projectPath, prj.IsActive());
		if (newlyAddedProject)
		{
			newlyAddedProject->m_parent = &prj;
			File* dspFile = File::Create(projectPath);
			prj.m_fileList.Add(dspFile);
		}
	} //while(1)

	// Close the .dsp file.
	file.Close();

	// Add the .dsw file.
	File* dswFile = File::Create(prj.m_name);
	prj.m_fileList.Add(dswFile);

	prj.m_fileList.Sort();
}


// Add a new project or workspace to the list of projects.
Project* WorkspaceInfo::AddProject(CString projectName, bool active)
{
	if (projectName.IsEmpty())
		return NULL;

	return AddHelper(projectName, active);
}


POSITION FindProject(const CString& projectName)
{
	// Is it already in the list?
	POSITION pos = s_projects.GetHeadPosition();
	while (pos)
	{
		POSITION lastPos = pos;
		Project* compProject = s_projects.GetNext(pos);

		if (projectName.CompareNoCase(compProject->GetName()) == 0)
			return lastPos;
	}

	return pos;
}

	
// Internal helper function.
Project* WorkspaceInfo::AddHelper(CString projectName, bool active)
{
	// Resolve the filename.
	ResolveFilename(GetWorkspaceLocation(), projectName);
	
	// Make sure there is an extension.
	int dotPosition = projectName.ReverseFind('.');
	if (dotPosition == -1)
	{
		// What?!
		return NULL;
	}

	// Is it already in the list?
	Project* project = NULL;
	POSITION projectPos = FindProject(projectName);
	if (projectPos)
	{
		project = s_projects.GetAt(projectPos);
	}
	
	// Make sure the file exists.
	CFileStatus fileStatus;
	if (!CFile::GetStatus(projectName, fileStatus))
	{
		if (projectPos)
		{
			// The project no longer exists.  Destroy it.
			delete project;
			s_projects.RemoveAt(projectPos);

			return NULL;
		}
	}

	// If there isn't a project, create a new project structure.
	if (!project)
	{
		project = new Project;
		project->m_name = projectName;
		project->m_newProject = true;
		project->SetActive(active);

		// Add it to the end of the projects list.
		projectPos = s_projects.AddTail(project);
	}

	project->m_workspaceProject = false;

	// Determine which type of file this is:
	CString ext = project->m_name.Mid(dotPosition + 1);
	ext.MakeLower();

	// Check the project time stamp.
	if (project->GetTimeStamp() != fileStatus.m_mtime)
	{
		// Set the project time stamp.
		project->m_timeStamp = fileStatus.m_mtime;

		if (ext == "dsw"  ||  ext == "vcw")
		{
			// This is a workspace file.
			ReadDSWFile(*project);
		}

		else if (ext == "dsp"  ||  ext == "vcp")
		{
			TRY
			{
				// Assume it is a project file.
				ReadDSPFile(*project);
			}
			CATCH_ALL(e)
			{
				e->Delete();
			}
			END_CATCH_ALL
		}
		else if (ext == "vcproj")
		{
			ReadVCProjFile(*project);
		}
	}
	else
	{
		// Check any projects in the list.
		for (int i = 0; i < project->m_fileList.GetCount(); i++)
		{
			File* file = (File*)project->m_fileList.Get(i);
			const CString& ext = file->GetExt();
			if (ext == "dsp"  ||  ext == "dsw"  ||  ext == "vcp"  ||  ext == "vcw"  ||  ext == "vcproj")
			{
				if (projectName.CompareNoCase(file->GetFullName()) != 0)
					AddProject(file->GetCaseFullName(), project->IsActive());
			}
		}
	}

	project->m_touched = true;
	
	return project;
}


static CString s_lastWorkspaceName;

// Refresh the projects list.
bool WorkspaceInfo::Refresh(void)
{
	// Turn off the workspace project flag.
	POSITION pos = GetProjectList().GetHeadPosition();
	while (pos)
	{
		Project* project = GetProjectList().GetNext(pos);
		project->m_workspaceProject = false;
	}
	
	for (int i = 0; i < s_fileList.GetCount(); ++i)
	{
		File* file = (File*)s_fileList.Get(i);
		file->m_workspaceFile = true;
	}

	// Only do this part if DevStudio exists.
	if (g_pApplication)
	{
		CString workspaceName = g_wwhizInterface->GetWorkspaceName();
		if (!workspaceName.IsEmpty())
		{
			bool doWorkspaceRead = true;

			// Did we read this workspace last time?
			if (workspaceName.CompareNoCase(s_lastWorkspaceName) == 0)
			{
//	g_filesChangedFileMap[workspaceName] = 0;
				// See if it changed.
//				int value;
//				if (!g_filesChangedFileMap.Lookup(workspaceName, value))
//					doWorkspaceRead = false;
//				else
//				{
/*					// See if the file is currently in the file list.
					File* file = (File*)GetActiveFileList().Find(workspaceName);
					if (file)
					{
						// Get the time stamp.
						CFileStatus fileStatus;
						if (CFile::GetStatus(workspaceName, fileStatus))
						{
							// If it is the same, then don't read the workspace information in.
							if (file->GetTimeStamp() == fileStatus.m_mtime)
							{
								doWorkspaceRead = false;
							}
						}
					}
*/
//				}
			}

			if (doWorkspaceRead)
			{
				Project* workspace = AddProject(workspaceName, true);
				s_lastWorkspaceName = workspaceName;

				// Assign the workspace projects.
				FileList& workspaceFileList = (FileList&)workspace->GetFileList();
				workspace->m_workspaceProject = true;
				for (int i = 0; i < workspaceFileList.GetCount(); ++i)
				{
					// Get the project name.
					File* projectFile = (File*)workspaceFileList.Get(i);
					projectFile->m_workspaceFile = true;

					Project* project =
						static_cast<Project*>(GetProjectList().Find(
							projectFile->GetCaseFullName()));
					project->m_workspaceProject = true;

					FileList& projectFileList = (FileList&)project->GetFileList();

					for (int j = 0; j < projectFileList.GetCount(); ++j)
					{
						File* file = (File*)projectFileList.Get(j);
						file->m_workspaceFile = true;
					}

					project->m_active = true;
				}
			}
		}
/*
		// First, get a pointer to the dispatch for the Projects collection
		CComPtr<IDispatch> pDispProjects;
		VERIFY_OK(g_pApplication->get_Projects(&pDispProjects));
		CComQIPtr<IProjects, &IID_IProjects> pProjects(pDispProjects);

		// Get the number of projects in the collection
		long projectCount;
		VERIFY_OK(pProjects->get_Count(&projectCount));

		// Iterate all the projects.
		for (long i = 1; i <= projectCount; i++)
		{
			CComVariant Vari = i;

			// Get the next project
			CComPtr<IGenericProject> pGenProject;
			VERIFY_OK(pProjects->Item(Vari, &pGenProject));
			CComQIPtr<IGenericProject, &IID_IGenericProject> pProject(pGenProject);

			// Get the project name.
			CComBSTR bszStr;
			VERIFY_OK(pProject->get_FullName(&bszStr));
			CString projectName = bszStr;

			Project* project = AddProject(projectName);
			if (project)
				project->m_workspaceProject = true;
		}
*/
	}

	// Remove unused projects.
	pos = s_projects.GetHeadPosition();
	while (pos)
	{
		POSITION oldPos = pos;
		Project* project = s_projects.GetNext(pos);
		if (!project->m_touched)
		{
			s_projects.RemoveAt(oldPos);
			delete project;
			g_filesRefreshed = true;
		}
		else
		{
			project->m_touched = false;

			if (project->m_changed)
			{
				project->m_changed = false;
				g_filesRefreshed = true;
			}

			project->m_lastActive = project->m_active;
		}
	}
	
	if (g_filesRefreshed)
	{
		// Add all files to global file list.
		s_fileList.RemoveAll();
		s_activeFileList.RemoveAll();
		pos = s_projects.GetHeadPosition();
		while (pos)
		{
			Project* project = s_projects.GetNext(pos);
			WWhizFileList& fileList = project->GetFileList();
			int fileListCount = fileList.GetCount();
			bool projectActive = project->IsActive();
			for (int i = 0; i < fileListCount; i++)
			{
				File* file = (File*)fileList.Get(i);
				if (projectActive)
					s_activeFileList.Add(file);
				s_fileList.Add(file);
			}
		}

		// Sort the global file array.
		s_activeFileList.Sort();
		s_fileList.Sort();

extern FileMap g_globalFileMap;
		g_globalFileMap.CleanUp();
		
		g_lastFileRefresh = CTime::GetCurrentTime();
	}
	
	g_filesChangedFileMap.RemoveAll();

	// Rebuilt stuff.
	return false;
}


extern FileMap g_globalFileMap;

FileMap& WorkspaceInfo::GetGlobalFileMap()
{
	return g_globalFileMap;
}


By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
United States United States
Joshua Jensen is a gamer at heart and as such, creates games for a living. He has the distinct pleasure of creating titles exclusively for the Xbox.

In his spare time, he maintains a Visual C++ add-in called Workspace Whiz! Find it at http://workspacewhiz.com/.

Comments and Discussions