aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lisp/international/mule-cmds.el154
1 files changed, 125 insertions, 29 deletions
diff --git a/lisp/international/mule-cmds.el b/lisp/international/mule-cmds.el
index 5352fb02f24..9340dec8074 100644
--- a/lisp/international/mule-cmds.el
+++ b/lisp/international/mule-cmds.el
@@ -303,6 +303,50 @@ CHARSETS is a list of character sets."
303 (sort codings (function (lambda (x y) (> (car x) (car y)))))) 303 (sort codings (function (lambda (x y) (> (car x) (car y))))))
304 ))) 304 )))
305 305
306(defun find-multibyte-characters (from to &optional maxcount excludes)
307 "Find multibyte characters in the region specified by FROM and TO.
308If FROM is a string, find multibyte characters in the string.
309The return value is an alist of the following format:
310 ((CHARSET COUNT CHAR ...) ...)
311where
312 CHARSET is a character set,
313 COUNT is a number of characters,
314 CHARs are found characters of the character set.
315Optional 3rd arg MAXCOUNT limits how many CHARs are put in the above list.
316Optioanl 4th arg EXCLUDE is a list of character sets to be ignored."
317 (let ((chars nil)
318 charset char)
319 (if (stringp from)
320 (let ((idx 0))
321 (while (setq idx (string-match "[^\000-\177]" from idx))
322 (setq char (aref from idx)
323 charset (char-charset char))
324 (if (not (memq charset excludes))
325 (let ((slot (assq charset chars)))
326 (if slot
327 (if (not (memq char (nthcdr 2 slot)))
328 (let ((count (nth 1 slot)))
329 (setcar (cdr slot) (1+ count))
330 (if (or (not maxcount) (< count maxcount))
331 (nconc slot (list char)))))
332 (setq chars (cons (list charset 1 char) chars)))))
333 (setq idx (1+ idx))))
334 (save-excursion
335 (goto-char from)
336 (while (re-search-forward "[^\000-\177]" to t)
337 (setq char (preceding-char)
338 charset (char-charset char))
339 (if (not (memq charset excludes))
340 (let ((slot (assq charset chars)))
341 (if slot
342 (if (not (memq char (nthcdr 2 slot)))
343 (let ((count (nth 1 slot)))
344 (setcar (cdr slot) (1+ count))
345 (if (or (not maxcount) (< count maxcount))
346 (nconc slot (list char)))))
347 (setq chars (cons (list charset 1 char) chars))))))))
348 (nreverse chars)))
349
306(defvar last-coding-system-specified nil 350(defvar last-coding-system-specified nil
307 "Most recent coding system explicitly specified by the user when asked. 351 "Most recent coding system explicitly specified by the user when asked.
308This variable is set whenever Emacs asks the user which coding system 352This variable is set whenever Emacs asks the user which coding system
@@ -326,9 +370,9 @@ Kludgy feature: if FROM is a string, the string is the target text,
326and TO is ignored." 370and TO is ignored."
327 (or default-coding-system 371 (or default-coding-system
328 (setq default-coding-system buffer-file-coding-system)) 372 (setq default-coding-system buffer-file-coding-system))
329 (let ((safe-coding-systems (if (stringp from) 373 (let* ((charsets (if (stringp from) (find-charset-string from)
330 (find-coding-systems-string from) 374 (find-charset-region from to)))
331 (find-coding-systems-region from to)))) 375 (safe-coding-systems (find-coding-systems-for-charsets charsets)))
332 (if (or (eq (car safe-coding-systems) 'undecided) 376 (if (or (eq (car safe-coding-systems) 'undecided)
333 (and default-coding-system 377 (and default-coding-system
334 (memq (coding-system-base default-coding-system) 378 (memq (coding-system-base default-coding-system)
@@ -345,34 +389,86 @@ and TO is ignored."
345 (setcar l mime-charset)) 389 (setcar l mime-charset))
346 (setq l (cdr l)))) 390 (setq l (cdr l))))
347 391
348 ;; Then, ask a user to select a proper coding system. 392 (let ((non-safe-chars (find-multibyte-characters
349 (save-window-excursion 393 from to 3
350 ;; At first, show a helpful message. 394 (and default-coding-system
351 (with-output-to-temp-buffer "*Warning*" 395 (coding-system-get default-coding-system
352 (save-excursion 396 'safe-charsets))))
353 (set-buffer standard-output) 397 overlays)
354 (insert (format "\ 398 (save-excursion
355The target text contains a multibyte character which can't be 399 ;; Highlight characters that default-coding-system can't encode.
356encoded safely by the coding system %s. 400 (when (integerp from)
401 (goto-char from)
402 (let ((found nil))
403 (while (and (not found)
404 (re-search-forward "[^\000-\177]" to t))
405 (setq found (assq (char-charset (preceding-char))
406 non-safe-chars))))
407 (beginning-of-line)
408 (set-window-start (selected-window) (point))
409 (save-excursion
410 (while (re-search-forward "[^\000-\177]" to t)
411 (let* ((char (preceding-char))
412 (charset (char-charset char)))
413 (when (assq charset non-safe-chars)
414 (setq overlays (cons (make-overlay (1- (point)) (point))
415 overlays))
416 (overlay-put (car overlays) 'face 'highlight))))))
417
418 ;; At last, ask a user to select a proper coding system.
419 (unwind-protect
420 (save-window-excursion
421 ;; At first, show a helpful message.
422 (with-output-to-temp-buffer "*Warning*"
423 (save-excursion
424 (set-buffer standard-output)
425 (insert "The target text contains the following non ASCII character(s):\n")
426 (let ((len (length non-safe-chars))
427 (shown 0))
428 (while (and non-safe-chars (< shown 3))
429 (when (> (length (car non-safe-chars)) 2)
430 (setq shown (1+ shown))
431 (insert (format "%25s: " (car (car non-safe-chars))))
432 (let ((l (nthcdr 2 (car non-safe-chars))))
433 (while l
434 (insert (car l))
435 (setq l (cdr l))))
436 (if (> (nth 1 (car non-safe-chars)) 3)
437 (insert "..."))
438 (insert "\n"))
439 (setq non-safe-chars (cdr non-safe-chars)))
440 (if (< shown len)
441 (insert (format "%27s\n" "..."))))
442 (insert (format "\
443These can't be encoded safely by the coding system %s.
357 444
358Please select one from the following safe coding systems:\n" 445Please select one from the following safe coding systems:\n"
359 default-coding-system)) 446 default-coding-system))
360 (let ((pos (point)) 447 (let ((pos (point))
361 (fill-prefix " ")) 448 (fill-prefix " "))
362 (mapcar (function (lambda (x) (princ " ") (princ x))) 449 (mapcar (function (lambda (x) (princ " ") (princ x)))
363 safe-coding-systems) 450 safe-coding-systems)
364 (fill-region-as-paragraph pos (point))))) 451 (fill-region-as-paragraph pos (point)))))
365 452
366 ;; Read a coding system. 453 ;; Read a coding system.
367 (unwind-protect 454 (let* ((safe-names (mapcar (lambda (x) (list (symbol-name x)))
368 (let* ((safe-names (mapcar (lambda (x) (list (symbol-name x))) 455 safe-coding-systems))
369 safe-coding-systems)) 456 (name (completing-read
370 (name (completing-read 457 (format "Select coding system (default %s): "
371 (format "Select coding system (default %s): " 458 (car safe-coding-systems))
372 (car safe-coding-systems)) 459 safe-names nil t nil nil
373 safe-names nil t nil nil (car (car safe-names))))) 460 (car (car safe-names)))))
374 (setq last-coding-system-specified (intern name))) 461 (setq last-coding-system-specified (intern name))
375 (kill-buffer "*Warning*")))))) 462 (if (integerp (coding-system-eol-type default-coding-system))
463 (setq last-coding-system-specified
464 (coding-system-change-eol-conversion
465 last-coding-system-specified
466 (coding-system-eol-type default-coding-system))))
467 last-coding-system-specified))
468 (kill-buffer "*Warning*")
469 (while overlays
470 (delete-overlay (car overlays))
471 (setq overlays (cdr overlays)))))))))
376 472
377(setq select-safe-coding-system-function 'select-safe-coding-system) 473(setq select-safe-coding-system-function 'select-safe-coding-system)
378 474