private void update(final HasComponentSelection hasSelectedRows) {
        boolean updating = false;
        String message = "";

        final String permissionCheck = checkPermissions();
        if (permissionCheck != null) {
            isHtml = false;
            showData(permissionCheck, null, null, isHtml);
            updating = true;

        } else {
            currentStreamId = null;
            currentPartIndex = null;
            currentRecordIndex = null;
            currentHighlightStrings = null;

            if (hasSelectedRows != null) {
                final List<ComponentSelection> selection = hasSelectedRows.getSelection();
                if (selection != null && selection.size() == 1) {
                    // Just use the first row.
                    final ComponentSelection selected = selection.get(0);
                    currentStreamId = getLong(getTextSettings().getStreamIdColumn(), selected);
                    if (currentStreamId == null) {
                        currentStreamId = getLong(selected.getParamValue(SpecialColumns.RESERVED_STREAM_ID));
                        if (currentStreamId == null) {
                            currentStreamId = getLong(selected.getParamValue(OLD_STREAM_ID));
                        }
                    }
                    currentPartIndex = convertToIndex(getLong(getTextSettings().getPartNoColumn(), selected));
                    currentRecordIndex = convertToIndex(getLong(getTextSettings().getRecordNoColumn(), selected));
                    if (currentRecordIndex == null) {
                        currentRecordIndex = getLong(selected.getParamValue(SpecialColumns.RESERVED_EVENT_ID));
                        if (currentRecordIndex == null) {
                            currentRecordIndex = getLong(selected.getParamValue(OLD_EVENT_ID));
                        }
                    }
                    final Long currentLineFrom = getLong(getTextSettings().getLineFromColumn(), selected);
                    final Long currentColFrom = getLong(getTextSettings().getColFromColumn(), selected);
                    final Long currentLineTo = getLong(getTextSettings().getLineToColumn(), selected);
                    final Long currentColTo = getLong(getTextSettings().getColToColumn(), selected);

//                    GWT.log("TextPresenter - selected table row = " + selected);
//                    GWT.log("TextPresenter - " +
//                            "streamIdField=" +
//                            streamIdField +
//                            "partNoField=" +
//                            partNoField +
//                            "recordNoField=" +
//                            recordNoField +
//                            "currentStreamId=" +
//                            currentStreamId +
//                            ", currentPartIndex=" +
//                            currentPartIndex +
//                            ", currentRecordIndex=" +
//                            currentRecordIndex);

                    // Validate settings.
                    if (getTextSettings().getStreamIdColumn() == null) {
                        message = "No stream id field is configured";

                    } else if (getTextSettings().getStreamIdColumn() != null && currentStreamId == null) {
                        message = "No stream id found in selection";

                    } else if (getTextSettings().getRecordNoColumn() == null
                               && !(
                            getTextSettings().getLineFromColumn() != null
                            && getTextSettings().getLineToColumn() != null)) { // Allow just line positions to
                        //                                                               be used rather than record no.
                        message = "No record number field is configured";

                    } else if (getTextSettings().getRecordNoColumn() != null && currentRecordIndex == null) {
                        message = "No record number field found in selection";

                    } else {
                        DataRange dataRange = null;
                        TextRange highlight = null;
                        if (currentLineFrom != null
                            && currentColFrom != null
                            && currentLineTo != null
                            && currentColTo != null) {
                            dataRange = DataRange.between(
                                    new DefaultLocation(currentLineFrom.intValue(), currentColFrom.intValue()),
                                    new DefaultLocation(currentLineTo.intValue(), currentColTo.intValue()));

                            highlight = new TextRange(
                                    new DefaultLocation(currentLineFrom.intValue(), currentColFrom.intValue()),
                                    new DefaultLocation(currentLineTo.intValue(), currentColTo.intValue()));
                        }

                        final SourceLocation sourceLocation = SourceLocation.builder(currentStreamId)
                                .withPartIndex(currentPartIndex != null
                                        ? currentPartIndex
                                        : 0)
                                .withRecordIndex(currentRecordIndex != null
                                        ? currentRecordIndex
                                        : 0)
                                .withDataRange(dataRange)
                                .withHighlight(highlight)
                                .build();

                        currentHighlightStrings = hasSelectedRows.getHighlights();

//                        OffsetRange currentStreamRange = new OffsetRange(sourceLocation.getPartNo() - 1, 1L);

//                        Builder dataRangeBuilder = DataRange.builder(currentStreamId)
//                                .withPartNumber(sourceLocation.getPartNo() - 1) // make zero based
//                                .withChildStreamType(null);

//                        request.setStreamId(currentStreamId);
//                        request.setStreamRange(currentStreamRange);
//                        request.setChildStreamType(null);

                        // If we have a source highlight then use it.
//                        if (highlight != null) {
//                            // lines 2=>3 means lines 2 & 3, lines 4=>4 means line 4
//                            // -1 to offset to make zero based
//                            // +1 to length to make inclusive
//                            currentPageRange = new OffsetRange(
//                                    highlight.getFrom().getLineNo() - 1L,
//                                    (long) highlight.getTo().getLineNo() - highlight.getFrom().getLineNo() + 1);
//                        } else {
//                            currentPageRange = new OffsetRange(sourceLocation.getRecordNo() - 1L, 1L);
//                        }

                        // TODO @AT Fix/implement
                        // If we have a source highlight then use it.
//                        if (highlight != null) {
////                            dataRangeBuilder
////                                    .fromLocation(highlight.getFrom())
////                                    .toLocation(highlight.getTo());
//                        } else {
////                            // TODO assume this is segmented data
//////                            currentPageRange = new OffsetRange(sourceLocation.getRecordNo() - 0L, 1L);
//////                            request.setPageRange(new OffsetRange(sourceLocation.getRecordNo() - 1L, 1L));
////
////                            // Convert it to zero based
////                            dataRangeBuilder.withSegmentNumber(sourceLocation.getSegmentNo() - 1L);
//                        }

                        final FetchDataRequest request = new FetchDataRequest(sourceLocation);
                        request.setPipeline(getTextSettings().getPipeline());
                        request.setShowAsHtml(getTextSettings().isShowAsHtml());

                        ensureFetchDataQueue();
                        fetchDataQueue.add(request);
                        delayedFetchDataTimer.cancel();
                        delayedFetchDataTimer.schedule(250);
                        updating = true;
                    }
                }
            }
        }

        // If we aren't updating the data display then clear it.
        if (!updating) {
            showData(message, null, null, isHtml);
        }
    }
The ranges returned are line/col positions in the input text. Thus the input text should
not be changed/formatted after the highlight ranges have been generated.
stroom-core-client/src/main/java/stroom/dashboard/client/text/TextPresenter.java