void
JXFSBindingTable::TableDrawCell
	(
	JPainter&		p,
	const JPoint&	cell,
	const JRect&	rect
	)
{
	JPoint editCell;
	if (GetEditedCell(&editCell) && cell == editCell)
		{
		return;
		}

	HilightIfSelected(p, cell, rect);

	const JFSBinding* b = itsBindingList->GetBinding(cell.y);
	JFSBinding::CommandType type;
	JBoolean singleFile;
	const JString& cmd = b->GetCommand(&type, &singleFile);

	if (cell.x == kPatternColumn)
		{
		p.SetFont(JGetMonospaceFontName(), kJDefaultMonoFontSize, JFontStyle());

		JRect r = rect;
		r.left += kHMarginWidth;
		p.String(r, b->GetPattern(), JPainter::kHAlignLeft, JPainter::kVAlignCenter);

		p.SetFont(JGetDefaultFontName(), kJDefaultFontSize, JFontStyle());
		}
	else if (cell.x == kCommandColumn)
		{
		p.SetFont(JGetMonospaceFontName(), kJDefaultMonoFontSize, JFontStyle());

		JRect r = rect;
		r.left += kHMarginWidth;
		p.String(r, cmd, JPainter::kHAlignLeft, JPainter::kVAlignCenter);

		p.SetFont(JGetDefaultFontName(), kJDefaultFontSize, JFontStyle());
		}
	else if (cell.x == kTypeColumn)
		{
		const JString& str = itsTypeMenu->GetItemText(kCmdTypeToMenuIndex[type]);
		p.String(rect, str, JPainter::kHAlignCenter, JPainter::kVAlignCenter);
		}
	else if (cell.x == kSingleFileColumn && singleFile)
		{
		JRect r;
		r.top    = rect.ycenter();
		r.left   = rect.xcenter();
		r.bottom = r.top+1;
		r.right  = r.left+1;
		r.Expand(3, 3);

		p.SetFilling(kJTrue);
		p.Ellipse(r);
		p.SetFilling(kJFalse);
		}
}
void
CBSymbolTable::TableDrawCell
	(
	JPainter&		p,
	const JPoint&	cell,
	const JRect&	rect
	)
{
	HilightIfSelected(p, cell, rect);

	const JIndex symbolIndex = CellToSymbolIndex(cell);

	CBLanguage lang;
	CBSymbolList::Type type;
	const JString& symbolName =
		itsSymbolList->GetSymbol(symbolIndex, &lang, &type);

	const JString* signature;
	itsSymbolList->GetSignature(symbolIndex, &signature);

	if (CalcColWidths(symbolName, signature))
		{
		AdjustColWidths();
		}

	const JXImage* icon     = NULL;
	const JFontStyle& style = (CBGetSymbolTypeList())->GetStyle(type, &icon);

	// draw icon

	if (icon != NULL)
		{
		JRect r = rect;
		r.right = r.left + kIconWidth;
		p.Image(*icon, icon->GetBounds(), r);
		}

	// draw name

	p.SetFontStyle(style);

	JRect r = rect;
	r.left += kIconWidth + kHMarginWidth;
	p.String(r, symbolName, JPainter::kHAlignLeft, JPainter::kVAlignCenter);

	if (signature != NULL)
		{
		r.left += (GetFontManager())->GetStringWidth(
			JGetDefaultFontName(), kJDefaultFontSize, JFontStyle(), symbolName);
		p.String(r, *signature, JPainter::kHAlignLeft, JPainter::kVAlignCenter);
		}
}
void
JX2DCurveNameList::TableDrawCell
	(
	JPainter&		p,
	const JPoint&	cell,
	const JRect&	rect
	)
{
	HilightIfSelected(p, cell, rect);

	const JString* curveName = itsNameList->NthElement(cell.y);

	JRect r = rect;
	r.left += kHMarginWidth;
	p.String(r, *curveName, JPainter::kHAlignLeft, JPainter::kVAlignCenter);
}
void
CMLineIndexTable::TableDrawCell
	(
	JPainter&		p,
	const JPoint&	cell,
	const JRect&	rect
	)
{
	HilightIfSelected(p, cell, rect);

	if (JIndex(cell.x) == kBreakpointColumn)
		{
		DrawBreakpoints(p, cell, rect);
		}

	else if (JIndex(cell.x) == kExecPointColumn && cell.y == itsCurrentLineIndex)
		{
		// We can't use a static polygon because line heights can vary,
		// e.g. due to underlines.

		const JCoordinate delta = rect.height()/2;

		JPolygon poly;
		poly.AppendElement(JPoint(rect.left+kMarginWidth,       rect.top));
		poly.AppendElement(JPoint(rect.left+kMarginWidth+delta, rect.top + delta));
		poly.AppendElement(JPoint(rect.left+kMarginWidth,       rect.top + 2*delta));

		p.SetPenColor(GetCurrentLineMarkerColor());
		p.SetFilling(kJTrue);
		p.Polygon(poly);

		p.SetPenColor(GetColormap()->GetBlackColor());
		p.SetFilling(kJFalse);
		p.Polygon(poly);
		}

	else if (JIndex(cell.x) == kLineNumberColumn)
		{
		p.SetFont(itsText->GetDefaultFont());

		JRect r  = rect;
		r.right -= kMarginWidth;

		const JString str = GetLineText(cell.y);
		p.String(r, str, JPainter::kHAlignRight);
		}
}
void
GMFilterNameTable::TableDrawCell
	(
	JPainter&		p,
	const JPoint&	cell,
	const JRect&	rect
	)
{
	assert(cell.y <= (JCoordinate)itsFilters->GetElementCount());

	HilightIfSelected(p, cell, rect);

	JRect r = rect;
	r.left += kHMarginWidth;
	p.JPainter::String(r, itsFilters->NthElement(cell.y)->GetNickname(),
			 JPainter::kHAlignLeft, JPainter::kVAlignCenter);
}
void
GLFitParameterTable::TableDrawCell
	(
	JPainter&		p,
	const JPoint&	cell,
	const JRect&	rect
	)
{
	HilightIfSelected(p, cell, rect);

	JIndex realIndex = cell.x;

	if (realIndex == kStartColIndex && !itsHasStartValues)
		{
		realIndex = kFitColIndex;
		}
	else if (realIndex == kFitColIndex && !itsHasStartValues)
		{
		realIndex = kErrorColIndex;
		}

	JString str;
	if (realIndex == kNameColIndex)
		{
		str	= *(itsNameList->NthElement(cell.y));
		}
	else if (realIndex == kStartColIndex)
		{
		str = JString(itsStartValues->GetElement(cell.y), JString::kPrecisionAsNeeded, JString::kStandardExponent, 0, 5);
		}
	else if (realIndex == kFitColIndex)
		{
		str = JString(itsFitValues->GetElement(cell.y), JString::kPrecisionAsNeeded, JString::kStandardExponent, 0, 5);
		}
	else if (realIndex == kErrorColIndex)
		{
		str = JString(itsErrorValues->GetElement(cell.y), JString::kPrecisionAsNeeded, JString::kStandardExponent, 0, 5);
		}

	JRect r = rect;
	r.left += kHMarginWidth;
	p.String(r, str, JPainter::kHAlignLeft, JPainter::kVAlignCenter);
}
void
SelectionTable::TableDrawCell
	(
	JPainter& 		p, 
	const JPoint& 	cell, 
	const JRect& 	rect
	)
{
	// JTable keeps track of what's selected. If we want just
	// basic hilighting of the selected cells, we can have JTable 
	// do it with this call:
	HilightIfSelected(p, cell, rect);

	// Convert the array's current element into a JString.
	JString cellNumber(itsData->GetElement(cell.y));

	// Draw the JString that holds the value. 
	p.String(rect, cellNumber, JPainter::kHAlignLeft, JPainter::kVAlignTop);
}
void
GMAccountList::TableDrawCell
	(
	JPainter&		p,
	const JPoint&	cell,
	const JRect&	rect
	)
{
	HilightIfSelected(p, cell, rect);

	JFontStyle fontstyle;
	if (itsDialog->GetDefaultIndex() == (JIndex)cell.y)
		{
		fontstyle.bold	= kJTrue;
		}

	p.SetFont(JGetDefaultFontName(), kJDefaultFontSize, fontstyle);

	JString str = itsAccountInfo->NthElement(cell.y)->GetNickname();

	// check that column is wide enough

	const JCoordinate w = p.GetStringWidth(str) + 2*kHMarginWidth;
	if (w > GetColWidth(1))
		{
		itsMinColWidth = w;
		}

	// draw string

	JRect r = rect;
	r.left += kHMarginWidth;
	p.String(r, str, JPainter::kHAlignLeft, JPainter::kVAlignCenter);
	if (cell.y == JCoordinate(itsAccountInfo->GetElementCount()))
		{
		AdjustColWidth();
		}
}
void
GLFitDescriptionList::TableDrawCell
	(
	JPainter&		p,
	const JPoint&	cell,
	const JRect&	rect
	)
{
	HilightIfSelected(p, cell, rect);

	const JString* curveName = itsNameList->NthElement(cell.y);

	const GLFitDescription& fd	= GetFitManager()->GetFitDescription(cell.y);

	JRect irect	= rect;
	irect.right	= rect.left + kIconWidth;
	if (fd.GetType()	== GLFitDescription::kPolynomial)
		{
		p.Image(*itsPolyIcon, itsPolyIcon->GetBounds(), irect);
		}
	else if (fd.GetType()	== GLFitDescription::kNonLinear)
		{
		p.Image(*itsNonLinearIcon, itsNonLinearIcon->GetBounds(), irect);
		}
	else if (fd.GetType()	== GLFitDescription::kModule)
		{
		p.Image(*itsExecutableIcon, itsExecutableIcon->GetBounds(), irect);
		}
	else if (fd.GetType()	>= GLFitDescription::kBLinear)
		{
		p.Image(*itsBuiltInIcon, itsBuiltInIcon->GetBounds(), irect);
		}
	
	JRect r = rect;
	r.left += kHMarginWidth + kIconWidth;
	p.String(r, *curveName, JPainter::kHAlignLeft, JPainter::kVAlignCenter);
}
void
JXStringTable::TableDrawCell
	(
	JPainter&		p,
	const JPoint&	cell,
	const JRect&	rect
	)
{
	JPoint editCell;
	if (!GetEditedCell(&editCell) || cell != editCell)
		{
		HilightIfSelected(p, cell, rect);

		JSize fontSize;
		const JString& fontName = GetFont(&fontSize);
		p.SetFont(fontName, fontSize, GetCellStyle(cell));

		const JString& str = itsStringData->GetString(cell);

		JRect r = rect;
		r.left += kHMarginWidth;
		p.String(r, str, JPainter::kHAlignLeft, JPainter::kVAlignCenter);
		}
}
void
CBCommandTable::TableDrawCell
	(
	JPainter&		p,
	const JPoint&	cell,
	const JRect&	rect
	)
{
	JPoint editCell;
	if (GetEditedCell(&editCell) && cell == editCell)
		{
		return;
		}

	HilightIfSelected(p, cell, rect);

	const CBCommandManager::CmdInfo info = itsCmdList->GetElement(cell.y);
	if (info.separator)
		{
		JPoint pt1 = rect.bottomLeft(), pt2 = rect.bottomRight();
		pt1.y--;
		pt2.y--;
		p.Line(pt1, pt2);
		}

	if (cell.x == kOptionsColumn)
		{
		JString s;
		if (info.isMake)
			{
			s += ",M";
			}
		if (info.isVCS)
			{
			s += ",V";
			}
		if (info.saveAll)
			{
			s += ",S";
			}
		if (info.oneAtATime)
			{
			s += ",O";
			}
		if (info.useWindow)
			{
			s += ",W";
			}
		if (info.raiseWindowWhenStart)
			{
			s += ",R";
			}
		if (info.beepWhenFinished)
			{
			s += ",B";
			}

		if (!s.IsEmpty())
			{
			if (s.GetFirstCharacter() == ',')
				{
				s.RemoveSubstring(1,1);
				}
			p.String(rect, s, JPainter::kHAlignCenter, JPainter::kVAlignCenter);
			}
		}
	else
		{
		const JString* s = NULL;
		JFontStyle style;
		if (cell.x == kMenuTextColumn)
			{
			s = info.menuText;
			}
		else if (cell.x == kMenuShortcutColumn)
			{
			s = info.menuShortcut;
			}
		else if (cell.x == kScriptNameColumn)
			{
			s = info.name;
			}
		else if (cell.x == kCommandColumn)
			{
			s = info.cmd;
			}
		else if (cell.x == kPathColumn)
			{
			s = info.path;
			style.color =
				CBCommandPathInput::GetTextColor(*s, itsBasePath, kJFalse, p.GetColormap());
			}
		assert( s != NULL );

		p.SetFont(itsFontName, itsFontSize, style);

		JRect r = rect;
		r.left += kHMarginWidth;
		p.String(r, *s, JPainter::kHAlignLeft, JPainter::kVAlignCenter);
		}
}
void
JXTreeListWidget::TableDrawCell
	(
	JPainter&		p,
	const JPoint&	cell,
	const JRect&	rect
	)
{
	if (JIndex(cell.x) == itsNodeColIndex && itsDrawSelectionFlag)
		{
		HilightIfSelected(p, cell, rect);
		}

	const JTreeNode* node = itsTreeList->GetNode(cell.y);
	if (JIndex(cell.x) == itsToggleOpenColIndex && node->IsOpenable())
		{
		p.ShiftOrigin(rect.topLeft());

		const JPolygon* triangle = (itsTreeList->IsOpen(cell.y) ?
									&kOpenTriangle : &kClosedTriangle);
		if (kOpenTriangle.IsEmpty())
			{
			kOpenTriangle.AppendElement(JPoint(5,  6));
			kOpenTriangle.AppendElement(JPoint(15, 6));
			kOpenTriangle.AppendElement(JPoint(10, 11));

			kClosedTriangle.AppendElement(JPoint(10, 3));
			kClosedTriangle.AppendElement(JPoint(15, 8));
			kClosedTriangle.AppendElement(JPoint(10, 13));
			}

		const JColormap* colormap = p.GetColormap();

		if ((itsToggleDragIndex == cell.y && itsMouseInToggleFlag) ||
			itsDNDTargetIndex == JIndex(cell.y))
			{
			p.SetFilling(kJTrue);
			p.SetPenColor(colormap->GetBlackColor());
			p.Polygon(*triangle);
			}
		else
			{
			p.SetFilling(kJTrue);
			p.SetPenColor(colormap->GetGrayColor(90));
			p.Polygon(*triangle);

			p.SetFilling(kJFalse);
			p.SetPenColor(colormap->GetBlackColor());
			p.Polygon(*triangle);
			}

		p.ShiftOrigin(-(rect.topLeft()));
		}

	else if (JIndex(cell.x) == itsNodeColIndex)
		{
		JRect r = rect;
		r.left += GetNodeIndent(cell.y);
		p.SetClipRect(r);
		TLWDrawNode(p, cell, r);
		// Table controls clip rect, so we don't have to reset it.
		}
}
void
GPMProcessTreeList::TableDrawCell
	(
	JPainter&		p,
	const JPoint&	cell,
	const JRect&	rect
	)
{
	GPMProcessTable::DrawRowBackground(p, cell, rect, (p.GetColormap())->GetGrayColor(95));

	if (cell.x == GPMProcessList::kTreeOpenClose ||
		cell.x == GPMProcessList::kTreeCommand)
		{
		JXNamedTreeListWidget::TableDrawCell(p, cell, rect);
		return;
		}

	HilightIfSelected(p, cell, rect);

	const JTreeNode* node        = GetTreeList()->GetNode(cell.y);
	const GPMProcessEntry& entry = * dynamic_cast<const GPMProcessEntry*>(node);

	JString str;
	JPainter::HAlignment halign = JPainter::kHAlignRight;
	if (cell.x == GPMProcessList::kTreeState)
		{
		GPMProcessTable::DrawProcessState(entry, p, rect, *itsZombieImage);
		}
	else if (cell.x == GPMProcessList::kTreePID)
		{
		str	= JString(entry.GetPID(), JString::kBase10);
		}
	else if (cell.x == GPMProcessList::kTreeUser)
		{
		str    = entry.GetUser();
		halign = JPainter::kHAlignLeft;
		}
/*	else if (cell.x == GPMProcessList::kTreePPID)
		{
		str	= JString(entry.GetPPID(), JString::kBase10);
		}
	else if (cell.x == GPMProcessList::kTreePriority)
		{
		str	= JString(entry.GetPriority(), JString::kBase10);
		}
*/	else if (cell.x == GPMProcessList::kTreeNice)
		{
		str	= JString(entry.GetNice(), JString::kBase10);
		}
	else if (cell.x == GPMProcessList::kTreeSize)
		{
		str	= JString(entry.GetSize(), JString::kBase10);
		}
/*	else if (cell.x == GPMProcessList::kTreeResident)
		{
		str	= JString(entry.GetResident(), JString::kBase10);
		}
	else if (cell.x == GPMProcessList::kTreeShare)
		{
		str	= JString(entry.GetShare(), JString::kBase10);
		}
*/	else if (cell.x == GPMProcessList::kTreeCPU)
		{
		str	= JString(entry.GetPercentCPU(), 1);
		}
	else if (cell.x == GPMProcessList::kTreeMemory)
		{
		str	= JString(entry.GetPercentMemory(), 1);
		}
	else if (cell.x == GPMProcessList::kTreeTime)
		{
		str	= JString(entry.GetTime(), JString::kBase10);
		}

	JRect r  = rect;
	r.left  += kHMarginWidth;
	r.right -= kHMarginWidth;
	p.JPainter::String(r, str, halign, JPainter::kVAlignCenter);
}