diff --git a/lisp/ChangeLog b/lisp/ChangeLog index a0ec02fdb66..e222e17ed07 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog @@ -1,8 +1,70 @@ +2013-01-30 Stefan Monnier + + * progmodes/make-mode.el (makefile-backslash-region): Don't compute + column if we're just deleting the backslashes. + (makefile-fill-paragraph): Use eolp. + +2013-01-30 Michael Albinus + + * autorevert.el (auto-revert-use-notify): Fix docstring. + +2013-01-30 Leo Liu + + * imenu.el (imenu--truncate-items): Fix subalist checking. + (Bug#13576) + +2013-01-30 Glenn Morris + + * mouse.el (mouse-drag-line): Avoid pushing same event onto + unread-command-events twice in some cases. This tries to implement + the 2012-07-26 changes in a different way. (Bug#13560) + +2013-01-30 Fabián Ezequiel Gallina + + * progmodes/python.el + (python-pdbtrack-comint-output-filter-function): Enhancements on + stacktrace detection. (thanks @gnovak) + +2013-01-30 Stefan Monnier + + * jit-lock.el (jit-lock-stealth-chunk-start): Don't widen (bug#13542). + (jit-lock-mode, jit-lock-functions, jit-lock-context-unfontify-pos): + Use defvar-local. + (jit-lock-register): Use setq-local. + +2013-01-30 Jay Belanger + + * calc-units.el (math-default-units-table): Remove initial value. + (calc-convert-units): Treat expressions where all the units cancel as + if they didn't have units. + +2013-01-30 Michael Albinus + + * net/tramp.el (tramp-process-connection-type): Fix docstring. + (tramp-completion-reread-directory-timeout): Fix type. + (tramp-connection-min-time-diff): New defcustom. + + * net/tramp-sh.el (tramp-maybe-open-connection): Use it. + +2013-01-30 Glenn Morris + + * imenu.el (imenu-default-create-index-function): + Put back a version of the infinite loop test removed 2013-01-23. + +2013-01-30 Fabián Ezequiel Gallina + + * progmodes/python.el (python-shell-parse-command): + Find python-shell-interpreter with modified environment. + +2013-01-30 Stefan Monnier + + * emacs-lisp/cl.el (cl-set-getf): Add compatibility alias. + 2013-01-29 Alan Mackenzie Amend to fontify /regexp/s in actions correctly. * cc-awk.el (c-awk-harmless-char-re, c-awk-harmless-string*-re): - (c-awk-harmless-string*-here-re): braces, parens and semicolons + (c-awk-harmless-string*-here-re): Braces, parens and semicolons are no longer included. (c-awk-harmless-line-char-re, c-awk-harmless-line-string*-re): What used to be these variables without "-line" in the name. @@ -19,13 +81,13 @@ 2013-01-29 Michael Albinus - * autorevert.el (auto-revert-use-notify): Use - `custom-initialize-default' for initialization. (Bug#13583) + * autorevert.el (auto-revert-use-notify): + Use `custom-initialize-default' for initialization. (Bug#13583) * net/ange-ftp.el (ange-ftp-skip-msgs): Add another message. - * net/tramp-sh.el (tramp-sh-handle-start-file-process): Catch - `suppress'. Otherwise, `tramp-run-real-handler' might be called + * net/tramp-sh.el (tramp-sh-handle-start-file-process): + Catch `suppress'. Otherwise, `tramp-run-real-handler' might be called in `tramp-file-name-handler'. (tramp-gw-tunnel-method, tramp-gw-socks-method): Declare for compatibility. @@ -21002,7 +21064,7 @@ * nxml/rng-xsd.el (rng-xsd-check-pattern): Use case-sensitive matching (Bug#8516). -2011-01-22 Jari Aalto +2011-05-22 Jari Aalto * vc/vc-dir.el (vc-default-dir-printer): Give edited tag a 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.") "If non-nil Auto Revert Mode uses file notification functions. This requires Emacs being compiled with file notification support (see `auto-revert-notify-enabled'). You should set this -variable through Custom only." +variable through Custom." :group 'auto-revert :type 'boolean :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." (math-composition-to-string cexpr)))))) (defvar math-default-units-table - #s(hash-table test equal data (1 (1))) + (make-hash-table :test 'equal) "A table storing previously converted units.") (defun math-get-default-units (expr) @@ -442,13 +442,19 @@ If COMP or STD is non-nil, put that in the units table instead." (calc-slow-wrapper (let ((expr (calc-top-n 1)) (uoldname nil) + (unitscancel nil) unew units defunits) - (unless (math-units-in-expr-p expr t) + (if (or (not (math-units-in-expr-p expr t)) + (setq unitscancel (eq (math-get-standard-units expr) 1))) (let ((uold (or old-units (progn - (setq uoldname (read-string "Old units: ")) + (setq uoldname + (if unitscancel + (read-string + "(The expression is unitless when simplified) Old Units: ") + (read-string "Old units: "))) (if (equal uoldname "") (progn (setq uoldname "1") @@ -460,47 +466,43 @@ If COMP or STD is non-nil, put that in the units table instead." (error "Bad format in units expression: %s" (nth 1 uold))) (setq expr (math-mul expr uold)))) (setq defunits (math-get-default-units expr)) - (if (equal defunits "1") - (progn - (calc-enter-result 1 "cvun" (math-simplify-units expr)) - (message "All units in expression cancel")) - (unless new-units - (setq new-units - (read-string (concat - (if uoldname - (concat "Old units: " - uoldname - ", new units") - "New units") - (if defunits - (concat - " (default " - defunits - "): ") - ": ")))) - (if (and - (string= new-units "") - defunits) - (setq new-units defunits))) - (when (string-match "\\` */" new-units) - (setq new-units (concat "1" new-units))) - (setq units (math-read-expr new-units)) - (when (eq (car-safe units) 'error) - (error "Bad format in units expression: %s" (nth 2 units))) - (if calc-ensure-consistent-units - (math-check-unit-consistency expr units)) - (let ((unew (math-units-in-expr-p units t)) - (std (and (eq (car-safe units) 'var) - (assq (nth 1 units) math-standard-units-systems))) - (comp (eq (car-safe units) '+))) - (unless (or unew std) - (error "No units specified")) - (let ((res - (if std - (math-simplify-units (math-to-standard-units expr (nth 1 std))) - (math-convert-units expr units (and uoldname (not (equal uoldname "1"))))))) - (math-put-default-units res (if comp units)) - (calc-enter-result 1 "cvun" res))))))) + (unless new-units + (setq new-units + (read-string (concat + (if uoldname + (concat "Old units: " + uoldname + ", new units") + "New units") + (if defunits + (concat + " (default " + defunits + "): ") + ": ")))) + (if (and + (string= new-units "") + defunits) + (setq new-units defunits))) + (when (string-match "\\` */" new-units) + (setq new-units (concat "1" new-units))) + (setq units (math-read-expr new-units)) + (when (eq (car-safe units) 'error) + (error "Bad format in units expression: %s" (nth 2 units))) + (if calc-ensure-consistent-units + (math-check-unit-consistency expr units)) + (let ((unew (math-units-in-expr-p units t)) + (std (and (eq (car-safe units) 'var) + (assq (nth 1 units) math-standard-units-systems))) + (comp (eq (car-safe units) '+))) + (unless (or unew std) + (error "No units specified")) + (let ((res + (if std + (math-simplify-units (math-to-standard-units expr (nth 1 std))) + (math-convert-units expr units (and uoldname (not (equal uoldname "1"))))))) + (math-put-default-units res (if comp units)) + (calc-enter-result 1 "cvun" res)))))) (defun calc-autorange-units (arg) (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 @@ ;; Author: David Ponce ;; Maintainer: Eric M. Ludlam -;; Version: 1.0pre7 +;; Version: 1.1 ;; Keywords: OO, lisp ;; 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 @@ ;;; Copyright (C) 2002-2003, 2005-2013 Free Software Foundation, Inc. ;; Author: Eric M. Ludlam -;; Version: 0.2 +;; Version: 1.3 ;; Keywords: OO, lisp ;; 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 @@ ;; Author: Eric M. Ludlam ;; Keywords: syntax tools -;; Version: 2.0 +;; Version: 2.1beta ;; This file is part of GNU Emacs. 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'." 'cl--map-keymap-recursively "24.3") (define-obsolete-function-alias 'cl-map-intervals 'cl--map-intervals "24.3") (define-obsolete-function-alias 'cl-map-extents 'cl--map-overlays "24.3") +(define-obsolete-function-alias 'cl-set-getf 'cl--set-getf "24.3") (defun cl-maclisp-member (item list) (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 @@ +2013-01-30 Christopher Schmidt + + * gnus-int.el (gnus-backend-trace-elapsed): New variable. + (gnus-backend-trace): Honour gnus-backend-trace. + + * mml.el (mml-insert-part): Insert closing tag. + + * mm-decode.el (mm-save-part): Handle invalid read-file-name results. + 2013-01-21 Lars Magne Ingebrigtsen * 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)." 'denied)) (defvar gnus-backend-trace nil) +(defvar gnus-backend-trace-elapsed nil) (defun gnus-backend-trace (type form) - (with-current-buffer (get-buffer-create "*gnus trace*") - (buffer-disable-undo) - (goto-char (point-max)) - (insert (format-time-string "%H:%M:%S") - (format " %.2fs %s %S\n" - (if (numberp gnus-backend-trace) - (- (float-time) gnus-backend-trace) - 0) - type form)) - (setq gnus-backend-trace (float-time)))) + (when gnus-backend-trace + (with-current-buffer (get-buffer-create "*gnus trace*") + (buffer-disable-undo) + (goto-char (point-max)) + (insert (format-time-string "%H:%M:%S") + (format " %.2fs %s %S\n" + (if (numberp gnus-backend-trace-elapsed) + (- (float-time) gnus-backend-trace-elapsed) + 0) + type form)) + (setq gnus-backend-trace-elapsed (float-time))))) (defun gnus-open-server (gnus-command-method) "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." (when filename (setq filename (gnus-map-function mm-file-name-rewrite-functions (file-name-nondirectory filename)))) - (setq file - (read-file-name - (or prompt - (format "Save MIME part to (default %s): " - (or filename ""))) - (or mm-default-directory default-directory) - (expand-file-name (or filename "") - (or mm-default-directory default-directory)))) + (while + (progn + (setq file + (read-file-name + (or prompt + (format "Save MIME part to (default %s): " + (or filename ""))) + (or mm-default-directory default-directory) + (expand-file-name (or filename "") + (or mm-default-directory default-directory)))) + (cond ((or (not file) (equal file "")) + (message "Please enter a file name") + t) + ((and (file-directory-p file) + (not filename)) + (message "Please enter a non-directory file name") + t) + (t nil))) + (sit-for 2) + (discard-input)) (if (file-directory-p file) (setq file (expand-file-name filename file)) (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." ;; when you send the message. (or (eq mail-user-agent 'message-user-agent) (setq mail-encode-mml t)) - (mml-insert-tag 'part 'type type 'disposition "inline")) + (mml-insert-tag 'part 'type type 'disposition "inline") + (save-excursion + (mml-insert-tag '/part))) (declare-function message-subscribed-p "message" ()) (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." (defun imenu--truncate-items (menulist) "Truncate all strings in MENULIST to `imenu-max-item-length'." - (mapcar (lambda (item) - (cond - ((consp (cdr item)) - (imenu--truncate-items (cdr item))) - ;; truncate if necessary - ((and (numberp imenu-max-item-length) - (> (length (car item)) imenu-max-item-length)) - (setcar item (substring (car item) 0 imenu-max-item-length))))) - menulist)) - + (mapc (lambda (item) + ;; truncate if necessary + (when (and (numberp imenu-max-item-length) + (> (length (car item)) imenu-max-item-length)) + (setcar item (substring (car item) 0 imenu-max-item-length))) + (when (imenu--subalist-p item) + (imenu--truncate-items (cdr item)))) + menulist)) (defun imenu--make-index-alist (&optional noerror) "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 ;; in these major modes. But save that change for later. (cond ((and imenu-prev-index-position-function imenu-extract-index-name-function) - (let ((index-alist '()) (pos (point)) + (let ((index-alist '()) (pos -1) name) (goto-char (point-max)) ;; Search for the function (while (funcall imenu-prev-index-position-function) + (when (= pos (point)) + (error "Infinite loop at %s:%d: imenu-prev-index-position-function does not move point" (buffer-name) pos)) (setq pos (point)) (save-excursion (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." ;;; Variables that are not customizable. -(defvar jit-lock-mode nil +(defvar-local jit-lock-mode nil "Non-nil means Just-in-time Lock mode is active.") -(make-variable-buffer-local 'jit-lock-mode) -(defvar jit-lock-functions nil +(defvar-local jit-lock-functions nil "Functions to do the actual fontification. They are called with two arguments: the START and END of the region to fontify.") -(make-variable-buffer-local 'jit-lock-functions) -(defvar jit-lock-context-unfontify-pos nil +(defvar-local jit-lock-context-unfontify-pos nil "Consider text after this position as contextually unfontified. If nil, contextual fontification is disabled.") -(make-variable-buffer-local 'jit-lock-context-unfontify-pos) - (defvar jit-lock-stealth-timer nil "Timer for stealth fontification in Just-in-time Lock mode.") @@ -305,7 +301,7 @@ that needs to be (re)fontified. If non-nil, CONTEXTUAL means that a contextual fontification would be useful." (add-hook 'jit-lock-functions fun nil t) (when (and contextual jit-lock-contextually) - (set (make-local-variable 'jit-lock-contextually) t)) + (setq-local jit-lock-contextually t)) (jit-lock-mode t)) (defun jit-lock-unregister (fun) @@ -439,41 +435,39 @@ Defaults to the whole buffer. END can be out of bounds." Value is nil if there is nothing more to fontify." (if (zerop (buffer-size)) nil - (save-restriction - (widen) - (let* ((next (text-property-not-all around (point-max) 'fontified t)) - (prev (previous-single-property-change around 'fontified)) - (prop (get-text-property (max (point-min) (1- around)) - 'fontified)) - (start (cond - ((null prev) - ;; There is no property change between AROUND - ;; and the start of the buffer. If PROP is - ;; non-nil, everything in front of AROUND is - ;; fontified, otherwise nothing is fontified. - (if (eq prop t) - nil - (max (point-min) - (- around (/ jit-lock-chunk-size 2))))) - ((eq prop t) - ;; PREV is the start of a region of fontified - ;; text containing AROUND. Start fontifying a - ;; chunk size before the end of the unfontified - ;; region in front of that. - (max (or (previous-single-property-change prev 'fontified) - (point-min)) - (- prev jit-lock-chunk-size))) - (t - ;; PREV is the start of a region of unfontified - ;; text containing AROUND. Start at PREV or - ;; chunk size in front of AROUND, whichever is - ;; nearer. - (max prev (- around jit-lock-chunk-size))))) - (result (cond ((null start) next) - ((null next) start) - ((< (- around start) (- next around)) start) - (t next)))) - result)))) + (let* ((next (text-property-not-all around (point-max) 'fontified t)) + (prev (previous-single-property-change around 'fontified)) + (prop (get-text-property (max (point-min) (1- around)) + 'fontified)) + (start (cond + ((null prev) + ;; There is no property change between AROUND + ;; and the start of the buffer. If PROP is + ;; non-nil, everything in front of AROUND is + ;; fontified, otherwise nothing is fontified. + (if (eq prop t) + nil + (max (point-min) + (- around (/ jit-lock-chunk-size 2))))) + ((eq prop t) + ;; PREV is the start of a region of fontified + ;; text containing AROUND. Start fontifying a + ;; chunk size before the end of the unfontified + ;; region in front of that. + (max (or (previous-single-property-change prev 'fontified) + (point-min)) + (- prev jit-lock-chunk-size))) + (t + ;; PREV is the start of a region of unfontified + ;; text containing AROUND. Start at PREV or + ;; chunk size in front of AROUND, whichever is + ;; nearer. + (max prev (- around jit-lock-chunk-size))))) + (result (cond ((null start) next) + ((null next) start) + ((< (- around start) (- next around)) start) + (t next)))) + result))) (defun jit-lock-stealth-fontify (&optional repeat) "Fontify buffers stealthily. @@ -564,7 +558,9 @@ non-nil in a repeated invocation of this function." (when jit-lock-context-unfontify-pos ;; (message "Jit-Context %s" (buffer-name)) (save-restriction - (widen) + ;; Don't be blindsided by narrowing that starts in the middle + ;; of a jit-lock-defer-multiline. + (widen) (when (and (>= jit-lock-context-unfontify-pos (point-min)) (< jit-lock-context-unfontify-pos (point-max))) ;; 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'." (frame-parameters frame))) 'right))) (draggable t) - finished event position growth dragged) + event position growth dragged) (cond ((eq line 'header) ;; Check whether header-line can be dragged at all. @@ -456,39 +456,33 @@ must be one of the symbols `header', `mode', or `vertical'." ;; Start tracking. (track-mouse - ;; Loop reading events and sampling the position of the mouse. - (while (not finished) - (setq event (read-event)) + ;; Loop reading events and sampling the position of the mouse, + ;; until there is a non-mouse-movement event. Also, + ;; scroll-bar-movement events are the same as mouse movement for + ;; our purposes. (Why? -- cyd) + ;; If you change this, check that all of the following still work: + ;; Resizing windows by dragging mode-lines and header lines, + ;; and vertical lines (in windows without scroll bars). + ;; Doing this should not select another window, even if + ;; mouse-autoselect-window is non-nil. + ;; Mouse-1 clicks in Info header lines should advance position + ;; by one node at a time if mouse-1-click-follows-link is non-nil, + ;; otherwise they should just select the window. + (while (progn + (setq event (read-event)) + (memq (car-safe event) + '(mouse-movement scroll-bar-movement + switch-frame select-window))) (setq position (mouse-position)) ;; Do nothing if ;; - there is a switch-frame event. ;; - the mouse isn't in the frame that we started in ;; - the mouse isn't in any Emacs frame - ;; Drag if - ;; - there is a mouse-movement event - ;; - there is a scroll-bar-movement event (Why? -- cyd) - ;; (same as mouse movement for our purposes) - ;; Quit if - ;; - there is a keyboard event or some other unknown event. (cond - ((not (consp event)) - (setq finished t)) ((memq (car event) '(switch-frame select-window)) nil) - ((not (memq (car event) '(mouse-movement scroll-bar-movement))) - (when (consp event) - ;; Do not unread a drag-mouse-1 event to avoid selecting - ;; some other window. For vertical line dragging do not - ;; unread mouse-1 events either (but only if we dragged at - ;; least once to allow mouse-1 clicks get through). - (unless (and dragged - (if (eq line 'vertical) - (memq (car event) '(drag-mouse-1 mouse-1)) - (eq (car event) 'drag-mouse-1))) - (push event unread-command-events))) - (setq finished t)) - ((not (and (eq (car position) frame) - (cadr position))) + ((not (and (eq (car position) frame) + (cadr position))) nil) ((eq line 'vertical) ;; Drag vertical divider. @@ -512,12 +506,13 @@ must be one of the symbols `header', `mode', or `vertical'." growth (- growth))))))) ;; Process the terminating event. - (when (and (mouse-event-p event) on-link (not dragged) - (mouse--remap-link-click-p start-event event)) - ;; If mouse-2 has never been done by the user, it doesn't have - ;; the necessary property to be interpreted correctly. - (put 'mouse-2 'event-kind 'mouse-click) - (setcar event 'mouse-2) + (unless dragged + (when (and (mouse-event-p event) on-link + (mouse--remap-link-click-p start-event event)) + ;; If mouse-2 has never been done by the user, it doesn't have + ;; the necessary property to be interpreted correctly. + (put 'mouse-2 'event-kind 'mouse-click) + (setcar event 'mouse-2)) (push event unread-command-events)))) (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.") (set-file-selinux-context . tramp-sh-handle-set-file-selinux-context) (file-acl . tramp-sh-handle-file-acl) (set-file-acl . tramp-sh-handle-set-file-acl) - (vc-registered . tramp-sh-handle-vc-registered) - (inotify-add-watch . tramp-sh-handle-inotify-add-watch)) + (vc-registered . tramp-sh-handle-vc-registered)) "Alist of handler functions. Operations not mentioned here will be handled by the normal Emacs functions.") @@ -3488,64 +3487,6 @@ Fall back to normal file name handler if no Tramp handler exists." ;; Default file name handlers, we don't care. (t (tramp-run-real-handler operation args))))))) -(defun tramp-sh-handle-inotify-add-watch (file-name aspect callback) - "Like `inotify-add-watch' for Tramp files." - (setq file-name (expand-file-name file-name)) - (unless (consp aspect) (setq aspect (cons aspect nil))) - (with-parsed-tramp-file-name file-name nil - (let* ((default-directory (file-name-directory file-name)) - (command (tramp-get-remote-inotifywait v)) - (aspect (mapconcat - (lambda (x) - (replace-regexp-in-string "-" "_" (symbol-name x))) - aspect ",")) - (p (and command - (start-file-process - "inotifywait" nil command "-mq" "-e" aspect localname)))) - (when (processp p) - (tramp-compat-set-process-query-on-exit-flag p nil) - (set-process-filter p 'tramp-sh-inotify-process-filter) - (tramp-set-connection-property p "inotify-callback" callback) - ;; Return the file-name vector as watch-descriptor. - (tramp-set-connection-property p "inotify-watch-descriptor" v))))) - -(defun tramp-sh-inotify-process-filter (proc string) - "Read output from \"inotifywait\" and add corresponding inotify events." - (tramp-message - (tramp-get-connection-property proc "vector" nil) 6 - (format "%s\n%s" proc string)) - (dolist (line (split-string string "[\n\r]+" 'omit-nulls)) - ;; Check, whether there is a problem. - (unless - (string-match - "^[^[:blank:]]+[[:blank:]]+\\([^[:blank:]]+\\)+\\([[:blank:]]+\\([^[:blank:]]+\\)\\)?[[:blank:]]*$" line) - (tramp-error proc 'filewatch-error "%s" line)) - - (let* ((object - (list - (tramp-get-connection-property - proc "inotify-watch-descriptor" nil) - ;; Aspect symbols. We filter out MOVE and CLOSE, which - ;; are convenience macros. See INOTIFY(7). - (mapcar - (lambda (x) - (intern-soft (replace-regexp-in-string "_" "-" (downcase x)))) - (delete "MOVE" (delete "CLOSE" - (split-string (match-string 1 line) "," 'omit-nulls)))) - ;; We cannot gather any cookie value. So we return 0 as - ;; "don't know". - 0 (match-string 3 line))) - (callback - (tramp-get-connection-property proc "inotify-callback" nil)) - (event `(file-inotify ,object ,callback))) - - ;; Usually, we would add an Emacs event now. Unfortunately, - ;; `unread-command-events' does not accept several events at - ;; once. Therefore, we apply the callback directly. - ;(setq unread-command-events (cons event unread-command-events))))) - (let ((last-input-event event)) - (funcall callback object))))) - ;;; Internal Functions: (defun tramp-maybe-send-script (vec script name) @@ -4416,7 +4357,7 @@ connection if a previous connection has died for some reason." (car tramp-current-connection))) (> (tramp-time-diff (current-time) (cdr tramp-current-connection)) - 5)) + (or tramp-connection-min-time-diff 0))) (throw 'suppress 'suppress)) ;; 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'." (tramp-message vec 5 "Finding a suitable `trash' command") (tramp-find-executable vec "trash" (tramp-get-remote-path vec)))) -(defun tramp-get-remote-inotifywait (vec) - (with-tramp-connection-property vec "inotifywait" - (tramp-message vec 5 "Finding a suitable `inotifywait' command") - (tramp-find-executable vec "inotifywait" (tramp-get-remote-path vec) t t))) - (defun tramp-get-remote-id (vec) (with-tramp-connection-property vec "id" (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." ;; for an override of the system default. (defcustom tramp-process-connection-type t "Overrides `process-connection-type' for connections from Tramp. -Tramp binds process-connection-type to the value given here before +Tramp binds `process-connection-type' to the value given here before opening a connection to a remote host." :group 'tramp :type '(choice (const nil) (const t) (const pty))) +(defcustom tramp-connection-min-time-diff 5 + "Defines seconds between two consecutive connection attempts. +This is necessary as self defense mechanism, in order to avoid +yo-yo connection attempts when the remote host is unavailable. + +A value of 0 or `nil' suppresses this check. This might be +necessary, when several out-of-order copy operations are +performed, or when several asynchronous processes will be started +in a short time frame. In those cases it is recommended to +let-bind this variable." + :group 'tramp + :version "24.4" + :type '(choice (const nil) integer)) + (defcustom tramp-completion-reread-directory-timeout 10 "Defines seconds since last remote command before rereading a directory. A 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' would require an immediate reread during filename completion, `nil' means to use always cached values for the directory contents." :group 'tramp - :type '(choice (const nil) integer)) + :type '(choice (const nil) (const t) integer)) ;;; Internal Variables: 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." (save-excursion (goto-char from) (let ((column makefile-backslash-column) - (endmark (make-marker))) - (move-marker endmark to) + (endmark (copy-marker to))) ;; Compute the smallest column number past the ends of all the lines. - (if makefile-backslash-align - (progn - (if (not delete-flag) - (while (< (point) to) - (end-of-line) - (if (= (preceding-char) ?\\) - (progn (forward-char -1) - (skip-chars-backward " \t"))) - (setq column (max column (1+ (current-column)))) - (forward-line 1))) - ;; Adjust upward to a tab column, if that doesn't push - ;; past the margin. - (if (> (% column tab-width) 0) - (let ((adjusted (* (/ (+ column tab-width -1) tab-width) - tab-width))) - (if (< adjusted (window-width)) - (setq column adjusted)))))) + (when (and makefile-backslash-align (not delete-flag)) + (while (< (point) to) + (end-of-line) + (if (= (preceding-char) ?\\) + (progn (forward-char -1) + (skip-chars-backward " \t"))) + (setq column (max column (1+ (current-column)))) + (forward-line 1)) + ;; Adjust upward to a tab column, if that doesn't push + ;; past the margin. + (if (> (% column tab-width) 0) + (let ((adjusted (* (/ (+ column tab-width -1) tab-width) + tab-width))) + (if (< adjusted (window-width)) + (setq column adjusted))))) ;; Don't modify blank lines at start of region. (goto-char from) (while (and (< (point) endmark) (eolp)) @@ -1296,9 +1293,9 @@ Fill comments, backslashed lines, and variable definitions specially." (while (= (preceding-char) ?\\) (end-of-line 0)) ;; Maybe we hit bobp, in which case we are not at EOL. - (if (eq (point) (line-end-position)) - (forward-char)) - (point))) + (if (eolp) + (1+ (point)) + (point)))) (end (save-excursion (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." (defun python-shell-parse-command () "Calculate the string used to execute the inferior Python process." - (format "%s %s" python-shell-interpreter python-shell-interpreter-args)) + (let ((process-environment (python-shell-calculate-process-environment)) + (exec-path (python-shell-calculate-exec-path))) + (format "%s %s" + (executable-find python-shell-interpreter) + python-shell-interpreter-args))) (defun python-shell-calculate-process-environment () "Calculate process environment given `python-shell-virtualenv-path'." @@ -2323,15 +2327,17 @@ Argument OUTPUT is a string with the output from the comint process." (file-name (with-temp-buffer (insert full-output) - (goto-char (point-min)) - ;; OK, this sucked but now it became a cool hack. The - ;; stacktrace information normally is on the first line - ;; but in some cases (like when doing a step-in) it is - ;; on the second. - (when (or (looking-at python-pdbtrack-stacktrace-info-regexp) - (and - (forward-line) - (looking-at python-pdbtrack-stacktrace-info-regexp))) + ;; When the debugger encounters a pdb.set_trace() + ;; command, it prints a single stack frame. Sometimes + ;; it prints a bit of extra information about the + ;; arguments of the present function. When ipdb + ;; encounters an exception, it prints the _entire_ stack + ;; trace. To handle all of these cases, we want to find + ;; the _last_ stack frame printed in the most recent + ;; batch of output, then jump to the corrsponding + ;; file/line number. + (goto-char (point-max)) + (when (re-search-backward python-pdbtrack-stacktrace-info-regexp nil t) (setq line-number (string-to-number (match-string-no-properties 2))) (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 @@ +2013-01-30 Eli Zaretskii + + * w32.c (sys_open): Zero out the flags for the new file descriptor. + (sys_close): Zero out the flags for the file descriptor before + closing it. (Bug#13546) + + * w32.c (parse_root, get_volume_info, readdir, read_unc_volume) + (logon_network_drive, stat_worker, symlink, chase_symlinks): Use + CharNextExA and CharPrevExA to iterate over file names encoded in + DBCS. (Bug#13553) + + * w32.c (w32_get_long_filename, init_environment, readlink): + Support file names encoded in DBCS codepages. + (readlink): Use the current file-name-coding-system, not the ANSI + codepage, to decode and handle targets of symlinks. + 2013-01-28 Eli Zaretskii * 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 . */ /* must include CRT headers *before* config.h */ #include -#include /* for _mbspbrk and _mbslwr */ +#include /* for _mbspbrk, _mbslwr, _mbsrchr, ... */ #undef access #undef chdir @@ -1730,12 +1730,17 @@ parse_root (char * name, char ** pPath) else if (IS_DIRECTORY_SEP (name[0]) && IS_DIRECTORY_SEP (name[1])) { int slashes = 2; + int dbcs_p = max_filename_mbslen () > 1; + name += 2; do { if (IS_DIRECTORY_SEP (*name) && --slashes == 0) break; - name++; + if (dbcs_p) + name = CharNextExA (file_name_codepage, name, 0); + else + name++; } while ( *name ); if (IS_DIRECTORY_SEP (name[0])) @@ -1800,7 +1805,7 @@ w32_get_long_filename (char * name, char * buf, int size) while (p != NULL && *p) { q = p; - p = strchr (q, '\\'); + p = _mbschr (q, '\\'); if (p) *p = '\0'; len = get_long_basename (full, o, size); if (len > 0) @@ -2072,16 +2077,16 @@ init_environment (char ** argv) if (!GetModuleFileName (NULL, modname, MAX_PATH)) emacs_abort (); - if ((p = strrchr (modname, '\\')) == NULL) + if ((p = _mbsrchr (modname, '\\')) == NULL) emacs_abort (); *p = 0; - if ((p = strrchr (modname, '\\')) && xstrcasecmp (p, "\\bin") == 0) + if ((p = _mbsrchr (modname, '\\')) && xstrcasecmp (p, "\\bin") == 0) { char buf[SET_ENV_BUF_SIZE]; *p = 0; - for (p = modname; *p; p++) + for (p = modname; *p; p = CharNext (p)) if (*p == '\\') *p = '/'; _snprintf (buf, sizeof (buf)-1, "emacs_dir=%s", modname); @@ -2096,17 +2101,17 @@ init_environment (char ** argv) || xstrcasecmp (p, "\\AMD64") == 0)) { *p = 0; - p = strrchr (modname, '\\'); + p = _mbsrchr (modname, '\\'); if (p != NULL) { *p = 0; - p = strrchr (modname, '\\'); + p = _mbsrchr (modname, '\\'); if (p && xstrcasecmp (p, "\\src") == 0) { char buf[SET_ENV_BUF_SIZE]; *p = 0; - for (p = modname; *p; p++) + for (p = modname; *p; p = CharNext (p)) if (*p == '\\') *p = '/'; _snprintf (buf, sizeof (buf)-1, "emacs_dir=%s", modname); @@ -2641,12 +2646,23 @@ get_volume_info (const char * name, const char ** pPath) { char *str = temp; int slashes = 4; + int dbcs_p = max_filename_mbslen () > 1; + rootname = temp; do { if (IS_DIRECTORY_SEP (*name) && --slashes == 0) break; - *str++ = *name++; + if (!dbcs_p) + *str++ = *name++; + else + { + const char *p = name; + + name = CharNextExA (file_name_codepage, name, 0); + memcpy (str, p, name - p); + str += name - p; + } } while ( *name ); @@ -2882,11 +2898,23 @@ readdir (DIR *dirp) { char filename[MAXNAMLEN + 3]; int ln; + int dbcs_p = max_filename_mbslen () > 1; strcpy (filename, dir_pathname); ln = strlen (filename) - 1; - if (!IS_DIRECTORY_SEP (filename[ln])) - strcat (filename, "\\"); + if (!dbcs_p) + { + if (!IS_DIRECTORY_SEP (filename[ln])) + strcat (filename, "\\"); + } + else + { + char *end = filename + ln + 1; + char *last_char = CharPrevExA (file_name_codepage, filename, end, 0); + + if (!IS_DIRECTORY_SEP (*last_char)) + strcat (filename, "\\"); + } strcat (filename, "*"); /* Note: No need to resolve symlinks in FILENAME, because @@ -2991,6 +3019,7 @@ read_unc_volume (HANDLE henum, char *readbuf, int size) DWORD bufsize = 512; char *buffer; char *ptr; + int dbcs_p = max_filename_mbslen () > 1; count = 1; buffer = alloca (bufsize); @@ -3001,7 +3030,13 @@ read_unc_volume (HANDLE henum, char *readbuf, int size) /* WNetEnumResource returns \\resource\share...skip forward to "share". */ ptr = ((LPNETRESOURCE) buffer)->lpRemoteName; ptr += 2; - while (*ptr && !IS_DIRECTORY_SEP (*ptr)) ptr++; + if (!dbcs_p) + while (*ptr && !IS_DIRECTORY_SEP (*ptr)) ptr++; + else + { + while (*ptr && !IS_DIRECTORY_SEP (*ptr)) + ptr = CharNextExA (file_name_codepage, ptr, 0); + } ptr++; strncpy (readbuf, ptr, size); @@ -3038,9 +3073,11 @@ logon_network_drive (const char *path) { NETRESOURCE resource; char share[MAX_PATH]; - int i, n_slashes; + int n_slashes; char drive[4]; UINT drvtype; + char *p; + int dbcs_p; if (IS_DIRECTORY_SEP (path[0]) && IS_DIRECTORY_SEP (path[1])) drvtype = DRIVE_REMOTE; @@ -3062,13 +3099,18 @@ logon_network_drive (const char *path) n_slashes = 2; strncpy (share, path, MAX_PATH); /* Truncate to just server and share name. */ - for (i = 2; i < MAX_PATH; i++) + dbcs_p = max_filename_mbslen () > 1; + for (p = share + 2; *p && p < share + MAX_PATH; ) { - if (IS_DIRECTORY_SEP (share[i]) && ++n_slashes > 3) + if (IS_DIRECTORY_SEP (*p) && ++n_slashes > 3) { - share[i] = '\0'; + *p = '\0'; break; } + if (dbcs_p) + p = CharNextExA (file_name_codepage, p, 0); + else + p++; } resource.dwType = RESOURCETYPE_DISK; @@ -3365,9 +3407,12 @@ sys_open (const char * path, int oflag, int mode) and system files. Force all file handles to be non-inheritable. */ int res = _open (mpath, (oflag & ~_O_CREAT) | _O_NOINHERIT, mode); - if (res >= 0) - return res; - return _open (mpath, oflag | _O_NOINHERIT, mode); + if (res < 0) + res = _open (mpath, oflag | _O_NOINHERIT, mode); + if (res >= 0 && res < MAXDESC) + fd_info[res].flags = 0; + + return res; } int @@ -3843,6 +3888,7 @@ stat_worker (const char * path, struct stat * buf, int follow_symlinks) DWORD access_rights = 0; DWORD fattrs = 0, serialnum = 0, fs_high = 0, fs_low = 0, nlinks = 1; FILETIME ctime, atime, wtime; + int dbcs_p; if (path == NULL || buf == NULL) { @@ -4040,6 +4086,7 @@ stat_worker (const char * path, struct stat * buf, int follow_symlinks) did not ask for extra precision, resolving symlinks will fly in the face of that request, since the user then wants the lightweight version of the code. */ + dbcs_p = max_filename_mbslen () > 1; rootdir = (path >= save_name + len - 1 && (IS_DIRECTORY_SEP (*path) || *path == 0)); @@ -4067,8 +4114,19 @@ stat_worker (const char * path, struct stat * buf, int follow_symlinks) } else if (rootdir) { - if (!IS_DIRECTORY_SEP (name[len-1])) - strcat (name, "\\"); + if (!dbcs_p) + { + if (!IS_DIRECTORY_SEP (name[len-1])) + strcat (name, "\\"); + } + else + { + char *end = name + len; + char *n = CharPrevExA (file_name_codepage, name, end, 0); + + if (!IS_DIRECTORY_SEP (*n)) + strcat (name, "\\"); + } if (GetDriveType (name) < 2) { errno = ENOENT; @@ -4080,15 +4138,37 @@ stat_worker (const char * path, struct stat * buf, int follow_symlinks) } else { - if (IS_DIRECTORY_SEP (name[len-1])) - name[len - 1] = 0; + if (!dbcs_p) + { + if (IS_DIRECTORY_SEP (name[len-1])) + name[len - 1] = 0; + } + else + { + char *end = name + len; + char *n = CharPrevExA (file_name_codepage, name, end, 0); + + if (IS_DIRECTORY_SEP (*n)) + *n = 0; + } /* (This is hacky, but helps when doing file completions on network drives.) Optimize by using information available from active readdir if possible. */ len = strlen (dir_pathname); - if (IS_DIRECTORY_SEP (dir_pathname[len-1])) - len--; + if (!dbcs_p) + { + if (IS_DIRECTORY_SEP (dir_pathname[len-1])) + len--; + } + else + { + char *end = dir_pathname + len; + char *n = CharPrevExA (file_name_codepage, dir_pathname, end, 0); + + if (IS_DIRECTORY_SEP (*n)) + len--; + } if (dir_find_handle != INVALID_HANDLE_VALUE && !(is_a_symlink && follow_symlinks) && strnicmp (save_name, dir_pathname, len) == 0 @@ -4359,6 +4439,7 @@ symlink (char const *filename, char const *linkname) char linkfn[MAX_PATH], *tgtfn; DWORD flags = 0; int dir_access, filename_ends_in_slash; + int dbcs_p; /* Diagnostics follows Posix as much as possible. */ if (filename == NULL || linkname == NULL) @@ -4384,6 +4465,8 @@ symlink (char const *filename, char const *linkname) return -1; } + dbcs_p = max_filename_mbslen () > 1; + /* Note: since empty FILENAME was already rejected, we can safely refer to FILENAME[1]. */ if (!(IS_DIRECTORY_SEP (filename[0]) || IS_DEVICE_SEP (filename[1]))) @@ -4398,8 +4481,21 @@ symlink (char const *filename, char const *linkname) char tem[MAX_PATH]; char *p = linkfn + strlen (linkfn); - while (p > linkfn && !IS_ANY_SEP (p[-1])) - p--; + if (!dbcs_p) + { + while (p > linkfn && !IS_ANY_SEP (p[-1])) + p--; + } + else + { + char *p1 = CharPrevExA (file_name_codepage, linkfn, p, 0); + + while (p > linkfn && !IS_ANY_SEP (*p1)) + { + p = p1; + p1 = CharPrevExA (file_name_codepage, linkfn, p1, 0); + } + } if (p > linkfn) strncpy (tem, linkfn, p - linkfn); tem[p - linkfn] = '\0'; @@ -4414,7 +4510,15 @@ symlink (char const *filename, char const *linkname) exist, but ends in a slash, we create a symlink to directory. If FILENAME exists and is a directory, we always create a symlink to directory. */ - filename_ends_in_slash = IS_DIRECTORY_SEP (filename[strlen (filename) - 1]); + if (!dbcs_p) + filename_ends_in_slash = IS_DIRECTORY_SEP (filename[strlen (filename) - 1]); + else + { + const char *end = filename + strlen (filename); + const char *n = CharPrevExA (file_name_codepage, filename, end, 0); + + filename_ends_in_slash = IS_DIRECTORY_SEP (*n); + } if (dir_access == 0 || filename_ends_in_slash) flags = SYMBOLIC_LINK_FLAG_DIRECTORY; @@ -4604,6 +4708,8 @@ readlink (const char *name, char *buf, size_t buf_size) WCHAR *lwname_src = reparse_data->SymbolicLinkReparseBuffer.PathBuffer + reparse_data->SymbolicLinkReparseBuffer.PrintNameOffset/sizeof(WCHAR); + /* This updates file_name_codepage which we need below. */ + int dbcs_p = max_filename_mbslen () > 1; /* According to MSDN, PrintNameLength does not include the terminating null character. */ @@ -4611,9 +4717,7 @@ readlink (const char *name, char *buf, size_t buf_size) memcpy (lwname, lwname_src, lwname_len); lwname[lwname_len/sizeof(WCHAR)] = 0; /* null-terminate */ - /* FIXME: Should we use the current file-name coding system - instead of the fixed value of the ANSI codepage? */ - lname_len = WideCharToMultiByte (w32_ansi_code_page, 0, lwname, -1, + lname_len = WideCharToMultiByte (file_name_codepage, 0, lwname, -1, lname, MAX_PATH, NULL, NULL); if (!lname_len) { @@ -4639,18 +4743,33 @@ readlink (const char *name, char *buf, size_t buf_size) else { size_t size_to_copy = buf_size; - BYTE *p = lname; + BYTE *p = lname, *p2; BYTE *pend = p + lname_len; /* Normalize like dostounix_filename does, but we don't want to assume that lname is null-terminated. */ - if (*p && p[1] == ':' && *p >= 'A' && *p <= 'Z') - *p += 'a' - 'A'; + if (dbcs_p) + p2 = CharNextExA (file_name_codepage, p, 0); + else + p2 = p + 1; + if (*p && *p2 == ':' && *p >= 'A' && *p <= 'Z') + { + *p += 'a' - 'A'; + p += 2; + } while (p <= pend) { if (*p == '\\') *p = '/'; - ++p; + if (dbcs_p) + { + p = CharNextExA (file_name_codepage, p, 0); + /* CharNextExA doesn't advance at null character. */ + if (!*p) + break; + } + else + ++p; } /* Testing for null-terminated LNAME is paranoia: WideCharToMultiByte should always return a @@ -4724,6 +4843,7 @@ chase_symlinks (const char *file) char link[MAX_PATH]; ssize_t res, link_len; int loop_count = 0; + int dbcs_p; if (is_windows_9x () == TRUE || !is_symlink (file)) return (char *)file; @@ -4731,13 +4851,27 @@ chase_symlinks (const char *file) if ((link_len = GetFullPathName (file, MAX_PATH, link, NULL)) == 0) return (char *)file; + dbcs_p = max_filename_mbslen () > 1; target[0] = '\0'; do { /* Remove trailing slashes, as we want to resolve the last non-trivial part of the link name. */ - while (link_len > 3 && IS_DIRECTORY_SEP (link[link_len-1])) - link[link_len--] = '\0'; + if (!dbcs_p) + { + while (link_len > 3 && IS_DIRECTORY_SEP (link[link_len-1])) + link[link_len--] = '\0'; + } + else if (link_len > 3) + { + char *n = CharPrevExA (file_name_codepage, link, link + link_len, 0); + + while (n >= link + 2 && IS_DIRECTORY_SEP (*n)) + { + n[1] = '\0'; + n = CharPrevExA (file_name_codepage, link, n, 0); + } + } res = readlink (link, target, MAX_PATH); if (res > 0) @@ -4750,8 +4884,21 @@ chase_symlinks (const char *file) the symlink, then copy the result back to target. */ char *p = link + link_len; - while (p > link && !IS_ANY_SEP (p[-1])) - p--; + if (!dbcs_p) + { + while (p > link && !IS_ANY_SEP (p[-1])) + p--; + } + else + { + char *p1 = CharPrevExA (file_name_codepage, link, p, 0); + + while (p > link && !IS_ANY_SEP (*p1)) + { + p = p1; + p1 = CharPrevExA (file_name_codepage, link, p1, 0); + } + } strcpy (p, target); strcpy (target, link); } @@ -6543,15 +6690,15 @@ sys_close (int fd) } } + if (fd >= 0 && fd < MAXDESC) + fd_info[fd].flags = 0; + /* Note that sockets do not need special treatment here (at least on NT and Windows 95 using the standard tcp/ip stacks) - it appears that closesocket is equivalent to CloseHandle, which is to be expected because socket handles are fully fledged kernel handles. */ rc = _close (fd); - if (rc == 0 && fd < MAXDESC) - fd_info[fd].flags = 0; - return rc; }