aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lisp/ChangeLog74
-rw-r--r--lisp/autorevert.el2
-rw-r--r--lisp/calc/calc-units.el90
-rw-r--r--lisp/cedet/cedet.el2
-rw-r--r--lisp/cedet/inversion.el2
-rw-r--r--lisp/cedet/semantic.el2
-rw-r--r--lisp/emacs-lisp/cl.el1
-rw-r--r--lisp/gnus/ChangeLog9
-rw-r--r--lisp/gnus/gnus-int.el22
-rw-r--r--lisp/gnus/mm-decode.el28
-rw-r--r--lisp/gnus/mml.el4
-rw-r--r--lisp/imenu.el22
-rw-r--r--lisp/jit-lock.el84
-rw-r--r--lisp/mouse.el59
-rw-r--r--lisp/net/tramp-sh.el68
-rw-r--r--lisp/net/tramp.el18
-rw-r--r--lisp/progmodes/make-mode.el41
-rw-r--r--lisp/progmodes/python.el26
-rw-r--r--src/ChangeLog16
-rw-r--r--src/w32.c233
20 files changed, 500 insertions, 303 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index a0ec02fdb66..e222e17ed07 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -1,8 +1,70 @@
12013-01-30 Stefan Monnier <monnier@iro.umontreal.ca>
2
3 * progmodes/make-mode.el (makefile-backslash-region): Don't compute
4 column if we're just deleting the backslashes.
5 (makefile-fill-paragraph): Use eolp.
6
72013-01-30 Michael Albinus <michael.albinus@gmx.de>
8
9 * autorevert.el (auto-revert-use-notify): Fix docstring.
10
112013-01-30 Leo Liu <sdl.web@gmail.com>
12
13 * imenu.el (imenu--truncate-items): Fix subalist checking.
14 (Bug#13576)
15
162013-01-30 Glenn Morris <rgm@gnu.org>
17
18 * mouse.el (mouse-drag-line): Avoid pushing same event onto
19 unread-command-events twice in some cases. This tries to implement
20 the 2012-07-26 changes in a different way. (Bug#13560)
21
222013-01-30 Fabián Ezequiel Gallina <fgallina@cuca>
23
24 * progmodes/python.el
25 (python-pdbtrack-comint-output-filter-function): Enhancements on
26 stacktrace detection. (thanks @gnovak)
27
282013-01-30 Stefan Monnier <monnier@iro.umontreal.ca>
29
30 * jit-lock.el (jit-lock-stealth-chunk-start): Don't widen (bug#13542).
31 (jit-lock-mode, jit-lock-functions, jit-lock-context-unfontify-pos):
32 Use defvar-local.
33 (jit-lock-register): Use setq-local.
34
352013-01-30 Jay Belanger <jay.p.belanger@gmail.com>
36
37 * calc-units.el (math-default-units-table): Remove initial value.
38 (calc-convert-units): Treat expressions where all the units cancel as
39 if they didn't have units.
40
412013-01-30 Michael Albinus <michael.albinus@gmx.de>
42
43 * net/tramp.el (tramp-process-connection-type): Fix docstring.
44 (tramp-completion-reread-directory-timeout): Fix type.
45 (tramp-connection-min-time-diff): New defcustom.
46
47 * net/tramp-sh.el (tramp-maybe-open-connection): Use it.
48
492013-01-30 Glenn Morris <rgm@gnu.org>
50
51 * imenu.el (imenu-default-create-index-function):
52 Put back a version of the infinite loop test removed 2013-01-23.
53
542013-01-30 Fabián Ezequiel Gallina <fgallina@cuca>
55
56 * progmodes/python.el (python-shell-parse-command):
57 Find python-shell-interpreter with modified environment.
58
592013-01-30 Stefan Monnier <monnier@iro.umontreal.ca>
60
61 * emacs-lisp/cl.el (cl-set-getf): Add compatibility alias.
62
12013-01-29 Alan Mackenzie <acm@muc.de> 632013-01-29 Alan Mackenzie <acm@muc.de>
2 64
3 Amend to fontify /regexp/s in actions correctly. 65 Amend to fontify /regexp/s in actions correctly.
4 * cc-awk.el (c-awk-harmless-char-re, c-awk-harmless-string*-re): 66 * cc-awk.el (c-awk-harmless-char-re, c-awk-harmless-string*-re):
5 (c-awk-harmless-string*-here-re): braces, parens and semicolons 67 (c-awk-harmless-string*-here-re): Braces, parens and semicolons
6 are no longer included. 68 are no longer included.
7 (c-awk-harmless-line-char-re, c-awk-harmless-line-string*-re): 69 (c-awk-harmless-line-char-re, c-awk-harmless-line-string*-re):
8 What used to be these variables without "-line" in the name. 70 What used to be these variables without "-line" in the name.
@@ -19,13 +81,13 @@
19 81
202013-01-29 Michael Albinus <michael.albinus@gmx.de> 822013-01-29 Michael Albinus <michael.albinus@gmx.de>
21 83
22 * autorevert.el (auto-revert-use-notify): Use 84 * autorevert.el (auto-revert-use-notify):
23 `custom-initialize-default' for initialization. (Bug#13583) 85 Use `custom-initialize-default' for initialization. (Bug#13583)
24 86
25 * net/ange-ftp.el (ange-ftp-skip-msgs): Add another message. 87 * net/ange-ftp.el (ange-ftp-skip-msgs): Add another message.
26 88
27 * net/tramp-sh.el (tramp-sh-handle-start-file-process): Catch 89 * net/tramp-sh.el (tramp-sh-handle-start-file-process):
28 `suppress'. Otherwise, `tramp-run-real-handler' might be called 90 Catch `suppress'. Otherwise, `tramp-run-real-handler' might be called
29 in `tramp-file-name-handler'. 91 in `tramp-file-name-handler'.
30 (tramp-gw-tunnel-method, tramp-gw-socks-method): Declare for 92 (tramp-gw-tunnel-method, tramp-gw-socks-method): Declare for
31 compatibility. 93 compatibility.
@@ -21002,7 +21064,7 @@
21002 * nxml/rng-xsd.el (rng-xsd-check-pattern): Use case-sensitive 21064 * nxml/rng-xsd.el (rng-xsd-check-pattern): Use case-sensitive
21003 matching (Bug#8516). 21065 matching (Bug#8516).
21004 21066
210052011-01-22 Jari Aalto <jari.aalto@cante.net> 210672011-05-22 Jari Aalto <jari.aalto@cante.net>
21006 21068
21007 * vc/vc-dir.el (vc-default-dir-printer): Give edited tag a 21069 * vc/vc-dir.el (vc-default-dir-printer): Give edited tag a
21008 different face (Bug#8178). 21070 different face (Bug#8178).
diff --git a/lisp/autorevert.el b/lisp/autorevert.el
index e44d4a88eda..fe6cf216363 100644
--- a/lisp/autorevert.el
+++ b/lisp/autorevert.el
@@ -278,7 +278,7 @@ This variable becomes buffer local when set in any fashion.")
278 "If non-nil Auto Revert Mode uses file notification functions. 278 "If non-nil Auto Revert Mode uses file notification functions.
279This requires Emacs being compiled with file notification 279This requires Emacs being compiled with file notification
280support (see `auto-revert-notify-enabled'). You should set this 280support (see `auto-revert-notify-enabled'). You should set this
281variable through Custom only." 281variable through Custom."
282 :group 'auto-revert 282 :group 'auto-revert
283 :type 'boolean 283 :type 'boolean
284 :set (lambda (variable value) 284 :set (lambda (variable value)
diff --git a/lisp/calc/calc-units.el b/lisp/calc/calc-units.el
index a3d037ee042..72d51d9241c 100644
--- a/lisp/calc/calc-units.el
+++ b/lisp/calc/calc-units.el
@@ -404,7 +404,7 @@ If EXPR is nil, return nil."
404 (math-composition-to-string cexpr)))))) 404 (math-composition-to-string cexpr))))))
405 405
406(defvar math-default-units-table 406(defvar math-default-units-table
407 #s(hash-table test equal data (1 (1))) 407 (make-hash-table :test 'equal)
408 "A table storing previously converted units.") 408 "A table storing previously converted units.")
409 409
410(defun math-get-default-units (expr) 410(defun math-get-default-units (expr)
@@ -442,13 +442,19 @@ If COMP or STD is non-nil, put that in the units table instead."
442 (calc-slow-wrapper 442 (calc-slow-wrapper
443 (let ((expr (calc-top-n 1)) 443 (let ((expr (calc-top-n 1))
444 (uoldname nil) 444 (uoldname nil)
445 (unitscancel nil)
445 unew 446 unew
446 units 447 units
447 defunits) 448 defunits)
448 (unless (math-units-in-expr-p expr t) 449 (if (or (not (math-units-in-expr-p expr t))
450 (setq unitscancel (eq (math-get-standard-units expr) 1)))
449 (let ((uold (or old-units 451 (let ((uold (or old-units
450 (progn 452 (progn
451 (setq uoldname (read-string "Old units: ")) 453 (setq uoldname
454 (if unitscancel
455 (read-string
456 "(The expression is unitless when simplified) Old Units: ")
457 (read-string "Old units: ")))
452 (if (equal uoldname "") 458 (if (equal uoldname "")
453 (progn 459 (progn
454 (setq uoldname "1") 460 (setq uoldname "1")
@@ -460,47 +466,43 @@ If COMP or STD is non-nil, put that in the units table instead."
460 (error "Bad format in units expression: %s" (nth 1 uold))) 466 (error "Bad format in units expression: %s" (nth 1 uold)))
461 (setq expr (math-mul expr uold)))) 467 (setq expr (math-mul expr uold))))
462 (setq defunits (math-get-default-units expr)) 468 (setq defunits (math-get-default-units expr))
463 (if (equal defunits "1") 469 (unless new-units
464 (progn 470 (setq new-units
465 (calc-enter-result 1 "cvun" (math-simplify-units expr)) 471 (read-string (concat
466 (message "All units in expression cancel")) 472 (if uoldname
467 (unless new-units 473 (concat "Old units: "
468 (setq new-units 474 uoldname
469 (read-string (concat 475 ", new units")
470 (if uoldname 476 "New units")
471 (concat "Old units: " 477 (if defunits
472 uoldname 478 (concat
473 ", new units") 479 " (default "
474 "New units") 480 defunits
475 (if defunits 481 "): ")
476 (concat 482 ": "))))
477 " (default " 483 (if (and
478 defunits 484 (string= new-units "")
479 "): ") 485 defunits)
480 ": ")))) 486 (setq new-units defunits)))
481 (if (and 487 (when (string-match "\\` */" new-units)
482 (string= new-units "") 488 (setq new-units (concat "1" new-units)))
483 defunits) 489 (setq units (math-read-expr new-units))
484 (setq new-units defunits))) 490 (when (eq (car-safe units) 'error)
485 (when (string-match "\\` */" new-units) 491 (error "Bad format in units expression: %s" (nth 2 units)))
486 (setq new-units (concat "1" new-units))) 492 (if calc-ensure-consistent-units
487 (setq units (math-read-expr new-units)) 493 (math-check-unit-consistency expr units))
488 (when (eq (car-safe units) 'error) 494 (let ((unew (math-units-in-expr-p units t))
489 (error "Bad format in units expression: %s" (nth 2 units))) 495 (std (and (eq (car-safe units) 'var)
490 (if calc-ensure-consistent-units 496 (assq (nth 1 units) math-standard-units-systems)))
491 (math-check-unit-consistency expr units)) 497 (comp (eq (car-safe units) '+)))
492 (let ((unew (math-units-in-expr-p units t)) 498 (unless (or unew std)
493 (std (and (eq (car-safe units) 'var) 499 (error "No units specified"))
494 (assq (nth 1 units) math-standard-units-systems))) 500 (let ((res
495 (comp (eq (car-safe units) '+))) 501 (if std
496 (unless (or unew std) 502 (math-simplify-units (math-to-standard-units expr (nth 1 std)))
497 (error "No units specified")) 503 (math-convert-units expr units (and uoldname (not (equal uoldname "1")))))))
498 (let ((res 504 (math-put-default-units res (if comp units))
499 (if std 505 (calc-enter-result 1 "cvun" res))))))
500 (math-simplify-units (math-to-standard-units expr (nth 1 std)))
501 (math-convert-units expr units (and uoldname (not (equal uoldname "1")))))))
502 (math-put-default-units res (if comp units))
503 (calc-enter-result 1 "cvun" res)))))))
504 506
505(defun calc-autorange-units (arg) 507(defun calc-autorange-units (arg)
506 (interactive "P") 508 (interactive "P")
diff --git a/lisp/cedet/cedet.el b/lisp/cedet/cedet.el
index ccc75a40f4b..d876b65303c 100644
--- a/lisp/cedet/cedet.el
+++ b/lisp/cedet/cedet.el
@@ -4,7 +4,7 @@
4 4
5;; Author: David Ponce <david@dponce.com> 5;; Author: David Ponce <david@dponce.com>
6;; Maintainer: Eric M. Ludlam <zappo@gnu.org> 6;; Maintainer: Eric M. Ludlam <zappo@gnu.org>
7;; Version: 1.0pre7 7;; Version: 1.1
8;; Keywords: OO, lisp 8;; Keywords: OO, lisp
9 9
10;; This file is part of GNU Emacs. 10;; This file is part of GNU Emacs.
diff --git a/lisp/cedet/inversion.el b/lisp/cedet/inversion.el
index bebb7b58e40..533d959f6b7 100644
--- a/lisp/cedet/inversion.el
+++ b/lisp/cedet/inversion.el
@@ -3,7 +3,7 @@
3;;; Copyright (C) 2002-2003, 2005-2013 Free Software Foundation, Inc. 3;;; Copyright (C) 2002-2003, 2005-2013 Free Software Foundation, Inc.
4 4
5;; Author: Eric M. Ludlam <zappo@gnu.org> 5;; Author: Eric M. Ludlam <zappo@gnu.org>
6;; Version: 0.2 6;; Version: 1.3
7;; Keywords: OO, lisp 7;; Keywords: OO, lisp
8 8
9;; This file is part of GNU Emacs. 9;; This file is part of GNU Emacs.
diff --git a/lisp/cedet/semantic.el b/lisp/cedet/semantic.el
index 73d0860c49f..decd3b15812 100644
--- a/lisp/cedet/semantic.el
+++ b/lisp/cedet/semantic.el
@@ -4,7 +4,7 @@
4 4
5;; Author: Eric M. Ludlam <zappo@gnu.org> 5;; Author: Eric M. Ludlam <zappo@gnu.org>
6;; Keywords: syntax tools 6;; Keywords: syntax tools
7;; Version: 2.0 7;; Version: 2.1beta
8 8
9;; This file is part of GNU Emacs. 9;; This file is part of GNU Emacs.
10 10
diff --git a/lisp/emacs-lisp/cl.el b/lisp/emacs-lisp/cl.el
index 19cd2cb9c74..9728dd71751 100644
--- a/lisp/emacs-lisp/cl.el
+++ b/lisp/emacs-lisp/cl.el
@@ -689,6 +689,7 @@ You can replace this macro with `gv-letplace'."
689 'cl--map-keymap-recursively "24.3") 689 'cl--map-keymap-recursively "24.3")
690(define-obsolete-function-alias 'cl-map-intervals 'cl--map-intervals "24.3") 690(define-obsolete-function-alias 'cl-map-intervals 'cl--map-intervals "24.3")
691(define-obsolete-function-alias 'cl-map-extents 'cl--map-overlays "24.3") 691(define-obsolete-function-alias 'cl-map-extents 'cl--map-overlays "24.3")
692(define-obsolete-function-alias 'cl-set-getf 'cl--set-getf "24.3")
692 693
693(defun cl-maclisp-member (item list) 694(defun cl-maclisp-member (item list)
694 (declare (obsolete member "24.3")) 695 (declare (obsolete member "24.3"))
diff --git a/lisp/gnus/ChangeLog b/lisp/gnus/ChangeLog
index 745e0ede5a8..7cb278f2a6f 100644
--- a/lisp/gnus/ChangeLog
+++ b/lisp/gnus/ChangeLog
@@ -1,3 +1,12 @@
12013-01-30 Christopher Schmidt <christopher@ch.ristopher.com>
2
3 * gnus-int.el (gnus-backend-trace-elapsed): New variable.
4 (gnus-backend-trace): Honour gnus-backend-trace.
5
6 * mml.el (mml-insert-part): Insert closing tag.
7
8 * mm-decode.el (mm-save-part): Handle invalid read-file-name results.
9
12013-01-21 Lars Magne Ingebrigtsen <larsi@gnus.org> 102013-01-21 Lars Magne Ingebrigtsen <larsi@gnus.org>
2 11
3 * gnus-sum.el (gnus-summary-read-group-1): Protect against not being 12 * gnus-sum.el (gnus-summary-read-group-1): Protect against not being
diff --git a/lisp/gnus/gnus-int.el b/lisp/gnus/gnus-int.el
index 81e0252cf93..2378b598eeb 100644
--- a/lisp/gnus/gnus-int.el
+++ b/lisp/gnus/gnus-int.el
@@ -248,18 +248,20 @@ If it is down, start it up (again)."
248 'denied)) 248 'denied))
249 249
250(defvar gnus-backend-trace nil) 250(defvar gnus-backend-trace nil)
251(defvar gnus-backend-trace-elapsed nil)
251 252
252(defun gnus-backend-trace (type form) 253(defun gnus-backend-trace (type form)
253 (with-current-buffer (get-buffer-create "*gnus trace*") 254 (when gnus-backend-trace
254 (buffer-disable-undo) 255 (with-current-buffer (get-buffer-create "*gnus trace*")
255 (goto-char (point-max)) 256 (buffer-disable-undo)
256 (insert (format-time-string "%H:%M:%S") 257 (goto-char (point-max))
257 (format " %.2fs %s %S\n" 258 (insert (format-time-string "%H:%M:%S")
258 (if (numberp gnus-backend-trace) 259 (format " %.2fs %s %S\n"
259 (- (float-time) gnus-backend-trace) 260 (if (numberp gnus-backend-trace-elapsed)
260 0) 261 (- (float-time) gnus-backend-trace-elapsed)
261 type form)) 262 0)
262 (setq gnus-backend-trace (float-time)))) 263 type form))
264 (setq gnus-backend-trace-elapsed (float-time)))))
263 265
264(defun gnus-open-server (gnus-command-method) 266(defun gnus-open-server (gnus-command-method)
265 "Open a connection to GNUS-COMMAND-METHOD." 267 "Open a connection to GNUS-COMMAND-METHOD."
diff --git a/lisp/gnus/mm-decode.el b/lisp/gnus/mm-decode.el
index b5e4d3e38e8..812ee7396dd 100644
--- a/lisp/gnus/mm-decode.el
+++ b/lisp/gnus/mm-decode.el
@@ -1298,14 +1298,26 @@ PROMPT overrides the default one used to ask user for a file name."
1298 (when filename 1298 (when filename
1299 (setq filename (gnus-map-function mm-file-name-rewrite-functions 1299 (setq filename (gnus-map-function mm-file-name-rewrite-functions
1300 (file-name-nondirectory filename)))) 1300 (file-name-nondirectory filename))))
1301 (setq file 1301 (while
1302 (read-file-name 1302 (progn
1303 (or prompt 1303 (setq file
1304 (format "Save MIME part to (default %s): " 1304 (read-file-name
1305 (or filename ""))) 1305 (or prompt
1306 (or mm-default-directory default-directory) 1306 (format "Save MIME part to (default %s): "
1307 (expand-file-name (or filename "") 1307 (or filename "")))
1308 (or mm-default-directory default-directory)))) 1308 (or mm-default-directory default-directory)
1309 (expand-file-name (or filename "")
1310 (or mm-default-directory default-directory))))
1311 (cond ((or (not file) (equal file ""))
1312 (message "Please enter a file name")
1313 t)
1314 ((and (file-directory-p file)
1315 (not filename))
1316 (message "Please enter a non-directory file name")
1317 t)
1318 (t nil)))
1319 (sit-for 2)
1320 (discard-input))
1309 (if (file-directory-p file) 1321 (if (file-directory-p file)
1310 (setq file (expand-file-name filename file)) 1322 (setq file (expand-file-name filename file))
1311 (setq file (expand-file-name 1323 (setq file (expand-file-name
diff --git a/lisp/gnus/mml.el b/lisp/gnus/mml.el
index 453086f4c20..3c9344a62c3 100644
--- a/lisp/gnus/mml.el
+++ b/lisp/gnus/mml.el
@@ -1440,7 +1440,9 @@ TYPE is the MIME type to use."
1440 ;; when you send the message. 1440 ;; when you send the message.
1441 (or (eq mail-user-agent 'message-user-agent) 1441 (or (eq mail-user-agent 'message-user-agent)
1442 (setq mail-encode-mml t)) 1442 (setq mail-encode-mml t))
1443 (mml-insert-tag 'part 'type type 'disposition "inline")) 1443 (mml-insert-tag 'part 'type type 'disposition "inline")
1444 (save-excursion
1445 (mml-insert-tag '/part)))
1444 1446
1445(declare-function message-subscribed-p "message" ()) 1447(declare-function message-subscribed-p "message" ())
1446(declare-function message-make-mail-followup-to "message" 1448(declare-function message-make-mail-followup-to "message"
diff --git a/lisp/imenu.el b/lisp/imenu.el
index ba0275099a1..80fc441c896 100644
--- a/lisp/imenu.el
+++ b/lisp/imenu.el
@@ -555,16 +555,14 @@ NOT share structure with ALIST."
555 555
556(defun imenu--truncate-items (menulist) 556(defun imenu--truncate-items (menulist)
557 "Truncate all strings in MENULIST to `imenu-max-item-length'." 557 "Truncate all strings in MENULIST to `imenu-max-item-length'."
558 (mapcar (lambda (item) 558 (mapc (lambda (item)
559 (cond 559 ;; truncate if necessary
560 ((consp (cdr item)) 560 (when (and (numberp imenu-max-item-length)
561 (imenu--truncate-items (cdr item))) 561 (> (length (car item)) imenu-max-item-length))
562 ;; truncate if necessary 562 (setcar item (substring (car item) 0 imenu-max-item-length)))
563 ((and (numberp imenu-max-item-length) 563 (when (imenu--subalist-p item)
564 (> (length (car item)) imenu-max-item-length)) 564 (imenu--truncate-items (cdr item))))
565 (setcar item (substring (car item) 0 imenu-max-item-length))))) 565 menulist))
566 menulist))
567
568 566
569(defun imenu--make-index-alist (&optional noerror) 567(defun imenu--make-index-alist (&optional noerror)
570 "Create an index alist for the definitions in the current buffer. 568 "Create an index alist for the definitions in the current buffer.
@@ -678,11 +676,13 @@ The alternate method, which is the one most often used, is to call
678 ;; in these major modes. But save that change for later. 676 ;; in these major modes. But save that change for later.
679 (cond ((and imenu-prev-index-position-function 677 (cond ((and imenu-prev-index-position-function
680 imenu-extract-index-name-function) 678 imenu-extract-index-name-function)
681 (let ((index-alist '()) (pos (point)) 679 (let ((index-alist '()) (pos -1)
682 name) 680 name)
683 (goto-char (point-max)) 681 (goto-char (point-max))
684 ;; Search for the function 682 ;; Search for the function
685 (while (funcall imenu-prev-index-position-function) 683 (while (funcall imenu-prev-index-position-function)
684 (when (= pos (point))
685 (error "Infinite loop at %s:%d: imenu-prev-index-position-function does not move point" (buffer-name) pos))
686 (setq pos (point)) 686 (setq pos (point))
687 (save-excursion 687 (save-excursion
688 (setq name (funcall imenu-extract-index-name-function))) 688 (setq name (funcall imenu-extract-index-name-function)))
diff --git a/lisp/jit-lock.el b/lisp/jit-lock.el
index 668f1ec963a..d879735c344 100644
--- a/lisp/jit-lock.el
+++ b/lisp/jit-lock.el
@@ -132,20 +132,16 @@ If nil, fontification is not deferred."
132 132
133;;; Variables that are not customizable. 133;;; Variables that are not customizable.
134 134
135(defvar jit-lock-mode nil 135(defvar-local jit-lock-mode nil
136 "Non-nil means Just-in-time Lock mode is active.") 136 "Non-nil means Just-in-time Lock mode is active.")
137(make-variable-buffer-local 'jit-lock-mode)
138 137
139(defvar jit-lock-functions nil 138(defvar-local jit-lock-functions nil
140 "Functions to do the actual fontification. 139 "Functions to do the actual fontification.
141They are called with two arguments: the START and END of the region to fontify.") 140They are called with two arguments: the START and END of the region to fontify.")
142(make-variable-buffer-local 'jit-lock-functions)
143 141
144(defvar jit-lock-context-unfontify-pos nil 142(defvar-local jit-lock-context-unfontify-pos nil
145 "Consider text after this position as contextually unfontified. 143 "Consider text after this position as contextually unfontified.
146If nil, contextual fontification is disabled.") 144If nil, contextual fontification is disabled.")
147(make-variable-buffer-local 'jit-lock-context-unfontify-pos)
148
149 145
150(defvar jit-lock-stealth-timer nil 146(defvar jit-lock-stealth-timer nil
151 "Timer for stealth fontification in Just-in-time Lock mode.") 147 "Timer for stealth fontification in Just-in-time Lock mode.")
@@ -305,7 +301,7 @@ that needs to be (re)fontified.
305If non-nil, CONTEXTUAL means that a contextual fontification would be useful." 301If non-nil, CONTEXTUAL means that a contextual fontification would be useful."
306 (add-hook 'jit-lock-functions fun nil t) 302 (add-hook 'jit-lock-functions fun nil t)
307 (when (and contextual jit-lock-contextually) 303 (when (and contextual jit-lock-contextually)
308 (set (make-local-variable 'jit-lock-contextually) t)) 304 (setq-local jit-lock-contextually t))
309 (jit-lock-mode t)) 305 (jit-lock-mode t))
310 306
311(defun jit-lock-unregister (fun) 307(defun jit-lock-unregister (fun)
@@ -439,41 +435,39 @@ Defaults to the whole buffer. END can be out of bounds."
439Value is nil if there is nothing more to fontify." 435Value is nil if there is nothing more to fontify."
440 (if (zerop (buffer-size)) 436 (if (zerop (buffer-size))
441 nil 437 nil
442 (save-restriction 438 (let* ((next (text-property-not-all around (point-max) 'fontified t))
443 (widen) 439 (prev (previous-single-property-change around 'fontified))
444 (let* ((next (text-property-not-all around (point-max) 'fontified t)) 440 (prop (get-text-property (max (point-min) (1- around))
445 (prev (previous-single-property-change around 'fontified)) 441 'fontified))
446 (prop (get-text-property (max (point-min) (1- around)) 442 (start (cond
447 'fontified)) 443 ((null prev)
448 (start (cond 444 ;; There is no property change between AROUND
449 ((null prev) 445 ;; and the start of the buffer. If PROP is
450 ;; There is no property change between AROUND 446 ;; non-nil, everything in front of AROUND is
451 ;; and the start of the buffer. If PROP is 447 ;; fontified, otherwise nothing is fontified.
452 ;; non-nil, everything in front of AROUND is 448 (if (eq prop t)
453 ;; fontified, otherwise nothing is fontified. 449 nil
454 (if (eq prop t) 450 (max (point-min)
455 nil 451 (- around (/ jit-lock-chunk-size 2)))))
456 (max (point-min) 452 ((eq prop t)
457 (- around (/ jit-lock-chunk-size 2))))) 453 ;; PREV is the start of a region of fontified
458 ((eq prop t) 454 ;; text containing AROUND. Start fontifying a
459 ;; PREV is the start of a region of fontified 455 ;; chunk size before the end of the unfontified
460 ;; text containing AROUND. Start fontifying a 456 ;; region in front of that.
461 ;; chunk size before the end of the unfontified 457 (max (or (previous-single-property-change prev 'fontified)
462 ;; region in front of that. 458 (point-min))
463 (max (or (previous-single-property-change prev 'fontified) 459 (- prev jit-lock-chunk-size)))
464 (point-min)) 460 (t
465 (- prev jit-lock-chunk-size))) 461 ;; PREV is the start of a region of unfontified
466 (t 462 ;; text containing AROUND. Start at PREV or
467 ;; PREV is the start of a region of unfontified 463 ;; chunk size in front of AROUND, whichever is
468 ;; text containing AROUND. Start at PREV or 464 ;; nearer.
469 ;; chunk size in front of AROUND, whichever is 465 (max prev (- around jit-lock-chunk-size)))))
470 ;; nearer. 466 (result (cond ((null start) next)
471 (max prev (- around jit-lock-chunk-size))))) 467 ((null next) start)
472 (result (cond ((null start) next) 468 ((< (- around start) (- next around)) start)
473 ((null next) start) 469 (t next))))
474 ((< (- around start) (- next around)) start) 470 result)))
475 (t next))))
476 result))))
477 471
478(defun jit-lock-stealth-fontify (&optional repeat) 472(defun jit-lock-stealth-fontify (&optional repeat)
479 "Fontify buffers stealthily. 473 "Fontify buffers stealthily.
@@ -564,7 +558,9 @@ non-nil in a repeated invocation of this function."
564 (when jit-lock-context-unfontify-pos 558 (when jit-lock-context-unfontify-pos
565 ;; (message "Jit-Context %s" (buffer-name)) 559 ;; (message "Jit-Context %s" (buffer-name))
566 (save-restriction 560 (save-restriction
567 (widen) 561 ;; Don't be blindsided by narrowing that starts in the middle
562 ;; of a jit-lock-defer-multiline.
563 (widen)
568 (when (and (>= jit-lock-context-unfontify-pos (point-min)) 564 (when (and (>= jit-lock-context-unfontify-pos (point-min))
569 (< jit-lock-context-unfontify-pos (point-max))) 565 (< jit-lock-context-unfontify-pos (point-max)))
570 ;; If we're in text that matches a complex multi-line 566 ;; If we're in text that matches a complex multi-line
diff --git a/lisp/mouse.el b/lisp/mouse.el
index 538e6a500bb..9c7bf6f9c36 100644
--- a/lisp/mouse.el
+++ b/lisp/mouse.el
@@ -425,7 +425,7 @@ must be one of the symbols `header', `mode', or `vertical'."
425 (frame-parameters frame))) 425 (frame-parameters frame)))
426 'right))) 426 'right)))
427 (draggable t) 427 (draggable t)
428 finished event position growth dragged) 428 event position growth dragged)
429 (cond 429 (cond
430 ((eq line 'header) 430 ((eq line 'header)
431 ;; Check whether header-line can be dragged at all. 431 ;; Check whether header-line can be dragged at all.
@@ -456,39 +456,33 @@ must be one of the symbols `header', `mode', or `vertical'."
456 456
457 ;; Start tracking. 457 ;; Start tracking.
458 (track-mouse 458 (track-mouse
459 ;; Loop reading events and sampling the position of the mouse. 459 ;; Loop reading events and sampling the position of the mouse,
460 (while (not finished) 460 ;; until there is a non-mouse-movement event. Also,
461 (setq event (read-event)) 461 ;; scroll-bar-movement events are the same as mouse movement for
462 ;; our purposes. (Why? -- cyd)
463 ;; If you change this, check that all of the following still work:
464 ;; Resizing windows by dragging mode-lines and header lines,
465 ;; and vertical lines (in windows without scroll bars).
466 ;; Doing this should not select another window, even if
467 ;; mouse-autoselect-window is non-nil.
468 ;; Mouse-1 clicks in Info header lines should advance position
469 ;; by one node at a time if mouse-1-click-follows-link is non-nil,
470 ;; otherwise they should just select the window.
471 (while (progn
472 (setq event (read-event))
473 (memq (car-safe event)
474 '(mouse-movement scroll-bar-movement
475 switch-frame select-window)))
462 (setq position (mouse-position)) 476 (setq position (mouse-position))
463 ;; Do nothing if 477 ;; Do nothing if
464 ;; - there is a switch-frame event. 478 ;; - there is a switch-frame event.
465 ;; - the mouse isn't in the frame that we started in 479 ;; - the mouse isn't in the frame that we started in
466 ;; - the mouse isn't in any Emacs frame 480 ;; - the mouse isn't in any Emacs frame
467 ;; Drag if
468 ;; - there is a mouse-movement event
469 ;; - there is a scroll-bar-movement event (Why? -- cyd)
470 ;; (same as mouse movement for our purposes)
471 ;; Quit if
472 ;; - there is a keyboard event or some other unknown event.
473 (cond 481 (cond
474 ((not (consp event))
475 (setq finished t))
476 ((memq (car event) '(switch-frame select-window)) 482 ((memq (car event) '(switch-frame select-window))
477 nil) 483 nil)
478 ((not (memq (car event) '(mouse-movement scroll-bar-movement))) 484 ((not (and (eq (car position) frame)
479 (when (consp event) 485 (cadr position)))
480 ;; Do not unread a drag-mouse-1 event to avoid selecting
481 ;; some other window. For vertical line dragging do not
482 ;; unread mouse-1 events either (but only if we dragged at
483 ;; least once to allow mouse-1 clicks get through).
484 (unless (and dragged
485 (if (eq line 'vertical)
486 (memq (car event) '(drag-mouse-1 mouse-1))
487 (eq (car event) 'drag-mouse-1)))
488 (push event unread-command-events)))
489 (setq finished t))
490 ((not (and (eq (car position) frame)
491 (cadr position)))
492 nil) 486 nil)
493 ((eq line 'vertical) 487 ((eq line 'vertical)
494 ;; Drag vertical divider. 488 ;; Drag vertical divider.
@@ -512,12 +506,13 @@ must be one of the symbols `header', `mode', or `vertical'."
512 growth 506 growth
513 (- growth))))))) 507 (- growth)))))))
514 ;; Process the terminating event. 508 ;; Process the terminating event.
515 (when (and (mouse-event-p event) on-link (not dragged) 509 (unless dragged
516 (mouse--remap-link-click-p start-event event)) 510 (when (and (mouse-event-p event) on-link
517 ;; If mouse-2 has never been done by the user, it doesn't have 511 (mouse--remap-link-click-p start-event event))
518 ;; the necessary property to be interpreted correctly. 512 ;; If mouse-2 has never been done by the user, it doesn't have
519 (put 'mouse-2 'event-kind 'mouse-click) 513 ;; the necessary property to be interpreted correctly.
520 (setcar event 'mouse-2) 514 (put 'mouse-2 'event-kind 'mouse-click)
515 (setcar event 'mouse-2))
521 (push event unread-command-events)))) 516 (push event unread-command-events))))
522 517
523(defun mouse-drag-mode-line (start-event) 518(defun mouse-drag-mode-line (start-event)
diff --git a/lisp/net/tramp-sh.el b/lisp/net/tramp-sh.el
index 65a514c8e36..a06d64d400a 100644
--- a/lisp/net/tramp-sh.el
+++ b/lisp/net/tramp-sh.el
@@ -988,8 +988,7 @@ This is used to map a mode number to a permission string.")
988 (set-file-selinux-context . tramp-sh-handle-set-file-selinux-context) 988 (set-file-selinux-context . tramp-sh-handle-set-file-selinux-context)
989 (file-acl . tramp-sh-handle-file-acl) 989 (file-acl . tramp-sh-handle-file-acl)
990 (set-file-acl . tramp-sh-handle-set-file-acl) 990 (set-file-acl . tramp-sh-handle-set-file-acl)
991 (vc-registered . tramp-sh-handle-vc-registered) 991 (vc-registered . tramp-sh-handle-vc-registered))
992 (inotify-add-watch . tramp-sh-handle-inotify-add-watch))
993 "Alist of handler functions. 992 "Alist of handler functions.
994Operations not mentioned here will be handled by the normal Emacs functions.") 993Operations not mentioned here will be handled by the normal Emacs functions.")
995 994
@@ -3488,64 +3487,6 @@ Fall back to normal file name handler if no Tramp handler exists."
3488 ;; Default file name handlers, we don't care. 3487 ;; Default file name handlers, we don't care.
3489 (t (tramp-run-real-handler operation args))))))) 3488 (t (tramp-run-real-handler operation args)))))))
3490 3489
3491(defun tramp-sh-handle-inotify-add-watch (file-name aspect callback)
3492 "Like `inotify-add-watch' for Tramp files."
3493 (setq file-name (expand-file-name file-name))
3494 (unless (consp aspect) (setq aspect (cons aspect nil)))
3495 (with-parsed-tramp-file-name file-name nil
3496 (let* ((default-directory (file-name-directory file-name))
3497 (command (tramp-get-remote-inotifywait v))
3498 (aspect (mapconcat
3499 (lambda (x)
3500 (replace-regexp-in-string "-" "_" (symbol-name x)))
3501 aspect ","))
3502 (p (and command
3503 (start-file-process
3504 "inotifywait" nil command "-mq" "-e" aspect localname))))
3505 (when (processp p)
3506 (tramp-compat-set-process-query-on-exit-flag p nil)
3507 (set-process-filter p 'tramp-sh-inotify-process-filter)
3508 (tramp-set-connection-property p "inotify-callback" callback)
3509 ;; Return the file-name vector as watch-descriptor.
3510 (tramp-set-connection-property p "inotify-watch-descriptor" v)))))
3511
3512(defun tramp-sh-inotify-process-filter (proc string)
3513 "Read output from \"inotifywait\" and add corresponding inotify events."
3514 (tramp-message
3515 (tramp-get-connection-property proc "vector" nil) 6
3516 (format "%s\n%s" proc string))
3517 (dolist (line (split-string string "[\n\r]+" 'omit-nulls))
3518 ;; Check, whether there is a problem.
3519 (unless
3520 (string-match
3521 "^[^[:blank:]]+[[:blank:]]+\\([^[:blank:]]+\\)+\\([[:blank:]]+\\([^[:blank:]]+\\)\\)?[[:blank:]]*$" line)
3522 (tramp-error proc 'filewatch-error "%s" line))
3523
3524 (let* ((object
3525 (list
3526 (tramp-get-connection-property
3527 proc "inotify-watch-descriptor" nil)
3528 ;; Aspect symbols. We filter out MOVE and CLOSE, which
3529 ;; are convenience macros. See INOTIFY(7).
3530 (mapcar
3531 (lambda (x)
3532 (intern-soft (replace-regexp-in-string "_" "-" (downcase x))))
3533 (delete "MOVE" (delete "CLOSE"
3534 (split-string (match-string 1 line) "," 'omit-nulls))))
3535 ;; We cannot gather any cookie value. So we return 0 as
3536 ;; "don't know".
3537 0 (match-string 3 line)))
3538 (callback
3539 (tramp-get-connection-property proc "inotify-callback" nil))
3540 (event `(file-inotify ,object ,callback)))
3541
3542 ;; Usually, we would add an Emacs event now. Unfortunately,
3543 ;; `unread-command-events' does not accept several events at
3544 ;; once. Therefore, we apply the callback directly.
3545 ;(setq unread-command-events (cons event unread-command-events)))))
3546 (let ((last-input-event event))
3547 (funcall callback object)))))
3548
3549;;; Internal Functions: 3490;;; Internal Functions:
3550 3491
3551(defun tramp-maybe-send-script (vec script name) 3492(defun tramp-maybe-send-script (vec script name)
@@ -4416,7 +4357,7 @@ connection if a previous connection has died for some reason."
4416 (car tramp-current-connection))) 4357 (car tramp-current-connection)))
4417 (> (tramp-time-diff 4358 (> (tramp-time-diff
4418 (current-time) (cdr tramp-current-connection)) 4359 (current-time) (cdr tramp-current-connection))
4419 5)) 4360 (or tramp-connection-min-time-diff 0)))
4420 (throw 'suppress 'suppress)) 4361 (throw 'suppress 'suppress))
4421 4362
4422 ;; If too much time has passed since last command was sent, look 4363 ;; If too much time has passed since last command was sent, look
@@ -5105,11 +5046,6 @@ This is used internally by `tramp-file-mode-from-int'."
5105 (tramp-message vec 5 "Finding a suitable `trash' command") 5046 (tramp-message vec 5 "Finding a suitable `trash' command")
5106 (tramp-find-executable vec "trash" (tramp-get-remote-path vec)))) 5047 (tramp-find-executable vec "trash" (tramp-get-remote-path vec))))
5107 5048
5108(defun tramp-get-remote-inotifywait (vec)
5109 (with-tramp-connection-property vec "inotifywait"
5110 (tramp-message vec 5 "Finding a suitable `inotifywait' command")
5111 (tramp-find-executable vec "inotifywait" (tramp-get-remote-path vec) t t)))
5112
5113(defun tramp-get-remote-id (vec) 5049(defun tramp-get-remote-id (vec)
5114 (with-tramp-connection-property vec "id" 5050 (with-tramp-connection-property vec "id"
5115 (tramp-message vec 5 "Finding POSIX `id' command") 5051 (tramp-message vec 5 "Finding POSIX `id' command")
diff --git a/lisp/net/tramp.el b/lisp/net/tramp.el
index 045304cbc4f..ea3b5d56a38 100644
--- a/lisp/net/tramp.el
+++ b/lisp/net/tramp.el
@@ -1018,11 +1018,25 @@ this variable to be set as well."
1018;; for an override of the system default. 1018;; for an override of the system default.
1019(defcustom tramp-process-connection-type t 1019(defcustom tramp-process-connection-type t
1020 "Overrides `process-connection-type' for connections from Tramp. 1020 "Overrides `process-connection-type' for connections from Tramp.
1021Tramp binds process-connection-type to the value given here before 1021Tramp binds `process-connection-type' to the value given here before
1022opening a connection to a remote host." 1022opening a connection to a remote host."
1023 :group 'tramp 1023 :group 'tramp
1024 :type '(choice (const nil) (const t) (const pty))) 1024 :type '(choice (const nil) (const t) (const pty)))
1025 1025
1026(defcustom tramp-connection-min-time-diff 5
1027 "Defines seconds between two consecutive connection attempts.
1028This is necessary as self defense mechanism, in order to avoid
1029yo-yo connection attempts when the remote host is unavailable.
1030
1031A value of 0 or `nil' suppresses this check. This might be
1032necessary, when several out-of-order copy operations are
1033performed, or when several asynchronous processes will be started
1034in a short time frame. In those cases it is recommended to
1035let-bind this variable."
1036 :group 'tramp
1037 :version "24.4"
1038 :type '(choice (const nil) integer))
1039
1026(defcustom tramp-completion-reread-directory-timeout 10 1040(defcustom tramp-completion-reread-directory-timeout 10
1027 "Defines seconds since last remote command before rereading a directory. 1041 "Defines seconds since last remote command before rereading a directory.
1028A remote directory might have changed its contents. In order to 1042A remote directory might have changed its contents. In order to
@@ -1033,7 +1047,7 @@ have been gone since last remote command execution. A value of `t'
1033would require an immediate reread during filename completion, `nil' 1047would require an immediate reread during filename completion, `nil'
1034means to use always cached values for the directory contents." 1048means to use always cached values for the directory contents."
1035 :group 'tramp 1049 :group 'tramp
1036 :type '(choice (const nil) integer)) 1050 :type '(choice (const nil) (const t) integer))
1037 1051
1038;;; Internal Variables: 1052;;; Internal Variables:
1039 1053
diff --git a/lisp/progmodes/make-mode.el b/lisp/progmodes/make-mode.el
index 8ab4c6f95b6..be718135f99 100644
--- a/lisp/progmodes/make-mode.el
+++ b/lisp/progmodes/make-mode.el
@@ -1213,26 +1213,23 @@ definition and conveniently use this command."
1213 (save-excursion 1213 (save-excursion
1214 (goto-char from) 1214 (goto-char from)
1215 (let ((column makefile-backslash-column) 1215 (let ((column makefile-backslash-column)
1216 (endmark (make-marker))) 1216 (endmark (copy-marker to)))
1217 (move-marker endmark to)
1218 ;; Compute the smallest column number past the ends of all the lines. 1217 ;; Compute the smallest column number past the ends of all the lines.
1219 (if makefile-backslash-align 1218 (when (and makefile-backslash-align (not delete-flag))
1220 (progn 1219 (while (< (point) to)
1221 (if (not delete-flag) 1220 (end-of-line)
1222 (while (< (point) to) 1221 (if (= (preceding-char) ?\\)
1223 (end-of-line) 1222 (progn (forward-char -1)
1224 (if (= (preceding-char) ?\\) 1223 (skip-chars-backward " \t")))
1225 (progn (forward-char -1) 1224 (setq column (max column (1+ (current-column))))
1226 (skip-chars-backward " \t"))) 1225 (forward-line 1))
1227 (setq column (max column (1+ (current-column)))) 1226 ;; Adjust upward to a tab column, if that doesn't push
1228 (forward-line 1))) 1227 ;; past the margin.
1229 ;; Adjust upward to a tab column, if that doesn't push 1228 (if (> (% column tab-width) 0)
1230 ;; past the margin. 1229 (let ((adjusted (* (/ (+ column tab-width -1) tab-width)
1231 (if (> (% column tab-width) 0) 1230 tab-width)))
1232 (let ((adjusted (* (/ (+ column tab-width -1) tab-width) 1231 (if (< adjusted (window-width))
1233 tab-width))) 1232 (setq column adjusted)))))
1234 (if (< adjusted (window-width))
1235 (setq column adjusted))))))
1236 ;; Don't modify blank lines at start of region. 1233 ;; Don't modify blank lines at start of region.
1237 (goto-char from) 1234 (goto-char from)
1238 (while (and (< (point) endmark) (eolp)) 1235 (while (and (< (point) endmark) (eolp))
@@ -1296,9 +1293,9 @@ Fill comments, backslashed lines, and variable definitions specially."
1296 (while (= (preceding-char) ?\\) 1293 (while (= (preceding-char) ?\\)
1297 (end-of-line 0)) 1294 (end-of-line 0))
1298 ;; Maybe we hit bobp, in which case we are not at EOL. 1295 ;; Maybe we hit bobp, in which case we are not at EOL.
1299 (if (eq (point) (line-end-position)) 1296 (if (eolp)
1300 (forward-char)) 1297 (1+ (point))
1301 (point))) 1298 (point))))
1302 (end 1299 (end
1303 (save-excursion 1300 (save-excursion
1304 (while (= (preceding-char) ?\\) 1301 (while (= (preceding-char) ?\\)
diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el
index 2f353feb323..2cb108cc316 100644
--- a/lisp/progmodes/python.el
+++ b/lisp/progmodes/python.el
@@ -1664,7 +1664,11 @@ uniqueness for different types of configurations."
1664 1664
1665(defun python-shell-parse-command () 1665(defun python-shell-parse-command ()
1666 "Calculate the string used to execute the inferior Python process." 1666 "Calculate the string used to execute the inferior Python process."
1667 (format "%s %s" python-shell-interpreter python-shell-interpreter-args)) 1667 (let ((process-environment (python-shell-calculate-process-environment))
1668 (exec-path (python-shell-calculate-exec-path)))
1669 (format "%s %s"
1670 (executable-find python-shell-interpreter)
1671 python-shell-interpreter-args)))
1668 1672
1669(defun python-shell-calculate-process-environment () 1673(defun python-shell-calculate-process-environment ()
1670 "Calculate process environment given `python-shell-virtualenv-path'." 1674 "Calculate process environment given `python-shell-virtualenv-path'."
@@ -2323,15 +2327,17 @@ Argument OUTPUT is a string with the output from the comint process."
2323 (file-name 2327 (file-name
2324 (with-temp-buffer 2328 (with-temp-buffer
2325 (insert full-output) 2329 (insert full-output)
2326 (goto-char (point-min)) 2330 ;; When the debugger encounters a pdb.set_trace()
2327 ;; OK, this sucked but now it became a cool hack. The 2331 ;; command, it prints a single stack frame. Sometimes
2328 ;; stacktrace information normally is on the first line 2332 ;; it prints a bit of extra information about the
2329 ;; but in some cases (like when doing a step-in) it is 2333 ;; arguments of the present function. When ipdb
2330 ;; on the second. 2334 ;; encounters an exception, it prints the _entire_ stack
2331 (when (or (looking-at python-pdbtrack-stacktrace-info-regexp) 2335 ;; trace. To handle all of these cases, we want to find
2332 (and 2336 ;; the _last_ stack frame printed in the most recent
2333 (forward-line) 2337 ;; batch of output, then jump to the corrsponding
2334 (looking-at python-pdbtrack-stacktrace-info-regexp))) 2338 ;; file/line number.
2339 (goto-char (point-max))
2340 (when (re-search-backward python-pdbtrack-stacktrace-info-regexp nil t)
2335 (setq line-number (string-to-number 2341 (setq line-number (string-to-number
2336 (match-string-no-properties 2))) 2342 (match-string-no-properties 2)))
2337 (match-string-no-properties 1))))) 2343 (match-string-no-properties 1)))))
diff --git a/src/ChangeLog b/src/ChangeLog
index abbe4ed6dd4..bb03ba10bb0 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,19 @@
12013-01-30 Eli Zaretskii <eliz@gnu.org>
2
3 * w32.c (sys_open): Zero out the flags for the new file descriptor.
4 (sys_close): Zero out the flags for the file descriptor before
5 closing it. (Bug#13546)
6
7 * w32.c (parse_root, get_volume_info, readdir, read_unc_volume)
8 (logon_network_drive, stat_worker, symlink, chase_symlinks): Use
9 CharNextExA and CharPrevExA to iterate over file names encoded in
10 DBCS. (Bug#13553)
11
12 * w32.c (w32_get_long_filename, init_environment, readlink):
13 Support file names encoded in DBCS codepages.
14 (readlink): Use the current file-name-coding-system, not the ANSI
15 codepage, to decode and handle targets of symlinks.
16
12013-01-28 Eli Zaretskii <eliz@gnu.org> 172013-01-28 Eli Zaretskii <eliz@gnu.org>
2 18
3 * w32.c (opendir): Now accepts a 'const char *'. 19 * w32.c (opendir): Now accepts a 'const char *'.
diff --git a/src/w32.c b/src/w32.c
index 6bcc8e19278..d0af53889e7 100644
--- a/src/w32.c
+++ b/src/w32.c
@@ -37,7 +37,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
37/* must include CRT headers *before* config.h */ 37/* must include CRT headers *before* config.h */
38 38
39#include <config.h> 39#include <config.h>
40#include <mbstring.h> /* for _mbspbrk and _mbslwr */ 40#include <mbstring.h> /* for _mbspbrk, _mbslwr, _mbsrchr, ... */
41 41
42#undef access 42#undef access
43#undef chdir 43#undef chdir
@@ -1730,12 +1730,17 @@ parse_root (char * name, char ** pPath)
1730 else if (IS_DIRECTORY_SEP (name[0]) && IS_DIRECTORY_SEP (name[1])) 1730 else if (IS_DIRECTORY_SEP (name[0]) && IS_DIRECTORY_SEP (name[1]))
1731 { 1731 {
1732 int slashes = 2; 1732 int slashes = 2;
1733 int dbcs_p = max_filename_mbslen () > 1;
1734
1733 name += 2; 1735 name += 2;
1734 do 1736 do
1735 { 1737 {
1736 if (IS_DIRECTORY_SEP (*name) && --slashes == 0) 1738 if (IS_DIRECTORY_SEP (*name) && --slashes == 0)
1737 break; 1739 break;
1738 name++; 1740 if (dbcs_p)
1741 name = CharNextExA (file_name_codepage, name, 0);
1742 else
1743 name++;
1739 } 1744 }
1740 while ( *name ); 1745 while ( *name );
1741 if (IS_DIRECTORY_SEP (name[0])) 1746 if (IS_DIRECTORY_SEP (name[0]))
@@ -1800,7 +1805,7 @@ w32_get_long_filename (char * name, char * buf, int size)
1800 while (p != NULL && *p) 1805 while (p != NULL && *p)
1801 { 1806 {
1802 q = p; 1807 q = p;
1803 p = strchr (q, '\\'); 1808 p = _mbschr (q, '\\');
1804 if (p) *p = '\0'; 1809 if (p) *p = '\0';
1805 len = get_long_basename (full, o, size); 1810 len = get_long_basename (full, o, size);
1806 if (len > 0) 1811 if (len > 0)
@@ -2072,16 +2077,16 @@ init_environment (char ** argv)
2072 2077
2073 if (!GetModuleFileName (NULL, modname, MAX_PATH)) 2078 if (!GetModuleFileName (NULL, modname, MAX_PATH))
2074 emacs_abort (); 2079 emacs_abort ();
2075 if ((p = strrchr (modname, '\\')) == NULL) 2080 if ((p = _mbsrchr (modname, '\\')) == NULL)
2076 emacs_abort (); 2081 emacs_abort ();
2077 *p = 0; 2082 *p = 0;
2078 2083
2079 if ((p = strrchr (modname, '\\')) && xstrcasecmp (p, "\\bin") == 0) 2084 if ((p = _mbsrchr (modname, '\\')) && xstrcasecmp (p, "\\bin") == 0)
2080 { 2085 {
2081 char buf[SET_ENV_BUF_SIZE]; 2086 char buf[SET_ENV_BUF_SIZE];
2082 2087
2083 *p = 0; 2088 *p = 0;
2084 for (p = modname; *p; p++) 2089 for (p = modname; *p; p = CharNext (p))
2085 if (*p == '\\') *p = '/'; 2090 if (*p == '\\') *p = '/';
2086 2091
2087 _snprintf (buf, sizeof (buf)-1, "emacs_dir=%s", modname); 2092 _snprintf (buf, sizeof (buf)-1, "emacs_dir=%s", modname);
@@ -2096,17 +2101,17 @@ init_environment (char ** argv)
2096 || xstrcasecmp (p, "\\AMD64") == 0)) 2101 || xstrcasecmp (p, "\\AMD64") == 0))
2097 { 2102 {
2098 *p = 0; 2103 *p = 0;
2099 p = strrchr (modname, '\\'); 2104 p = _mbsrchr (modname, '\\');
2100 if (p != NULL) 2105 if (p != NULL)
2101 { 2106 {
2102 *p = 0; 2107 *p = 0;
2103 p = strrchr (modname, '\\'); 2108 p = _mbsrchr (modname, '\\');
2104 if (p && xstrcasecmp (p, "\\src") == 0) 2109 if (p && xstrcasecmp (p, "\\src") == 0)
2105 { 2110 {
2106 char buf[SET_ENV_BUF_SIZE]; 2111 char buf[SET_ENV_BUF_SIZE];
2107 2112
2108 *p = 0; 2113 *p = 0;
2109 for (p = modname; *p; p++) 2114 for (p = modname; *p; p = CharNext (p))
2110 if (*p == '\\') *p = '/'; 2115 if (*p == '\\') *p = '/';
2111 2116
2112 _snprintf (buf, sizeof (buf)-1, "emacs_dir=%s", modname); 2117 _snprintf (buf, sizeof (buf)-1, "emacs_dir=%s", modname);
@@ -2641,12 +2646,23 @@ get_volume_info (const char * name, const char ** pPath)
2641 { 2646 {
2642 char *str = temp; 2647 char *str = temp;
2643 int slashes = 4; 2648 int slashes = 4;
2649 int dbcs_p = max_filename_mbslen () > 1;
2650
2644 rootname = temp; 2651 rootname = temp;
2645 do 2652 do
2646 { 2653 {
2647 if (IS_DIRECTORY_SEP (*name) && --slashes == 0) 2654 if (IS_DIRECTORY_SEP (*name) && --slashes == 0)
2648 break; 2655 break;
2649 *str++ = *name++; 2656 if (!dbcs_p)
2657 *str++ = *name++;
2658 else
2659 {
2660 const char *p = name;
2661
2662 name = CharNextExA (file_name_codepage, name, 0);
2663 memcpy (str, p, name - p);
2664 str += name - p;
2665 }
2650 } 2666 }
2651 while ( *name ); 2667 while ( *name );
2652 2668
@@ -2882,11 +2898,23 @@ readdir (DIR *dirp)
2882 { 2898 {
2883 char filename[MAXNAMLEN + 3]; 2899 char filename[MAXNAMLEN + 3];
2884 int ln; 2900 int ln;
2901 int dbcs_p = max_filename_mbslen () > 1;
2885 2902
2886 strcpy (filename, dir_pathname); 2903 strcpy (filename, dir_pathname);
2887 ln = strlen (filename) - 1; 2904 ln = strlen (filename) - 1;
2888 if (!IS_DIRECTORY_SEP (filename[ln])) 2905 if (!dbcs_p)
2889 strcat (filename, "\\"); 2906 {
2907 if (!IS_DIRECTORY_SEP (filename[ln]))
2908 strcat (filename, "\\");
2909 }
2910 else
2911 {
2912 char *end = filename + ln + 1;
2913 char *last_char = CharPrevExA (file_name_codepage, filename, end, 0);
2914
2915 if (!IS_DIRECTORY_SEP (*last_char))
2916 strcat (filename, "\\");
2917 }
2890 strcat (filename, "*"); 2918 strcat (filename, "*");
2891 2919
2892 /* Note: No need to resolve symlinks in FILENAME, because 2920 /* Note: No need to resolve symlinks in FILENAME, because
@@ -2991,6 +3019,7 @@ read_unc_volume (HANDLE henum, char *readbuf, int size)
2991 DWORD bufsize = 512; 3019 DWORD bufsize = 512;
2992 char *buffer; 3020 char *buffer;
2993 char *ptr; 3021 char *ptr;
3022 int dbcs_p = max_filename_mbslen () > 1;
2994 3023
2995 count = 1; 3024 count = 1;
2996 buffer = alloca (bufsize); 3025 buffer = alloca (bufsize);
@@ -3001,7 +3030,13 @@ read_unc_volume (HANDLE henum, char *readbuf, int size)
3001 /* WNetEnumResource returns \\resource\share...skip forward to "share". */ 3030 /* WNetEnumResource returns \\resource\share...skip forward to "share". */
3002 ptr = ((LPNETRESOURCE) buffer)->lpRemoteName; 3031 ptr = ((LPNETRESOURCE) buffer)->lpRemoteName;
3003 ptr += 2; 3032 ptr += 2;
3004 while (*ptr && !IS_DIRECTORY_SEP (*ptr)) ptr++; 3033 if (!dbcs_p)
3034 while (*ptr && !IS_DIRECTORY_SEP (*ptr)) ptr++;
3035 else
3036 {
3037 while (*ptr && !IS_DIRECTORY_SEP (*ptr))
3038 ptr = CharNextExA (file_name_codepage, ptr, 0);
3039 }
3005 ptr++; 3040 ptr++;
3006 3041
3007 strncpy (readbuf, ptr, size); 3042 strncpy (readbuf, ptr, size);
@@ -3038,9 +3073,11 @@ logon_network_drive (const char *path)
3038{ 3073{
3039 NETRESOURCE resource; 3074 NETRESOURCE resource;
3040 char share[MAX_PATH]; 3075 char share[MAX_PATH];
3041 int i, n_slashes; 3076 int n_slashes;
3042 char drive[4]; 3077 char drive[4];
3043 UINT drvtype; 3078 UINT drvtype;
3079 char *p;
3080 int dbcs_p;
3044 3081
3045 if (IS_DIRECTORY_SEP (path[0]) && IS_DIRECTORY_SEP (path[1])) 3082 if (IS_DIRECTORY_SEP (path[0]) && IS_DIRECTORY_SEP (path[1]))
3046 drvtype = DRIVE_REMOTE; 3083 drvtype = DRIVE_REMOTE;
@@ -3062,13 +3099,18 @@ logon_network_drive (const char *path)
3062 n_slashes = 2; 3099 n_slashes = 2;
3063 strncpy (share, path, MAX_PATH); 3100 strncpy (share, path, MAX_PATH);
3064 /* Truncate to just server and share name. */ 3101 /* Truncate to just server and share name. */
3065 for (i = 2; i < MAX_PATH; i++) 3102 dbcs_p = max_filename_mbslen () > 1;
3103 for (p = share + 2; *p && p < share + MAX_PATH; )
3066 { 3104 {
3067 if (IS_DIRECTORY_SEP (share[i]) && ++n_slashes > 3) 3105 if (IS_DIRECTORY_SEP (*p) && ++n_slashes > 3)
3068 { 3106 {
3069 share[i] = '\0'; 3107 *p = '\0';
3070 break; 3108 break;
3071 } 3109 }
3110 if (dbcs_p)
3111 p = CharNextExA (file_name_codepage, p, 0);
3112 else
3113 p++;
3072 } 3114 }
3073 3115
3074 resource.dwType = RESOURCETYPE_DISK; 3116 resource.dwType = RESOURCETYPE_DISK;
@@ -3365,9 +3407,12 @@ sys_open (const char * path, int oflag, int mode)
3365 and system files. Force all file handles to be 3407 and system files. Force all file handles to be
3366 non-inheritable. */ 3408 non-inheritable. */
3367 int res = _open (mpath, (oflag & ~_O_CREAT) | _O_NOINHERIT, mode); 3409 int res = _open (mpath, (oflag & ~_O_CREAT) | _O_NOINHERIT, mode);
3368 if (res >= 0) 3410 if (res < 0)
3369 return res; 3411 res = _open (mpath, oflag | _O_NOINHERIT, mode);
3370 return _open (mpath, oflag | _O_NOINHERIT, mode); 3412 if (res >= 0 && res < MAXDESC)
3413 fd_info[res].flags = 0;
3414
3415 return res;
3371} 3416}
3372 3417
3373int 3418int
@@ -3843,6 +3888,7 @@ stat_worker (const char * path, struct stat * buf, int follow_symlinks)
3843 DWORD access_rights = 0; 3888 DWORD access_rights = 0;
3844 DWORD fattrs = 0, serialnum = 0, fs_high = 0, fs_low = 0, nlinks = 1; 3889 DWORD fattrs = 0, serialnum = 0, fs_high = 0, fs_low = 0, nlinks = 1;
3845 FILETIME ctime, atime, wtime; 3890 FILETIME ctime, atime, wtime;
3891 int dbcs_p;
3846 3892
3847 if (path == NULL || buf == NULL) 3893 if (path == NULL || buf == NULL)
3848 { 3894 {
@@ -4040,6 +4086,7 @@ stat_worker (const char * path, struct stat * buf, int follow_symlinks)
4040 did not ask for extra precision, resolving symlinks will fly 4086 did not ask for extra precision, resolving symlinks will fly
4041 in the face of that request, since the user then wants the 4087 in the face of that request, since the user then wants the
4042 lightweight version of the code. */ 4088 lightweight version of the code. */
4089 dbcs_p = max_filename_mbslen () > 1;
4043 rootdir = (path >= save_name + len - 1 4090 rootdir = (path >= save_name + len - 1
4044 && (IS_DIRECTORY_SEP (*path) || *path == 0)); 4091 && (IS_DIRECTORY_SEP (*path) || *path == 0));
4045 4092
@@ -4067,8 +4114,19 @@ stat_worker (const char * path, struct stat * buf, int follow_symlinks)
4067 } 4114 }
4068 else if (rootdir) 4115 else if (rootdir)
4069 { 4116 {
4070 if (!IS_DIRECTORY_SEP (name[len-1])) 4117 if (!dbcs_p)
4071 strcat (name, "\\"); 4118 {
4119 if (!IS_DIRECTORY_SEP (name[len-1]))
4120 strcat (name, "\\");
4121 }
4122 else
4123 {
4124 char *end = name + len;
4125 char *n = CharPrevExA (file_name_codepage, name, end, 0);
4126
4127 if (!IS_DIRECTORY_SEP (*n))
4128 strcat (name, "\\");
4129 }
4072 if (GetDriveType (name) < 2) 4130 if (GetDriveType (name) < 2)
4073 { 4131 {
4074 errno = ENOENT; 4132 errno = ENOENT;
@@ -4080,15 +4138,37 @@ stat_worker (const char * path, struct stat * buf, int follow_symlinks)
4080 } 4138 }
4081 else 4139 else
4082 { 4140 {
4083 if (IS_DIRECTORY_SEP (name[len-1])) 4141 if (!dbcs_p)
4084 name[len - 1] = 0; 4142 {
4143 if (IS_DIRECTORY_SEP (name[len-1]))
4144 name[len - 1] = 0;
4145 }
4146 else
4147 {
4148 char *end = name + len;
4149 char *n = CharPrevExA (file_name_codepage, name, end, 0);
4150
4151 if (IS_DIRECTORY_SEP (*n))
4152 *n = 0;
4153 }
4085 4154
4086 /* (This is hacky, but helps when doing file completions on 4155 /* (This is hacky, but helps when doing file completions on
4087 network drives.) Optimize by using information available from 4156 network drives.) Optimize by using information available from
4088 active readdir if possible. */ 4157 active readdir if possible. */
4089 len = strlen (dir_pathname); 4158 len = strlen (dir_pathname);
4090 if (IS_DIRECTORY_SEP (dir_pathname[len-1])) 4159 if (!dbcs_p)
4091 len--; 4160 {
4161 if (IS_DIRECTORY_SEP (dir_pathname[len-1]))
4162 len--;
4163 }
4164 else
4165 {
4166 char *end = dir_pathname + len;
4167 char *n = CharPrevExA (file_name_codepage, dir_pathname, end, 0);
4168
4169 if (IS_DIRECTORY_SEP (*n))
4170 len--;
4171 }
4092 if (dir_find_handle != INVALID_HANDLE_VALUE 4172 if (dir_find_handle != INVALID_HANDLE_VALUE
4093 && !(is_a_symlink && follow_symlinks) 4173 && !(is_a_symlink && follow_symlinks)
4094 && strnicmp (save_name, dir_pathname, len) == 0 4174 && strnicmp (save_name, dir_pathname, len) == 0
@@ -4359,6 +4439,7 @@ symlink (char const *filename, char const *linkname)
4359 char linkfn[MAX_PATH], *tgtfn; 4439 char linkfn[MAX_PATH], *tgtfn;
4360 DWORD flags = 0; 4440 DWORD flags = 0;
4361 int dir_access, filename_ends_in_slash; 4441 int dir_access, filename_ends_in_slash;
4442 int dbcs_p;
4362 4443
4363 /* Diagnostics follows Posix as much as possible. */ 4444 /* Diagnostics follows Posix as much as possible. */
4364 if (filename == NULL || linkname == NULL) 4445 if (filename == NULL || linkname == NULL)
@@ -4384,6 +4465,8 @@ symlink (char const *filename, char const *linkname)
4384 return -1; 4465 return -1;
4385 } 4466 }
4386 4467
4468 dbcs_p = max_filename_mbslen () > 1;
4469
4387 /* Note: since empty FILENAME was already rejected, we can safely 4470 /* Note: since empty FILENAME was already rejected, we can safely
4388 refer to FILENAME[1]. */ 4471 refer to FILENAME[1]. */
4389 if (!(IS_DIRECTORY_SEP (filename[0]) || IS_DEVICE_SEP (filename[1]))) 4472 if (!(IS_DIRECTORY_SEP (filename[0]) || IS_DEVICE_SEP (filename[1])))
@@ -4398,8 +4481,21 @@ symlink (char const *filename, char const *linkname)
4398 char tem[MAX_PATH]; 4481 char tem[MAX_PATH];
4399 char *p = linkfn + strlen (linkfn); 4482 char *p = linkfn + strlen (linkfn);
4400 4483
4401 while (p > linkfn && !IS_ANY_SEP (p[-1])) 4484 if (!dbcs_p)
4402 p--; 4485 {
4486 while (p > linkfn && !IS_ANY_SEP (p[-1]))
4487 p--;
4488 }
4489 else
4490 {
4491 char *p1 = CharPrevExA (file_name_codepage, linkfn, p, 0);
4492
4493 while (p > linkfn && !IS_ANY_SEP (*p1))
4494 {
4495 p = p1;
4496 p1 = CharPrevExA (file_name_codepage, linkfn, p1, 0);
4497 }
4498 }
4403 if (p > linkfn) 4499 if (p > linkfn)
4404 strncpy (tem, linkfn, p - linkfn); 4500 strncpy (tem, linkfn, p - linkfn);
4405 tem[p - linkfn] = '\0'; 4501 tem[p - linkfn] = '\0';
@@ -4414,7 +4510,15 @@ symlink (char const *filename, char const *linkname)
4414 exist, but ends in a slash, we create a symlink to directory. If 4510 exist, but ends in a slash, we create a symlink to directory. If
4415 FILENAME exists and is a directory, we always create a symlink to 4511 FILENAME exists and is a directory, we always create a symlink to
4416 directory. */ 4512 directory. */
4417 filename_ends_in_slash = IS_DIRECTORY_SEP (filename[strlen (filename) - 1]); 4513 if (!dbcs_p)
4514 filename_ends_in_slash = IS_DIRECTORY_SEP (filename[strlen (filename) - 1]);
4515 else
4516 {
4517 const char *end = filename + strlen (filename);
4518 const char *n = CharPrevExA (file_name_codepage, filename, end, 0);
4519
4520 filename_ends_in_slash = IS_DIRECTORY_SEP (*n);
4521 }
4418 if (dir_access == 0 || filename_ends_in_slash) 4522 if (dir_access == 0 || filename_ends_in_slash)
4419 flags = SYMBOLIC_LINK_FLAG_DIRECTORY; 4523 flags = SYMBOLIC_LINK_FLAG_DIRECTORY;
4420 4524
@@ -4604,6 +4708,8 @@ readlink (const char *name, char *buf, size_t buf_size)
4604 WCHAR *lwname_src = 4708 WCHAR *lwname_src =
4605 reparse_data->SymbolicLinkReparseBuffer.PathBuffer 4709 reparse_data->SymbolicLinkReparseBuffer.PathBuffer
4606 + reparse_data->SymbolicLinkReparseBuffer.PrintNameOffset/sizeof(WCHAR); 4710 + reparse_data->SymbolicLinkReparseBuffer.PrintNameOffset/sizeof(WCHAR);
4711 /* This updates file_name_codepage which we need below. */
4712 int dbcs_p = max_filename_mbslen () > 1;
4607 4713
4608 /* According to MSDN, PrintNameLength does not include the 4714 /* According to MSDN, PrintNameLength does not include the
4609 terminating null character. */ 4715 terminating null character. */
@@ -4611,9 +4717,7 @@ readlink (const char *name, char *buf, size_t buf_size)
4611 memcpy (lwname, lwname_src, lwname_len); 4717 memcpy (lwname, lwname_src, lwname_len);
4612 lwname[lwname_len/sizeof(WCHAR)] = 0; /* null-terminate */ 4718 lwname[lwname_len/sizeof(WCHAR)] = 0; /* null-terminate */
4613 4719
4614 /* FIXME: Should we use the current file-name coding system 4720 lname_len = WideCharToMultiByte (file_name_codepage, 0, lwname, -1,
4615 instead of the fixed value of the ANSI codepage? */
4616 lname_len = WideCharToMultiByte (w32_ansi_code_page, 0, lwname, -1,
4617 lname, MAX_PATH, NULL, NULL); 4721 lname, MAX_PATH, NULL, NULL);
4618 if (!lname_len) 4722 if (!lname_len)
4619 { 4723 {
@@ -4639,18 +4743,33 @@ readlink (const char *name, char *buf, size_t buf_size)
4639 else 4743 else
4640 { 4744 {
4641 size_t size_to_copy = buf_size; 4745 size_t size_to_copy = buf_size;
4642 BYTE *p = lname; 4746 BYTE *p = lname, *p2;
4643 BYTE *pend = p + lname_len; 4747 BYTE *pend = p + lname_len;
4644 4748
4645 /* Normalize like dostounix_filename does, but we don't 4749 /* Normalize like dostounix_filename does, but we don't
4646 want to assume that lname is null-terminated. */ 4750 want to assume that lname is null-terminated. */
4647 if (*p && p[1] == ':' && *p >= 'A' && *p <= 'Z') 4751 if (dbcs_p)
4648 *p += 'a' - 'A'; 4752 p2 = CharNextExA (file_name_codepage, p, 0);
4753 else
4754 p2 = p + 1;
4755 if (*p && *p2 == ':' && *p >= 'A' && *p <= 'Z')
4756 {
4757 *p += 'a' - 'A';
4758 p += 2;
4759 }
4649 while (p <= pend) 4760 while (p <= pend)
4650 { 4761 {
4651 if (*p == '\\') 4762 if (*p == '\\')
4652 *p = '/'; 4763 *p = '/';
4653 ++p; 4764 if (dbcs_p)
4765 {
4766 p = CharNextExA (file_name_codepage, p, 0);
4767 /* CharNextExA doesn't advance at null character. */
4768 if (!*p)
4769 break;
4770 }
4771 else
4772 ++p;
4654 } 4773 }
4655 /* Testing for null-terminated LNAME is paranoia: 4774 /* Testing for null-terminated LNAME is paranoia:
4656 WideCharToMultiByte should always return a 4775 WideCharToMultiByte should always return a
@@ -4724,6 +4843,7 @@ chase_symlinks (const char *file)
4724 char link[MAX_PATH]; 4843 char link[MAX_PATH];
4725 ssize_t res, link_len; 4844 ssize_t res, link_len;
4726 int loop_count = 0; 4845 int loop_count = 0;
4846 int dbcs_p;
4727 4847
4728 if (is_windows_9x () == TRUE || !is_symlink (file)) 4848 if (is_windows_9x () == TRUE || !is_symlink (file))
4729 return (char *)file; 4849 return (char *)file;
@@ -4731,13 +4851,27 @@ chase_symlinks (const char *file)
4731 if ((link_len = GetFullPathName (file, MAX_PATH, link, NULL)) == 0) 4851 if ((link_len = GetFullPathName (file, MAX_PATH, link, NULL)) == 0)
4732 return (char *)file; 4852 return (char *)file;
4733 4853
4854 dbcs_p = max_filename_mbslen () > 1;
4734 target[0] = '\0'; 4855 target[0] = '\0';
4735 do { 4856 do {
4736 4857
4737 /* Remove trailing slashes, as we want to resolve the last 4858 /* Remove trailing slashes, as we want to resolve the last
4738 non-trivial part of the link name. */ 4859 non-trivial part of the link name. */
4739 while (link_len > 3 && IS_DIRECTORY_SEP (link[link_len-1])) 4860 if (!dbcs_p)
4740 link[link_len--] = '\0'; 4861 {
4862 while (link_len > 3 && IS_DIRECTORY_SEP (link[link_len-1]))
4863 link[link_len--] = '\0';
4864 }
4865 else if (link_len > 3)
4866 {
4867 char *n = CharPrevExA (file_name_codepage, link, link + link_len, 0);
4868
4869 while (n >= link + 2 && IS_DIRECTORY_SEP (*n))
4870 {
4871 n[1] = '\0';
4872 n = CharPrevExA (file_name_codepage, link, n, 0);
4873 }
4874 }
4741 4875
4742 res = readlink (link, target, MAX_PATH); 4876 res = readlink (link, target, MAX_PATH);
4743 if (res > 0) 4877 if (res > 0)
@@ -4750,8 +4884,21 @@ chase_symlinks (const char *file)
4750 the symlink, then copy the result back to target. */ 4884 the symlink, then copy the result back to target. */
4751 char *p = link + link_len; 4885 char *p = link + link_len;
4752 4886
4753 while (p > link && !IS_ANY_SEP (p[-1])) 4887 if (!dbcs_p)
4754 p--; 4888 {
4889 while (p > link && !IS_ANY_SEP (p[-1]))
4890 p--;
4891 }
4892 else
4893 {
4894 char *p1 = CharPrevExA (file_name_codepage, link, p, 0);
4895
4896 while (p > link && !IS_ANY_SEP (*p1))
4897 {
4898 p = p1;
4899 p1 = CharPrevExA (file_name_codepage, link, p1, 0);
4900 }
4901 }
4755 strcpy (p, target); 4902 strcpy (p, target);
4756 strcpy (target, link); 4903 strcpy (target, link);
4757 } 4904 }
@@ -6543,15 +6690,15 @@ sys_close (int fd)
6543 } 6690 }
6544 } 6691 }
6545 6692
6693 if (fd >= 0 && fd < MAXDESC)
6694 fd_info[fd].flags = 0;
6695
6546 /* Note that sockets do not need special treatment here (at least on 6696 /* Note that sockets do not need special treatment here (at least on
6547 NT and Windows 95 using the standard tcp/ip stacks) - it appears that 6697 NT and Windows 95 using the standard tcp/ip stacks) - it appears that
6548 closesocket is equivalent to CloseHandle, which is to be expected 6698 closesocket is equivalent to CloseHandle, which is to be expected
6549 because socket handles are fully fledged kernel handles. */ 6699 because socket handles are fully fledged kernel handles. */
6550 rc = _close (fd); 6700 rc = _close (fd);
6551 6701
6552 if (rc == 0 && fd < MAXDESC)
6553 fd_info[fd].flags = 0;
6554
6555 return rc; 6702 return rc;
6556} 6703}
6557 6704