void
GMessageHeader::DecodeMIMEHeader
	(
	JString* header
	)
{
	JArray<JIndexRange> subList;
	JSize count	= encodedMIMEQRegex.MatchAll(*header, &subList);
	JBoolean qType	= kJTrue;
	if (count == 0)
		{
		count	= encodedMIMEBRegex.MatchAll(*header, &subList);
		qType	= kJFalse;
		}
	if (count > 0)
		{
		JString temp;
		JIndex mIndex		= 1;
		const JSize count	= subList.GetElementCount();
		for (JIndex i = 1; i <= count; i++)
			{
			JIndexRange range	= subList.GetElement(i);
//			if ((range.first != mIndex) &&
//				RangeContainsNWS(*header, mIndex, range.first))
//				{
//				temp += header->GetSubstring(mIndex, range.first - 1);
//				}
			if (range.first != mIndex)
				{
				JString trimmed = header->GetSubstring(mIndex, range.first - 1);
				trimmed.TrimWhitespace();
				if (!trimmed.IsEmpty())
					{
					temp += header->GetSubstring(mIndex, range.first - 1);
					}
				}
			temp   += DecodeMIMEWord(qType, header, range);
			mIndex	= range.last + 1;
			}
		if (mIndex < header->GetLength())
			{
			temp   += header->GetSubstring(mIndex, header->GetLength());
			}
		*header = temp;
		}
}
void
GRaggedFloatTableData::SetRow
	(
	const JIndex				index,
	const JArray<JFloat>&	rowData
	)
{
	const JSize colCount = GetDataColCount();
	assert( rowData.GetElementCount() == colCount );

	for (JIndex i=1; i<=colCount; i++)
		{
		JArray<JFloat>* dataCol = itsCols->NthElement(i);
		dataCol->SetElement(index, rowData.GetElement(i));
		}

	Broadcast(JTableData::RectChanged(JRect(index, 1, index+1, colCount+1)));
}
void
TestWidget::PrintSelectionTargets
	(
	const Time time
	)
{
	JXDisplay* display         = GetDisplay();
	JXSelectionManager* selMgr = GetSelectionManager();
	JXDNDManager* dndMgr       = GetDNDManager();

	JArray<Atom> typeList;
	if (selMgr->GetAvailableTypes(kJXClipboardName, time, &typeList))
		{
		std::cout << std::endl;
		std::cout << "Data types available from the clipboard:" << std::endl;
		std::cout << std::endl;

		const JSize typeCount = typeList.GetElementCount();
		for (JIndex i=1; i<=typeCount; i++)
			{
			const Atom type = typeList.GetElement(i);
			std::cout << XGetAtomName(*display, type) << std::endl;
			}

		for (JIndex i=1; i<=typeCount; i++)
			{
			const Atom type = typeList.GetElement(i);
			if (type == XA_STRING ||
				type == selMgr->GetUtf8StringXAtom() ||
				type == selMgr->GetMimePlainTextXAtom())
				{
				std::cout << std::endl;
				PrintSelectionText(kJXClipboardName, time, type);
				}
			}
		}
	else
		{
		std::cout << std::endl;
		std::cout << "Unable to access the clipboard." << std::endl;
		std::cout << std::endl;
		}
}
JX2DCurveOptionsDialog::JX2DCurveOptionsDialog
	(
	JXWindowDirector*			supervisor,
	const JArray<J2DCurveInfo>&	array,
	const JArray<JBoolean>&		hasXErrors,
	const JArray<JBoolean>&		hasYErrors,
	const JArray<JBoolean>&		isFunction,
	const JArray<JBoolean>&		isScatter,
	const JIndex				startIndex
	)
	:
	JXDialogDirector(supervisor, kJTrue),
	itsCurrentIndex(startIndex)
{
	assert( array.IndexValid(startIndex) );

	itsCurveInfo = new JArray<J2DCurveInfo>;
	assert(itsCurveInfo != NULL);

	const JSize count = array.GetElementCount();
	for (JIndex i=1; i<=count; i++)
		{
		J2DCurveInfo info = array.GetElement(i);
		info.name = new JString(*info.name);
		assert(info.name != NULL);
		itsCurveInfo->AppendElement(info);
		}

	itsHasXErrors = new JArray<JBoolean>(hasXErrors);
	assert( itsHasXErrors != NULL );

	itsHasYErrors = new JArray<JBoolean>(hasYErrors);
	assert( itsHasYErrors != NULL );

	itsIsFunction = new JArray<JBoolean>(isFunction);
	assert( itsIsFunction != NULL );

	itsIsScatter = new JArray<JBoolean>(isScatter);
	assert( itsIsScatter != NULL );

	BuildWindow();
}
void
TestWidget::PrintSelectionTargets
	(
	const Time time
	)
{
	JXDisplay* display         = GetDisplay();
	JXSelectionManager* selMgr = GetSelectionManager();
	JXDNDManager* dndMgr       = GetDNDManager();

	JArray<Atom> typeList;
	if (selMgr->GetAvailableTypes(kJXClipboardName, time, &typeList))
		{
		cout << endl;
		cout << "Data types available from the clipboard:" << endl;
		cout << endl;

		Atom textType = None;
		const JSize typeCount = typeList.GetElementCount();
		for (JIndex i=1; i<=typeCount; i++)
			{
			const Atom type = typeList.GetElement(i);
			cout << XGetAtomName(*display, type) << endl;
			if (type == XA_STRING)
				{
				textType = type;
				}
			}
		cout << endl;

		if (textType != None)
			{
			PrintSelectionText(kJXClipboardName, time, textType);
			}
		}
	else
		{
		cout << endl;
		cout << "Unable to access the clipboard." << endl;
		cout << endl;
		}
}
JBoolean
CBStylerBase::TypeStylesChanged
	(
	const JArray<JFontStyle>& newTypeStyles
	)
	const
{
	const JSize count = itsTypeStyles->GetElementCount();
	assert( newTypeStyles.GetElementCount() == count );

	for (JIndex i=1; i<=count; i++)
		{
		if (itsTypeStyles->GetElement(i) != newTypeStyles.GetElement(i))
			{
			return kJTrue;
			}
		}

	return kJFalse;
}
void
GRaggedFloatTableData::RemoveRow
	(
	const JIndex index
	)
{
	assert( index < GetRowCount() );

	const JSize colCount = itsCols->GetElementCount();
	for (JIndex i=1; i<=colCount; i++)
		{
		JArray<JFloat>* colData = itsCols->NthElement(i);
		const JSize rowCount = colData->GetElementCount();

		if (index <= rowCount)
			{
			RemoveElement(index, i);
			}
		}

}
void
JXGC::SetDashList
	(
	const JArray<JSize>&	dashList,
	const JSize				offset
	)
{
	const JSize dashCount = dashList.GetElementCount();

	char* xDashList = new char [ dashCount ];
	assert( xDashList != NULL );

	for (JIndex i=1; i<=dashCount; i++)
		{
		xDashList[i-1] = dashList.GetElement(i);
		}

	XSetDashes(*itsDisplay, itsXGC, offset, xDashList, dashCount);

	delete [] xDashList;
}
void
GRaggedFloatTableData::MoveRow
	(
	const JIndex origIndex,
	const JIndex newIndex
	)
{
	const JSize colCount = itsCols->GetElementCount();
	for (JIndex i=1; i<=colCount; i++)
		{
		JArray<JFloat>* colData = itsCols->NthElement(i);
		const JSize rowCount = colData->GetElementCount();
		if ( (origIndex <= rowCount) && (newIndex <= rowCount) )
			{
			colData->MoveElementToIndex(origIndex, newIndex);
			}
		}

	if (itsBroadcast)
		{
		Broadcast(JTableData::RowMoved(origIndex, newIndex));
		}
}
JBoolean
CBSymbolList::UpdateFinished
	(
	const JArray<JFAID_t>&	deadFileList,
	JProgressDisplay&		pg
	)
{
	DeleteProcess();

	// reset to lenient search

	itsSymbolList->SetCompareFunction(CompareSymbols);

	// toss files that no longer exist

	const JSize fileCount = deadFileList.GetElementCount();
	if (fileCount > 0)
		{
		pg.FixedLengthProcessBeginning(fileCount, JGetString(kCleaningUpID), kJFalse, kJTrue);

		for (JIndex i=1; i<=fileCount; i++)
			{
			RemoveFile(deadFileList.GetElement(i));
			pg.IncrementProgress();
			}

		pg.ProcessFinished();
		}

	if (itsChangedDuringParseFlag && !CBInUpdateThread())
		{
		itsReparseAllFlag = kJFalse;
		Broadcast(Changed());
		}

	return itsChangedDuringParseFlag;
}
void
GRaggedFloatTableData::InsertRow
	(
	const JIndex				index,
	const JOrderedSet<JFloat>*	initData
	)
{
	assert( initData == NULL || initData->GetElementCount() == GetDataColCount() );

	const JSize colCount = itsCols->GetElementCount();
	for (JIndex i=1; i<=colCount; i++)
		{
		JArray<JFloat>* colData = itsCols->NthElement(i);
		if (index <= colData->GetElementCount())
			{
			JFloat value = 0;
			if ((initData != NULL) && (i <= initData->GetElementCount()))
				{
				value = initData->GetElement(i);
				}
			InsertElement(index, i);
			}
		}
}
void
CBStylerBase::SetDefaultFontColor
	(
	const JColorIndex color
	)
{
JIndex i;

	if (color != itsDefColor)
		{
		for (i=1; i<=itsTypeNameCount; i++)
			{
			JFontStyle style = itsTypeStyles->GetElement(i);
			if (style.color == itsDefColor)
				{
				style.color = color;
				itsTypeStyles->SetElement(i, style);
				}
			}

		JArray<WordStyle> wordList;
		GetWordList(*itsWordStyles, &wordList, kJFalse);
		const JSize wordCount = wordList.GetElementCount();
		for (i=1; i<=wordCount; i++)
			{
			WordStyle data = wordList.GetElement(i);
			if (data.value.color == itsDefColor)
				{
				data.value.color = color;
				itsWordStyles->SetElement(data.key, data.value);
				}
			}

		itsDefColor = color;
		}
}
JParseResult
JParseAsSummation
	(
	const JCharacter*		origExpr,
	const JSize				origLength,
	const JVariableList*	theVariableList,
	JFunction**				theFunction,
	const JBoolean			allowUIF
	)
{
	*theFunction = NULL;

	// remove enclosing parentheses

	const JCharacter* expr = origExpr;
	const JSize length     = JStripParentheses(&expr, origLength);

	// build a list of the locations of all visible + and - operators

	const JCharacter* plusStr  = JPGetAdditionString();
	const JSize plusLength     = JPGetAdditionStringLength();
	const JCharacter* minusStr = JPGetSubtractionString();
	const JSize minusLength    = JPGetSubtractionStringLength();

	JArray<JCharacter> opList;
	JArray<JSize> opOffsetList;
	JArray<JSize> argOffsetList;
	JSize lastOffset = 0;
	while (1)
		{
		JSize plusOffset;
		const JBoolean foundPlus =
			JFindFirstOperator(expr + lastOffset, length - lastOffset,
							   plusStr, &plusOffset);
		plusOffset += lastOffset;

		JSize minusOffset;
		const JBoolean foundMinus =
			JFindFirstOperator(expr + lastOffset, length - lastOffset,
							   minusStr, &minusOffset);
		minusOffset += lastOffset;

		JCharacter opType;
		JSize opOffset, argOffset;
		if (foundPlus && foundMinus && plusOffset < minusOffset)
			{
			opType = '+';
			opOffset  = plusOffset;
			argOffset = plusOffset + plusLength;
			}
		else if (foundPlus && foundMinus && minusOffset < plusOffset)
			{
			opType = '-';
			opOffset  = minusOffset;
			argOffset = minusOffset + minusLength;
			}
		else if (foundPlus)
			{
			opType = '+';
			opOffset  = plusOffset;
			argOffset = plusOffset + plusLength;
			}
		else if (foundMinus)
			{
			opType = '-';
			opOffset  = minusOffset;
			argOffset = minusOffset + minusLength;
			}
		else
			{
			break;
			}

		if (!JIsExponentSign(expr, opOffset, argOffset))
			{
			opList.AppendElement(opType);
			opOffsetList.AppendElement(opOffset);
			argOffsetList.AppendElement(argOffset);
			}

		lastOffset = argOffset;
		}

	if (opList.IsEmpty())
		{
		return kJNotMyProblem;
		}
	else if (opList.GetElementCount() == 1 && opOffsetList.GetElement(1) == 0)
		{
		const JSize argOffset = argOffsetList.GetElement(1);
		JFunction* arg = NULL;
		if (!JRecurseFunction(expr + argOffset, length - argOffset, theVariableList,
							  &arg, allowUIF))
			{
			return kJParseError;
			}

		if (opList.GetElement(1) == '-')
			{
			*theFunction = new JNegation(arg);
			assert( *theFunction != NULL );
			return kJParsedOK;
			}
		else	// we ignore leading +
			{
			*theFunction = arg;
			return kJParsedOK;
			}
		}
	else
		{
		JSummation* sum = new JSummation;
		assert( sum != NULL );

		// No operand in front means implied +

		if (opOffsetList.GetElement(1) > 0)
			{
			opList.PrependElement('+');
			opOffsetList.PrependElement(0);
			argOffsetList.PrependElement(0);
			}

		// We append an extra element at the end of the list
		// so our loop catches the last summand.

		opList.AppendElement('+');
		opOffsetList.AppendElement(length);
		argOffsetList.AppendElement(length);

		// Parse each summand

		const JSize opCount = opList.GetElementCount();
		for (JIndex i=1; i<opCount; i++)
			{
			const JCharacter opType = opList.GetElement(i);
			const JSize startOffset = argOffsetList.GetElement(i);
			const JSize endOffset   = opOffsetList.GetElement(i+1);

			JFunction* arg = NULL;
			if (!JRecurseFunction(expr + startOffset, endOffset - startOffset,
								  theVariableList, &arg, allowUIF))
				{
				delete sum;
				return kJParseError;
				}
			else if (opType == '+')
				{
				sum->SetArg(i, arg);
				}
			else	// opType == '-'
				{
				JNegation* negArg = new JNegation(arg);
				assert( negArg != NULL );
				sum->SetArg(i, negArg);
				}
			}

		*theFunction = sum;
		return kJParsedOK;
		}
}
JBoolean
TestWidget::WillAcceptDrop
	(
	const JArray<Atom>&	typeList,
	Atom*				action,
	const JPoint&		pt,
	const Time			time,
	const JXWidget*		source
	)
{
	JXDNDManager* dndMgr = GetDNDManager();
	JXDisplay* display   = GetDisplay();

	JBoolean hasURIList = kJFalse;

	std::cout << std::endl;
	std::cout << "Data types available from DND source:" << std::endl;
	std::cout << std::endl;

	const JSize typeCount = typeList.GetElementCount();
	for (JIndex i=1; i<=typeCount; i++)
		{
		const Atom type = typeList.GetElement(i);
		std::cout << XGetAtomName(*display, type) << std::endl;

		if (type == GetSelectionManager()->GetURLXAtom())
			{
			hasURIList = kJTrue;
			}
		}

	if (hasURIList)
		{
		if (its2Rect.Contains(pt) || its3Rect.Contains(pt))
			{
			std::cout << std::endl;
			std::cout << "Accepting the drop of type text/uri-list" << std::endl;
			std::cout << std::endl;

			*action = dndMgr->GetDNDActionPrivateXAtom();
			return kJTrue;
			}
		else
			{
			return kJFalse;
			}
		}
	else if (*action == dndMgr->GetDNDActionCopyXAtom())
		{
		std::cout << std::endl;
		std::cout << "Accepting the drop" << std::endl;
		std::cout << std::endl;

		PrintSelectionText(dndMgr->GetDNDSelectionName(), time,
						   GetSelectionManager()->GetMimePlainTextXAtom());
		return kJTrue;
		}
	else
		{
		std::cout << std::endl;
		std::cout << "Not accepting the drop because the action isn't copy" << std::endl;
		std::cout << "Action: " << XGetAtomName(*display, *action) << std::endl;
		std::cout << std::endl;

		PrintSelectionText(dndMgr->GetDNDSelectionName(), time,
						   GetSelectionManager()->GetMimePlainTextXAtom());

		return kJFalse;
		}
}
void
GMMIMEParser::ParseMIMEHeader
	(
	std::istream&		input,
	GMIMEHeader*	header,
	const JBoolean	display
	)
{
	JString data;
	JCharacter c	= input.peek();
	if (c == '\n')
		{
//		input.get(c);
		}
//	input >> std::ws;

	// first we need to search for the first empty line. This line is the
	// end of the header.

	JString line;
	while (1)
		{
		JBoolean found;
		line = JReadLine(input, &found);
		if (line.IsEmpty())
			{
			break;
			}
		if (isspace(line.GetFirstCharacter()))
			{
			line.TrimWhitespace();
			if (line.IsEmpty())
				{
				break;
				}
			data.AppendCharacter(' ');
			}
		else if (!data.IsEmpty())
			{
			data.AppendCharacter('\n');
			}
		data += line;
		}
	data.AppendCharacter('\n');

	// we now need to search through the header for parameter:value pairs
	// using the gmime_header_regex defined above.

	JArray<JIndexRange> ranges;
	gmime_header_regex.MatchAll(data, &ranges);

	JSize count = ranges.GetElementCount();
	for (JSize i = 1; i <= count; i++)
		{
		JIndexRange range = ranges.GetElement(i);
		JString parmValPair = data.GetSubstring(range);
		JString parm;
		JString val;
		if (parmValPair.BeginsWith("MIME") ||
			parmValPair.BeginsWith("Mime") ||
			parmValPair.BeginsWith("Content"))
			{
			CleanParmValPair(parmValPair, &parm, &val);
			parm.ToLower();
			if (parm == "mime-Version")
				{
				val.TrimWhitespace();
				header->SetVersion(val);
				}
			else if (parm == "content-type")
				{
				ParseContentType(val, header);
				}
			else if (parm == "content-transfer-encoding")
				{
				val.TrimWhitespace();
				val.ToLower();
				header->SetEncoding(val);
				}
			else if (parm == "content-disposition")
				{
				ParseContentDisposition(val, header);
				}
			}
		}

	// this is a nested message, so some of the headers need to be displayed
	if (display)
		{
		JString text = "---------\n";
		JIndex findex	= 1;
		if (data.BeginsWith("From: ") || data.LocateSubstring("\nFrom: ", &findex))
			{
			if (findex > 1)
				{
				findex ++;
				}
			JIndex eindex	= findex;
			if (data.LocateNextSubstring("\n", &eindex) && (eindex > findex + 1))
				{
				text += data.GetSubstring(findex, eindex - 1);
				text += "\n";
				}
			}
		findex	= 1;
		if (data.BeginsWith("Date: ") || data.LocateSubstring("\nDate: ", &findex))
			{
			if (findex > 1)
				{
				findex ++;
				}
			JIndex eindex	= findex;
			if (data.LocateNextSubstring("\n", &eindex) && (eindex > findex + 1))
				{
				text += data.GetSubstring(findex, eindex - 1);
				text += "\n";
				}
			}
		findex	= 1;
		const JCharacter* kSubjectStr	= "Subject: ";
		if (data.BeginsWith("Subject: ") || data.LocateSubstring("\nSubject: ", &findex))
			{
			if (findex > 1)
				{
				findex ++;
				}
			JIndex eindex	= findex;
			if (data.LocateNextSubstring("\n", &eindex) && (eindex > findex + 1))
				{
				text += data.GetSubstring(findex, eindex - 1);
				text += "\n";
				}
			}
		WriteTextString(&text, GMIMEHeader());
		}
}
JBoolean
CBCtagsUser::HasExuberantCtags()
{
	if (itsHasExuberantCtagsFlag == kUntested)
		{
		itsHasExuberantCtagsFlag = kFailure;

		// this hack is required on Linux kernel 2.3.x (4/19/2000)
		j_sig_func*	origHandler = signal(SIGCHLD, emptyHandler);

		pid_t pid;

		#if defined _J_SUNOS
		pid_t* ppid = NULL;
		#else
		pid_t* ppid = &pid;
		#endif

		int fromFD;
		JError err = JExecute(kCheckVersionCmd, ppid,
							  kJIgnoreConnection, NULL,
							  kJCreatePipe, &fromFD,
							  kJTossOutput, NULL);
		if (err.OK())
			{
			JString vers;
			JReadAll(fromFD, &vers);

			JArray<JIndexRange> matchList;
			if (versionPattern.Match(vers, &matchList))
				{
				matchList.RemoveElement(1);

				const JSize count = matchList.GetElementCount();
				JString s;
				for (JIndex i=1; i<=count; i++)
					{
					JUInt v = 0;
					const JIndexRange r = matchList.GetElement(i);
					if (!r.IsEmpty())
						{
						s = vers.GetSubstring(r);
						while (!isdigit(s.GetFirstCharacter()))
							{
							s.RemoveSubstring(1, 1);
							}
						const JBoolean ok = s.ConvertToUInt(&v);
						assert( ok );
						}

					if (v > kMinVersion[i-1] ||
						(i == count && v == kMinVersion[i-1]))
						{
						itsHasExuberantCtagsFlag = kSuccess;
						break;
						}
					else if (v < kMinVersion[i-1])
						{
						break;
						}
					}
				}
			}

		if (origHandler != SIG_ERR)
			{
			signal(SIGCHLD, origHandler);
			}
		}

	return JI2B( itsHasExuberantCtagsFlag == kSuccess );
}
void
JPartition::AdjustCompartmentsAfterDragAll
	(
	const JCoordinate coord
	)
{
JIndex i;

	// compress compartments in front of itsDragIndex+1

	if (coord < itsStartCoord)
		{
		JArray<JCoordinate> origSizes = *itsSizes;
		JArray<JCoordinate> minSizes  = *itsMinSizes;
		JSize count = origSizes.GetElementCount();
		for (i=count; i>itsDragIndex; i--)
			{
			origSizes.RemoveElement(i);
			minSizes.RemoveElement(i);
			}

		JArray<JCoordinate> newSizes;
		const JCoordinate reqSize = itsStartCoord - coord;
		JCoordinate newSpace;
		const JBoolean ok = CreateSpace(origSizes, minSizes, 0, reqSize, reqSize,
										&newSizes, &newSpace);
		assert( ok );

		for (i=1; i<=itsDragIndex; i++)
			{
			itsSizes->SetElement(i, newSizes.GetElement(i));
			}
		itsSizes->SetElement(itsDragIndex+1,
							 itsSizes->GetElement(itsDragIndex+1) + reqSize);

		SetCompartmentSizes();
		}

	// compress compartments after itsDragIndex

	else if (coord > itsStartCoord)
		{
		const JSize compartmentCount = GetCompartmentCount();

		JArray<JCoordinate> origSizes = *itsSizes;
		JArray<JCoordinate> minSizes  = *itsMinSizes;
		for (i=1; i<=itsDragIndex; i++)
			{
			origSizes.RemoveElement(1);
			minSizes.RemoveElement(1);
			}

		JArray<JCoordinate> newSizes;
		const JCoordinate reqSize = coord - itsStartCoord;
		JCoordinate newSpace;
		const JBoolean ok = CreateSpace(origSizes, minSizes, 0, reqSize, reqSize,
										&newSizes, &newSpace);
		assert( ok );

		itsSizes->SetElement(itsDragIndex,
							 itsSizes->GetElement(itsDragIndex) + reqSize);
		for (i=itsDragIndex+1; i<=compartmentCount; i++)
			{
			itsSizes->SetElement(i, newSizes.GetElement(i-itsDragIndex));
			}

		SetCompartmentSizes();
		}
}
JBoolean
JPartition::CreateSpace
	(
	const JArray<JCoordinate>&	origSizes,
	const JArray<JCoordinate>&	minSizes,
	const JIndex				elasticIndex,
	const JCoordinate			reqSize,
	const JCoordinate			minReqSize,
	JArray<JCoordinate>*		newSizes,
	JCoordinate*				newSpace
	)
	const
{
	assert( reqSize >= 0 && minReqSize >= 0 && reqSize >= minReqSize );

	*newSpace = 0;
	if (reqSize == 0)
		{
		*newSizes = origSizes;
		return kJTrue;
		}

	// try shrinking the elastic compartment first

	if (elasticIndex > 0)
		{
		const JCoordinate size    = origSizes.GetElement(elasticIndex);
		const JCoordinate minSize = minSizes.GetElement(elasticIndex);

		const JCoordinate availSpace = size - minSize;
		if (availSpace >= reqSize)
			{
			*newSizes = origSizes;
			newSizes->SetElement(elasticIndex, size - reqSize);
			*newSpace = reqSize;
			return kJTrue;
			}
		}

	// distribute the load among all the other compartments
	// (shrink each to min, then expand to fill whatever space is left)

	const JSize compartmentCount = origSizes.GetElementCount();

	JCoordinate currSize = 0;
	JCoordinate minSize  = 0;
	for (JIndex i=1; i<=compartmentCount; i++)
		{
		currSize += origSizes.GetElement(i);
		minSize  += minSizes.GetElement(i);
		}

	if (currSize < minSize + minReqSize)
		{
		return kJFalse;
		}
	else if (currSize < minSize + reqSize)
		{
		*newSizes = minSizes;
		*newSpace = currSize - minSize;
		}
	else
		{
		FillSpace(minSizes, 0, currSize - minSize - reqSize, newSizes);
		*newSpace = reqSize;
		}

	return kJTrue;
}
JBoolean
JXImageSelection::GetImage
	(
	JXSelectionManager* selMgr,
	const Atom			selectionName,
	const Time			time,
	JXColormap*			colormap,
	JXImage**			image,
	const JBoolean		allowApproxColors
	)
{
	JXDisplay* display   = colormap->GetDisplay();
	const Atom xpmXAtom  = display->RegisterXAtom(kXPMXAtomName);
	const Atom gifXAtom  = display->RegisterXAtom(kGIFXAtomName);
	const Atom pngXAtom  = display->RegisterXAtom(kPNGXAtomName);
	const Atom jpegXAtom = display->RegisterXAtom(kJPEGXAtomName);

	JArray<Atom> typeList;
	if (selMgr->GetAvailableTypes(selectionName, time, &typeList))
		{
		JBoolean xpm=kJFalse, gif=kJFalse, png=kJFalse, jpeg=kJFalse;

		const JSize count = typeList.GetElementCount();
		for (JIndex i=1; i<=count; i++)
			{
			const Atom type = typeList.GetElement(i);
			xpm  = JI2B( xpm  || type == xpmXAtom  );
			gif  = JI2B( gif  || type == gifXAtom  );
			png  = JI2B( png  || type == pngXAtom  );
			jpeg = JI2B( jpeg || type == jpegXAtom );
			}

		while (xpm || gif || png || jpeg)
			{
			Atom type = None;
			if (png)
				{
				png  = kJFalse;
				type = pngXAtom;
				}
			else if (gif)
				{
				gif  = kJFalse;
				type = gifXAtom;
				}
			else if (xpm)
				{
				xpm  = kJFalse;
				type = xpmXAtom;
				}
			else if (jpeg)		// JPEG is lossy
				{
				jpeg = kJFalse;
				type = jpegXAtom;
				}

			Atom returnType;
			unsigned char* data;
			JSize dataLength;
			JXSelectionManager::DeleteMethod delMethod;
			JString fileName;
			if (selMgr->GetData(selectionName, time, type,
								&returnType, &data, &dataLength, &delMethod) &&
				(JCreateTempFile(&fileName)).OK())
				{
				ofstream output(fileName);
				output.write((char*) data, dataLength);
				output.close();

				selMgr->DeleteData(&data, delMethod);

				const JError err =
					JXImage::CreateFromFile(display, colormap, fileName, image,
											allowApproxColors);
				JRemoveFile(fileName);

				if (err.OK())
					{
					return kJTrue;
					}
				}
			}
		}

	*image = NULL;
	return kJFalse;
}
SCCircuitVarList::SCCircuitVarList
	(
	istream&			input,
	const JFileVersion	vers
	)
	:
	JVariableList()
{
JIndex i;

	SCCircuitVarListX();

	JSize varCount;
	input >> varCount;

	JArray<JIndex> misfitIndexList;
	JPtrArray<JString> misfitFnList(JPtrArrayT::kDeleteAll);
	for (i=1; i<=varCount; i++)
		{
		VarInfo info;

		info.name = new JString;
		assert( info.name != NULL );
		input >> *(info.name);

		input >> info.value;

		JBoolean isFunction;
		input >> isFunction;
		if (isFunction)
			{
			JString* fStr = new JString;
			assert( fStr != NULL );
			input >> *fStr;
			(JGetUserNotification())->SetSilent(kJTrue);	// complain the second time
			if (JParseFunction(*fStr, this, &(info.f)))
				{
				delete fStr;
				}
			else
				{
				info.f = NULL;
				misfitIndexList.AppendElement(i);
				misfitFnList.Append(fStr);
				}
			(JGetUserNotification())->SetSilent(kJFalse);
			}

		input >> info.visible;

		itsVars->AppendElement(info);
		}

	const JSize misfitCount = misfitIndexList.GetElementCount();
	for (i=1; i<=misfitCount; i++)
		{
		const JIndex j      = misfitIndexList.GetElement(i);
		VarInfo info        = itsVars->GetElement(j);
		const JString* fStr = misfitFnList.NthElement(i);
		if (JParseFunction(*fStr, this, &(info.f)))
			{
			itsVars->SetElement(j, info);
			}
		}
}
void
ClipboardWidget::Paste()
{
	// Get the window and selection manager for use below.
	JXWindow* window           = GetWindow();
	JXSelectionManager* selMgr = GetSelectionManager();

	// If the clipboard is not empty, retrieve the available types.
	JArray<Atom> typeList;
	if (selMgr->GetAvailableTypes(kJXClipboardName, CurrentTime, &typeList))
		{

		// Loop through the available types to see if the clipboard has
		// one that we want.
		const JSize typeCount = typeList.GetElementCount();
		for (JIndex i=1; i<=typeCount; i++)
			{
			const Atom atom = typeList.GetElement(i);

			// Check if the i-th type is one we can use.
			if (atom == XA_STRING || atom == selMgr->GetTextXAtom())
				{
				// Get the data of the appropriate type.
				unsigned char* data = NULL;
				JSize dataLength;
				Atom returnType;
				JXSelectionManager::DeleteMethod dMethod;
				if (selMgr->GetData(kJXClipboardName, CurrentTime,
						atom, &returnType, &data, &dataLength,
						&dMethod))
					{
					// We can only handle the simplest format.
					if (returnType == XA_STRING)
						{
						// Copy the data into our text.
						itsText.Set(reinterpret_cast<JCharacter*>(data), dataLength);

						// Our text changed, so we need to refresh.
						Refresh();
						}

					// This is required to delete the allocated data.
					// Forgetting to do this will cause a memory leak!
					selMgr->DeleteData(&data, dMethod);

					if (returnType == XA_STRING)
						{
						// We succeeded, so we return.
						return;
						}
					}
				else
					{
					(JGetUserNotification())->ReportError(
						"Unable to retrieve text from the clipboard.");
					}
				}
			}

		// If we got this far, the data type that we want wasn't on the
		// clipboard.
		(JGetUserNotification())->ReportError("Unable to paste from clipboard.");
		}
	else
		{
		// There isn't anything on the clipboard.
		(JGetUserNotification())->ReportError("Clipboard is empty.");
		}
}