dos-w32.el 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439
  1. ;; dos-w32.el --- Functions shared among MS-DOS and W32 (NT/95) platforms
  2. ;; Copyright (C) 1996, 2001-2015 Free Software Foundation, Inc.
  3. ;; Maintainer: Geoff Voelker <voelker@cs.washington.edu>
  4. ;; Keywords: internal
  5. ;; Package: emacs
  6. ;; This file is part of GNU Emacs.
  7. ;; GNU Emacs is free software: you can redistribute it and/or modify
  8. ;; it under the terms of the GNU General Public License as published by
  9. ;; the Free Software Foundation, either version 3 of the License, or
  10. ;; (at your option) any later version.
  11. ;; GNU Emacs is distributed in the hope that it will be useful,
  12. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. ;; GNU General Public License for more details.
  15. ;; You should have received a copy of the GNU General Public License
  16. ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
  17. ;;; Commentary:
  18. ;; Parts of this code are duplicated functions taken from dos-fns.el
  19. ;; and winnt.el.
  20. ;;; Code:
  21. ;; Use ";" instead of ":" as a path separator (from files.el).
  22. (when (memq system-type '(ms-dos windows-nt))
  23. (setq path-separator ";")
  24. (push 'file-name-history minibuffer-history-case-insensitive-variables)
  25. ;; Set the null device (for compile.el).
  26. (setq null-device "NUL")
  27. (setq-default buffer-file-coding-system 'undecided-dos))
  28. ;; For distinguishing file types based upon suffixes. DEPRECATED, DO NOT USE!
  29. (defcustom file-name-buffer-file-type-alist
  30. '(("[:/].*config.sys$" . nil) ; config.sys text
  31. ("\\.\\(obj\\|exe\\|com\\|lib\\|sys\\|bin\\|ico\\|pif\\|class\\)$" . t)
  32. ; MS-Dos stuff
  33. ("\\.\\(dll\\|drv\\|386\\|vxd\\|fon\\|fnt\\|fot\\|ttf\\|grp\\)$" . t)
  34. ; Windows stuff
  35. ("\\.\\(bmp\\|wav\\|avi\\|mpg\\|jpg\\|tif\\|mov\\|au\\)$" . t)
  36. ; known binary data files
  37. ("\\.\\(arc\\|zip\\|pak\\|lzh\\|zoo\\)$" . t)
  38. ; Packers
  39. ("\\.\\(a\\|o\\|tar\\|z\\|gz\\|taz\\|jar\\)$" . t)
  40. ; Unix stuff
  41. ("\\.sx[dmicw]$" . t) ; OpenOffice.org
  42. ("\\.tp[ulpw]$" . t) ; borland Pascal stuff
  43. ("[:/]tags$" . nil) ; emacs TAGS file
  44. )
  45. "Alist used in the past for distinguishing text files from binary files.
  46. Each element has the form (REGEXP . TYPE), where REGEXP is matched
  47. against the file name, and TYPE is nil for text, t for binary.
  48. This variable is deprecated, not used anywhere, and will soon be deleted."
  49. :type '(repeat (cons regexp boolean))
  50. :group 'dos-fns
  51. :group 'w32)
  52. (make-obsolete-variable 'file-name-buffer-file-type-alist
  53. 'file-coding-system-alist
  54. "24.4")
  55. (defun find-buffer-file-type-coding-system (command)
  56. "Choose a coding system for a file operation in COMMAND.
  57. COMMAND is a list that specifies the operation, an I/O primitive, as its
  58. CAR, and the arguments that might be given to that operation as its CDR.
  59. If operation is `insert-file-contents', the coding system is chosen based
  60. upon the filename (the CAR of the arguments beyond the operation), the contents
  61. of `w32-untranslated-filesystem-list' and `file-name-buffer-file-type-alist',
  62. and whether the file exists:
  63. If it matches in `w32-untranslated-filesystem-list':
  64. If the file exists: `undecided'
  65. If the file does not exist: `undecided-unix'
  66. Otherwise:
  67. If the file exists: `undecided'
  68. If the file does not exist default value of `buffer-file-coding-system'
  69. Note that the CAR of arguments to `insert-file-contents' operation could
  70. be a cons cell of the form (FILENAME . BUFFER), where BUFFER is a buffer
  71. into which the file's contents were already read, but not yet decoded.
  72. If operation is `write-region', the coding system is chosen based
  73. upon the value of `buffer-file-coding-system'. If
  74. `buffer-file-coding-system' is non-nil, its value is used.
  75. Otherwise, it is `undecided-dos'.
  76. The most common situation is when DOS and Unix files are read and
  77. written, and their names do not match in `w32-untranslated-filesystem-list'.
  78. In these cases, the coding system initially will be `undecided'.
  79. As the file is read in the DOS case, the coding system will be
  80. changed to `undecided-dos' as CR/LFs are detected. As the file
  81. is read in the Unix case, the coding system will be changed to
  82. `undecided-unix' as LFs are detected. In both cases,
  83. `buffer-file-coding-system' will be set to the appropriate coding
  84. system, and the value of `buffer-file-coding-system' will be used
  85. when writing the file."
  86. (let ((op (nth 0 command))
  87. (undecided nil) (undecided-unix nil)
  88. target target-buf)
  89. (cond ((eq op 'insert-file-contents)
  90. (setq target (nth 1 command))
  91. ;; If TARGET is a cons cell, it has the form (FILENAME . BUFFER),
  92. ;; where BUFFER is a buffer into which the file was already read,
  93. ;; but its contents were not yet decoded. (This form of the
  94. ;; arguments is used, e.g., in arc-mode.el.) This function
  95. ;; doesn't care about the contents, it only looks at the file's
  96. ;; name, which is the CAR of the cons cell.
  97. (when (consp target)
  98. (setq target-buf
  99. (and (bufferp (cdr target))
  100. (buffer-name (cdr target))))
  101. (setq target (car target)))
  102. (cond ((or
  103. ;; For any existing file, decide based on contents.
  104. (file-exists-p target)
  105. ;; If TARGET does not exist as a file, replace its
  106. ;; base name with TARGET-BUF and try again. This
  107. ;; is for jka-compr's sake, which strips the
  108. ;; compression (.gz etc.) extension from the
  109. ;; FILENAME, but leaves it in the BUFFER's name.
  110. (and (stringp target-buf)
  111. (file-exists-p
  112. (expand-file-name target-buf
  113. (file-name-directory target)))))
  114. (setq undecided t))
  115. ;; Next check for a non-DOS file system.
  116. ((w32-untranslated-file-p target)
  117. (setq undecided-unix t)))
  118. (cond (undecided-unix '(undecided-unix . undecided-unix))
  119. (undecided '(undecided . undecided))
  120. (t (cons (default-value 'buffer-file-coding-system)
  121. (default-value 'buffer-file-coding-system)))))
  122. ((eq op 'write-region)
  123. (if buffer-file-coding-system
  124. (cons buffer-file-coding-system
  125. buffer-file-coding-system)
  126. ;; Normally this is used only in a non-file-visiting
  127. ;; buffer, because normally buffer-file-coding-system is non-nil
  128. ;; in a file-visiting buffer.
  129. '(undecided-dos . undecided-dos))))))
  130. (make-obsolete 'find-buffer-file-type-coding-system nil "24.4")
  131. (defun find-file-binary (filename)
  132. "Visit file FILENAME and treat it as binary."
  133. ;; FIXME: Why here rather than in files.el?
  134. ;; FIXME: Can't we use find-file-literally for the same purposes?
  135. (interactive "FFind file binary: ")
  136. (let ((coding-system-for-read 'no-conversion)) ;; FIXME: undecided-unix?
  137. (find-file filename)))
  138. (defun find-file-text (filename)
  139. "Visit file FILENAME and treat it as a text file."
  140. (interactive "FFind file text: ")
  141. (let ((coding-system-for-read 'undecided-dos))
  142. (find-file filename)))
  143. (defun w32-find-file-not-found-set-buffer-file-coding-system ()
  144. (with-current-buffer (current-buffer)
  145. (let ((coding buffer-file-coding-system))
  146. ;; buffer-file-coding-system is already set by
  147. ;; find-operation-coding-system, which was called from
  148. ;; insert-file-contents. All that's left is to change
  149. ;; the EOL conversion, if required by the user.
  150. (when (and (null coding-system-for-read)
  151. (or inhibit-eol-conversion
  152. (w32-untranslated-file-p (buffer-file-name))))
  153. (setq coding (coding-system-change-eol-conversion coding 0))
  154. (setq buffer-file-coding-system coding))
  155. nil)))
  156. ;; To set the default coding system on new files.
  157. (add-hook 'find-file-not-found-functions
  158. 'w32-find-file-not-found-set-buffer-file-coding-system)
  159. ;;; To accommodate filesystems that do not require CR/LF translation.
  160. (define-obsolete-variable-alias 'untranslated-filesystem-list
  161. 'w32-untranslated-filesystem-list "24.4")
  162. (defvar w32-untranslated-filesystem-list nil
  163. "List of filesystems that require no CR/LF translation when reading
  164. and writing files. Each filesystem in the list is a string naming
  165. the directory prefix corresponding to the filesystem.")
  166. (defun w32-untranslated-canonical-name (filename)
  167. "Return FILENAME in a canonicalized form for use with the functions
  168. dealing with untranslated filesystems."
  169. (if (memq system-type '(ms-dos windows-nt cygwin))
  170. ;; The canonical form for DOS/W32 is with A-Z downcased and all
  171. ;; directory separators changed to directory-sep-char.
  172. (let ((name
  173. (mapconcat (lambda (char)
  174. (char-to-string (if (and (<= ?A char ?Z))
  175. (+ (- char ?A) ?a)
  176. char)))
  177. filename nil)))
  178. ;; Use expand-file-name to canonicalize directory separators, except
  179. ;; with bare drive letters (which would have the cwd appended).
  180. ;; Avoid expanding names that could trigger ange-ftp to prompt
  181. ;; for passwords, though.
  182. (if (or (string-match-p "^.:\\'" name)
  183. (string-match-p "^/[^/:]+:" name))
  184. name
  185. (expand-file-name name)))
  186. filename))
  187. (defun w32-untranslated-file-p (filename)
  188. "Return t if FILENAME is on a filesystem that does not require
  189. CR/LF translation, and nil otherwise."
  190. (let ((fs (w32-untranslated-canonical-name filename))
  191. (ufs-list w32-untranslated-filesystem-list)
  192. (found nil))
  193. (while (and (not found) ufs-list)
  194. (if (string-match-p (concat "^" (car ufs-list)) fs)
  195. (setq found t)
  196. (setq ufs-list (cdr ufs-list))))
  197. found))
  198. (define-obsolete-function-alias 'add-untranslated-filesystem
  199. 'w32-add-untranslated-filesystem "24.4")
  200. (defun w32-add-untranslated-filesystem (filesystem)
  201. "Add FILESYSTEM to the list of filesystems that do not require
  202. CR/LF translation. FILESYSTEM is a string containing the directory
  203. prefix corresponding to the filesystem. For example, for a Unix
  204. filesystem mounted on drive Z:, FILESYSTEM could be \"Z:\"."
  205. ;; We use "D", not "f", to avoid confusing the user: "f" prompts
  206. ;; with a directory, but RET returns the current buffer's file, not
  207. ;; its directory.
  208. (interactive "DUntranslated file system: ")
  209. (let ((fs (w32-untranslated-canonical-name filesystem)))
  210. (if (member fs w32-untranslated-filesystem-list)
  211. w32-untranslated-filesystem-list
  212. (push fs w32-untranslated-filesystem-list))))
  213. (define-obsolete-function-alias 'remove-untranslated-filesystem
  214. 'w32-remove-untranslated-filesystem "24.4")
  215. (defun w32-remove-untranslated-filesystem (filesystem)
  216. "Remove FILESYSTEM from the list of filesystems that do not require
  217. CR/LF translation. FILESYSTEM is a string containing the directory
  218. prefix corresponding to the filesystem. For example, for a Unix
  219. filesystem mounted on drive Z:, FILESYSTEM could be \"Z:\"."
  220. (interactive "fUntranslated file system: ")
  221. (setq w32-untranslated-filesystem-list
  222. (delete (w32-untranslated-canonical-name filesystem)
  223. w32-untranslated-filesystem-list)))
  224. ;;; Support for printing under DOS/Windows, see lpr.el and ps-print.el.
  225. (define-obsolete-variable-alias 'direct-print-region-use-command-dot-com
  226. 'w32-direct-print-region-use-command-dot-com "24.4")
  227. (defcustom w32-direct-print-region-use-command-dot-com t
  228. "If non-nil, use command.com to print on Windows 9x."
  229. :type 'boolean
  230. :group 'dos-fns
  231. :group 'w32)
  232. ;; Function to actually send data to the printer port.
  233. ;; Supports writing directly, and using various programs.
  234. (defun w32-direct-print-region-helper (printer
  235. start end
  236. lpr-prog
  237. _delete-text _buf _display
  238. rest)
  239. (let* (;; Ignore case when matching known external program names.
  240. (case-fold-search t)
  241. ;; Convert / to \ in printer name, for sake of external programs.
  242. (printer
  243. (if (stringp printer)
  244. (subst-char-in-string ?/ ?\\ printer)
  245. printer))
  246. ;; Find a directory that is local, to work-around Windows bug.
  247. (safe-dir
  248. (let ((safe-dirs (list "c:/" (getenv "windir") (getenv "TMPDIR"))))
  249. (while (not (file-attributes (car safe-dirs)))
  250. (setq safe-dirs (cdr safe-dirs)))
  251. (car safe-dirs)))
  252. (tempfile
  253. (subst-char-in-string
  254. ?/ ?\\
  255. (make-temp-name
  256. (expand-file-name "EP" temporary-file-directory))))
  257. ;; capture output for diagnosis
  258. (errbuf (list (get-buffer-create " *print-region-helper*") t)))
  259. ;; It seems that we must be careful about the directory name that
  260. ;; gets added to the printer port name by write-region when using
  261. ;; the standard "PRN" or "LPTx" ports, because the write can fail if
  262. ;; the directory is on a network drive. The same is true when
  263. ;; asking command.com to copy the file.
  264. ;; No action is needed for UNC printer names, which is just as well
  265. ;; because `expand-file-name' doesn't support UNC names on MS-DOS.
  266. (if (and (stringp printer) (not (string-match-p "^\\\\" printer)))
  267. (setq printer
  268. (subst-char-in-string ?/ ?\\ (expand-file-name printer safe-dir))))
  269. ;; Handle known programs specially where necessary.
  270. (unwind-protect
  271. (cond
  272. ;; nprint.exe is the standard print command on Netware
  273. ((string-match-p "\\`nprint\\(\\.exe\\)?\\'"
  274. (file-name-nondirectory lpr-prog))
  275. (write-region start end tempfile nil 0)
  276. (call-process lpr-prog nil errbuf nil
  277. tempfile (concat "P=" printer)))
  278. ;; print.exe is a standard command on NT
  279. ((string-match-p "\\`print\\(\\.exe\\)?\\'"
  280. (file-name-nondirectory lpr-prog))
  281. ;; Be careful not to invoke print.exe on MS-DOS or Windows 9x
  282. ;; though, because it is a TSR program there (hangs Emacs).
  283. (or (and (eq system-type 'windows-nt)
  284. (null (getenv "winbootdir")))
  285. (error "Printing via print.exe is not supported on MS-DOS or Windows 9x"))
  286. ;; It seems that print.exe always appends a form-feed so we
  287. ;; should make sure to omit the last FF in the data.
  288. (if (and (> end start)
  289. (char-equal (char-before end) ?\C-l))
  290. (setq end (1- end)))
  291. ;; cancel out annotate function for non-PS case
  292. (let ((write-region-annotate-functions nil))
  293. (write-region start end tempfile nil 0))
  294. (call-process lpr-prog nil errbuf nil
  295. (concat "/D:" printer) tempfile))
  296. ;; support lpr and similar programs for convenience, but
  297. ;; supply an explicit filename because the NT version of lpr
  298. ;; can't read from stdin.
  299. ((> (length lpr-prog) 0)
  300. (write-region start end tempfile nil 0)
  301. (setq rest (append rest (list tempfile)))
  302. (apply 'call-process lpr-prog nil errbuf nil rest))
  303. ;; Run command.com to access printer port on Windows 9x, unless
  304. ;; we are supposed to append to an existing (non-empty) file,
  305. ;; to work around a bug in Windows 9x that prevents Windows
  306. ;; programs from accessing LPT ports reliably.
  307. ((and (eq system-type 'windows-nt)
  308. (getenv "winbootdir")
  309. ;; Allow cop-out so command.com isn't invoked
  310. w32-direct-print-region-use-command-dot-com
  311. ;; file-attributes fails on LPT ports on Windows 9x but
  312. ;; not on NT, so handle both cases for safety.
  313. (eq (or (nth 7 (file-attributes printer)) 0) 0))
  314. (write-region start end tempfile nil 0)
  315. (let ((w32-quote-process-args nil))
  316. (call-process "command.com" nil errbuf nil "/c"
  317. (format "copy /b %s %s" tempfile printer))))
  318. ;; write directly to the printer port
  319. (t
  320. (write-region start end printer t 0)))
  321. ;; ensure we remove the tempfile if created
  322. (if (file-exists-p tempfile)
  323. (delete-file tempfile)))))
  324. (defvar printer-name)
  325. (declare-function default-printer-name "w32fns.c")
  326. (define-obsolete-function-alias 'direct-print-region-function
  327. 'w32-direct-print-region-function "24.4")
  328. (defun w32-direct-print-region-function (start end
  329. &optional lpr-prog
  330. delete-text buf display
  331. &rest rest)
  332. "DOS/Windows-specific function to print the region on a printer.
  333. Writes the region to the device or file which is a value of
  334. `printer-name' (which see), unless the value of `lpr-command'
  335. indicates a specific program should be invoked."
  336. ;; DOS printers need the lines to end with CR-LF pairs, so make
  337. ;; sure it always happens that way, unless the buffer is binary.
  338. (let* ((coding coding-system-for-write)
  339. (coding-base
  340. (if (null coding) 'undecided (coding-system-base coding)))
  341. (eol-type (coding-system-eol-type coding-base))
  342. ;; Make each print-out eject the final page, but don't waste
  343. ;; paper if the file ends with a form-feed already.
  344. (write-region-annotate-functions
  345. (cons
  346. (lambda (_start end)
  347. (if (not (char-equal (char-before end) ?\f))
  348. `((,end . "\f"))))
  349. write-region-annotate-functions))
  350. (printer (or (and (boundp 'dos-printer)
  351. (stringp (symbol-value 'dos-printer))
  352. (symbol-value 'dos-printer))
  353. printer-name
  354. (default-printer-name))))
  355. (or (eq coding-system-for-write 'no-conversion)
  356. (setq coding-system-for-write
  357. (aref eol-type 1))) ; force conversion to DOS EOLs
  358. (w32-direct-print-region-helper printer start end lpr-prog
  359. delete-text buf display rest)))
  360. (defvar lpr-headers-switches)
  361. ;; Set this to nil if you have a port of the `pr' program
  362. ;; (e.g., from GNU Textutils), or if you have an `lpr'
  363. ;; program (see above) that can print page headers.
  364. ;; If `lpr-headers-switches' is non-nil (the default) and
  365. ;; `print-region-function' is set to `dos-print-region-function',
  366. ;; then requests to print page headers will be silently
  367. ;; ignored, and `print-buffer' and `print-region' produce
  368. ;; the same output as `lpr-buffer' and `lpr-region', accordingly.
  369. (when (memq system-type '(ms-dos windows-nt))
  370. (setq lpr-headers-switches "(page headers are not supported)"))
  371. (defvar ps-printer-name)
  372. (define-obsolete-function-alias 'direct-ps-print-region-function
  373. 'w32-direct-ps-print-region-function "24.4")
  374. (defun w32-direct-ps-print-region-function (start end
  375. &optional lpr-prog
  376. delete-text buf display
  377. &rest rest)
  378. "DOS/Windows-specific function to print the region on a PostScript printer.
  379. Writes the region to the device or file which is a value of
  380. `ps-printer-name' (which see), unless the value of `ps-lpr-command'
  381. indicates a specific program should be invoked."
  382. (let ((printer (or (and (boundp 'dos-ps-printer)
  383. (stringp (symbol-value 'dos-ps-printer))
  384. (symbol-value 'dos-ps-printer))
  385. ps-printer-name
  386. (default-printer-name))))
  387. (w32-direct-print-region-helper printer start end lpr-prog
  388. delete-text buf display rest)))
  389. ;(setq ps-lpr-command "gs")
  390. ;(setq ps-lpr-switches '("-q" "-dNOPAUSE" "-sDEVICE=epson" "-r240x60"
  391. ; "-sOutputFile=LPT1"))
  392. (provide 'dos-w32)
  393. ;;; dos-w32.el ends here