protected VariousChoicesPanel createFunctionConflictPanel(final Function[] functions,
			final TaskMonitor monitor) {

		if (functions[RESULT] == null) {
			MergeManager.showBlockingError("Error Creating Function Conflict Panel",
				"RESULT function is null.");
			return null;
		}
		Address myEntryPoint = functions[MY].getEntryPoint();

		StackFrame latestStack = functions[LATEST].getStackFrame();
		StackFrame myStack = functions[MY].getStackFrame();

		VariousChoicesPanel panel = getEmptyVariousPanel();

		int conflictCount = 0;
		try {
			conflictCount = funcConflicts.get(myEntryPoint);
		}
		catch (NoValueException e) {
			MergeManager.showBlockingError("Error Creating Function Conflict Panel",
				"Couldn't get conflict information for MY function at " +
					myEntryPoint.toString(true) + ".");
			return null;
		}

		int conflicts = conflictCount;
		runSwing(() -> {

			panel.setTitle("Function");
			String text = getConflictPrefixString(functions) +
				" has conflicting changes.<br>Choose the desired result for each conflict.<br>";
			panel.setHeader(text);
			panel.addInfoRow("Conflict", new String[] { LATEST_TITLE, MY_TITLE }, true);

			if ((conflicts & FUNC_NAME) != 0) {
				String latest = functions[LATEST].getName();
				String my = functions[MY].getName();
				panel.addSingleChoice("Name", new String[] { latest, my },
					new FunctionDetailChangeListener(FUNC_NAME, functions, panel, monitor));
			}
//			if ((conflicts & FUNC_RETURN_TYPE) != 0) {
//				String latest = latestFunc.getReturnType().getName();
//				String my = myFunc.getReturnType().getName();
//				DataType latestDt = latestFunc.getReturnType();
//				DataType myDt = myFunc.getReturnType();
//				long latestID = programs[LATEST].getDataTypeManager().getID(latestDt);
//				long myID = programs[MY].getDataTypeManager().getID(myDt);
//				DataType latestResultDt = getResultDataType(latestID, programs[LATEST]);
//				DataType myResultDt = getResultDataType(myID, programs[MY]);
//				if (latestResultDt != null) {
//					latest = latestResultDt.getName();
//				}
//				if (myResultDt != null) {
//					my = myResultDt.getName();
//				}
//				panel.addSingleChoice("Return Type", new String[] { latest, my },
//					new FunctionDetailChangeListener(FUNC_RETURN_TYPE, entryPt, panel, monitor));
//			}
			if (((conflicts & FUNC_RETURN_ADDRESS_OFFSET) != 0)) {
				String latest = DiffUtility.toSignedHexString(latestStack.getReturnAddressOffset());
				String my = DiffUtility.toSignedHexString(myStack.getReturnAddressOffset());
				panel.addSingleChoice("Return Address Offset", new String[] { latest, my },
					new FunctionDetailChangeListener(FUNC_RETURN_ADDRESS_OFFSET, functions, panel,
						monitor));
			}
// For now, we are not allowing you to set the parameter offset or local size outright.
//			if ((conflicts & FUNC_PARAMETER_OFFSET) != 0) {
//				String latest = DiffUtility.toSignedHexString(latestStack.getParameterOffset());
//				String my = DiffUtility.toSignedHexString(myStack.getParameterOffset());
//				panel.addSingleChoice(
//					"Parameter Offset",
//					new String[] { latest, my },
//					new FunctionDetailChangeListener(FUNC_PARAMETER_OFFSET, entryPt, panel, monitor));
//			}
//			if ((conflicts & FUNC_LOCAL_SIZE) != 0) {
//				String latest = DiffUtility.toSignedHexString(latestStack.getLocalSize());
//				String my = DiffUtility.toSignedHexString(myStack.getLocalSize());
//				panel.addSingleChoice("Local Size", new String[] { latest, my },
//					new FunctionDetailChangeListener(FUNC_LOCAL_SIZE, entryPt, panel, monitor));
//			}
			if ((conflicts & FUNC_STACK_PURGE_SIZE) != 0) {
				String latest =
					DiffUtility.toSignedHexString(functions[LATEST].getStackPurgeSize());
				String my = DiffUtility.toSignedHexString(functions[MY].getStackPurgeSize());
				panel.addSingleChoice("Stack Purge Size", new String[] { latest, my },
					new FunctionDetailChangeListener(FUNC_STACK_PURGE_SIZE, functions, panel,
						monitor));
			}
			if ((conflicts & FUNC_INLINE) != 0) {
				String latest = Boolean.toString(functions[LATEST].isInline());
				String my = Boolean.toString(functions[MY].isInline());
				panel.addSingleChoice("Is Inline?", new String[] { latest, my },
					new FunctionDetailChangeListener(FUNC_INLINE, functions, panel, monitor));
			}
			if ((conflicts & FUNC_NO_RETURN) != 0) {
				String latest = Boolean.toString(functions[LATEST].hasNoReturn());
				String my = Boolean.toString(functions[MY].hasNoReturn());
				panel.addSingleChoice("Has No Return?", new String[] { latest, my },
					new FunctionDetailChangeListener(FUNC_NO_RETURN, functions, panel, monitor));
			}
			if ((conflicts & FUNC_CALLING_CONVENTION) != 0) {
				String latest = functions[LATEST].getCallingConventionName();
				String my = functions[MY].getCallingConventionName();
				panel.addSingleChoice("Calling Convention", new String[] { latest, my },
					new FunctionDetailChangeListener(FUNC_CALLING_CONVENTION, functions, panel,
						monitor));
			}
//		if ((conflicts & FUNC_CUSTOM_STORAGE) != 0) {
//			String latest = Boolean.toString(functions[LATEST].hasCustomVariableStorage());
//			String my = Boolean.toString(functions[MY].hasCustomVariableStorage());
//			panel.addSingleChoice("Custom Storage", new String[] { latest, my },
//				new FunctionDetailChangeListener(FUNC_CUSTOM_STORAGE, functions, panel, monitor));
//		}
			if ((conflicts & FUNC_SIGNATURE_SOURCE) != 0) {
				SourceType latest = functions[LATEST].getSignatureSource();
				SourceType my = functions[MY].getSignatureSource();
				panel.addSingleChoice("Signature Source",
					new String[] { latest.toString(), my.toString() },
					new FunctionDetailChangeListener(FUNC_SIGNATURE_SOURCE, functions, panel,
						monitor));
			}

		});
		return panel;
	}
This is a generic method for displaying the contents of the information 
buffer to the user.
Ghidra/Features/Base/src/main/java/ghidra/app/merge/listing/AbstractFunctionMerger.java