Exemple #1
0
JVCSType
JGetVCSType
	(
	const JCharacter*	path,
	const JBoolean		deepInspection
	)
{
	JString p = path, n;
	if (JFileExists(path) ||
		!JDirectoryExists(path))	// broken link
		{
		JSplitPathAndName(path, &p, &n);
		}

	// can't read newer versions

	JString vcsDir = JCombinePathAndName(p, kSubversionDirName);
	vcsDir         = JCombinePathAndName(vcsDir, kSubversionFileName);
	if (JFileExists(vcsDir))
		{
		if (!deepInspection)
			{
			return kJSVNType;
			}

		JSize size;
		const JError err = JGetFileLength(vcsDir, &size);
		if (err.OK() && size > 10)
			{
			return kJSVNType;
			}
		}

	vcsDir = JCombinePathAndName(p, kCVSDirName);
	if (JDirectoryExists(vcsDir))
		{
		return kJCVSType;
		}

	vcsDir = JCombinePathAndName(p, kSCCSDirName);
	if (JDirectoryExists(vcsDir))
		{
		return kJSCCSType;
		}

	// check git & new svc last, since they need to search directory tree up to root

	if (JSearchGitRoot(p, &n))
	{
		return kJGitType;
	}
	else if (!deepInspection && jSearchVCSRoot(p, kSubversionDirName, &n))
	{
		return kJSVNType;
	}

	return kJUnknownVCSType;
}
JError
JCreateTempFile
	(
	const JCharacter*	path,
	const JCharacter*	prefix,
	JString*			fullName
	)
{
	JString p;
	if (!JStringEmpty(path))
		{
		p = path;
		}
	else if (!JGetTempDirectory(&p))
		{
		return JDirEntryDoesNotExist("/tmp");
		}

	if (!JStringEmpty(prefix))
		{
		p = JCombinePathAndName(p, prefix);
		}
	else
		{
		p = JCombinePathAndName(p, "temp_file_");
		}

	p      += "XXXXXX";
	char* s = p.AllocateCString();

	jclear_errno();
	int fd = mkstemp(s);
	if (fd != -1)
		{
		close(fd);
		*fullName = s;
		delete [] s;
		return JNoError();
		}

	fullName->Clear();
	delete [] s;

	// EINVAL counts as unexpected

	const int err = jerrno();
	if (err == EEXIST)
		{
		return JAccessDenied(p);
		}
	else
		{
		return JUnexpectedError(err);
		}
}
void
GMMIMEParser::WriteAttachment
	(
	const JString&		data,
	const GMIMEHeader&	header
	)
{
	JString filename = header.GetFileName();
	if (filename.IsEmpty())
		{
		const JError err = JCreateTempFile(itsAttachDir, NULL, &filename);
		if (!err.OK())
			{
			err.ReportIfError();
			return;
			}
		}
	else
		{
		filename = JCombinePathAndName(itsAttachDir, filename);
		}

	AdjustAttachmentName(header, &filename);
	std::ofstream os(filename);
	if (header.GetEncoding() == kBase64Encoding)
		{
		std::istrstream is(data.GetCString(), data.GetLength());
		JDecodeBase64(is, os);
		}
	else
		{
		data.Print(os);
		}
}
Exemple #4
0
void
JUpdateCVSIgnore
	(
	const JCharacter* ignoreFullName
	)
{
	JString path, name;
	JSplitPathAndName(ignoreFullName, &path, &name);
	const JString cvsFile = JCombinePathAndName(path, ".cvsignore");

	if (!JFileExists(cvsFile) && JGetVCSType(path) != kJCVSType)
		{
		return;
		}

	JString cvsData;
	JReadFile(cvsFile, &cvsData);
	if (!cvsData.IsEmpty() && !cvsData.EndsWith("\n"))
		{
		cvsData += "\n";
		}

	name += "\n";
	if (!cvsData.Contains(name))
		{
		JEditVCS(cvsFile);
		cvsData += name;

		ofstream output(cvsFile);
		cvsData.Print(output);
		}
}
Exemple #5
0
JBoolean
jSearchVCSRoot
	(
	const JCharacter*	path,
	const JCharacter*	vcsDirName,
	JString*			vcsRoot
	)
{
	JString p = path, n;
	if (JFileExists(path) ||
		!JDirectoryExists(path))	// broken link
		{
		JSplitPathAndName(path, &p, &n);
		}

	do
		{
		n = JCombinePathAndName(p, vcsDirName);
		if (JDirectoryExists(n))
			{
			*vcsRoot = p;
			return kJTrue;
			}

		JSplitPathAndName(p, &p, &n);
		}
		while (!JIsRootDirectory(p));

	vcsRoot->Clear();
	return kJFalse;
}
JBoolean
CBNewProjectSaveFileDialog::GetProjectTemplate
	(
	JString* fullName
	)
	const
{
	if (itsTemplateIndex == kNoTemplateCmd)
		{
		fullName->Clear();
		return kJFalse;
		}
	else
		{
		JString nmShortcut;
		const JBoolean ok = itsTemplateMenu->GetItemNMShortcut(itsTemplateIndex, &nmShortcut);
		assert( ok );

		JString sysDir, userDir;
		JXGetProgramDataDirectories(CBProjectDocument::GetTemplateDirectoryName(),
									&sysDir, &userDir);

		*fullName = JCombinePathAndName(
			nmShortcut == kUserTemplateMarker ? userDir : sysDir,
			itsTemplateMenu->GetItemText(itsTemplateIndex));
		return kJTrue;
		}
}
Exemple #7
0
JBoolean
JIsManagedByVCS
	(
	const JCharacter*	fullName,
	JVCSType*			returnType
	)
{
	const JVCSType type = JGetVCSType(fullName);

	JBoolean isManaged = kJFalse;
	if (type == kJSVNType)
		{
		JString path, name, entriesFileName, data, pattern;
		JSplitPathAndName(fullName, &path, &name);
		entriesFileName = JCombinePathAndName(path, kSubversionDirName);
		entriesFileName = JCombinePathAndName(entriesFileName, kSubversionFileName);
		JReadFile(entriesFileName, &data);

		if (data.BeginsWith("<?xml"))
			{
			pattern = "<entry[^>]+name=\"" + JRegex::BackslashForLiteral(name) + "\"(.|\n)*?>";
			const JRegex r(pattern);
			isManaged = r.Match(data);
			}
		else
			{
			std::istrstream input(data, data.GetLength());

			const JString version = JReadLine(input);
			if (version == "8" || version == "9" || version == "10")
				{
				pattern = "\n\f\n" + name + "\n";
				JIgnoreUntil(input, pattern, &isManaged);
				}
			}
		}
	else if (type == kJGitType)
		{
		isManaged = kJTrue;	// TODO: ask git (until then, better safe than sorry)
		}

	if (returnType != NULL)
		{
		*returnType = (isManaged ? type : kJUnknownVCSType);
		}
	return isManaged;
}
Exemple #8
0
void
SyGAddRecentFile
	(
	const JCharacter* fullname
	)
{
	JString recentDir;
	JString filename;
	JString path;
	if (SyGGetRecentFileDirectory(&recentDir) &&
		JSplitPathAndName(fullname, &path, &filename))
		{
		const JString recentFile = JCombinePathAndName(recentDir, filename);
		if (JNameUsed(recentFile))
			{
			JRemoveFile(recentFile);
			JCreateSymbolicLink(fullname, recentFile);
			return;
			}

		// remove oldest links such that only kRecentFileCount - 1 remain

		JDirInfo* info;
		if (JDirInfo::Create(recentDir, &info))
			{
			JBoolean changed = kJFalse;

			JSize count = info->GetEntryCount();
			for (JIndex i=1; i<=count; i++)
				{
				if (info->GetEntry(i).IsBrokenLink())
					{
					JRemoveFile(info->GetEntry(i).GetFullName());
					changed = kJTrue;
					}
				}

			if (changed)
				{
				info->ForceUpdate();
				}

			count = info->GetEntryCount();
			if (count >= kRecentFileCount)
				{
				info->ChangeSort(JDirEntry::CompareModTimes, JOrderedSetT::kSortDescending);
				for (JIndex i=count; i>=kRecentFileCount; i--)
					{
					JRemoveFile(info->GetEntry(i).GetFullName());
					}
				}

			// add new entry

			JCreateSymbolicLink(fullname, recentFile);
			}
		}
}
void
GPMProcessEntry::ReadStat()
{
	const JSize uTime = itsUTime, sTime = itsSTime;

	JString str = JCombinePathAndName(itsProcPath, "stat");
	std::ifstream is(str);
	if (is.good())
		{
		is >> itsPID;
		is >> std::ws;
		itsCommand = JReadUntilws(is);
		if (itsCommand.GetLength() > 2)
			{
			itsCommand = itsCommand.GetSubstring(2, itsCommand.GetLength() - 1);
			}
		JString state = JReadUntilws(is);
		if (state.Contains("S"))
			{
			itsState = kSleep;
			}
		else if (state.Contains("D"))
			{
			itsState = kUnIntSleep;
			}
		else if (state.Contains("Z"))
			{
			itsState = kZombie;
			}
		else if (state.Contains("T"))
			{
			itsState = kStopped;
			}
		else
			{
			itsState = kRun;
			}
		is >> itsPPID;
		is >> std::ws;
		int toss;
		is >> toss;
		is >> toss;
		is >> toss;
		is >> toss;
		is >> toss;
		is >> toss;
		is >> toss;
		is >> toss;
		is >> toss;
		is >> itsUTime;
		is >> itsSTime;
		is >> toss;
		is >> toss;
		is >> itsPriority;
		is >> itsNice;
		}
Exemple #10
0
void
SMTPMessage::SetAccount
	(
	GMAccount* account
	)
{
	itsSMTPServer	= account->GetSMTPServer();
	itsFullName		= account->GetFullName();
	itsSMTPUser		= account->GetSMTPUser();
	JString dir		= account->GetMailDir();
	dir				= JCombinePathAndName(dir, "Sent");
	time_t now;
	time(&now);

	struct tm* local_time	= localtime(&now);
	JString outbox			= gcl_months[local_time->tm_mon];
	outbox					+= "_" + JString(local_time->tm_year + 1900, JString::kBase10);
	itsOutbox				= JCombinePathAndName(dir, outbox);
}
JBoolean
WWGetDataFileName
	(
	const JCharacter*	fileName,
	JString*			fullName
	)
{
	const JString relName = JCombinePathAndName(kWWDirectoryRoot, fileName);
	return JExpandHomeDirShortcut(relName, fullName);
}
JString
JXGetNewDirDialog::GetNewDirName()
	const
{
	JString dirName = GetString();
	if (JIsRelativePath(dirName))
		{
		dirName = JCombinePathAndName(itsBasePath, dirName);
		}
	return dirName;
}
JBoolean
JConvertToAbsolutePath
	(
	const JCharacter*	path,
	const JCharacter*	base,		// can be NULL
	JString*			result
	)
{
	assert( !JStringEmpty(path) && result != NULL );

	JBoolean ok = kJTrue;
	if (path[0] == '/')
		{
		*result = path;
		}
	else if (path[0] == '~')
		{
		ok = JExpandHomeDirShortcut(path, result);
		}
	else if (!JStringEmpty(base))
		{
		*result = JCombinePathAndName(base, path);
		}
	else
		{
		const JString currDir = JGetCurrentDirectory();
		*result = JCombinePathAndName(currDir, path);
		}

	if (ok)
		{
		return JNameUsed(*result);
		}
	else
		{
		result->Clear();
		return kJFalse;
		}
}
void
GAddressBookMgr::AddDefaultAddressBook
	(
	JTree* tree
	)
{
	JString fullName;
	if (JGetPrefsDirectory(&fullName))
		{
		fullName = JCombinePathAndName(fullName, ".addressbook");
		AddAddressBook(fullName, tree);
		}
}
Exemple #15
0
JBoolean
SyGGetTrashDirectory
	(
	JString*		path,
	const JBoolean	reportErrors
	)
{
	if (!theTrashDir.IsEmpty())
		{
		*path = theTrashDir;
		return kJTrue;
		}

	if (!JGetPrefsDirectory(path))
		{
		if (reportErrors)
			{
			(JGetUserNotification())->ReportError(JGetString(kNoPrefsDirID));
			}
		return kJFalse;
		}

	*path = JCombinePathAndName(*path, kTrashDirName);

	JError err = JNoError();
	if (!JDirectoryExists(*path))
		{
		err = JCreateDirectory(*path, kTrashCanPerms);
		}
	else
		{
		err = JSetPermissions(*path, kTrashCanPerms);
		}

	if (err.OK())
		{
		theTrashDir       = *path;
		const JBoolean ok = JDirInfo::Create(theTrashDir, &theTrashDirInfo);
		assert( ok );
		return kJTrue;
		}
	else
		{
		path->Clear();
		if (reportErrors)
			{
			(JGetStringManager())->ReportError(kCreateTrashErrorID, err);
			}
		return kJFalse;
		}
}
JString
JXFileHistoryMenu::GetFile
	(
	const JIndex index
	)
	const
{
	JString path;
	const JBoolean ok = GetItemNMShortcut(index, &path);
	assert( ok );
	path.TrimWhitespace();

	return JCombinePathAndName(path, JXTextMenu::GetItemText(index));
}
Exemple #17
0
JBoolean
SyGCreateGlobals
	(
	SyGApplication* app
	)
{
	theApplication = app;

	SyGCreateIcons();

	JString oldPrefsFile, newPrefsFile;
	if (JGetPrefsDirectory(&oldPrefsFile))
		{
		oldPrefsFile = JCombinePathAndName(oldPrefsFile, ".gSystemG.pref");
		if (JFileExists(oldPrefsFile) &&
			(JPrefsFile::GetFullName(app->GetSignature(), &newPrefsFile)).OK() &&
			!JFileExists(newPrefsFile))
			{
			JRenameFile(oldPrefsFile, newPrefsFile);
			}
		}

	JBoolean isNew;
	thePrefsMgr = new SyGPrefsMgr(&isNew);
	assert(thePrefsMgr != NULL);

	JXInitHelp(kSyGTOCHelpName, kSyGHelpSectionCount, kSyGHelpSectionName);

	JXWDManager* wdMgr = new JXWDManager(app->GetCurrentDisplay(), kJTrue);
	assert( wdMgr != NULL );
	// registers itself

	theMDIServer = new SyGMDIServer;
	assert( theMDIServer != NULL );

	theManPageDialog = new SyGViewManPageDialog(JXGetPersistentWindowOwner());
	assert( theManPageDialog != NULL );

	theFindFileDialog = new SyGFindFileDialog(JXGetPersistentWindowOwner());
	assert( theFindFileDialog != NULL );

	theAltChooseSaveFile = new SyGChooseSaveFile(thePrefsMgr, kSAltCSSetupID);
	assert( theAltChooseSaveFile != NULL );

	JString trashDir;
	SyGGetTrashDirectory(&trashDir, kJFalse);	// silently creates it

	return isNew;
}
Exemple #18
0
JBoolean
SyGGetRecentFileDirectory
	(
	JString*		path,
	const JBoolean	reportErrors
	)
{
	if (!theRecentFileDir.IsEmpty())
		{
		*path = theRecentFileDir;
		return kJTrue;
		}

	if (!JGetPrefsDirectory(path))
		{
		if (reportErrors)
			{
			(JGetUserNotification())->ReportError(JGetString(kNoPrefsDirID));
			}
		return kJFalse;
		}

	*path = JCombinePathAndName(*path, kRecentFileDirName);

	JError err = JNoError();
	if (!JDirectoryExists(*path))
		{
		err = JCreateDirectory(*path, kRecentFileDirPerms);
		}
	else
		{
		err = JSetPermissions(*path, kRecentFileDirPerms);
		}

	if (err.OK())
		{
		theRecentFileDir = *path;
		return kJTrue;
		}
	else
		{
		path->Clear();
		if (reportErrors)
			{
			(JGetStringManager())->ReportError(kCreateRecentFileDirErrorID, err);
			}
		return kJFalse;
		}
}
JString
JXCurrentPathMenu::GetPath
	(
	const JIndex itemIndex
	)
	const
{
	JString path = GetItemText(1);
	for (JIndex i=2; i<=itemIndex; i++)
		{
		path = JCombinePathAndName(path, GetItemText(i));
		}
	JAppendDirSeparator(&path);
	return path;
}
JString
JXPathInput::GetTextForChoosePath()
	const
{
	JString text = GetText();
	if (text.IsEmpty() && HasBasePath())
		{
		text = itsBasePath;
		}
	else if (!text.IsEmpty() && JIsRelativePath(text) && HasBasePath())
		{
		text = JCombinePathAndName(itsBasePath, text);
		}
	return text;
}
Exemple #21
0
JString
JGetUniqueDirEntryName
	(
	const JCharacter*	path,
	const JCharacter*	namePrefix,
	const JCharacter*	nameSuffix,
	const JIndex		startIndex
	)
{
	assert( !JStringEmpty(namePrefix) );

	JString fullPath;
	if (JStringEmpty(path))
		{
		if (!JGetTempDirectory(&fullPath))
			{
			fullPath = JGetCurrentDirectory();
			}
		}
	else
		{
		const JBoolean ok = JConvertToAbsolutePath(path, NULL, &fullPath);
		assert( ok );
		}
	assert( JDirectoryExists(fullPath) );

	const JString prefix = JCombinePathAndName(fullPath, namePrefix);

	JString name;
	for (JIndex i=startIndex; i<=kJIndexMax; i++)
		{
		name = prefix;
		if (i > 1)
			{
			name += JString(i, JString::kBase10);
			}
		if (!JStringEmpty(nameSuffix))
			{
			name += nameSuffix;
			}
		if (!JNameUsed(name))
			{
			break;
			}
		}
	return name;
}
JError
JUncompressFile
	(
	const JCharacter*	origFileName,
	JString*			newFileName,
	const JCharacter*	dirName,
	JProcess**			process
	)
{
	// generate a file name if one is not provided

	if (newFileName->IsEmpty())
		{
		const JError err = JCreateTempFile(dirName, NULL, newFileName);
		if (!err.OK())
			{
			return err;
			}
		}
	else if (!JStringEmpty(dirName))
		{
		*newFileName = JCombinePathAndName(dirName, *newFileName);
		}

	// construct the command

	JString cmd = "gunzip --to-stdout ";
	cmd += JPrepArgForExec(origFileName);
	cmd += " >| ";
	cmd += JPrepArgForExec(*newFileName);

	cmd = "/bin/sh -c " + JPrepArgForExec(cmd);

	// run the command

	if (process != NULL)
		{
		return JProcess::Create(process, cmd);
		}
	else
		{
		JString errText;
		return JRunProgram(cmd, &errText);
		}
}
Exemple #23
0
void
JEditVCS
	(
	const JCharacter* fullName
	)
{
	if (JFileExists(fullName) && !JFileWritable(fullName))
		{
		JString path, name;
		JSplitPathAndName(fullName, &path, &name);

		JString vcsDir = JCombinePathAndName(path, kCVSDirName);
		if (JDirectoryExists(vcsDir))
			{
			const JString cmd = "cd " + path + "; cvs edit " + name;
			system(cmd);
			}
		}
}
JString
JXFileInput::GetTextForChooseFile()
	const
{
	JString text = GetText();
	if (text.IsEmpty() && HasBasePath())
		{
		text = itsBasePath;
		JAppendDirSeparator(&text);
		}
	if (text.EndsWith(ACE_DIRECTORY_SEPARATOR_STR))
		{
		text.AppendCharacter('*');
		}
	if (!text.IsEmpty() && JIsRelativePath(text) && HasBasePath())
		{
		text = JCombinePathAndName(itsBasePath, text);
		}
	return text;
}
void
CBExecOutputDocument::ConvertSelectionToFullPath
	(
	JString* fileName
	)
	const
{
	if (JIsAbsolutePath(*fileName))
		{
		return;
		}

	const JString testName = JCombinePathAndName(itsPath, *fileName);
	if (JFileExists(testName))
		{
		*fileName = testName;
		}
	else
		{
		CBTextDocument::ConvertSelectionToFullPath(fileName);
		}
}
void
XDLink::SetProgram
	(
	const JCharacter* fileName
	)
{
	Send("detach");

//	StopDebugger();		// avoid broadcasting DebuggerRestarted
//	StartDebugger();

	itsProgramConfigFileName.Clear();
	itsSourcePathList->DeleteAll();

	JString fullName;
	if (!JConvertToAbsolutePath(fileName, NULL, &fullName) ||
		!JFileReadable(fullName))
		{
		const JString error = JGetString("ConfigFileUnreadable::XDLink");
		Broadcast(UserOutput(error, kJTrue));
		return;
		}
	else if (CMMDIServer::IsBinary(fullName))
		{
		const JString error = JGetString("ConfigFileIsBinary::XDLink");
		Broadcast(UserOutput(error, kJTrue));
		return;
		}

	JString line;
	if (!CMMDIServer::GetLanguage(fullName, &line) ||
		JStringCompare(line, "php", kJFalse) != 0)
		{
		const JString error = JGetString("ConfigFileWrongLanguage::XDLink");
		Broadcast(UserOutput(error, kJTrue));
		return;
		}

	JString path, name, suffix;
	JSplitPathAndName(fullName, &path, &name);
	JSplitRootAndSuffix(name, &itsProgramName, &suffix);

	itsProgramConfigFileName = fullName;

	ifstream input(fullName);
	while (1)
		{
		line = JReadLine(input);
		line.TrimWhitespace();

		if (line.BeginsWith("source-path:"))
			{
			line.RemoveSubstring(1, 12);
			line.TrimWhitespace();

			name = JCombinePathAndName(path, line);
			itsSourcePathList->Append(name);
			}
		else if (!line.IsEmpty() && !line.BeginsWith("code-medic:"))
			{
			line.Prepend("Unknown option: ");
			line.AppendCharacter('\n');
			Broadcast(UserOutput(line, kJTrue));
			}

		if (!input.good())
			{
			break;
			}
		}

	XDSetProgramTask* task = new XDSetProgramTask();
	assert( task != NULL );
	task->Go();
}
JError
JCreateTempDirectory
	(
	const JCharacter*	path,
	const JCharacter*	prefix,
	JString*			fullName
	)
{
	JString p;
	if (!JStringEmpty(path))
		{
		p = path;
		}
	else if (!JGetTempDirectory(&p))
		{
		return JDirEntryDoesNotExist("/tmp");
		}

	if (!JStringEmpty(prefix))
		{
		p = JCombinePathAndName(p, prefix);
		}
	else
		{
		p = JCombinePathAndName(p, "temp_dir_");
		}

	p      += "XXXXXX";
	char* s = p.AllocateCString();

	jclear_errno();
	char* d = mkdtemp(s);
	if (d != NULL)
		{
		*fullName = s;
		JAppendDirSeparator(fullName);
		delete [] s;
		return JNoError();
		}

	fullName->Clear();
	delete [] s;

	// EINVAL counts as unexpected

	const int err = jerrno();
	if (err == EEXIST)
		{
		return JDirEntryAlreadyExists(p);
		}
	else if (err == EFAULT)
		{
		return JSegFault();
		}
	else if (err == EACCES)
		{
		return JAccessDenied(p);
		}
	else if (err == ENAMETOOLONG)
		{
		return JNameTooLong();
		}
	else if (err == ENOENT)
		{
		return JBadPath(p);
		}
	else if (err == ENOTDIR)
		{
		return JComponentNotDirectory(p);
		}
	else if (err == ENOMEM)
		{
		return JNoKernelMemory();
		}
	else if (err == EROFS)
		{
		return JFileSystemReadOnly();
		}
	else if (err == ELOOP)
		{
		return JPathContainsLoop(p);
		}
	else if (err == ENOSPC)
		{
		return JFileSystemFull();
		}
	else
		{
		return JUnexpectedError(err);
		}
}
JBoolean
JExpandHomeDirShortcut
	(
	const JCharacter*	path,
	JString*			result,
	JString*			homeDir,
	JSize*				homeLength
	)
{
	assert( !JStringEmpty(path) && result != NULL );

	JBoolean ok = kJTrue;
	if (path[0] == '~' && path[1] == '\0')
		{
		ok = JGetHomeDirectory(result);
		if (ok && homeDir != NULL)
			{
			*homeDir = *result;
			}
		if (ok && homeLength != NULL)
			{
			*homeLength = 1;
			}
		}
	else if (path[0] == '~' && path[1] == '/')
		{
		ok = JGetHomeDirectory(result);
		if (ok && homeDir != NULL)
			{
			*homeDir = *result;
			}
		if (ok && homeLength != NULL)
			{
			*homeLength = 2;
			}
		if (ok && path[2] != '\0')
			{
			*result = JCombinePathAndName(*result, path+2);
			}
		}
	else if (path[0] == '~')
		{
		JString userName = path+1;
		JIndex i;
		const JBoolean found = userName.LocateSubstring("/", &i);
		if (found)
			{
			userName.RemoveSubstring(i, userName.GetLength());
			}

		ok = JGetHomeDirectory(userName, result);
		if (ok && homeDir != NULL)
			{
			*homeDir = *result;
			}
		if (ok && homeLength != NULL)
			{
			*homeLength = found ? i+1 : strlen(path);
			}
		if (ok && found && path[i+1] != '\0')
			{
			*result = JCombinePathAndName(*result, path+i+1);
			}
		}
	else
		{
		*result = path;
		if (homeDir != NULL)
			{
			homeDir->Clear();
			}
		if (homeLength != NULL)
			{
			*homeLength = 0;
			}
		}

	if (ok)
		{
		return kJTrue;
		}
	else
		{
		result->Clear();
		if (homeDir != NULL)
			{
			homeDir->Clear();
			}
		if (homeLength != NULL)
			{
			*homeLength = 0;
			}
		return kJFalse;
		}
}
JBoolean
JGetTrueName
	(
	const JCharacter*	name,
	JString*			trueName
	)
{
	trueName->Clear();

	if (!JNameUsed(name))
		{
		return kJFalse;
		}

	// check if it is a directory

	else if (JDirectoryExists(name))
		{
		const JString currPath = JGetCurrentDirectory();

		JError err = JChangeDirectory(name);
		if (!err.OK())
			{
			return kJFalse;
			}

		*trueName = JGetCurrentDirectory();

		err = JChangeDirectory(currPath);
		assert_ok( err );

		return kJTrue;
		}

	// it is a file, socket, fifo, etc.

	else
		{
		JString origPath, fileName;
		JSplitPathAndName(name, &origPath, &fileName);

		// get true directory

		JString truePath;
		if (!JGetTrueName(origPath, &truePath))
			{
			return kJFalse;
			}

		// resolve symbolic link

		JString target;
		if ((JGetSymbolicLinkTarget(name, &target)).OK())
			{
			if (JIsRelativePath(target))
				{
				target.Prepend(truePath);
				}
			return JGetTrueName(target, trueName);
			}
		else
			{
			*trueName = JCombinePathAndName(truePath, fileName);
			return kJTrue;
			}
		}
}
void
CBCompileDocument::ConvertSelectionToFullPath
	(
	JString* fileName
	)
	const
{
	(CBGetDocumentManager())->SetActiveListDocument(const_cast<CBCompileDocument*>(this));

	if (JIsAbsolutePath(*fileName))
		{
		return;
		}

	CBTextEditor* te       = GetTextEditor();
	const JString& text    = te->GetText();
	const JIndex caretChar = te->GetInsertionIndex();

	JArray<JIndexRange> matchList;
	JStack<JIndex, JArray<JIndex> > dirStack;

	JIndex i=1;
	while (dirMarkerPattern.MatchFrom(text, i, &matchList))
		{
		i = (matchList.GetElement(1)).last + 1;
		if (i >= caretChar)
			{
			break;
			}

		if (!(matchList.GetElement(3)).IsEmpty())					// Entering
			{
			dirStack.Push(i);
			}
		else														// Leaving
			{
			assert( !(matchList.GetElement(4)).IsEmpty() );
			JIndex j;
			dirStack.Pop(&j);
			}
		}

	JIndex startChar;
	if (dirStack.Peek(&startChar))
		{
		JIndex endChar = startChar;
		if (text.GetCharacter(endChar) != '\'' &&
			text.LocateNextSubstring("\'", &endChar))
			{
			endChar--;
			JString testName = text.GetSubstring(startChar, endChar);
			testName         = JCombinePathAndName(testName, *fileName);
			if (JFileExists(testName))
				{
				*fileName = testName;
				return;
				}
			}
		}

	CBExecOutputDocument::ConvertSelectionToFullPath(fileName);
}