Tracking Unauthorized Changes
Suppose that, in spite of our precautions against unwanted buffer-modifying commands, the user manages to invoke one anyway. The state of the crossword grid on the screen won't match the data structure in crossword-grid. How can we recover?
One way is to attach a function to after-change-functions (see the section called Clever Approach in Chapter 4) that is invoked every time the buffer changes. If the change was "unauthorized," we must somehow resynchronize the buffer and the crossword-grid data structure.
What's "unauthorized"? Trivially, it's the opposite of "authorized," so let's add a mechanism to "authorize" changes to the buffer.
(defvar crossword-changes-authorized nil
"Are changes currently authorized?")
(make-variable-buffer-local 'crossword-changes-authorized)
(defmacro crossword-authorize (&rest subexprs)
"Execute subexpressions, authorizing changes."
'(let ((crossword-changes-authorized t))
,@subexprs))This is a macro that can be wrapped around function bodies where buffer changes happen. It temporarily sets crossword-changes-authorized to t, executes the function body, then reverts crossword-changes-authorized to its previous value. By default, changes are not authorized. So to prevent the user from corrupting the buffer, we must rewrite crossword-insert-grid and crossword-update-display to authorize the changes they make:
(defun crossword-insert-grid (crossword) "Insert CROSSWORD into the current buffer." (crossword-authorize (mapcar 'crossword-insert-row ...
Become an O’Reilly member and get unlimited access to this title plus top books and audiobooks from O’Reilly and nearly 200 top publishers, thousands of courses curated by job role, 150+ live events each month,
and much more.
Read now
Unlock full access