+(defvar buffer-substring-filters nil
+ "List of filter functions for `filter-buffer-substring'.
+Each function must accept a single argument, a string, and return
+a string. The buffer substring is passed to the first function
+in the list, and the return value of each function is passed to
+the next. The return value of the last function is used as the
+return value of `filter-buffer-substring'.
+
+If this variable is nil, no filtering is performed.")
+
+(defun filter-buffer-substring (beg end &optional delete)
+ "Return the buffer substring between BEG and END, after filtering.
+The buffer substring is passed through each of the filter
+functions in `buffer-substring-filters', and the value from the
+last filter function is returned. If `buffer-substring-filters'
+is nil, the buffer substring is returned unaltered.
+
+If DELETE is non-nil, the text between BEG and END is deleted
+from the buffer.
+
+Point is temporarily set to BEG before caling
+`buffer-substring-filters', in case the functions need to know
+where the text came from.
+
+This function should be used instead of `buffer-substring' or
+`delete-and-extract-region' when you want to allow filtering to
+take place. For example, major or minor modes can use
+`buffer-substring-filters' to extract characters that are special
+to a buffer, and should not be copied into other buffers."
+ (save-excursion
+ (goto-char beg)
+ (let ((string (if delete (delete-and-extract-region beg end)
+ (buffer-substring beg end))))
+ (dolist (filter buffer-substring-filters string)
+ (setq string (funcall filter string))))))
+