void
JPTPrinter::InvertPageOrder
	(
	const JString&	text,
	ostream&		output
	)
	const
{
	JIndex endIndex   = text.GetLength() + 1;
	JIndex startIndex = endIndex - 1;
	while (text.LocatePrevSubstring(kPageSeparatorStr, kPageSeparatorStrLength, &startIndex))
		{
		const JIndex i = startIndex + kPageSeparatorStrLength;
		if (endIndex > i)
			{
			output.write(text.GetCString() + i-1, endIndex - i);
			}
		output << kPageSeparatorStr;

		endIndex = startIndex;
		startIndex--;
		}

	if (endIndex > 1)
		{
		output.write(text.GetCString(), endIndex-1);
		}
}
Exemple #2
0
JString
CMLink::Build2DArrayExpressionForCFamilyLanguage
	(
	const JCharacter*	origExpr,
	const JInteger		rowIndex,
	const JInteger		colIndex
	)
{
	JString expr = origExpr;

	const JBoolean usesI = expr.Contains("$i");		// row
	const JBoolean usesJ = expr.Contains("$j");		// col

	const JString iStr(rowIndex, 0);	// must use floating point conversion
	const JString jStr(colIndex, 0);	// must use floating point conversion

	// We have to do both at the same time because otherwise we lose a $.

	if (usesI || usesJ)
		{
		const JCharacter* map[] =
			{
			"i", iStr.GetCString(),
			"j", jStr.GetCString()
			};
		(JGetStringManager())->Replace(&expr, map, sizeof(map));
		}

	if (!usesI || !usesJ)
		{
		if (expr.GetFirstCharacter() != '(' ||
			expr.GetLastCharacter()  != ')')
			{
			expr.PrependCharacter('(');
			expr.AppendCharacter(')');
			}

		if (!usesI)
			{
			expr.AppendCharacter('[');
			expr += iStr;
			expr.AppendCharacter(']');
			}
		if (!usesJ)
			{
			expr.AppendCharacter('[');
			expr += jStr;
			expr.AppendCharacter(']');
			}
		}

	return expr;
}
Exemple #3
0
JString
CMLink::Build1DArrayExpressionForCFamilyLanguage
	(
	const JCharacter*	origExpr,
	const JInteger		index
	)
{
	JString expr = origExpr;

	const JString indexStr(index, 0);	// must use floating point conversion
	if (expr.Contains("$i"))
		{
		const JCharacter* map[] =
			{
			"i", indexStr.GetCString()
			};
		(JGetStringManager())->Replace(&expr, map, sizeof(map));
		}
	else
		{
		if (expr.GetFirstCharacter() != '(' ||
			expr.GetLastCharacter()  != ')')
			{
			expr.PrependCharacter('(');
			expr.AppendCharacter(')');
			}

		expr.AppendCharacter('[');
		expr += indexStr;
		expr.AppendCharacter(']');
		}

	return expr;
}
void
CBCommand::ReportInfiniteLoop
	(
	const CBFunctionStack&	fnStack,
	const JIndex			startIndex
	)
{
	const JSize cmdCount = fnStack.GetElementCount();
	JString loop;
	for (JIndex i=startIndex; i>=1; i--)
		{
		if (!loop.IsEmpty())
			{
			loop += " -> ";
			}
		loop += fnStack.Peek(i);
		}
	loop += " -> ";
	loop += fnStack.Peek(startIndex);

	const JCharacter* map[] =
		{
		"loop", loop.GetCString()
		};
	const JString msg = JGetString("InfiniteLoop::CBCommand", map, sizeof(map));
	(JGetUserNotification())->ReportError(msg);
}
void
JCheckSiteName
	(
	const JCharacter*	encSiteSuffix,
	const JCharacter	siteCode,
	const JCharacter*	map[],
	const JSize			size
	)
{
	JString siteSuffix = encSiteSuffix;
	const JSize len    = siteSuffix.GetLength();
	for (JIndex i=1; i<=len; i++)
		{
		siteSuffix.SetCharacter(i, siteSuffix.GetCharacter(i) ^ siteCode);
		}

	map[1] = siteSuffix.GetCString();

	if (!(JGetHostName()).EndsWith(siteSuffix, kJFalse))
		{
		const JString msg = JGetString(kWrongSiteID, map, size);
		(JGetUserNotification())->DisplayMessage(msg);
		exit(0);
		}
}
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);
		}
}
void
CBFunctionMenu::SetEmptyMenuItems()
{
	JString name = CBCtagsUser::GetFunctionMenuTitle(itsFileType);
	name.ToLower();

	const JCharacter* map[] =
		{
		"name", name.GetCString()
		};
	const JString menuItems = JGetString(kEmptyMenuID, map, sizeof(map));
	SetMenuItems(menuItems);
}
void
CBSearchDocument::AppendText
	(
	const JString& text
	)
{
	if (text.GetFirstCharacter() == CBSearchTE::kIncrementProgress)
		{
		itsIndicator->IncrementValue();
		return;
		}

	CBTextEditor* te = GetTextEditor();

	itsFoundFlag = kJTrue;
	const std::string s(text.GetCString(), text.GetLength());
	std::istringstream input(s);

	if (text.GetFirstCharacter() == CBSearchTE::kError)
		{
		input.ignore();
		JString msg;
		JReadAll(input, &msg);

		const JIndex startIndex = te->GetTextLength() + 1;
		te->SetCaretLocation(startIndex);
		te->Paste(msg);
		te->Paste("\n");
		if (!itsOnlyListFilesFlag)
			{
			te->Paste("\n");
			}

		te->SetFontStyle(startIndex, startIndex + msg.GetLength()-1,
						 GetErrorStyle(), kJTrue);
		}
	else if (itsOnlyListFilesFlag)
		{
		JString fileName;
		input >> fileName;
		CBExecOutputDocument::AppendText(fileName);

		if (itsIsReplaceFlag)
			{
			ReplaceAll(fileName);
			}
		}
	else
		{
void
CBSymbolList::ParseFile
	(
	const JCharacter*		fileName,
	const CBTextFileType	fileType,
	const JFAID_t			id
	)
{
	JString data;
	CBLanguage lang;
	if (ProcessFile(fileName, fileType, &data, &lang))
		{
		std::istrstream input(data.GetCString(), data.GetLength());
		ReadSymbolList(input, lang, fileName, id);
		itsChangedDuringParseFlag = kJTrue;
		}
}
const JCharacter*
SyGApplication::GetNMShortcut
	(
	JIndex* i
	)
	const
{
	if (*i <= kShortcutKeyCount)
		{
		kShortcutStr.SetCharacter(6, kShortcutKey[*i-1]);
		(*i)++;
		return kShortcutStr.GetCString();
		}
	else
		{
		return NULL;
		}
}
void
GDBGetSourceFileList::HandleSuccess
	(
	const JString& origData
	)
{
	if (origData.BeginsWith("Source files for which symbols have been read in:"))
		{
		(JXGetApplication())->DisplayBusyCursor();

		JXFileListTable* table = (GetFileList())->GetTable();
		table->RemoveAllFiles();

		JString data = origData;
		JIndex i,j;
		while (data.LocateSubstring("Source files for which symbols", &i))
			{
			j = i;
			if (!data.LocateNextSubstring(":", &j))
				{
				j = data.GetLength();
				}
			data.ReplaceSubstring(i, j, ",");
			}
		data.TrimWhitespace();		// no comma after last file

		std::istrstream input(data.GetCString(), data.GetLength());
		JString fullName, path, name, s;
		JBoolean foundDelimiter;
		do
			{
			input >> ws;
			fullName = JReadUntil(input, ',', &foundDelimiter);
			fullName.TrimWhitespace();
			if (!fullName.IsEmpty())
				{
				JSplitPathAndName(fullName, &path, &name);
				table->AddFile(name);
				}
			}
			while (foundDelimiter);
		}
JString
XDLink::Build1DArrayExpression
	(
	const JCharacter*	origExpr,
	const JInteger		index
	)
{
	JString expr = origExpr;

	const JString indexStr(index, 0);	// must use floating point conversion
	if (expr.Contains("$i"))
		{
		// double literal $'s

		for (JIndex i=expr.GetLength()-1; i>=1; i--)
			{
			if (expr.GetCharacter(i)   == '$' &&
				expr.GetCharacter(i+1) != 'i')
				{
				expr.InsertCharacter('$', i);
				}
			}

		const JCharacter* map[] =
			{
			"i", indexStr.GetCString()
			};
		(JGetStringManager())->Replace(&expr, map, sizeof(map));
		}
	else
		{
		expr.AppendCharacter('[');
		expr += indexStr;
		expr.AppendCharacter(']');
		}

	return expr;
}
void
War2Wiz::ReceiveMessage
	(
	const JIndex	senderIndex,
	WarSocket&		socket
	)
{
	WarPlayer* sender = itsPlayerList->NthElement(senderIndex);

	JString s;
	const JBoolean ok = socket.GetNextMessage(&s);
	assert( ok );

	jistrstream(input, s.GetCString(), s.GetLength());
	WWMessageType type;
	input >> type;

	if (type == kWWClientIdentity)
		{
		ReceiveClientIdentity(senderIndex, sender, input);
		}

	else if (type == kWWClientAlive)
		{
		socket.ResetTimer();
		}

	else if (type == kWWChatMessage)
		{
		JIndex receiverIndex;
		JString msg;
		input >> receiverIndex >> msg;
		if (receiverIndex == kWWAllPlayersIndex || PlayerIndexValid(receiverIndex))
			{
			SendChatMessage(senderIndex, receiverIndex, msg);
			}
		}
CBLanguage
CBFnMenuUpdater::UpdateMenu
	(
	const JCharacter*		fileName,
	const CBTextFileType	fileType,
	const JBoolean			sort,
	const JBoolean			includeNS,
	const JBoolean			pack,
	JXTextMenu*				menu,
	JArray<JIndex>*			lineIndexList
	)
{
	menu->RemoveAllItems();
	lineIndexList->RemoveAll();

	if (pack)
		{
		menu->SetDefaultFontSize(JGetDefaultFontSize()-2, kJFalse);
		menu->CompressHeight(kJTrue);
		}
	else
		{
		menu->SetDefaultFontSize(JGetDefaultFontSize(), kJFalse);
		menu->CompressHeight(kJFalse);
		}

	JString data;
	CBLanguage lang;
	if (ProcessFile(fileName, fileType, &data, &lang))
		{
		std::istrstream input(data.GetCString(), data.GetLength());
		ReadFunctionList(input, CBGetLanguage(fileType),
						 sort, includeNS, menu, lineIndexList);
		}
	return lang;
}
JBoolean
JXImageSelection::ConvertData
	(
	const Atom		requestType,
	Atom*			returnType,
	unsigned char**	data,
	JSize*			dataLength,
	JSize*			bitsPerBlock
	)
	const
{
	*data         = NULL;
	*dataLength   = 0;
	*returnType   = None;
	*bitsPerBlock = 8;

	if (itsImage == NULL)
		{
		return kJFalse;
		}

	JString fileName;
	if (!(JCreateTempFile(&fileName)).OK())
		{
		return kJFalse;
		}

	JError err = JUnknownError(1);
	if (requestType == itsXPMXAtom)
		{
		err = itsImage->WriteXPM(fileName);
		}
	else if (requestType == itsGIFXAtom)
		{
		err = itsImage->WriteGIF(fileName, kJFalse);	// if too many colors, use PNG
		}
	else if (requestType == itsPNGXAtom)
		{
		err = itsImage->WritePNG(fileName);
		}
	else if (requestType == itsJPEGXAtom)
		{
		err = itsImage->WriteJPEG(fileName);
		}

	if (err.OK())
		{
		JString imageData;
		JReadFile(fileName, &imageData);
		JRemoveFile(fileName);

		*returnType = requestType;
		*dataLength = imageData.GetLength();
		*data       = new unsigned char[ *dataLength ];
		if (*data != NULL)
			{
			memcpy(*data, imageData.GetCString(), *dataLength);
			return kJTrue;
			}
		}

	JRemoveFile(fileName);
	return kJFalse;
}
Exemple #16
0
void
JTEStyler::UpdateStyles
	(
	const JTextEditor*				te,
	const JString&					text,
	JRunArray<JTextEditor::Font>*	styles,
	JIndexRange*					recalcRange,
	JIndexRange*					redrawRange,
	const JBoolean					deletion,
	JArray<TokenData>*				tokenStartList
	)
{
	if (!itsActiveFlag)
		{
		tokenStartList->RemoveAll();
		return;
		}

	const JSize textLength = text.GetLength();
	if (textLength == 0)
		{
		tokenStartList->RemoveAll();
		return;
		}

	te->GetDefaultFont(&itsDefFontID, &itsFontSize, &itsDefFontStyle, &itsDefFontAlign);
	itsFontName = te->GetDefaultFontName();

	TokenData tokenData;
	if (recalcRange->first == 1 && recalcRange->last >= text.GetLength())
		{
		itsRedoAllFlag = kJTrue;
		itsCheckRange.Set(1, text.GetLength());

		tokenStartList->RemoveAll();
		tokenData = TokenData(1, GetFirstTokenExtraData());
		tokenStartList->AppendElement(tokenData);

		styles->RemoveAll();
		}
	else
		{
		itsRedoAllFlag = kJFalse;

		// calculate the range that needs to be checked

		JIndex firstIndex = recalcRange->first;
		JIndex lastIndex  = recalcRange->last;
		if ((deletion && firstIndex > 1) || firstIndex > textLength)
			{
			// This fixes the case when the last character of the token is deleted.

			firstIndex--;

			// This fixes the case when the style run and the token both
			// end at the inserted text.  (e.g. "x [ y ]" <- "x // y ]")

			lastIndex++;
			}
		if (lastIndex > textLength)
			{
			// We can't decrease recalcRange's end index, and we can't find
			// textLength+1 in *styles.

			lastIndex = textLength;
			}

		JIndex runIndex1, firstIndexInRun1;
		JBoolean ok = styles->FindRun(firstIndex, &runIndex1, &firstIndexInRun1);
		assert( ok );

		JIndex runIndex2        = runIndex1;
		JIndex firstIndexInRun2 = firstIndexInRun1;
		ok = styles->FindRun(firstIndex, lastIndex, &runIndex2, &firstIndexInRun2);
		assert( ok );
		run_assert(styles, lastIndex, runIndex2, firstIndexInRun2);

		itsCheckRange.Set(firstIndexInRun1, firstIndexInRun2 + styles->GetRunLength(runIndex2)-1);

		// let derived class expand the range

		JIndexRange savedRange = itsCheckRange;
		PreexpandCheckRange(text, *styles, *recalcRange, deletion, &itsCheckRange);
		assert( itsCheckRange.Contains(savedRange) &&
				itsCheckRange.last <= styles->GetElementCount() );

		// find nearest token in front of itsCheckRange

		if (tokenStartList->IsEmpty())
			{
			tokenData = TokenData(1, GetFirstTokenExtraData());
			tokenStartList->AppendElement(tokenData);
			}
		else
			{
			JBoolean foundTokenStart;
			TokenData target(itsCheckRange.first, TokenExtra());
			JIndex tokenStartIndex =
				tokenStartList->SearchSorted1(target, JOrderedSetT::kAnyMatch, &foundTokenStart);
			if (!foundTokenStart)
				{
				tokenStartIndex--;	// wants to insert -after- the value
				}
			tokenData = tokenStartList->GetElement(tokenStartIndex);

			// the rest of the token starts are invalid

			const JSize tokenStartCount = tokenStartList->GetElementCount();
			if (tokenStartIndex < tokenStartCount)
				{
				tokenStartList->RemoveNextElements(tokenStartIndex+1, tokenStartCount - tokenStartIndex);
				}
			}

		// While typing in one place, it is much faster to back up from itsCheckRange
		// than to start from the top.

		itsTokenRunIndex   = runIndex1;
		itsTokenFirstInRun = firstIndexInRun1;
		ok = styles->FindRun(firstIndex, tokenData.startIndex, &itsTokenRunIndex, &itsTokenFirstInRun);
		assert( ok );
		run_assert(styles, tokenData.startIndex, itsTokenRunIndex, itsTokenFirstInRun);
		}

	// prepare to accumulate new token starts

	itsTokenStartList  = tokenStartList;
	itsTokenStartCount = 0;
	itsTokenStart      = tokenData.startIndex;

	// scan the text and adjust the styles

	std::istrstream input(text.GetCString(), text.GetLength());
	JSeekg(input, itsTokenStart-1);

	itsTE          = te;
	itsFontMgr     = te->TEGetFontManager();
	itsText        = &text;
	itsStyles      = styles;
	itsRecalcRange = recalcRange;
	itsRedrawRange = redrawRange;

	#if DEBUG_TIMING_INFO
	JStopWatch timer;
	timer.StartTimer();
	#endif

	Scan(input, tokenData.data);

	#if DEBUG_TIMING_INFO
	timer.StopTimer();
	cout << "JTEStyler: " << timer.PrintTimeInterval() << endl;
	#endif

	itsTE             = NULL;
	itsFontMgr        = NULL;
	itsText           = NULL;
	itsStyles         = NULL;
	itsRecalcRange    = NULL;
	itsRedrawRange    = NULL;
	itsTokenStartList = NULL;
}
void
CMLineIndexTable::OpenLineMenu
	(
	const JIndex			lineIndex,
	const JPoint&			pt,
	const JXButtonStates&	buttonStates,
	const JXKeyModifiers&	modifiers,
	const JBoolean			onlyBreakpoints,
	const JIndex			firstBPIndex
	)
{
	if (itsLineMenu == NULL)
		{
		itsLineMenu = jnew JXTextMenu("", this, kFixedLeft, kFixedTop, 0,0, 10,10);
		assert( itsLineMenu != NULL );
		itsLineMenu->SetToHiddenPopupMenu(kJTrue);
		itsLineMenu->SetUpdateAction(JXMenu::kDisableNone);
		ListenTo(itsLineMenu);
		}

	itsLineMenuLineIndex  = lineIndex;
	itsIsFullLineMenuFlag = !onlyBreakpoints;

	itsLineMenu->RemoveAllItems();
	if (itsIsFullLineMenuFlag)
		{
		itsLineMenu->AppendMenuItems(kLineMenuStr);
		}
	itsLineMenu->AppendMenuItems(kAllBreakpointsMenuStr);

	JIndex bpIndex = firstBPIndex;
	if (bpIndex == 0 && !GetFirstBreakpointOnLine(lineIndex, &bpIndex))
		{
		bpIndex == 0;
		}

	itsLineMenuBPRange.SetToNothing();
	if (itsBPList->IndexValid(bpIndex))
		{
		itsLineMenuBPRange.first = bpIndex;
		}

	while (itsBPList->IndexValid(bpIndex))
		{
		itsLineMenuBPRange.last = bpIndex;
		const CMBreakpoint* bp  = itsBPList->NthElement(bpIndex);

		const JString bpIndexStr(bp->GetDebuggerIndex(), 0);
		const JString ignoreCountStr(bp->GetIgnoreCount(), 0);
		const JCharacter* map[] =
			{
			"index",        bpIndexStr.GetCString(),
			"ignore_count", ignoreCountStr.GetCString()
			};

		JString s = kBreakpointMenuStr;
		(JGetStringManager())->Replace(&s, map, sizeof(map));

		itsLineMenu->AppendMenuItems(s);

		if (!HasMultipleBreakpointsOnLine(bpIndex))
			{
			break;
			}
		bpIndex++;
		}

	JTableSelection& s = GetTableSelection();
	s.ClearSelection();
	s.SelectRow(lineIndex);
	if (itsDeselectTask == NULL)
		{
		itsDeselectTask = jnew CMDeselectLineTask(this);
		assert( itsDeselectTask != NULL );
		itsDeselectTask->Start();
		}

	itsLineMenu->PopUp(this, pt, buttonStates, modifiers);
}
JError
JExecute
	(
	const JCharacter*		argv[],
	const JSize				size,
	pid_t*					childPID,
	const JExecuteAction	toAction,
	int*					toFD,
	const JExecuteAction	origFromAction,
	int*					fromFD,
	const JExecuteAction	errAction,
	int*					errFD
	)
{
	assert( size > sizeof(JCharacter*) );
	assert( argv[ (size/sizeof(JCharacter*)) - 1 ] == NULL );

	const JExecuteAction fromAction =
		(origFromAction == kJForceNonblockingPipe ? kJCreatePipe : origFromAction);

	assert( toAction != kJTossOutput && toAction != kJAttachToFromFD &&
			toAction != kJForceNonblockingPipe );
	assert( fromAction != kJAttachToFromFD );
	assert( errAction != kJForceNonblockingPipe );

	assert( (toAction != kJCreatePipe && toAction != kJAttachToFD) ||
			toFD != NULL );
	assert( (fromAction != kJCreatePipe && fromAction != kJAttachToFD) ||
			fromFD != NULL );
	assert( (errAction != kJCreatePipe && errAction != kJAttachToFD) ||
			errFD != NULL );

	JString progName;
	if (!JProgramAvailable(argv[0], &progName))
		{
		return JProgramNotAvailable(argv[0]);
		}
	argv[0] = progName.GetCString();

	int fd[3][2];

	if (toAction == kJCreatePipe)
		{
		const JError err = JCreatePipe(fd[0]);
		if (!err.OK())
			{
			return err;
			}
		}

	if (fromAction == kJCreatePipe)
		{
		const JError err = JCreatePipe(fd[1]);
		if (!err.OK())
			{
			if (toAction == kJCreatePipe)
				{
				close(fd[0][0]);
				close(fd[0][1]);
				}
			return err;
			}
		}

	if (errAction == kJCreatePipe)
		{
		const JError err = JCreatePipe(fd[2]);
		if (!err.OK())
			{
			if (toAction == kJCreatePipe)
				{
				close(fd[0][0]);
				close(fd[0][1]);
				}
			if (fromAction == kJCreatePipe)
				{
				close(fd[1][0]);
				close(fd[1][1]);
				}
			return err;
			}
		}

	pid_t pid;
	const JError err = JThisProcess::Fork(&pid);
	if (!err.OK())
		{
		if (toAction == kJCreatePipe)
			{
			close(fd[0][0]);
			close(fd[0][1]);
			}
		if (fromAction == kJCreatePipe)
			{
			close(fd[1][0]);
			close(fd[1][1]);
			}
		if (errAction == kJCreatePipe)
			{
			close(fd[2][0]);
			close(fd[2][1]);
			}
		return err;
		}

	// child

	else if (pid == 0)
		{
		const int stdinFD = fileno(stdin);
		if (toAction == kJCreatePipe)
			{
			dup2(fd[0][0], stdinFD);
			close(fd[0][0]);
			close(fd[0][1]);
			}
		else if (toAction == kJAttachToFD)
			{
			dup2(*toFD, stdinFD);
			close(*toFD);
			}

		const int stdoutFD = fileno(stdout);
		if (fromAction == kJCreatePipe)
			{
			dup2(fd[1][1], stdoutFD);
			close(fd[1][0]);
			close(fd[1][1]);
			}
		else if (fromAction == kJAttachToFD)
			{
			dup2(*fromFD, stdoutFD);
			close(*fromFD);
			}
		else if (fromAction == kJTossOutput)
			{
			FILE* nullFile = fopen("/dev/null", "a");
			int nullfd     = fileno(nullFile);
			dup2(nullfd, stdoutFD);
			fclose(nullFile);
			}

		const int stderrFD = fileno(stderr);
		if (errAction == kJCreatePipe)
			{
			dup2(fd[2][1], stderrFD);
			close(fd[2][0]);
			close(fd[2][1]);
			}
		else if (errAction == kJAttachToFD)
			{
			dup2(*errFD, stderrFD);
			close(*errFD);
			}
		else if (errAction == kJTossOutput)
			{
			FILE* nullFile = fopen("/dev/null", "a");
			int nullfd     = fileno(nullFile);
			dup2(nullfd, stderrFD);
			fclose(nullFile);
			}
		else if (errAction == kJAttachToFromFD && fromAction != kJIgnoreConnection)
			{
			dup2(stdoutFD, stderrFD);
			}

		ACE_OS::execvp(argv[0], const_cast<char* const*>(argv));

		cerr << "Unable to run program \"" << argv[0] << '"' << endl;
		cerr << endl;
		cerr << "JExecute()::execvp() failed" << endl;
		cerr << "Errno value: " << jerrno() << endl;

		JThisProcess::Exit(1);
		return JNoError();
		}

	// parent

	else
		{
		if (origFromAction == kJForceNonblockingPipe)
			{
			pid_t pid2;
			const JError err2 = JThisProcess::Fork(&pid2);
			if (err2.OK() && pid2 == 0)
				{
				for (int i=0; i<150; i++)
					{
					JWait(0.1);

					int value = fcntl(fd[1][1], F_GETFL, 0);
					if (value & O_NONBLOCK)
						{
						cerr << "turning off nonblocking for cout: " << value << endl;
						fcntl(fd[1][1], F_SETFL, value & (~ O_NONBLOCK));
						}
					}

				JThisProcess::Exit(0);
				return JNoError();
				}

			JProcess* p = new JProcess(pid2);
			p->KillAtExit(kJTrue);
			}

		if (toAction == kJCreatePipe)
			{
			close(fd[0][0]);
			*toFD = fd[0][1];
			}
		if (fromAction == kJCreatePipe)
			{
			close(fd[1][1]);
			*fromFD = fd[1][0];
			}
		if (errAction == kJCreatePipe)
			{
			close(fd[2][1]);
			*errFD = fd[2][0];
			}

		if (childPID == NULL)
			{
			return JWaitForChild(pid);
			}
		else
			{
			*childPID = pid;
			return JNoError();
			}
		}
}
JString
GMessageHeader::DecodeMIMEWord
	(
	const JBoolean		qType,
	JString*			header,
	const JIndexRange	range
	)
{
	JString temp;
	JIndex findex	= range.first;
	// first ? '=?'
	JBoolean ok		= header->LocateNextSubstring("?", &findex);
	if (!ok)
		{
		return temp;
		}
	findex++;
	// second ? '?Q'
	ok		= header->LocateNextSubstring("?", &findex);
	if (!ok)
		{
		return temp;
		}
	// third ? 'Q?'
	findex++;
	ok		= header->LocateNextSubstring("?", &findex);
	if (!ok || (findex > range.last))
		{
		return temp;
		}
	JIndex endIndex	= findex + 1;
	// final ? '?='
	ok		= header->LocateNextSubstring("?", &endIndex);
	if (!ok || (endIndex > range.last))
		{
		return temp;
		}
	// so the encoded text is between findex and endIndex.
	if (qType)
		{
		JIndex dIndex	= findex + 1;
		while (dIndex < endIndex)
			{
			JCharacter c	= header->GetCharacter(dIndex);
			if (c == '=')
				{
				JString hex	= header->GetSubstring(dIndex + 1, dIndex + 2);
				hex.Prepend("0x");
				JInteger hexVal;
				if (hex.ConvertToInteger(&hexVal))
					{
					c	= (JCharacter)hexVal;
					temp.AppendCharacter(c);
					dIndex += 3;
					}
				}
			else if (c == '_')
				{
				temp.AppendCharacter(' ');
				dIndex++;
				}
			else
				{
				temp.AppendCharacter(c);
				dIndex++;
				}
			}
		}
	else
		{
		if (findex + 1 > header->GetLength())
			{
			return temp;
			}
		if (endIndex - 1 < findex + 1)
			{
			return temp;
			}
		temp = header->GetSubstring(findex + 1, endIndex - 1);
		const std::string s(temp.GetCString(), temp.GetLength());
		std::istringstream is(s);
		std::ostringstream os;
		JDecodeBase64(is, os);
		temp = os.str();
		}
	return temp;
}
JString
XDLink::Build2DArrayExpression
	(
	const JCharacter*	origExpr,
	const JInteger		rowIndex,
	const JInteger		colIndex
	)
{
	JString expr = origExpr;

	const JBoolean usesI = expr.Contains("$i");		// row
	const JBoolean usesJ = expr.Contains("$j");		// col

	const JString iStr(rowIndex, 0);	// must use floating point conversion
	const JString jStr(colIndex, 0);	// must use floating point conversion

	// We have to do both at the same time because otherwise we lose a $.

	if (usesI || usesJ)
		{
		// double literal $'s

		for (JIndex i=expr.GetLength()-1; i>=1; i--)
			{
			if (expr.GetCharacter(i)   == '$' &&
				expr.GetCharacter(i+1) != 'i' &&
				expr.GetCharacter(i+1) != 'j')
				{
				expr.InsertCharacter('$', i);
				}
			}

		const JCharacter* map[] =
			{
			"i", iStr.GetCString(),
			"j", jStr.GetCString()
			};
		(JGetStringManager())->Replace(&expr, map, sizeof(map));
		}

	if (!usesI || !usesJ)
		{
		if (expr.GetFirstCharacter() != '(' ||
			expr.GetLastCharacter()  != ')')
			{
			expr.PrependCharacter('(');
			expr.AppendCharacter(')');
			}

		if (!usesI)
			{
			expr.AppendCharacter('[');
			expr += iStr;
			expr.AppendCharacter(']');
			}
		if (!usesJ)
			{
			expr.AppendCharacter('[');
			expr += jStr;
			expr.AppendCharacter(']');
			}
		}

	return expr;
}
void
XDLink::ReceiveMessageFromDebugger()
{
	itsLink->StopTimer();

	JString data;
	const JBoolean ok = itsLink->GetNextMessage(&data);
	assert( ok );

	if (data.IsEmpty() || data.GetFirstCharacter() != '<')
		{
		return;
		}

	Broadcast(DebugOutput(data, kOutputType));

	if (itsInitFinishedFlag)
		{
		if (!itsProgramIsStoppedFlag)
			{
			itsProgramIsStoppedFlag = kJTrue;
			Broadcast(ProgramStopped(CMLocation("", 1)));
			}

		itsDebuggerBusyFlag = kJFalse;
		Broadcast(DebuggerReadyForInput());
		}

	xmlDoc* doc = xmlReadMemory(data.GetCString(), data.GetLength(),
								NULL, NULL, XML_PARSE_NOCDATA);
	if (doc != NULL)
		{
		xmlNode* root = xmlDocGetRootElement(doc);

		if (root != NULL && strcmp((char*) root->name, "init") == 0)
			{
			itsIDEKey         = JGetXMLNodeAttr(root, "idekey");
			const JString uri = JGetXMLNodeAttr(root, "fileuri");

			const JCharacter* map[] =
				{
				"idekey", itsIDEKey,
				"uri",    uri
				};
			JString msg = JGetString("ConnectionInfo::XDLink", map, sizeof(map));
			Broadcast(UserOutput(msg, kJFalse));

			Send("feature_set -n show_hidden -v 1");
			Send("step_into");

			JString programName;
			GetProgram(&programName);

			Broadcast(AttachedToProcess());
			Broadcast(SymbolsLoaded(JI2B(uri == itsScriptURI), programName));

			itsInitFinishedFlag = kJTrue;
			itsScriptURI        = uri;
			}
		else if (root != NULL && strcmp((char*) root->name, "response") == 0)
			{
			const JString status = JGetXMLNodeAttr(root, "status");
			const JString reason = JGetXMLNodeAttr(root, "reason");
			if (status == "break" && reason == "error" &&
				root->children != NULL && root->children->children != NULL &&
				strcmp((char*) root->children->name, "error") == 0 &&
				root->children->children->type == XML_TEXT_NODE)
				{
				JString msg            = (char*) root->children->children->content;
				const JString encoding = JGetXMLNodeAttr(root->children, "encoding");
				if (encoding == "base64")
					{
					msg.DecodeBase64(&msg);
					}
				msg += "\n";
				Broadcast(UserOutput(msg, kJTrue));
				}

			const JString idStr = JGetXMLNodeAttr(root, "transaction_id");
			JUInt id;
			if (idStr.ConvertToUInt(&id))
				{
				HandleCommandRunning(id);
				}

			CMCommand* cmd;
			if (GetRunningCommand(&cmd))
				{
				itsParsedDataRoot = root;

				cmd->Finished(JI2B(
					root->children == NULL || strcmp((char*) root->children->name, "error") != 0));

				itsParsedDataRoot = NULL;

				SetRunningCommand(NULL);
				if (!HasForegroundCommands())
					{
					RunNextCommand();
					}
				}

			if (status == "stopping" || status == "stopped")
				{
				CancelAllCommands();

				XDCloseSocketTask* task = new XDCloseSocketTask(itsLink);
				assert( task != NULL );
				task->Go();
				}
			}

		xmlFreeDoc(doc);
		}
}
JBoolean
JXInputField::InputValid()
{
	const JSize length  = GetTextLength();

	JString errorStr;
	if (itsMinLength == 1 && length == 0)
		{
		errorStr = JGetString("EmptyError::JXInputField");
		}
	else if (itsMinLength > 0 && itsMinLength == itsMaxLength &&
			 length != itsMinLength)
		{
		if (itsMaxLength == 1)
			{
			errorStr = JGetString("Require1Char::JXInputField");
			}
		else
			{
			const JString s(itsMinLength, 0);
			const JCharacter* map[] =
				{
				"count", s.GetCString()
				};
			errorStr = JGetString("RequireNChar::JXInputField", map, sizeof(map));
			}
		}
	else if (itsMinLength > 0 && itsMaxLength > 0 &&
			 (length < itsMinLength || itsMaxLength < length))
		{
		const JString n(itsMinLength, 0), m(itsMaxLength, 0);
		const JCharacter* map[] =
			{
			"min", n.GetCString(),
			"max", m.GetCString()
			};
		errorStr = JGetString("RangeNMChar::JXInputField", map, sizeof(map));
		}
	else if (itsMinLength > 0 && length < itsMinLength)
		{
		const JString n(itsMinLength, 0);
		const JCharacter* map[] =
			{
			"min", n.GetCString()	// itsMinLength > 1, see above
			};
		errorStr = JGetString("MinNChar::JXInputField", map, sizeof(map));
		}
	else if (itsMaxLength > 0 && length > itsMaxLength)
		{
		if (itsMaxLength == 1)
			{
			errorStr = JGetString("Max1Char::JXInputField");
			}
		else
			{
			const JString n(itsMaxLength, 0);
			const JCharacter* map[] =
				{
				"max", n.GetCString()
				};
			errorStr = JGetString("MaxNChar::JXInputField", map, sizeof(map));
			}
		}

	if (errorStr.IsEmpty())
		{
		return kJTrue;
		}
	else
		{
		(JGetUserNotification())->ReportError(errorStr);
		return kJFalse;
		}
}