private void emitTextMatch(Function function, TreeMap<Integer, TextLine> linesRangeMap,
				Matcher matcher) {

			List<TextLine> lineMatches = new ArrayList<>();

			int pos = 0;
			int start = matcher.start();
			int end = matcher.end();
			for (pos = start; pos < end; pos++) {

				// grab the line that contains the current character position
				TextLine line = linesRangeMap.floorEntry(pos).getValue();

				// This will be positive if the current line contains the match start character.
				// In this case, let the line know it has the start.  If we don't set the start,
				// then the line match will start at 0.
				int lineStartOffset = start - line.getOffset(); // relative offset
				if (lineStartOffset >= 0) {
					line.setMatchStart(lineStartOffset);
				}

				// In this case, let the line know it has the end.  If we don't set the end, 
				// then the line match will end at the end of the line.
				if (end <= line.getEndOffset()) {
					int relativeEnd = end - line.getOffset();
					line.setMatchEnd(relativeEnd);
				}

				lineMatches.add(line);
				pos = line.getEndOffset();
			}

			// Use the first line for attributes of the match, like line number and address
			TextLine firstLine = lineMatches.get(0);
			int lineNumber = firstLine.getLineNumber();
			AddressSet addresses = getAddresses(function, firstLine.getCLine());
			LocationReferenceContext context = createMatchContext(lineMatches);
			TextMatch match =
				new TextMatch(function, addresses, lineNumber, searchText, context, true);
			callback.accept(match);
		}
Uses the given matcher to search for all matches, which may span multiple lines.
Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/search/DecompilerTextFinder.java