+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Case fixing
+
+(defun vhdl-fix-case-region-1 (beg end upper-case word-regexp &optional count)
+ "Convert all words matching WORD-REGEXP in region to lower or upper case,
+depending on parameter UPPER-CASE."
+ (let ((case-replace nil)
+ (last-update 0))
+ (vhdl-prepare-search-2
+ (save-excursion
+ (goto-char end)
+ (setq end (point-marker))
+ (goto-char beg)
+ (while (re-search-forward word-regexp end t)
+ (or (vhdl-in-literal)
+ (if upper-case
+ (upcase-word -1)
+ (downcase-word -1)))
+ (when (and count vhdl-progress-interval (not noninteractive)
+ (< vhdl-progress-interval
+ (- (nth 1 (current-time)) last-update)))
+ (message "Fixing case... (%2d%s)"
+ (+ (* count 20) (/ (* 20 (- (point) beg)) (- end beg)))
+ "%")
+ (setq last-update (nth 1 (current-time)))))
+ (goto-char end)))))
+
+(defun vhdl-fix-case-region (beg end &optional arg)
+ "Convert all VHDL words in region to lower or upper case, depending on
+options vhdl-upper-case-{keywords,types,attributes,enum-values}."
+ (interactive "r\nP")
+ (vhdl-fix-case-region-1
+ beg end vhdl-upper-case-keywords vhdl-keywords-regexp 0)
+ (vhdl-fix-case-region-1
+ beg end vhdl-upper-case-types vhdl-types-regexp 1)
+ (vhdl-fix-case-region-1
+ beg end vhdl-upper-case-attributes (concat "'" vhdl-attributes-regexp) 2)
+ (vhdl-fix-case-region-1
+ beg end vhdl-upper-case-enum-values vhdl-enum-values-regexp 3)
+ (vhdl-fix-case-region-1
+ beg end vhdl-upper-case-constants vhdl-constants-regexp 4)
+ (when vhdl-progress-interval (message "Fixing case...done")))
+
+(defun vhdl-fix-case-buffer ()
+ "Convert all VHDL words in buffer to lower or upper case, depending on
+options vhdl-upper-case-{keywords,types,attributes,enum-values}."
+ (interactive)
+ (vhdl-fix-case-region (point-min) (point-max)))
+
+(defun vhdl-fix-case-word (&optional arg)
+ "Convert word after cursor to upper case if necessary."
+ (interactive "p")
+ (save-excursion
+ (when arg (backward-word 1))
+ (vhdl-prepare-search-1
+ (when (and vhdl-upper-case-keywords
+ (looking-at vhdl-keywords-regexp))
+ (upcase-word 1))
+ (when (and vhdl-upper-case-types
+ (looking-at vhdl-types-regexp))
+ (upcase-word 1))
+ (when (and vhdl-upper-case-attributes
+ (looking-at vhdl-attributes-regexp))
+ (upcase-word 1))
+ (when (and vhdl-upper-case-enum-values
+ (looking-at vhdl-enum-values-regexp))
+ (upcase-word 1))
+ (when (and vhdl-upper-case-constants
+ (looking-at vhdl-constants-regexp))
+ (upcase-word 1)))))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Fix statements
+;; - force each statement to be on a separate line except when on same line
+;; with 'end' keyword
+
+(defun vhdl-fix-statement-region (beg end &optional arg)
+ "Force statements in region on separate line except when on same line
+with 'end' keyword (necessary for correct indentation).
+Currently supported keywords: 'begin', 'if'."
+ (interactive "r\nP")
+ (vhdl-prepare-search-2
+ (let (point)
+ (save-excursion
+ (goto-char end)
+ (setq end (point-marker))
+ (goto-char beg)
+ ;; `begin' keyword
+ (while (re-search-forward
+ "^\\s-*[^ \t\n].*?\\(\\<begin\\>\\)\\(.*\\<end\\>\\)?" end t)
+ (goto-char (match-end 0))
+ (setq point (point-marker))
+ (when (and (match-string 1)
+ (or (not (match-string 2))
+ (save-excursion (goto-char (match-end 2))
+ (vhdl-in-literal)))
+ (not (save-excursion (goto-char (match-beginning 1))
+ (vhdl-in-literal))))
+ (goto-char (match-beginning 1))
+ (insert "\n")
+ (indent-according-to-mode))
+ (goto-char point))
+ (goto-char beg)
+ ;; `for', `if' keywords
+ (while (re-search-forward "\\<\\(for\\|if\\)\\>" end t)
+ (goto-char (match-end 1))
+ (setq point (point-marker))
+ ;; exception: in literal or preceded by `end' or label
+ (when (and (not (save-excursion (goto-char (match-beginning 1))
+ (vhdl-in-literal)))
+ (save-excursion
+ (beginning-of-line 1)
+ (save-match-data
+ (and (re-search-forward "^\\s-*\\([^ \t\n].*\\)"
+ (match-beginning 1) t)
+ (not (string-match
+ "\\(\\<end\\>\\|\\<wait\\>\\|\\w+\\s-*:\\)\\s-*$"
+ (match-string 1)))))))
+ (goto-char (match-beginning 1))
+ (insert "\n")
+ (indent-according-to-mode))
+ (goto-char point))))))
+
+(defun vhdl-fix-statement-buffer ()
+ "Force statements in buffer on separate line except when on same line
+with 'end' keyword (necessary for correct indentation)."
+ (interactive)
+ (vhdl-fix-statement-region (point-min) (point-max)))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Trailing spaces
+
+(defun vhdl-remove-trailing-spaces-region (beg end &optional arg)
+ "Remove trailing spaces in region."
+ (interactive "r\nP")
+ (save-excursion
+ (goto-char end)
+ (setq end (point-marker))
+ (goto-char beg)
+ (while (re-search-forward "[ \t]+$" end t)
+ (unless (vhdl-in-literal)
+ (replace-match "" nil nil)))))
+
+(defun vhdl-remove-trailing-spaces ()
+ "Remove trailing spaces in buffer."
+ (interactive)
+ (vhdl-remove-trailing-spaces-region (point-min) (point-max)))
+