chiark / gitweb /
el/dot-emacs.el: Better fontification for Ediff.
[profile] / el / dot-emacs.el
index d657295da6c66160aceb1beb84af4068ab5f1d51..d83057a9880827fc61a9145e485494bd6e89e718 100644 (file)
@@ -57,6 +57,12 @@ (defun mdw-wrong ()
   (interactive)
   (error "wrong button"))
 
+(defun mdw-emacs-version-p (major &optional minor)
+  "Return non-nil if the running Emacs is at least version MAJOR.MINOR."
+  (or (> emacs-major-version major)
+      (and (= emacs-major-version major)
+          (>= emacs-minor-version (or minor 0)))))
+
 ;; Some error trapping.
 ;;
 ;; If individual bits of this file go tits-up, we don't particularly want
@@ -96,6 +102,15 @@ (defun mdw-config (sym)
                    (concat "(" (buffer-string) ")")))))))
   (cdr (assq sym mdw-config)))
 
+;; Width configuration.
+
+(defvar mdw-column-width
+  (string-to-number (or (mdw-config 'emacs-width) "77"))
+  "Width of Emacs columns.")
+(defvar mdw-text-width mdw-column-width
+  "Expected width of text within columns.")
+(put 'mdw-text-width 'safe-local-variable 'integerp)
+
 ;; Local variables hacking.
 
 (defun run-local-vars-mode-hook ()
@@ -189,10 +204,9 @@ (defun mdw-divvy-window (&optional width)
   "Split a wide window into appropriate widths."
   (interactive "P")
   (setq width (cond (width (prefix-numeric-value width))
-                   ((and window-system
-                         (>= emacs-major-version 22))
-                    77)
-                   (t 78)))
+                   ((and window-system (mdw-emacs-version-p 22))
+                    mdw-column-width)
+                   (t (1+ mdw-column-width))))
   (let* ((win (selected-window))
         (sb-width (mdw-horizontal-window-overhead))
         (c (/ (+ (window-width) sb-width)
@@ -225,6 +239,7 @@ (defmacro mdw-advise-to-inhibit-raise-frame (function)
        ad-do-it)))
 
 (mdw-advise-to-inhibit-raise-frame select-frame-set-input-focus)
+(mdw-advise-to-inhibit-raise-frame appt-disp-window)
 
 ;; Bug fix for markdown-mode, which breaks point positioning during
 ;; `query-replace'.
@@ -233,6 +248,32 @@ (defadvice markdown-check-change-for-wiki-link
   "Save match data around the `markdown-mode' `after-change-functions' hook."
   (save-match-data ad-do-it))
 
+;; Bug fix for `bbdb-canonicalize-address': on Emacs 24, `run-hook-with-args'
+;; always returns nil, with the result that all email addresses are lost.
+;; Replace the function entirely.
+(defadvice bbdb-canonicalize-address
+    (around mdw-bug-fix activate compile)
+  "Don't use `run-hook-with-args', because that doesn't work."
+  (let ((net (ad-get-arg 0)))
+
+    ;; Make sure this is a proper hook list.
+    (if (functionp bbdb-canonicalize-net-hook)
+       (setq bbdb-canonicalize-net-hook (list bbdb-canonicalize-net-hook)))
+
+    ;; Iterate over the hooks until things converge.
+    (let ((donep nil))
+      (while (not donep)
+       (let (next (changep nil)
+             hook (hooks bbdb-canonicalize-net-hook))
+         (while hooks
+           (setq hook (pop hooks))
+           (setq next (funcall hook net))
+           (if (not (equal next net))
+               (setq changep t
+                     net next)))
+         (setq donep (not changep)))))
+    (setq ad-return-value net)))
+
 ;; Transient mark mode hacks.
 
 (defadvice exchange-point-and-mark
@@ -254,6 +295,11 @@ (defadvice exchange-point-and-mark
 
 ;; Functions for sexp diary entries.
 
+(defun mdw-not-org-mode (form)
+  "As FORM, but not in Org mode agenda."
+  (and (not mdw-diary-for-org-mode-p)
+       (eval form)))
+
 (defun mdw-weekday (l)
   "Return non-nil if `date' falls on one of the days of the week in L.
 L is a list of day numbers (from 0 to 6 for Sunday through to
@@ -265,6 +311,50 @@ (defun mdw-weekday (l)
        (memq (nth d '(sunday monday tuesday wednesday
                              thursday friday saturday)) l))))
 
+(defun mdw-discordian-date (date)
+  "Return the Discordian calendar date corresponding to DATE.
+
+The return value is (YOLD . st-tibs-day) or (YOLD SEASON DAYNUM DOW).
+
+The original is by David Pearson.  I modified it to produce date components
+as output rather than a string."
+  (let* ((days ["Sweetmorn" "Boomtime" "Pungenday"
+               "Prickle-Prickle" "Setting Orange"])
+        (months ["Chaos" "Discord" "Confusion"
+                 "Bureaucracy" "Aftermath"])
+        (day-count [0 31 59 90 120 151 181 212 243 273 304 334])
+        (year (- (extract-calendar-year date) 1900))
+        (month (1- (extract-calendar-month date)))
+        (day (1- (extract-calendar-day date)))
+        (julian (+ (aref day-count month) day))
+        (dyear (+ year 3066)))
+    (if (and (= month 1) (= day 28))
+       (cons dyear 'st-tibs-day)
+      (list dyear
+           (aref months (floor (/ julian 73)))
+           (1+ (mod julian 73))
+           (aref days (mod julian 5))))))
+
+(defun mdw-diary-discordian-date ()
+  "Convert the date in `date' to a string giving the Discordian date."
+  (let* ((ddate (mdw-discordian-date date))
+        (tail (format "in the YOLD %d" (car ddate))))
+    (if (eq (cdr ddate) 'st-tibs-day)
+       (format "St Tib's Day %s" tail)
+      (let ((season (cadr ddate))
+           (daynum (caddr ddate))
+           (dayname (cadddr ddate)))
+      (format "%s, the %d%s day of %s %s"
+             dayname
+             daynum
+             (let ((ldig (mod daynum 10)))
+               (cond ((= ldig 1) "st")
+                     ((= ldig 2) "nd")
+                     ((= ldig 3) "rd")
+                     (t "th")))
+             season
+             tail)))))
+
 (defun mdw-todo (&optional when)
   "Return non-nil today, or on WHEN, whichever is later."
   (let ((w (calendar-absolute-from-gregorian (calendar-current-date)))
@@ -284,6 +374,52 @@ (defun mdw-todo (&optional when)
                                (nth 2 when))))))))
     (eq w d)))
 
+(defvar mdw-diary-for-org-mode-p nil)
+
+(defadvice org-agenda-list (around mdw-preserve-links activate)
+  (let ((mdw-diary-for-org-mode-p t))
+    ad-do-it))
+
+(defadvice diary-add-to-list (before mdw-trim-leading-space compile activate)
+  "Trim leading space from the diary entry string."
+  (save-match-data
+    (let ((str (ad-get-arg 1))
+         (done nil) old)
+      (while (not done)
+       (setq old str)
+       (setq str (cond ((null str) nil)
+                       ((string-match "\\(^\\|\n\\)[ \t]+" str)
+                        (replace-match "\\1" nil nil str))
+                       ((and mdw-diary-for-org-mode-p
+                             (string-match (concat
+                                            "\\(^\\|\n\\)"
+                                            "\\(" diary-time-regexp
+                                            "\\(-" diary-time-regexp "\\)?"
+                                            "\\)"
+                                            "\\(\t[ \t]*\\| [ \t]+\\)")
+                                           str))
+                        (replace-match "\\1\\2 " nil nil str))
+                       ((and (not mdw-diary-for-org-mode-p)
+                             (string-match "\\[\\[[^][]*]\\[\\([^][]*\\)]]"
+                                           str))
+                        (replace-match "\\1" nil nil str))
+                       (t str)))
+       (if (equal str old) (setq done t)))
+      (ad-set-arg 1 str))))
+
+(defadvice org-bbdb-anniversaries (after mdw-fixup-list compile activate)
+  "Return a string rather than a list."
+  (with-temp-buffer
+    (let ((anyp nil))
+      (dolist (e (let ((ee ad-return-value))
+                  (if (atom ee) (list ee) ee)))
+       (when e
+         (when anyp (insert ?\n))
+         (insert e)
+         (setq anyp t)))
+      (setq ad-return-value
+           (and anyp (buffer-string))))))
+
 ;; Fighting with Org-mode's evil key maps.
 
 (defvar mdw-evil-keymap-keys
@@ -451,6 +587,27 @@ (let ((path exec-path))
          (setenv "REAL_MOVEMAIL" try))
       (setq path (cdr path)))))
 
+;; AUTHINFO GENERIC kludge.
+
+(defvar nntp-authinfo-generic nil
+  "Set to the `NNTPAUTH' string to pass on to `authinfo-kludge'.
+
+Use this to arrange for per-server settings.")
+
+(defun nntp-open-authinfo-kludge (buffer)
+  "Open a connection to SERVER using `authinfo-kludge'."
+  (let ((proc (start-process "nntpd" buffer
+                            "env" (concat "NNTPAUTH="
+                                          (or nntp-authinfo-generic
+                                              (getenv "NNTPAUTH")
+                                              (error "NNTPAUTH unset")))
+                            "authinfo-kludge" nntp-address)))
+    (set-buffer buffer)
+    (nntp-wait-for-string "^\r*200")
+    (beginning-of-line)
+    (delete-region (point-min) (point))
+    proc))
+
 (eval-after-load "erc"
     '(load "~/.ercrc.el"))
 
@@ -834,7 +991,7 @@ (defun mdw-misc-mode-config ()
   (setq page-delimiter "\f\\|^.*-\\{6\\}.*$")
   (setq comment-column 40)
   (auto-fill-mode 1)
-  (setq fill-column 77)
+  (setq fill-column mdw-text-width)
   (and (fboundp 'gtags-mode)
        (gtags-mode))
   (if (fboundp 'hs-minor-mode)
@@ -844,16 +1001,27 @@ (defun mdw-misc-mode-config ()
   (trap (turn-on-font-lock)))
 
 (defun mdw-post-local-vars-misc-mode-config ()
+  (setq whitespace-line-column mdw-text-width)
   (when (and mdw-do-misc-mode-hacking
             (not buffer-read-only))
     (setq show-trailing-whitespace t)
     (mdw-whitespace-mode 1)))
 (add-hook 'hack-local-variables-hook 'mdw-post-local-vars-misc-mode-config)
 
-(defadvice toggle-read-only (after mdw-angry-fruit-salad activate)
-  (when mdw-do-misc-mode-hacking
-    (setq show-trailing-whitespace (not buffer-read-only))
-    (mdw-whitespace-mode (if buffer-read-only 0 1))))
+(defmacro mdw-advise-update-angry-fruit-salad (&rest funcs)
+  `(progn ,@(mapcar (lambda (func)
+                     `(defadvice ,func
+                          (after mdw-angry-fruit-salad activate)
+                        (when mdw-do-misc-mode-hacking
+                          (setq show-trailing-whitespace
+                                (not buffer-read-only))
+                          (mdw-whitespace-mode (if buffer-read-only 0 1)))))
+                   funcs)))
+(mdw-advise-update-angry-fruit-salad toggle-read-only
+                                    read-only-mode
+                                    view-mode
+                                    view-mode-enable
+                                    view-mode-disable)
 
 (eval-after-load 'gtags
   '(progn
@@ -995,12 +1163,14 @@ (defun mdw-toggle-full-screen (&optional frame)
 ;;;--------------------------------------------------------------------------
 ;;; General fontification.
 
+(make-face 'mdw-virgin-face)
+
 (defmacro mdw-define-face (name &rest body)
   "Define a face, and make sure it's actually set as the definition."
   (declare (indent 1)
           (debug 0))
   `(progn
-     (make-face ',name)
+     (copy-face 'mdw-virgin-face ',name)
      (defvar ,name ',name)
      (put ',name 'face-defface-spec ',body)
      (face-spec-set ',name ',body nil)))
@@ -1014,7 +1184,7 @@ (mdw-define-face fixed-pitch
   (((type w32)) :family "courier new" :height 85)
   (((type x)) :family "6x13" :foundry "trad" :height 130)
   (t :foreground "white" :background "black"))
-(if (>= emacs-major-version 23)
+(if (mdw-emacs-version-p 23)
     (mdw-define-face variable-pitch
       (((type x)) :family "sans" :height 100))
   (mdw-define-face variable-pitch
@@ -1078,6 +1248,9 @@ (mdw-define-face dired-perm-write
 (mdw-define-face trailing-whitespace
   (((class color)) :background "red")
   (t :inverse-video t))
+(mdw-define-face whitespace-line
+  (((class color)) :background "darkred")
+  (t :inverse-video t))
 (mdw-define-face mdw-punct-face
   (((type tty)) :foreground "yellow") (t :foreground "burlywood2"))
 (mdw-define-face mdw-number-face
@@ -1113,30 +1286,66 @@ (mdw-define-face message-separator
   (t :background "red" :foreground "white" :weight bold))
 (mdw-define-face message-cited-text
   (default :slant italic)
-  (((type tty)) :foreground "green") (t :foreground "SeaGreen1"))
+  (((type tty)) :foreground "cyan") (t :foreground "SkyBlue1"))
 (mdw-define-face message-header-cc
-  (default :weight bold)
+  (default :slant italic)
   (((type tty)) :foreground "green") (t :foreground "SeaGreen1"))
 (mdw-define-face message-header-newsgroups
-  (default :weight bold)
+  (default :slant italic)
   (((type tty)) :foreground "green") (t :foreground "SeaGreen1"))
 (mdw-define-face message-header-subject
-  (default :weight bold)
   (((type tty)) :foreground "green") (t :foreground "SeaGreen1"))
 (mdw-define-face message-header-to
-  (default :weight bold)
   (((type tty)) :foreground "green") (t :foreground "SeaGreen1"))
 (mdw-define-face message-header-xheader
-  (default :weight bold)
+  (default :slant italic)
   (((type tty)) :foreground "green") (t :foreground "SeaGreen1"))
 (mdw-define-face message-header-other
-  (default :weight bold)
+  (default :slant italic)
   (((type tty)) :foreground "green") (t :foreground "SeaGreen1"))
 (mdw-define-face message-header-name
+  (default :weight bold)
   (((type tty)) :foreground "green") (t :foreground "SeaGreen1"))
+
 (mdw-define-face which-func
   (t nil))
 
+(mdw-define-face gnus-header-name
+  (default :weight bold)
+  (((type tty)) :foreground "green") (t :foreground "SeaGreen1"))
+(mdw-define-face gnus-header-subject
+  (((type tty)) :foreground "green") (t :foreground "SeaGreen1"))
+(mdw-define-face gnus-header-from
+  (((type tty)) :foreground "green") (t :foreground "SeaGreen1"))
+(mdw-define-face gnus-header-to
+  (((type tty)) :foreground "green") (t :foreground "SeaGreen1"))
+(mdw-define-face gnus-header-content
+  (default :slant italic)
+  (((type tty)) :foreground "green") (t :foreground "SeaGreen1"))
+
+(mdw-define-face gnus-cite-1
+  (((type tty)) :foreground "cyan") (t :foreground "SkyBlue1"))
+(mdw-define-face gnus-cite-2
+  (((type tty)) :foreground "blue") (t :foreground "RoyalBlue2"))
+(mdw-define-face gnus-cite-3
+  (((type tty)) :foreground "magenta") (t :foreground "MediumOrchid"))
+(mdw-define-face gnus-cite-4
+  (((type tty)) :foreground "red") (t :foreground "firebrick2"))
+(mdw-define-face gnus-cite-5
+  (((type tty)) :foreground "yellow") (t :foreground "burlywood2"))
+(mdw-define-face gnus-cite-6
+  (((type tty)) :foreground "green") (t :foreground "SeaGreen1"))
+(mdw-define-face gnus-cite-7
+  (((type tty)) :foreground "cyan") (t :foreground "SlateBlue1"))
+(mdw-define-face gnus-cite-8
+  (((type tty)) :foreground "blue") (t :foreground "RoyalBlue2"))
+(mdw-define-face gnus-cite-9
+  (((type tty)) :foreground "magenta") (t :foreground "purple2"))
+(mdw-define-face gnus-cite-10
+  (((type tty)) :foreground "red") (t :foreground "DarkOrange2"))
+(mdw-define-face gnus-cite-11
+  (t :foreground "grey"))
+
 (mdw-define-face diff-header
   (t nil))
 (mdw-define-face diff-index
@@ -1158,6 +1367,58 @@ (mdw-define-face diff-context
 (mdw-define-face diff-refine-change
   (((class color) (type x)) :background "RoyalBlue4")
   (t :underline t))
+(mdw-define-face diff-refine-removed
+  (((class color) (type x)) :background "#500")
+  (t :underline t))
+(mdw-define-face diff-refine-added
+  (((class color) (type x)) :background "#050")
+  (t :underline t))
+
+(setq ediff-force-faces t)
+(mdw-define-face ediff-current-diff-A
+  (((class color) (type x)) :background "darkred")
+  (((class color) (type tty)) :background "red")
+  (t :inverse-video t))
+(mdw-define-face ediff-fine-diff-A
+  (((class color) (type x)) :background "red3")
+  (((class color) (type tty)) :inverse-video t)
+  (t :inverse-video nil))
+(mdw-define-face ediff-even-diff-A
+  (((class color) (type x)) :background "#300"))
+(mdw-define-face ediff-odd-diff-A
+  (((class color) (type x)) :background "#300"))
+(mdw-define-face ediff-current-diff-B
+  (((class color) (type x)) :background "darkgreen")
+  (((class color) (type tty)) :background "magenta")
+  (t :inverse-video t))
+(mdw-define-face ediff-fine-diff-B
+  (((class color) (type x)) :background "green4")
+  (((class color) (type tty)) :inverse-video t)
+  (t :inverse-video nil))
+(mdw-define-face ediff-even-diff-B
+  (((class color) (type x)) :background "#020"))
+(mdw-define-face ediff-odd-diff-B
+  (((class color) (type x)) :background "#020"))
+(mdw-define-face ediff-current-diff-C
+  (((class color) (type x)) :background "darkblue")
+  (((class color) (type tty)) :background "blue")
+  (t :inverse-video t))
+(mdw-define-face ediff-fine-diff-C
+  (((class color) (type x)) :background "blue1")
+  (((class color) (type tty)) :inverse-video t)
+  (t :inverse-video nil))
+(mdw-define-face ediff-even-diff-C
+  (((class color) (type x)) :background "#004"))
+(mdw-define-face ediff-odd-diff-C
+  (((class color) (type x)) :background "#004"))
+(mdw-define-face ediff-current-diff-Ancestor
+  (((class color) (type x)) :background "#630")
+  (((class color) (type tty)) :background "blue")
+  (t :inverse-video t))
+(mdw-define-face ediff-even-diff-Ancestor
+  (((class color) (type x)) :background "#320"))
+(mdw-define-face ediff-odd-diff-Ancestor
+  (((class color) (type x)) :background "#320"))
 
 (mdw-define-face dylan-header-background
   (((class color) (type x)) :background "NavyBlue")
@@ -1173,7 +1434,7 @@ (mdw-define-face magit-diff-hunk-header
   (t :foreground "SkyBlue1"))
 (mdw-define-face magit-item-highlight
   (((type tty)) :background "blue")
-  (t :background "DarkSeaGreen4"))
+  (t :background "grey11"))
 (mdw-define-face magit-log-head-label-remote
   (((type tty)) :background "cyan" :foreground "green")
   (t :background "grey11" :foreground "DarkSeaGreen2" :box t))
@@ -1255,17 +1516,6 @@ (let ((dollar (make-glyph-code ?$ 'mdw-ellipsis-face))
 ;;;--------------------------------------------------------------------------
 ;;; C programming configuration.
 
-;; Linux kernel hacking.
-
-(defvar linux-c-mode-hook)
-
-(defun linux-c-mode ()
-  (interactive)
-  (c-mode)
-  (setq major-mode 'linux-c-mode)
-  (setq mode-name "Linux C")
-  (run-hooks 'linux-c-mode-hook))
-
 ;; Make C indentation nice.
 
 (defun mdw-c-lineup-arglist (langelem)
@@ -1284,28 +1534,108 @@ (defun mdw-c-indent-extern-mumble (langelem)
        c-basic-offset
       nil)))
 
-(defun mdw-c-style ()
-  (c-add-style "[mdw] C and C++ style"
-              '((c-basic-offset . 2)
-                (comment-column . 40)
-                (c-class-key . "class")
-                (c-backslash-column . 72)
-                (c-offsets-alist
-                 (substatement-open . (add 0 c-indent-one-line-block))
-                 (defun-open . (add 0 c-indent-one-line-block))
-                 (arglist-cont-nonempty . mdw-c-lineup-arglist)
-                 (topmost-intro . mdw-c-indent-extern-mumble)
-                 (cpp-define-intro . 0)
-                 (knr-argdecl . 0)
-                 (inextern-lang . [0])
-                 (label . 0)
-                 (case-label . +)
-                 (access-label . -)
-                 (inclass . +)
-                 (inline-open . ++)
-                 (statement-cont . +)
-                 (statement-case-intro . +)))
-              t))
+(defun mdw-c-indent-arglist-nested (langelem)
+  "Indent continued argument lists.
+If we've nested more than one argument list, then only introduce a single
+indentation anyway."
+  (let ((context c-syntactic-context)
+       (pos (c-langelem-2nd-pos c-syntactic-element))
+       (should-indent-p t))
+    (while (and context
+               (eq (caar context) 'arglist-cont-nonempty))
+      (when (and (= (caddr (pop context)) pos)
+                context
+                (memq (caar context) '(arglist-intro
+                                       arglist-cont-nonempty)))
+       (setq should-indent-p nil)))
+    (if should-indent-p '+ 0)))
+
+(defvar mdw-define-c-styles-hook nil
+  "Hook run when `cc-mode' starts up to define styles.")
+
+(defmacro mdw-define-c-style (name &rest assocs)
+  "Define a C style, called NAME (a symbol), setting ASSOCs.
+A function, named `mdw-define-c-style/NAME', is defined to actually install
+the style using `c-add-style', and added to the hook
+`mdw-define-c-styles-hook'.  If CC Mode is already loaded, then the style is
+set."
+  (declare (indent defun))
+  (let* ((name-string (symbol-name name))
+        (func (intern (concat "mdw-define-c-style/" name-string))))
+    `(progn
+       (defun ,func () (c-add-style ,name-string ',assocs))
+       (and (featurep 'cc-mode) (,func))
+       (add-hook 'mdw-define-c-styles-hook ',func))))
+
+(eval-after-load "cc-mode"
+  '(run-hooks 'mdw-define-c-styles-hook))
+
+(mdw-define-c-style mdw-trustonic-c
+  (c-basic-offset . 4)
+  (comment-column . 0)
+  (c-indent-comment-alist (anchored-comment . (column . 0))
+                         (end-block . (space . 1))
+                         (cpp-end-block . (space . 1))
+                         (other . (space . 1)))
+  (c-class-key . "class")
+  (c-backslash-column . 0)
+  (c-auto-align-backslashes . nil)
+  (c-label-minimum-indentation . 0)
+  (c-offsets-alist (substatement-open . (add 0 c-indent-one-line-block))
+                  (defun-open . (add 0 c-indent-one-line-block))
+                  (arglist-cont-nonempty . mdw-c-indent-arglist-nested)
+                  (topmost-intro . mdw-c-indent-extern-mumble)
+                  (cpp-define-intro . 0)
+                  (knr-argdecl . 0)
+                  (inextern-lang . [0])
+                  (label . 0)
+                  (case-label . +)
+                  (access-label . -2)
+                  (inclass . +)
+                  (inline-open . ++)
+                  (statement-cont . +)
+                  (statement-case-intro . +)))
+
+(mdw-define-c-style mdw-c
+  (c-basic-offset . 2)
+  (comment-column . 40)
+  (c-class-key . "class")
+  (c-backslash-column . 72)
+  (c-label-minimum-indentation . 0)
+  (c-offsets-alist (substatement-open . (add 0 c-indent-one-line-block))
+                  (defun-open . (add 0 c-indent-one-line-block))
+                  (arglist-cont-nonempty . mdw-c-lineup-arglist)
+                  (topmost-intro . mdw-c-indent-extern-mumble)
+                  (cpp-define-intro . 0)
+                  (knr-argdecl . 0)
+                  (inextern-lang . [0])
+                  (label . 0)
+                  (case-label . +)
+                  (access-label . -)
+                  (inclass . +)
+                  (inline-open . ++)
+                  (statement-cont . +)
+                  (statement-case-intro . +)))
+
+(defun mdw-set-default-c-style (modes style)
+  "Update the default CC Mode style for MODES to be STYLE.
+
+MODES may be a list of major mode names or a singleton.  STYLE is a style
+name, as a symbol."
+  (let ((modes (if (listp modes) modes (list modes)))
+       (style (symbol-name style)))
+    (setq c-default-style
+         (append (mapcar (lambda (mode)
+                           (cons mode style))
+                         modes)
+                 (remove-if (lambda (assoc)
+                              (memq (car assoc) modes))
+                            (if (listp c-default-style)
+                                c-default-style
+                              (list (cons 'other c-default-style))))))))
+(setq c-default-style "mdw-c")
+
+(mdw-set-default-c-style '(c-mode c++-mode) 'mdw-c)
 
 (defvar mdw-c-comment-fill-prefix
   `((,(concat "\\([ \t]*/?\\)"
@@ -1324,78 +1654,87 @@ (defun mdw-fontify-c-and-c++ ()
   (modify-syntax-entry ?\n "> b")
 
   ;; Other stuff.
-  (mdw-c-style)
-  (setq c-hanging-comment-ender-p nil)
-  (setq c-backslash-column 72)
-  (setq c-label-minimum-indentation 0)
   (setq mdw-fill-prefix mdw-c-comment-fill-prefix)
 
   ;; Now define things to be fontified.
   (make-local-variable 'font-lock-keywords)
   (let ((c-keywords
-        (mdw-regexps "and"             ;C++
-                     "and_eq"          ;C++
-                     "asm"             ;K&R, GCC
-                     "auto"            ;K&R, C89
-                     "bitand"          ;C++
-                     "bitor"           ;C++
-                     "bool"            ;C++, C9X macro
-                     "break"           ;K&R, C89
-                     "case"            ;K&R, C89
-                     "catch"           ;C++
-                     "char"            ;K&R, C89
-                     "class"           ;C++
-                     "complex"         ;C9X macro, C++ template type
-                     "compl"           ;C++
-                     "const"           ;C89
-                     "const_cast"      ;C++
-                     "continue"        ;K&R, C89
-                     "defined"         ;C89 preprocessor
-                     "default"         ;K&R, C89
-                     "delete"          ;C++
-                     "do"              ;K&R, C89
-                     "double"          ;K&R, C89
-                     "dynamic_cast"    ;C++
-                     "else"            ;K&R, C89
-                     ;; "entry"        ;K&R -- never used
-                     "enum"            ;C89
-                     "explicit"        ;C++
-                     "export"          ;C++
-                     "extern"          ;K&R, C89
-                     "float"           ;K&R, C89
-                     "for"             ;K&R, C89
-                     ;; "fortran"      ;K&R
-                     "friend"          ;C++
-                     "goto"            ;K&R, C89
-                     "if"              ;K&R, C89
-                     "imaginary"       ;C9X macro
-                     "inline"          ;C++, C9X, GCC
-                     "int"             ;K&R, C89
-                     "long"            ;K&R, C89
-                     "mutable"         ;C++
-                     "namespace"       ;C++
-                     "new"             ;C++
-                     "operator"        ;C++
-                     "or"              ;C++
-                     "or_eq"           ;C++
-                     "private"         ;C++
-                     "protected"       ;C++
-                     "public"          ;C++
-                     "register"        ;K&R, C89
+        (mdw-regexps "alignas"          ;C11 macro, C++11
+                     "alignof"          ;C++11
+                     "and"              ;C++, C95 macro
+                     "and_eq"           ;C++, C95 macro
+                     "asm"              ;K&R, C++, GCC
+                     "atomic"           ;C11 macro, C++11 template type
+                     "auto"             ;K&R, C89
+                     "bitand"           ;C++, C95 macro
+                     "bitor"            ;C++, C95 macro
+                     "bool"             ;C++, C99 macro
+                     "break"            ;K&R, C89
+                     "case"             ;K&R, C89
+                     "catch"            ;C++
+                     "char"             ;K&R, C89
+                     "char16_t"         ;C++11, C11 library type
+                     "char32_t"         ;C++11, C11 library type
+                     "class"            ;C++
+                     "complex"          ;C99 macro, C++ template type
+                     "compl"            ;C++, C95 macro
+                     "const"            ;C89
+                     "constexpr"        ;C++11
+                     "const_cast"       ;C++
+                     "continue"         ;K&R, C89
+                     "decltype"         ;C++11
+                     "defined"          ;C89 preprocessor
+                     "default"          ;K&R, C89
+                     "delete"           ;C++
+                     "do"               ;K&R, C89
+                     "double"           ;K&R, C89
+                     "dynamic_cast"     ;C++
+                     "else"             ;K&R, C89
+                     ;; "entry"         ;K&R -- never used
+                     "enum"             ;C89
+                     "explicit"         ;C++
+                     "export"           ;C++
+                     "extern"           ;K&R, C89
+                     "float"            ;K&R, C89
+                     "for"              ;K&R, C89
+                     ;; "fortran"       ;K&R
+                     "friend"           ;C++
+                     "goto"             ;K&R, C89
+                     "if"               ;K&R, C89
+                     "imaginary"        ;C99 macro
+                     "inline"           ;C++, C99, GCC
+                     "int"              ;K&R, C89
+                     "long"             ;K&R, C89
+                     "mutable"          ;C++
+                     "namespace"        ;C++
+                     "new"              ;C++
+                     "noexcept"         ;C++11
+                     "noreturn"         ;C11 macro
+                     "not"              ;C++, C95 macro
+                     "not_eq"           ;C++, C95 macro
+                     "nullptr"          ;C++11
+                     "operator"         ;C++
+                     "or"               ;C++, C95 macro
+                     "or_eq"            ;C++, C95 macro
+                     "private"          ;C++
+                     "protected"        ;C++
+                     "public"           ;C++
+                     "register"         ;K&R, C89
                      "reinterpret_cast" ;C++
-                     "restrict"         ;C9X
+                     "restrict"         ;C99
                      "return"           ;K&R, C89
                      "short"            ;K&R, C89
                      "signed"           ;C89
                      "sizeof"           ;K&R, C89
                      "static"           ;K&R, C89
+                     "static_assert"    ;C11 macro, C++11
                      "static_cast"      ;C++
                      "struct"           ;K&R, C89
                      "switch"           ;K&R, C89
                      "template"         ;C++
                      "throw"            ;C++
                      "try"              ;C++
-                     "this"             ;C++
+                     "thread_local"     ;C11 macro, C++11
                      "typedef"          ;C89
                      "typeid"           ;C++
                      "typeof"           ;GCC
@@ -1408,12 +1747,19 @@ (defun mdw-fontify-c-and-c++ ()
                      "volatile"         ;C89
                      "wchar_t"          ;C++, C89 library type
                      "while"            ;K&R, C89
-                     "xor"              ;C++
-                     "xor_eq"           ;C++
-                     "_Bool"            ;C9X
-                     "_Complex"         ;C9X
-                     "_Imaginary"       ;C9X
-                     "_Pragma"          ;C9X preprocessor
+                     "xor"              ;C++, C95 macro
+                     "xor_eq"           ;C++, C95 macro
+                     "_Alignas"         ;C11
+                     "_Alignof"         ;C11
+                     "_Atomic"          ;C11
+                     "_Bool"            ;C99
+                     "_Complex"         ;C99
+                     "_Generic"         ;C11
+                     "_Imaginary"       ;C99
+                     "_Noreturn"        ;C11
+                     "_Pragma"          ;C99 preprocessor
+                     "_Static_assert"   ;C11
+                     "_Thread_local"    ;C11
                      "__alignof__"      ;GCC
                      "__asm__"          ;GCC
                      "__attribute__"    ;GCC
@@ -1429,9 +1775,9 @@ (defun mdw-fontify-c-and-c++ ()
                      "__volatile__"     ;GCC
                      ))
        (c-constants
-        (mdw-regexps "false"           ;C++, C9X macro
+        (mdw-regexps "false"            ;C++, C99 macro
                      "this"             ;C++
-                     "true"             ;C++, C9X macro
+                     "true"             ;C++, C99 macro
                      ))
        (preprocessor-keywords
         (mdw-regexps "assert" "define" "elif" "else" "endif" "error"
@@ -1483,12 +1829,8 @@ (defun mdw-fontify-c-and-c++ ()
 ;;;--------------------------------------------------------------------------
 ;;; AP calc mode.
 
-(defun apcalc-mode ()
-  (interactive)
-  (c-mode)
-  (setq major-mode 'apcalc-mode)
-  (setq mode-name "AP Calc")
-  (run-hooks 'apcalc-mode-hook))
+(define-derived-mode apcalc-mode c-mode "AP Calc"
+  "Major mode for editing Calc code.")
 
 (defun mdw-fontify-apcalc ()
 
@@ -1497,9 +1839,6 @@ (defun mdw-fontify-apcalc ()
   (modify-syntax-entry ?/ ". 14")
 
   ;; Other stuff.
-  (mdw-c-style)
-  (setq c-hanging-comment-ender-p nil)
-  (setq c-backslash-column 72)
   (setq comment-start "/* ")
   (setq comment-end " */")
   (setq mdw-fill-prefix mdw-c-comment-fill-prefix)
@@ -1537,25 +1876,22 @@ (defun mdw-fontify-apcalc ()
 
 ;; Make indentation nice.
 
-(defun mdw-java-style ()
-  (c-add-style "[mdw] Java style"
-              '((c-basic-offset . 2)
-                (c-offsets-alist (substatement-open . 0)
-                                 (label . +)
-                                 (case-label . +)
-                                 (access-label . 0)
-                                 (inclass . +)
-                                 (statement-case-intro . +)))
-              t))
+(mdw-define-c-style mdw-java
+  (c-basic-offset . 2)
+  (c-backslash-column . 72)
+  (c-offsets-alist (substatement-open . 0)
+                  (label . +)
+                  (case-label . +)
+                  (access-label . 0)
+                  (inclass . +)
+                  (statement-case-intro . +)))
+(mdw-set-default-c-style 'java-mode 'mdw-java)
 
 ;; Declare Java fontification style.
 
 (defun mdw-fontify-java ()
 
   ;; Other stuff.
-  (mdw-java-style)
-  (setq c-hanging-comment-ender-p nil)
-  (setq c-backslash-column 72)
   (setq mdw-fill-prefix mdw-c-comment-fill-prefix)
 
   ;; Now define things to be fontified.
@@ -1734,25 +2070,22 @@ (defun mdw-fontify-scala ()
 
 ;; Make indentation nice.
 
-(defun mdw-csharp-style ()
-  (c-add-style "[mdw] C# style"
-              '((c-basic-offset . 2)
-                (c-offsets-alist (substatement-open . 0)
-                                 (label . 0)
-                                 (case-label . +)
-                                 (access-label . 0)
-                                 (inclass . +)
-                                 (statement-case-intro . +)))
-              t))
+(mdw-define-c-style mdw-csharp
+  (c-basic-offset . 2)
+  (c-backslash-column . 72)
+  (c-offsets-alist (substatement-open . 0)
+                  (label . 0)
+                  (case-label . +)
+                  (access-label . 0)
+                  (inclass . +)
+                  (statement-case-intro . +)))
+(mdw-set-default-c-style 'csharp-mode 'mdw-csharp)
 
 ;; Declare C# fontification style.
 
 (defun mdw-fontify-csharp ()
 
   ;; Other stuff.
-  (mdw-csharp-style)
-  (setq c-hanging-comment-ender-p nil)
-  (setq c-backslash-column 72)
   (setq mdw-fill-prefix mdw-c-comment-fill-prefix)
 
   ;; Now define things to be fontified.
@@ -2065,21 +2398,19 @@ (defun mdw-fontify-rust ()
 
 ;; Make Awk indentation nice.
 
-(defun mdw-awk-style ()
-  (c-add-style "[mdw] Awk style"
-              '((c-basic-offset . 2)
-                (c-offsets-alist (substatement-open . 0)
-                                 (statement-cont . 0)
-                                 (statement-case-intro . +)))
-              t))
+(mdw-define-c-style mdw-awk
+  (c-basic-offset . 2)
+  (c-offsets-alist (substatement-open . 0)
+                  (c-backslash-column . 72)
+                  (statement-cont . 0)
+                  (statement-case-intro . +)))
+(mdw-set-default-c-style 'awk-mode 'mdw-awk)
 
 ;; Declare Awk fontification style.
 
 (defun mdw-fontify-awk ()
 
   ;; Miscellaneous fiddling.
-  (mdw-awk-style)
-  (setq c-backslash-column 72)
   (mdw-standard-fill-prefix "\\([ \t]*#+[ \t]*\\)")
 
   ;; Now define things to be fontified.
@@ -2305,6 +2636,7 @@ (defun mdw-fontify-asm ()
   (modify-syntax-entry ?. "w")
   (modify-syntax-entry ?\n ">")
   (setf fill-prefix nil)
+  (local-set-key ";" 'self-insert-command)
   (mdw-standard-fill-prefix "\\([ \t]*;+[ \t]*\\)"))
 
 (defun mdw-asm-set-comment ()
@@ -2719,6 +3051,10 @@ (defun mdw-fontify-tex ()
   (modify-syntax-entry ?$ "." font-lock-syntax-table)
   (local-set-key [?$] 'self-insert-command)
 
+  ;; Make `tab' be useful, given that tab stops in TeX don't work well.
+  (local-set-key "\C-i" 'indent-relative)
+  (setq indent-tabs-mode nil)
+
   ;; Set fill prefix.
   (mdw-standard-fill-prefix "\\([ \t]*%+[ \t]*\\)")