public void decrementAndAddSelection(int rows) {
		int[] rowsSelected = getSelectedRows();

		// If the last row selected is still within the table, just update our selection model.
		if (rowsSelected[0] - rows >= 0) {
			if (rowsSelected.length > 0) {
				Pair filePos = model.getFilePositionForRow(rowsSelected[0] - rows);
				if (filePos == null) {
					return;
				}
				model.selectedByteStart = filePos.getStart();

				// Now update the viewport...
				if (!viewportUtility.isInViewport(rowsSelected[0] - rows)) {
					viewportUtility.scrollViewportTo(rowsSelected[0] - rows);
				}
			}
		}

		// If it's beyond the bounds of the table, we have to load a new chunk.
		else {
			try {

				List<String> lines = reader.readPreviousChunk();
				if (lines.size() == 0) {
					return;
				}

				((FVTableModel) getModel()).addRowsToTop(lines);

				Pair filePos = model.getFilePositionForRow(lines.size() - rows);
				if (filePos == null) {
					return;
				}
				model.selectedByteStart = filePos.getStart();

				SwingUtilities.invokeLater(() -> {

					// Now slide the viewport back up to account for what we just read in.
					viewportUtility.moveViewportDown(lines.size(), false);
	
					if (model.getSize() > model.MAX_VISIBLE_CHUNKS) {
						Chunk chunk = model.remove(model.getSize() - 1);
						if (chunk == null) {
							return;
						}
						((FVTableModel) this.getModel()).removeRowsFromBottom(chunk.linesInChunk);
					}
				});

			}
			catch (IOException e) {
				Msg.error(this, "Error reading next chunk of data", e);
			}
		}
	}
Decrements the selection by the number of rows given, and adds the new rows to the 
selection.

@param rows
Ghidra/Framework/Project/src/main/java/ghidra/framework/main/logviewer/ui/FVTable.java