diff options
| author | Stefan Monnier | 2015-06-16 14:28:38 -0400 |
|---|---|---|
| committer | Stefan Monnier | 2015-06-16 14:28:38 -0400 |
| commit | a1f543b4aa2309aecfd4ee2c6c220c71a97bbea8 (patch) | |
| tree | 6e1d03bc9a6969e6b41231ebd2c08c9b7ce0ad37 | |
| parent | 08f8fb327bf375d9e52752621f6108c8cdf94471 (diff) | |
| download | emacs-a1f543b4aa2309aecfd4ee2c6c220c71a97bbea8.tar.gz emacs-a1f543b4aa2309aecfd4ee2c6c220c71a97bbea8.zip | |
(filepos-to-bufferpos): Add missing cases. Make sure it terminates.
* lisp/international/mule-util.el (filepos-to-bufferpos--dos):
New auxiliary function, extracted from filepos-to-bufferpos.
Make sure it terminates.
(filepos-to-bufferpos): Use it to fix the latin-1-dos case.
Add support for the `exact' quality.
| -rw-r--r-- | lisp/international/mule-util.el | 64 |
1 files changed, 48 insertions, 16 deletions
diff --git a/lisp/international/mule-util.el b/lisp/international/mule-util.el index 2b4638bb2c8..2a53e40b4fd 100644 --- a/lisp/international/mule-util.el +++ b/lisp/international/mule-util.el | |||
| @@ -311,6 +311,25 @@ per-character basis, this may not be accurate." | |||
| 311 | charset-list) | 311 | charset-list) |
| 312 | nil))))))))) | 312 | nil))))))))) |
| 313 | 313 | ||
| 314 | (defun filepos-to-bufferpos--dos (byte f) | ||
| 315 | (let ((eol-offset 0) | ||
| 316 | ;; Make sure we terminate, even if BYTE falls right in the middle | ||
| 317 | ;; of a CRLF or some other weird corner case. | ||
| 318 | (omin 0) (omax most-positive-fixnum) | ||
| 319 | pos lines) | ||
| 320 | (while | ||
| 321 | (progn | ||
| 322 | (setq pos (funcall f (- byte eol-offset))) | ||
| 323 | ;; Adjust POS for DOS EOL format. | ||
| 324 | (setq lines (1- (line-number-at-pos pos))) | ||
| 325 | (and (not (= lines eol-offset)) (> omax omin))) | ||
| 326 | (if (> lines eol-offset) | ||
| 327 | (setq omax (min (1- omax) lines) | ||
| 328 | eol-offset omax) | ||
| 329 | (setq omin (max (1+ omin) lines) | ||
| 330 | eol-offset omin))) | ||
| 331 | pos)) | ||
| 332 | |||
| 314 | ;;;###autoload | 333 | ;;;###autoload |
| 315 | (defun filepos-to-bufferpos (byte &optional quality coding-system) | 334 | (defun filepos-to-bufferpos (byte &optional quality coding-system) |
| 316 | "Try to return the buffer position corresponding to a particular file position. | 335 | "Try to return the buffer position corresponding to a particular file position. |
| @@ -320,9 +339,9 @@ to `buffer-file-coding-system'. | |||
| 320 | QUALITY can be: | 339 | QUALITY can be: |
| 321 | `approximate', in which case we may cut some corners to avoid | 340 | `approximate', in which case we may cut some corners to avoid |
| 322 | excessive work. | 341 | excessive work. |
| 342 | `exact', in which case we may end up re-(en/de)coding a large | ||
| 343 | part of the file/buffer. | ||
| 323 | nil, in which case we may return nil rather than an approximation." | 344 | nil, in which case we may return nil rather than an approximation." |
| 324 | ;; `exact', in which case we may end up re-(en|de)coding a large | ||
| 325 | ;; part of the file. | ||
| 326 | (unless coding-system (setq coding-system buffer-file-coding-system)) | 345 | (unless coding-system (setq coding-system buffer-file-coding-system)) |
| 327 | (let ((eol (coding-system-eol-type coding-system)) | 346 | (let ((eol (coding-system-eol-type coding-system)) |
| 328 | (type (coding-system-type coding-system)) | 347 | (type (coding-system-type coding-system)) |
| @@ -331,23 +350,36 @@ QUALITY can be: | |||
| 331 | (`utf-8 | 350 | (`utf-8 |
| 332 | (when (coding-system-get coding-system :bom) | 351 | (when (coding-system-get coding-system :bom) |
| 333 | (setq byte (max 0 (- byte 3)))) | 352 | (setq byte (max 0 (- byte 3)))) |
| 334 | (let (pos lines (eol-offset 0)) | 353 | (if (= eol 1) |
| 335 | (while | 354 | (filepos-to-bufferpos--dos (+ pm byte) #'byte-to-position) |
| 336 | (progn | 355 | (byte-to-position (+ pm byte)))) |
| 337 | (setq pos (byte-to-position (+ pm byte (- eol-offset)))) | ||
| 338 | ;; Adjust POS for DOS EOL format. | ||
| 339 | (when (= eol 1) | ||
| 340 | (setq lines (1- (line-number-at-pos pos))) | ||
| 341 | (not (= lines eol-offset)))) | ||
| 342 | (setq eol-offset lines)) | ||
| 343 | pos)) | ||
| 344 | ;; FIXME: What if it's a 2-byte charset? Are there such beasts? | 356 | ;; FIXME: What if it's a 2-byte charset? Are there such beasts? |
| 345 | (`charset (+ pm byte)) | 357 | (`charset |
| 358 | (if (= eol 1) | ||
| 359 | (filepos-to-bufferpos--dos (+ pm byte) #'identity) | ||
| 360 | (+ pm byte))) | ||
| 346 | (_ | 361 | (_ |
| 347 | (pcase quality | 362 | (pcase quality |
| 348 | (`approximate (+ pm (byte-to-position byte))) | 363 | (`approximate (byte-to-position (+ pm byte))) |
| 349 | ;; (`exact ...) | 364 | (`exact |
| 350 | ))))) | 365 | ;; Rather than assume that the file exists and still holds the right |
| 366 | ;; data, we reconstruct it based on the buffer's content. | ||
| 367 | (let ((buf (current-buffer))) | ||
| 368 | (with-temp-buffer | ||
| 369 | (set-buffer-multibyte nil) | ||
| 370 | (let ((tmp-buf (current-buffer))) | ||
| 371 | (with-current-buffer buf | ||
| 372 | (save-restriction | ||
| 373 | (widen) | ||
| 374 | ;; Since encoding should always return more bytes than | ||
| 375 | ;; there were chars, encoding all chars up to (+ byte pm) | ||
| 376 | ;; guarantees the encoded result has at least `byte' bytes. | ||
| 377 | (encode-coding-region pm (min (point-max) (+ pm byte)) | ||
| 378 | coding-system tmp-buf))) | ||
| 379 | (+ pm (length | ||
| 380 | (decode-coding-region (point-min) | ||
| 381 | (min (point-max) (+ pm byte)) | ||
| 382 | coding-system t)))))))))))) | ||
| 351 | 383 | ||
| 352 | (provide 'mule-util) | 384 | (provide 'mule-util) |
| 353 | 385 | ||