private ListingField getFieldByFunction(ProxyObj<?> proxy, int varWidth, List<Reference> xrefs,
			List<Reference> offcuts) {

		int totalXrefs = xrefs.size() + offcuts.size();
		if (totalXrefs == 0) {
			return null;
		}

		boolean tooMany = totalXrefs > maxXRefs;

		Object obj = proxy.getObject();
		CodeUnit cu = (CodeUnit) obj;
		Program program = cu.getProgram();
		FontMetrics metrics = getMetrics();
		FunctionManager functionManager = program.getFunctionManager();

		//
		// Bin all xrefs by containing function, which may be null
		//
		List<Reference> noFunction = new ArrayList<>();
		TreeMap<Function, List<Reference>> xrefsByFunction = new TreeMap<>((f1, f2) -> {
			return f1.getEntryPoint().compareTo(f2.getEntryPoint());
		});
		for (Reference ref : CollectionUtils.asIterable(xrefs, offcuts)) {

			Function function = functionManager.getFunctionContaining(ref.getFromAddress());
			if (function == null) {
				noFunction.add(ref);
			}
			else {
				xrefsByFunction.computeIfAbsent(function, r -> new ArrayList<>()).add(ref);
			}
		}

		//
		// Create the function rows
		//
		Set<Reference> offcutSet = new HashSet<>(offcuts);
		Predicate<Reference> isOffcut = r -> offcutSet.contains(r);
		ListingFieldHighlightFactoryAdapter hlFactory =
			new ListingFieldHighlightFactoryAdapter(hlProvider);
		Function currentFunction = functionManager.getFunctionContaining(cu.getMinAddress());
		List<TextField> functionRows = createXrefRowsByFunction(program, currentFunction,
			xrefsByFunction, isOffcut, varWidth, hlFactory);

		//
		// TODO maxXRefs makes sense when simply displaying xrefs.  What does max mean when
		//      binning xrefs by function.  Currently, we use the max as the max row count, but
		//      this may need to be changed and it may require a new tool option.
		//

		int maxLines = maxXRefs;
		int availableLines = maxLines - functionRows.size();
		if (tooMany) {
			// save room for the "more" field at the end
			availableLines = Math.max(1, availableLines--);
		}

		//
		// Create the row for xrefs not in a function
		//

		//
		// Note: the objects we build here want the 'data' row as a parameter, not the screen row.
		//       Our screen rows are what we are building to display; a data row we are here
		//       defining to be a single xref.   This is a somewhat arbitrary decision.
		int dataRow = totalXrefs - noFunction.size();
		TextField noFunctionXrefsField = createWrappingXrefRow(program, dataRow, noFunction,
			currentFunction, isOffcut, availableLines, hlFactory);

		List<TextField> allFields = new ArrayList<>();
		allFields.addAll(functionRows);
		if (noFunctionXrefsField != null) {
			allFields.add(noFunctionXrefsField);
		}

		int newStartX = startX + varWidth;
		if (tooMany) {
			// add the [more] element
			int lastRow = allFields.size() - 1;
			AttributedString as =
				new AttributedString(MORE_XREFS_STRING, XrefColors.DEFAULT, metrics);
			TextFieldElement moreElement = new TextFieldElement(as, lastRow, 0);
			ClippingTextField ctf = new ClippingTextField(newStartX, width, moreElement, hlFactory);
			allFields.add(ctf);
		}

		CompositeVerticalLayoutTextField compositefield =
			new CompositeVerticalLayoutTextField(allFields, newStartX, width, maxXRefs, hlFactory);
		XrefListingField listingField =
			new XrefListingField(this, proxy, compositefield, hlFactory);
		return listingField;
	}
Constructs a new XRefFieldFactory based on the provider and model.

@param name the owner of this field factory
@param model the model that the field belongs to.
@param hlProvider the HightLightProvider.
@param displayOptions the Options for display properties.
@param fieldOptions the Options for field specific properties.
Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/field/XRefFieldFactory.java