
(setq track-eol nil)

;;(defun d-movement--frame-width ()
;;  (- (frame-width) 2))

;; (d-movement--is-correct-mode)
;;
;; (or (not 1) (not 2))
;;
;; (not (and 1 2))
;;
(defun d-movement--is-correct-mode ()
  (save-match-data
    (or (eq major-mode 'emacs-lisp-mode)
        (eq major-mode 'c++-mode)
        ;;
        ;; NOTE: patch to prevent Emacs from munging "dir" buffers
        ;;
        (and (eq major-mode 'text-mode) (or (not (buffer-file-name)) (not (string-match "/info/dir$" (buffer-file-name)))))
        (eq major-mode 'html-mode)
        (eq major-mode 'help-mode)
        (eq major-mode 'compilation-mode)
        (eq major-mode 'occur-mode)
        ;;(eq major-mode 'apropos-mode) ;; NOTE: cannot do as underline EOLs look ugly
        (eq major-mode 'java-mode)
        (eq major-mode 'latex-mode)
        ;;(eq major-mode 'sh-mode)
        (eq major-mode 'jtw-mode)
        ;;(eq major-mode 'makefile-mode) ;; NOTE: cannot do as smegulator
        )))

;;(setq minor-mode-alist (cons '(t (if (d-movement--is-correct-mode) " M")) minor-mode-alist))

;;(setq minor-mode-alist (cons '(t (if foo " Z" "")) minor-mode-alist))

(d-quote (defun d-movement--get-string ()
         (if (d-movement--is-correct-mode)
             " Move" "")))

;;(setq foo nil)
;;(setq foo t)
;;(setq foo "123")

;;(setq minor-mode-alist (cons '(t (:eval (foo)) minor-mode-alist))
;;(setq minor-mode-alist (cons '(t (:eval (d-movement--get-string)) minor-mode-alist) minor-mode-alist))
(setq minor-mode-alist (cons '(t (:eval (if (d-movement--is-correct-mode) " Mvmt" ""))) minor-mode-alist))

(defun d-movement--line-width ()
  (let ((w (d-current-line-width)))
    (if (< w (frame-width))
        (frame-width)
      w)))

;;(defun save-ro-mod (code)
;;  (let ((mod (buffer-modified-p))
;;        (ro  buffer-read-only))
;;    (setq buffer-read-only nil)
;;    (eval code)
;;    (set-buffer-modified-p mod)
;;    (setq buffer-read-only ro)))
;;
;;;
;;; NOTE: this is cool!
;;;
(defmacro d-movement--save-ro-mod (&rest code)
  (list 'let
        '((mod (buffer-modified-p)) (ro buffer-read-only))
        '(setq buffer-read-only nil)
        ;;(eval (cons 'progn code))
        (cons 'progn code)
        '(set-buffer-modified-p mod)
        '(setq buffer-read-only ro)))

(defun d-movement--pad-line-fast ()
  (let ((mod (buffer-modified-p))
        (ro  buffer-read-only))
  (save-excursion
    (setq buffer-read-only nil)
    (move-to-column (1- (frame-width)) t)
    (set-buffer-modified-p mod)
    (setq buffer-read-only ro))))

(defun d-movement--unpad-line-slow ()
  (let ((mod (buffer-modified-p))
        (ro  buffer-read-only))
    (setq buffer-read-only nil)
    (save-excursion
      (end-of-line)
      (while (or (eq (char-after (1- (point))) ? ) (eq (char-after (1- (point))) ?\t))
        (backward-delete-char 1)))
    (set-buffer-modified-p mod)
    (setq buffer-read-only ro)))

;;;
;;; Don't need to make this more efficient as it only operates on one line
;;;
(defun d-movement--munge-line ()
  (d-movement--save-ro-mod (save-match-data
                              (save-excursion
                                (end-of-line)

                                (cond
                                 ((< (current-column) (1- (frame-width)))
                                  (move-to-column (1- (frame-width)) t)
                                  )

                                 ((> (current-column) (1- (frame-width)))
                                  (let (done)
                                    (while (and (> (save-excursion
                                                     (forward-char -1)
                                                     (current-column)) (- (frame-width) 2))
                                                (not done))
                                      (if (save-excursion
                                            (forward-char -1)
                                            (looking-at "[ \t]"))
                                          (backward-delete-char 1)
                                        (setq done t))))))))))

;;;
;;; (d-movement--pad-buffer)
;;;
(defun d-movement--pad-buffer ()
  (interactive)
  (save-match-data
    (let ((mod (buffer-modified-p))
          (ro  buffer-read-only)
          (m   (point-marker)))
      (setq buffer-read-only nil)
      (save-excursion
        (goto-char (point-min))
        (while (not (eobp))
          (d-movement--pad-line-fast)
          (forward-line 1)))
      (goto-char (marker-position m))
      (set-marker m nil)
      (set-buffer-modified-p mod)
      (setq buffer-read-only ro))))

(defun d-movement--unpad-buffer ()
  (interactive)
  (save-match-data
    (if (and (d-movement--is-correct-mode)
             (or (not (buffer-file-name))
                 (and (buffer-file-name) (not (string-match "\\.tar\\.gz" (buffer-file-name))))))
        (let ((mod     (buffer-modified-p))
              (ro      buffer-read-only)
              (m-point (point-marker))
              ;;(m-mark  (mark-marker))
              )
          ;;(debug)
          (save-excursion
            (setq buffer-read-only nil)
            (if (fboundp 'delete-trailing-whitespace)
                (delete-trailing-whitespace)
              (message "Void function delete-trailing-whitespace")))

          (goto-char (marker-position m-point))
          (set-marker m-point nil)

          ;;(set-mark (marker-position m-mark))
          ;;(set-mark m-mark)
          ;;(set-marker m-mark nil)

          (set-buffer-modified-p mod)
          (setq buffer-read-only ro)))))

(global-set-key [(end)] 'd-movement-end-of-line)

(defun d-movement-end-of-line ()
  (interactive)
  (save-match-data
    ;;    (not empty-line)
    (when (not (save-excursion (beginning-of-line) (looking-at "^[ \t]*$")))
      (end-of-line)
      (if (and (d-movement--is-correct-mode) (re-search-backward "[^ \r\n\t]" (point-at-bol) t))
          (forward-char 1)))))


(global-set-key [(shift end)]        'd-movement-end-of-buffer)
(global-set-key [(meta end)]         'd-movement-end-of-buffer)
(global-set-key [(control end)]      'd-movement-end-of-buffer)
(global-set-key [(control meta end)] 'd-movement-end-of-buffer)

(defun d-movement-end-of-buffer ()
  (interactive)
  (end-of-buffer)
  (beginning-of-line))

(if (fboundp 'd-backspace-key) (global-set-key [backspace] 'd-backspace-key))
(if (fboundp 'd-delete-key)    (global-set-key [delete]    'd-delete-key))

(defun d-movement-reset-bindings ()
  (interactive)
  (global-set-key [(end)]   'end-of-line)
  ;;(global-set-key [(end)]   'd-movement-end-of-line)
  (global-set-key [(left)]  'backward-char)
  (global-set-key [(right)] 'forward-char)
  (global-set-key [(up)]    'previous-line)
  (global-set-key [(down)]  'next-line)
 )

(safe-require 'd-movement-advice)
(safe-require 'd-movement-hooks)
(safe-require 'd-movement-leftright)
(safe-require 'd-movement-post-command-hook)
(safe-require 'd-movement-updown)

(if (and (not noninteractive) os-type--text-p)
    (hscroll-global-mode 1))

(provide 'd-movement)



