-If `ansi-color-get-face' returns nil, then we either got a
-null-sequence, or we stumbled upon some garbage. In either
-case we return nil."
- (let ((new-faces (ansi-color-get-face escape-sequence)))
- (cond ((null new-faces)
- nil)
- ((eq (car new-faces) 'default)
- (cdr new-faces))
- (t
- ;; Like (append NEW-FACES FACES)
- ;; but delete duplicates in FACES.
- (let ((modified-faces (copy-sequence faces)))
- (dolist (face (nreverse new-faces))
- (setq modified-faces (delete face modified-faces))
- (push face modified-faces))
- modified-faces)))))
+Returns nil only if there's no match for `ansi-color-parameter-regexp'."
+ (let ((i 0)
+ codes val)
+ (while (string-match ansi-color-parameter-regexp escape-seq i)
+ (setq i (match-end 0)
+ val (string-to-number (match-string 1 escape-seq) 10))
+ ;; It so happens that (string-to-number "") => 0.
+ (push val codes))
+ (nreverse codes)))
+
+(defun ansi-color-apply-sequence (escape-sequence codes)
+ "Apply ESCAPE-SEQUENCE to CODES and return the new list of codes.
+
+ESCAPE-SEQUENCE is an escape sequence parsed by
+`ansi-color-parse-sequence'.
+
+For each new code, the following happens: if it is 1-7, add it to
+the list of codes; if it is 21-25 or 27, delete appropriate
+parameters from the list of codes; if it is 30-37 resp. 39, the
+foreground color code is replaced or added resp. deleted; if it
+is 40-47 resp. 49, the background color code is replaced or added
+resp. deleted; any other code is discarded together with the old
+codes. Finally, the so changed list of codes is returned."
+ (let ((new-codes (ansi-color-parse-sequence escape-sequence)))
+ (while new-codes
+ (let* ((new (pop new-codes))
+ (q (/ new 10)))
+ (setq codes
+ (pcase q
+ (0 (unless (memq new '(0 8 9))
+ (cons new (remq new codes))))
+ (2 (unless (memq new '(20 26 28 29))
+ ;; The standard says `21 doubly underlined' while
+ ;; http://en.wikipedia.org/wiki/ANSI_escape_code claims
+ ;; `21 Bright/Bold: off or Underline: Double'.
+ (remq (- new 20) (pcase new
+ (22 (remq 1 codes))
+ (25 (remq 6 codes))
+ (_ codes)))))
+ ((or 3 4) (let ((r (mod new 10)))
+ (unless (= r 8)
+ (let (beg)
+ (while (and codes (/= q (/ (car codes) 10)))
+ (push (pop codes) beg))
+ (setq codes (nconc (nreverse beg) (cdr codes)))
+ (if (= r 9)
+ codes
+ (cons new codes))))))
+ (_ nil)))))
+ codes))