void
JXStringCompletionMenu::CompletionRequested
	(
	const JSize prefixLength
	)
{
	itsRequestCount++;
	if (itsRequestCount > 1 && !IsEmpty())
		{
		itsPrefixLength = prefixLength;

		// prepend "insert tab character" option

		JString s;
		if (itsAllowTabChar &&
			(!GetItemShortcuts(1, &s) || s != kInsertTabShortcut))
			{
			PrependItem(kInsertTabStr, kPlainType, kInsertTabShortcut);
			}

		// place it next to the caret (use the character in front of the caret)

		const JIndex charIndex = itsTE->GetInsertionIndex() - 1;
		const JCoordinate x    = itsTE->GetCharRight(charIndex) + 2;
		const JIndex lineIndex = itsTE->GetLineForChar(charIndex);
		const JCoordinate y    = itsTE->GetLineTop(lineIndex) - GetFrameHeight();
		Place(x,y);

		// open it

		HandleShortcut('\t', JXKeyModifiers(GetDisplay()));
		}
}
void
JXStringCompletionMenu::HandleSelection
	(
	const JIndex index
	)
{
	if (itsAllowTabChar && index == kInsertTabCmd)
		{
		// tab may insert spaces
		itsTE->JXTEBase::HandleKeyPress('\t', JXKeyModifiers(GetDisplay()));
		}
	else if (index - (itsAllowTabChar ? kSpecialCmdCount : 0) <= kMaxItemCount)
		{
		JString s = GetItemText(index);
		s.RemoveSubstring(1, kItemPrefixLength + itsPrefixLength);
		itsTE->Paste(s);
		}
}
void
CBExecOutputDocument::Receive
	(
	JBroadcaster*	sender,
	const Message&	message
	)
{
	if (sender == itsRecordLink && message.Is(JMessageProtocolT::kMessageReady))
		{
		ReceiveRecord();
		}
	else if (sender == itsDataLink && message.Is(JAsynchDataReceiverT::kDataReady))
		{
		ReceiveData(message);
		}

	else if (sender == itsProcess && message.Is(JProcess::kFinished))
		{
		const JProcess::Finished* info =
			dynamic_cast<const JProcess::Finished*>(&message);
		assert( info != NULL );
		const JBoolean stayOpen = ProcessFinished(*info);

		// let somebody else start a new process

		itsClearWhenStartFlag = kJFalse;	// in case they call SetConnection() in ReceiveWithFeedback()
		Finished msg(info->Successful(), JI2B(info->GetReason() != kJChildFinished));
		BroadcastWithFeedback(&msg);
		itsClearWhenStartFlag = JI2B(itsUseCount == 0 && !msg.SomebodyIsWaiting());

		if (itsUseCount == 0 && !stayOpen && !ProcessRunning())
			{
			Close();
			}
		}

	else if (sender == itsPauseButton && message.Is(JXButton::kPushed))
		{
		ToggleProcessRunning();
		}
	else if (sender == itsStopButton && message.Is(JXButton::kPushed))
		{
		StopProcess();
		}
	else if (sender == itsKillButton && message.Is(JXButton::kPushed))
		{
		KillProcess();
		}

	else if (sender == itsEOFButton && message.Is(JXButton::kPushed))
		{
		if (!(itsCmdInput->GetText()).IsEmpty())
			{
			itsCmdInput->HandleKeyPress(kJReturnKey, JXKeyModifiers(GetDisplay()));
			}
		CloseOutFD();
		UpdateButtons();
		}

	else
		{
		CBTextDocument::Receive(sender, message);
		}
}