;;(add-hook 'LaTeX-mode-hook 'd-latex-stuff)

(if (boundp 'tex-mode-hook)
    (add-hook 'tex-mode-hook 'd-latex-stuff)
  (add-hook 'find-file-hook 'd-latex-stuff))

(defun d-latex-stuff ()
  (interactive)
  ;;(d-foo)
  (when (eq major-mode 'latex-mode)

    (font-lock-mode 0)
    (modify-syntax-entry ?_ "w")

    ;;(modify-syntax-entry ?% "_")

    (d-font-lock-add-end
     '(
       ("\\\\verb!\\([^!]*\\)!" (0 'fg:lightred t) (1 'd-latex--tt-face t))
       ("\\\\i{\\([^}]*\\)}" (0 'fg:lightred t) (1 'italic t))

       ("\\\\[ibt]{\\([^{}]*\\)}" (1 'd-latex--tt-face t))

       ("section\\*?{\\(.*\\)}" (1 'font-lock-reference-face))
       ("`+[^$']*'+" (0 'fg:lightgreen))

       ("\\verb![^!]*!" 0 'fg:white t)
       ;;("\\\\[a-z_]+" 0 'font-lock-keyword-face t)
       ("\\\\Def[a-zA-Z]+" 0 'd-face-cc-debugging t)

       ("\\\\def\\(\\\\[a-zA-Z_]+\\)" 1 'd-face-cc-debugging t)
       ;;("\\\\def\\(\\\\[a-z_]+\\)" 1 'd-face-cc-debugging t)

       ("^%[^\r\n]*$" 0 'font-lock-comment-face t)

       ("\\\\my[a-z]*" 0 'fg:lightgreen t)

       ("\\\\hrule"    0 'bold t)
       ("\\\\hspace"   0 'bold t)

       ))

    (font-lock-mode 1)

    (local-unset-key [delete])
    (local-set-key [f9] 'd-latex--f9)
    (local-set-key [(shift f9)] 'd-latex--shift-f9)
    (local-set-key [(meta f9)] 'd-latex--meta-f9)
    ;;(local-set-key [kp-enter] 'd-latex--kp-enter)
    ;;(local-set-key [kp-enter] 'call-last-kbd-macro)
    (local-set-key "\t" 'd-latex--tab-key)
    (local-set-key "\C-j" 'd-latex--enter)
    (local-set-key "\C-m" 'd-latex--enter)
    (local-set-key [(meta control \\)] 'd-latex--meta-control-backslash)
    (local-unset-key [(meta g)])
    (define-key tex-mode-map "\t" 'd-latex--tab)
    (define-key tex-mode-map "\C-m" 'd-latex--enter)
    (define-key tex-mode-map [(return)] 'd-latex--enter)
    (define-key tex-mode-map [(meta control \\)] 'd-latex--meta-control-backslash)

    )
  )

;;(global-set-key [f9] 'd-latex--f9)
;;(global-set-key [(shift f9)] 'd-latex--shift-f9)
;;(global-set-key [(meta f9)] 'd-latex--meta-f9)

(defun d-latex--shift-f9 ()
  (interactive)
  (let ((cmd  (read-from-minibuffer "Compile command: " (car compile-history) nil nil '(compile-history . 1)))
        (flag t))
    (condition-case err
        (kill-compilation)
      (error
       (setq flag nil)
       ))
    (if flag
        (sit-for 2))
    (setq compile-history (cons cmd compile-history))
    (compile cmd)))

(defun d-latex--f9 ()
  (interactive)
  (let ((flag t))
    (condition-case err
        (kill-compilation)
      (error
       (setq flag nil)
       ))
    (if flag
        (sit-for 2))
    (compile (or (car compile-history)
                 (and (boundp 'compile-history)
                      (car compile-history))
                 "make "))))

(defun d-latex--meta-f9 ()
  (interactive)
  (let ((s   (buffer-name))
        (cmd nil))
    (if (string-match "\\([-_a-zA-Z0-9]+\\)\\.tex" s)
        (setq cmd (concat "ghostview " (substring s (match-beginning 1) (match-end 1)) ".ps &"))
      (setq s (car compile-history))
      (if (string-match "\\([-_a-zA-Z0-9]+\\)\\.do" s)
          (setq cmd (concat "ghostview " (substring s (match-beginning 1) (match-end 1)) ".ps &")))
      )
    (if cmd (save-window-excursion
              (shell-command cmd)))
    ))

(defun d-latex--kp-enter ()
  (interactive)
  (progn
    (skip-syntax-forward " ")
    (insert "\\t{")
    (forward-sexp)
    (insert "}")))

;;(remove-hook 'font-lock-mode-hook 'd-latex--fonts)
;;(add-hook 'font-lock-mode-hook 'd-latex--fonts)

;;(copy-face 'fg:lightblue 'd-latex--tt-face)
(copy-face 'd-face-special-reference 'd-latex--tt-face)


(when emacs-dialect--xemacs-p
  (make-face 'd-latex--tt-face)
  (make-face-unitalic 'd-latex--tt-face)
  (make-face-bold     'd-latex--tt-face)
;;  (copy-face 'italic 'd-latex--tt-face)
;;  (make-face 'd-latex--tt-face)
;;  (set-face-foreground 'd-latex--tt-face "#fff")
;;  (set-face-background 'd-latex--tt-face bg-colour-lighter)
;;  (set-face-underline-p 'd-latex--tt-face nil)
  )

;;(d-latex--get-current-indentation)
(defun d-latex--get-current-indentation ()
  ;;(message "*** d-latex--get-current-indentation")
  (- (save-excursion
       (beginning-of-line)
       (skip-chars-forward " \t")
       (point))
     (point-at-bol)
     )
  )

(defun d-latex--set-current-indentation (proper-i)
  (if (not (eq proper-i (d-latex--get-current-indentation)))
      (let ((p nil))
        (beginning-of-line)
        (setq p (point))
        (while (looking-at "[ \t]")
          (forward-char))
        (delete-region p (point))
        (insert (make-string proper-i ?\ ))
        ;;(message "*** d-latex--set-current-indentation")
        )))

(defun d-latex--goto-previous-nontrivial-line ()
  (beginning-of-line)
  (forward-line -1)
  (let (done empty-line-regexp)
    (while (not done)
      (setq done t)
      (if (looking-at "\\\\end{verbatim}")
          (progn
            (setq done nil)
            (while (not (looking-at "\\\\begin{verbatim}"))
              (forward-line -1))
            (forward-line -1)
            ))
      (if (looking-at "m4_end_indent")
          (progn
            (setq done nil)
            (while (not (looking-at "m4_begin_indent"))
              (forward-line -1))
            (forward-line -1)
            ))
      (if (looking-at "\\\\end{tabular}")
          (progn
            (setq done nil)
            (while (not (looking-at "\\\\begin{tabular}"))
              (forward-line -1))
            (forward-line -1)
            ))
      (setq empty-line-regexp "^[\t ]*$")
      (beginning-of-line)
      (if (/= (point) (point-min))
          (if (save-excursion
                (beginning-of-line)
                (looking-at empty-line-regexp))
              (progn
                (setq done nil)
                (while (and (save-excursion
                              (beginning-of-line)
                              (looking-at empty-line-regexp))
                            (/= (point) (point-min)))
                  (forward-line -1)
                  (beginning-of-line)
                  ))))
      )))

(defun d-latex--get-current-begins ()
  (save-excursion
    (beginning-of-line)
    (skip-chars-forward " \t")
    (cond
     ((looking-at "m4_begin_[a-z]*")
      1)
     ((and (looking-at "\\\\begin{")
           (not (looking-at "\\\\begin{document}")))
      1)
     (t 0))))

(defun d-latex--get-current-ends ()
  (save-excursion
    (beginning-of-line)
    (skip-chars-forward " \t")
    (cond
     ((looking-at "m4_end_[a-z]*")
      1)
     ((and (looking-at "\\\\end{")
           (not (looking-at "\\\\end{document}")))
           1)
     (t 0))))

(defvar d-latex--basic-indent 2)

(defun d-latex--inside-block (block-name)
  (cond
   (t

    (let ((bv (save-excursion
                (beginning-of-line)
                (re-search-backward (concat "^\\\\begin{" block-name "}") nil t)))
          (ev (save-excursion
                (end-of-line)
                (re-search-backward (concat "^\\\\end{" block-name "}") nil t))))
      (if bv
          ;; bv non-nil
          (if ev
              ;; ev non-nil
              (if (> bv ev)
                  t)
            ;; ev nil
            t
            )
        ;; bv is nil
        nil
        )))))

(defun d-latex--inside-block-notblock ()
  (cond
   (t

    (let ((bv (save-excursion
                (beginning-of-line)
                (re-search-backward "^m4_begin_indent[ \t]*$" nil t)))
          (ev (save-excursion
                (end-of-line)
                (re-search-backward "^m4_end_indent[ \t]*$" nil t))))
      (if bv
          ;; bv non-nil
          (if ev
              ;; ev non-nil
              (if (> bv ev)
                  t)
            ;; ev nil
            t
            )
        ;; bv is nil
        nil
        )))))

(defun d-latex--tab ()
  (interactive)
  (let ((proper-i)
        (c-end)
        (p-indent)
        (p-begin))

    (d-quote (not (save-excursion
                    (beginning-of-line)
                    (re-search-backward "^\\\\begin{document}" nil t)))
             (debug 100)
             0)
    (setq proper-i (cond
                    ((save-excursion
                       (beginning-of-line)
                       (looking-at "^[ \t]*\\\\begin{verbatim}"))
                     ;;(debug 200)
                     0)

                    ((save-excursion
                       (beginning-of-line)
                       (looking-at "^[ \t]*\\\\end{verbatim}"))
                     ;;(debug 300)
                     0)
                    ((save-excursion
                       (beginning-of-line)
                       (looking-at "^[ \t]*m4_begin_indent"))
                     ;;(debug 200)
                     0)

                    ((save-excursion
                       (beginning-of-line)
                       (looking-at "^[ \t]*m4_end_indent"))
                     ;;(debug 300)
                     0)

                    ((save-excursion
                       (beginning-of-line)
                       (looking-at "^[ \t]*\\\\begin{tabular}"))
                     ;;(debug 400)
                     0)

                    ((save-excursion
                       (beginning-of-line)
                       (looking-at "^[ \t]*\\\\end{tabular}"))
                     ;;(debug 500)
                     0)

                    ((save-excursion
                       (beginning-of-line)
                       (looking-at "^[ \t]*\\\\begin{align}"))
                     ;;(debug 600)
                     0)

                    ((save-excursion
                       (beginning-of-line)
                       (looking-at "^[ \t]*\\\\end{align}"))
                     ;;(debug 700)
                     0)

                    ((d-latex--inside-block-notblock)
                     (d-latex--get-current-indentation)
                     )
                    ((d-latex--inside-block "verbatim")
                     ;;(debug "Knife fight")
                     (d-latex--get-current-indentation)
                     )
                    ((d-latex--inside-block "tabular")
                     (d-latex--get-current-indentation))

                    ((d-latex--inside-block "align")
                     (d-latex--get-current-indentation))

                    ;; ELSE PART:
                    (t
                     (save-excursion
                       ;;(message "foo1")
                       (beginning-of-line)
                       ;;(message "foo2")
                       (setq c-end (* (d-latex--get-current-ends) d-latex--basic-indent))
                       ;;(message "foo3")
                       (d-latex--goto-previous-nontrivial-line)
                       ;;(message "foo4")
                       (setq p-indent (d-latex--get-current-indentation))
                       ;;(message "foo5")
                       (setq p-begin (* (d-latex--get-current-begins) d-latex--basic-indent))
                       ;;(message "foo6")
                       (+ p-indent p-begin (- c-end))
                       ))
                    ;; END COND:
                    )
          ;; END SETQ:
          )
    (setq proper-i (max proper-i 0))
    (d-latex--set-current-indentation proper-i)
    ;;(debug "Antler")
    ;; END LET:
    )
  )

(defun d-latex--tab-key ()
  (interactive)
  (save-excursion
    (d-latex--tab))
  (beginning-of-line)
  (if (looking-at "^[ \t]*")
      (skip-chars-forward " \t")))

(defun d-latex--enter ()
  (interactive)
  (if (save-excursion
        (beginning-of-line)
        (looking-at "^%%%"))
      (insert "\n%%% ")
    (insert "\n"))
    (d-latex--tab-key))

(defun d-latex--meta-control-backslash ()
  (interactive)
  (save-excursion
    (goto-char (point-min))
    (while (not (eobp))
      (forward-line 1)
      (d-latex--tab)
      )))

(defadvice fill-paragraph (around d-latex activate)
  ad-do-it
  (if (eq major-mode 'latex-mode)
      (d-latex--meta-control-backslash)))

(d-quote (setq auto-mode-alist
             (append '(("\\.tex$" . latex-mode)
                       ) auto-mode-alist)))

(provide 'd-latex)
;;; d-latex.el ends here
