Subject: bug#18183: 24.3; table-fixed-width-mode fails with kill/yank

From: Boruch Baum <[email-masked]>
Date: Tue, 8 Dec 2020 02:18:02 -0500

Hi Lars. I've been doing some more work on the bug and have a solution
for the secondary issue found, the one that I marked previously as
'tangent'. In that related bug, aborting from a table.el edit sets POINT
at the beginning of the table instead of where it was upon entry to the
edit session. The solution was simply to save and restore point. The
saving is done in function org-src--edit-element and the restore is
performed in function org-edit-src-abort. Here are the modified
functions with the two additional lines marked with arrows ; <------

(defun org-src--edit-element
    (datum name &optional initialize write-back contents remote)
  "Edit DATUM contents in a dedicated buffer NAME.

INITIALIZE is a function to call upon creating the buffer.

When WRITE-BACK is non-nil, assume contents will replace original
region.  Moreover, if it is a function, apply it in the edit
buffer, from point min, before returning the contents.

When CONTENTS is non-nil, display them in the edit buffer.
Otherwise, show DATUM contents as specified by
`org-src--contents-area'.

When REMOTE is non-nil, do not try to preserve point or mark when
moving from the edit area to the source.

Leave point in edit buffer."
  (setq org-src--saved-temp-window-config (current-window-configuration))
  (let* ((area (org-src--contents-area datum))
	 (beg (copy-marker (nth 0 area)))
	 (end (copy-marker (nth 1 area) t))
	 (old-edit-buffer (org-src--edit-buffer beg end))
         (fixed table-fixed-width-mode)
	 (contents (or contents (nth 2 area))))
    (if (and old-edit-buffer
	     (or (not org-src-ask-before-returning-to-edit-buffer)
		 (y-or-n-p "Return to existing edit buffer ([n] will revert changes)? ")))
	;; Move to existing buffer.
	(org-src-switch-to-buffer old-edit-buffer 'return)
      (setq-local org-src--return-point (point)) ; <-------
      ;; Discard old edit buffer.
      (when old-edit-buffer
	(with-current-buffer old-edit-buffer (org-src--remove-overlay))
	(kill-buffer old-edit-buffer))
      (let* ((org-mode-p (derived-mode-p 'org-mode))
	     (source-tab-width (if indent-tabs-mode tab-width 0))
	     (type (org-element-type datum))
	     (ind (org-with-wide-buffer
		   (goto-char (org-element-property :begin datum))
		   (org-get-indentation)))
	     (preserve-ind
	      (and (memq type '(example-block src-block))
		   (or (org-element-property :preserve-indent datum)
		       org-src-preserve-indentation)))
	     ;; Store relative positions of mark (if any) and point
	     ;; within the edited area.
	     (point-coordinates (and (not remote)
				     (org-src--coordinates (point) beg end)))
	     (mark-coordinates (and (not remote)
				    (org-region-active-p)
				    (let ((m (mark)))
				      (and (>= m beg) (>= end m)
					   (org-src--coordinates m beg end)))))
	     ;; Generate a new edit buffer.
	     (buffer (generate-new-buffer name))
	     ;; Add an overlay on top of source.
	     (overlay (org-src--make-source-overlay beg end buffer)))
	;; Switch to edit buffer.
	(org-src-switch-to-buffer buffer 'edit)
        (setq-local table-fixed-width-mode fixed)
	;; Insert contents.
	(insert contents)
	(remove-text-properties (point-min) (point-max)
				'(display nil invisible nil intangible nil))
	(unless preserve-ind (org-do-remove-indentation))
	(set-buffer-modified-p nil)
	(setq buffer-file-name nil)
	;; Initialize buffer.
	(when (functionp initialize)
	  (let ((org-inhibit-startup t))
	    (condition-case e
		(funcall initialize)
	      (error (message "Initialization fails with: %S"
			      (error-message-string e))))))
	;; Transmit buffer-local variables for exit function.  It must
	;; be done after initializing major mode, as this operation
	;; may reset them otherwise.
	(setq-local org-src--tab-width source-tab-width)
	(setq-local org-src--from-org-mode org-mode-p)
	(setq-local org-src--beg-marker beg)
	(setq-local org-src--end-marker end)
	(setq-local org-src--remote remote)
	(setq-local org-src--source-type type)
	(setq-local org-src--block-indentation ind)
	(setq-local org-src--preserve-indentation preserve-ind)
	(setq-local org-src--overlay overlay)
	(setq-local org-src--allow-write-back write-back)
	;; Start minor mode.
	(org-src-mode)
	;; Move mark and point in edit buffer to the corresponding
	;; location.
	(if remote
	    (progn
	      ;; Put point at first non read-only character after
	      ;; leading blank.
	      (goto-char
	       (or (text-property-any (point-min) (point-max) 'read-only nil)
		   (point-max)))
	      (skip-chars-forward " \r\t\n"))
	  ;; Set mark and point.
	  (when mark-coordinates
	    (org-src--goto-coordinates mark-coordinates (point-min) (point-max))
	    (push-mark (point) 'no-message t)
	    (setq deactivate-mark nil))
	  (org-src--goto-coordinates
	   point-coordinates (point-min) (point-max)))))))

(defun org-edit-src-abort ()
  "Abort editing of the src code and return to the Org buffer."
  (interactive)
  (let (org-src--allow-write-back)
    (org-edit-src-exit)
    (goto-char org-src--return-point)))  ; <-------

If you feel that this should be an independent bug report, I can do
that. Also, if after you test and verify / approve, should you want it
in diff format or anything else, let me know.

--
hkp://keys.gnupg.net
CA45 09B5 5351 7C11 A9D1  7286 0036 9E45 1595 8BC0