aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Monnier2015-06-16 14:28:38 -0400
committerStefan Monnier2015-06-16 14:28:38 -0400
commita1f543b4aa2309aecfd4ee2c6c220c71a97bbea8 (patch)
tree6e1d03bc9a6969e6b41231ebd2c08c9b7ce0ad37
parent08f8fb327bf375d9e52752621f6108c8cdf94471 (diff)
downloademacs-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.el64
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'.
320QUALITY can be: 339QUALITY 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