 	private var lastChangeRange: NSRange?
 	private var lastChangeDelta: Int = 0
 	private var timerRunning = false
+	private var lastChangeMaxDelta: Int = 0
+	private var changedLocation: Int = 0
 
 	override func viewDidLoad() {
 		useParser = true

		lastChangeTimer = DispatchSource.makeTimerSource(queue: .main)
		lastChangeTimer.schedule(deadline: .now() + .milliseconds(500), repeating: .milliseconds(500), leeway: .milliseconds(100))
		lastChangeTimer.setEventHandler { [weak self] in
			guard let me = self else { return }
			guard let lastRange = me.lastChangeRange, let editor = me.editor else { return }
			let curTime = Date.timeIntervalSinceReferenceDate
			if (curTime - me.lastTextChange) > Defaults[.previewUpdateDelay] {
				me.lastTextChange = curTime
				defer { me.lastChangeRange = nil }
				if let oc = me.outputController,
					oc.contentsEdited(contents: editor.string, range: lastRange, delta: me.lastChangeDelta)
				{
					if me.ignoreContentChanges { return }
					me.save(edits: editor.string, reload: false)

		// really does nothing, but call to be safe
		super.contentsChanged(contents, range: range, changeLength: delta)
		lastTextChange = Date.timeIntervalSinceReferenceDate
		if lastChangeRange == nil {
			lastChangeRange = range
			changedLocation = range.location
		}
		if delta < 0 {
			changedLocation += delta
		}
		lastChangeDelta += abs(delta)
	}

	/// subclasses should override and save contents via save(edits:). super should not be called
