Mercurial > hg > xemacs-beta
comparison src/fileio.c @ 211:78478c60bfcd r20-4b4
Import from CVS: tag r20-4b4
author | cvs |
---|---|
date | Mon, 13 Aug 2007 10:05:51 +0200 |
parents | 41ff10fd062f |
children | 78f53ef88e17 |
comparison
equal
deleted
inserted
replaced
210:49f55ca3ba57 | 211:78478c60bfcd |
---|---|
18 along with XEmacs; see the file COPYING. If not, write to | 18 along with XEmacs; see the file COPYING. If not, write to |
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | 19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
20 Boston, MA 02111-1307, USA. */ | 20 Boston, MA 02111-1307, USA. */ |
21 | 21 |
22 /* Synched up with: Mule 2.0, FSF 19.30. */ | 22 /* Synched up with: Mule 2.0, FSF 19.30. */ |
23 /* More syncing: FSF Emacs 19.34.6 by Marc Paquette <marcpa@cam.org> */ | |
23 | 24 |
24 #include <config.h> | 25 #include <config.h> |
25 #include "lisp.h" | 26 #include "lisp.h" |
26 | 27 |
27 #include "buffer.h" | 28 #include "buffer.h" |
47 | 48 |
48 #ifdef HPUX | 49 #ifdef HPUX |
49 #include <netio.h> | 50 #include <netio.h> |
50 #ifdef HPUX_PRE_8_0 | 51 #ifdef HPUX_PRE_8_0 |
51 #include <errnet.h> | 52 #include <errnet.h> |
53 #endif /* HPUX_PRE_8_0 */ | |
54 #endif /* HPUX */ | |
55 | |
56 #ifdef WINDOWSNT | |
57 #define NOMINMAX 1 | |
58 #include <windows.h> | |
59 #include <stdlib.h> | |
60 #include <fcntl.h> | |
61 #endif /* not WINDOWSNT */ | |
62 | |
63 #ifdef DOS_NT | |
64 #define CORRECT_DIR_SEPS(s) \ | |
65 do { if ('/' == DIRECTORY_SEP) dostounix_filename (s); \ | |
66 else unixtodos_filename (s); \ | |
67 } while (0) | |
68 /* On Windows, drive letters must be alphabetic - on DOS, the Netware | |
69 redirector allows the six letters between 'Z' and 'a' as well. */ | |
70 #ifdef MSDOS | |
71 #define IS_DRIVE(x) ((x) >= 'A' && (x) <= 'z') | |
52 #endif | 72 #endif |
53 #endif /* HPUX */ | 73 #ifdef WINDOWSNT |
74 #define IS_DRIVE(x) isalpha (x) | |
75 #endif | |
76 /* Need to lower-case the drive letter, or else expanded | |
77 filenames will sometimes compare inequal, because | |
78 `expand-file-name' doesn't always down-case the drive letter. */ | |
79 #define DRIVE_LETTER(x) (tolower (x)) | |
80 #endif /* DOS_NT */ | |
54 | 81 |
55 /* Nonzero during writing of auto-save files */ | 82 /* Nonzero during writing of auto-save files */ |
56 static int auto_saving; | 83 static int auto_saving; |
57 | 84 |
58 /* Set by auto_save_1 to mode of original file so Fwrite_region_internal | 85 /* Set by auto_save_1 to mode of original file so Fwrite_region_internal |
83 Lisp_Object Vauto_save_list_file_name; | 110 Lisp_Object Vauto_save_list_file_name; |
84 | 111 |
85 int disable_auto_save_when_buffer_shrinks; | 112 int disable_auto_save_when_buffer_shrinks; |
86 | 113 |
87 Lisp_Object Qfile_name_handler_alist; | 114 Lisp_Object Qfile_name_handler_alist; |
115 | |
116 #ifdef DOS_NT | |
117 /* Until we can figure out how to deal with the functions in this file in | |
118 a civilized fashion, this will remain #ifdef'ed out. -slb */ | |
119 /* Syncing with FSF 19.34.6 note: although labelled as NT-specific, these | |
120 two lisp variables are compiled in even when not defined(DOS_NT). | |
121 Need to check if we should bracket them between #ifdef's. | |
122 --marcpa */ | |
123 /* On NT, specifies the directory separator character, used (eg.) when | |
124 expanding file names. This can be bound to / or \. | |
125 | |
126 This needs to be initialized statically, because file name functions | |
127 are called during initialization. */ | |
128 Lisp_Object Vdirectory_sep_char = '/'; | |
129 | |
130 /* For the benefit of backwards compatability with earlier versions of | |
131 Emacs on DOS_NT, provide a way to disable the REPLACE option support | |
132 in insert-file-contents. */ | |
133 Lisp_Object Vinsert_file_contents_allow_replace; | |
134 #endif /* DOS_NT */ | |
88 | 135 |
89 /* These variables describe handlers that have "already" had a chance | 136 /* These variables describe handlers that have "already" had a chance |
90 to handle the current operation. | 137 to handle the current operation. |
91 | 138 |
92 Vinhibit_file_name_handlers is a list of file name handlers. | 139 Vinhibit_file_name_handlers is a list of file name handlers. |
413 file = FILE_SYSTEM_CASE (file); | 460 file = FILE_SYSTEM_CASE (file); |
414 #endif | 461 #endif |
415 beg = XSTRING_DATA (file); | 462 beg = XSTRING_DATA (file); |
416 p = beg + XSTRING_LENGTH (file); | 463 p = beg + XSTRING_LENGTH (file); |
417 | 464 |
418 while (p != beg && !IS_ANY_SEP (p[-1])) | 465 while (p != beg && !IS_ANY_SEP (p[-1]) |
419 p--; | 466 #ifdef DOS_NT |
467 /* only recognise drive specifier at beginning */ | |
468 && !(p[-1] == ':' && p == beg + 2) | |
469 #endif | |
470 ) p--; | |
420 | 471 |
421 if (p == beg) | 472 if (p == beg) |
422 return Qnil; | 473 return Qnil; |
423 #ifdef DOS_NT | 474 #ifdef DOS_NT |
424 /* Expansion of "c:" to drive and default directory. */ | 475 /* Expansion of "c:" to drive and default directory. */ |
425 /* (NT does the right thing.) */ | 476 /* (NT does the right thing.) */ |
426 if (p == beg + 2 && beg[1] == ':') | 477 if (p == beg + 2 && beg[1] == ':') |
427 { | 478 { |
428 int drive = (*beg) - 'a'; | |
429 /* MAXPATHLEN+1 is guaranteed to be enough space for getdefdir. */ | 479 /* MAXPATHLEN+1 is guaranteed to be enough space for getdefdir. */ |
430 Bufbyte *res = (Bufbyte *) alloca (MAXPATHLEN + 5); | 480 Bufbyte *res = alloca (MAXPATHLEN + 1); |
431 unsigned char *res1; | 481 if (getdefdir (toupper (*beg) - 'A' + 1, res)) |
432 #ifdef WINDOWSNT | |
433 res1 = res; | |
434 /* The NT version places the drive letter at the beginning already. */ | |
435 #else /* not WINDOWSNT */ | |
436 /* On MSDOG we must put the drive letter in by hand. */ | |
437 res1 = res + 2; | |
438 #endif /* not WINDOWSNT */ | |
439 if (getdefdir (drive + 1, res)) | |
440 { | 482 { |
441 #ifdef MSDOS | 483 if (!IS_DIRECTORY_SEP (res[strlen ((char *) res) - 1])) |
442 res[0] = drive + 'a'; | |
443 res[1] = ':'; | |
444 #endif /* MSDOS */ | |
445 if (IS_DIRECTORY_SEP (res[strlen ((char *) res) - 1])) | |
446 strcat ((char *) res, "/"); | 484 strcat ((char *) res, "/"); |
447 beg = res; | 485 beg = res; |
448 p = beg + strlen ((char *) beg); | 486 p = beg + strlen ((char *) beg); |
449 } | 487 } |
450 } | 488 } |
489 CORRECT_DIR_SEPS (beg); | |
451 #endif /* DOS_NT */ | 490 #endif /* DOS_NT */ |
452 return make_string (beg, p - beg); | 491 return make_string (beg, p - beg); |
453 } | 492 } |
454 | 493 |
455 DEFUN ("file-name-nondirectory", Ffile_name_nondirectory, 1, 1, 0, /* | 494 DEFUN ("file-name-nondirectory", Ffile_name_nondirectory, 1, 1, 0, /* |
473 return call2_check_string (handler, Qfile_name_nondirectory, file); | 512 return call2_check_string (handler, Qfile_name_nondirectory, file); |
474 | 513 |
475 beg = XSTRING_DATA (file); | 514 beg = XSTRING_DATA (file); |
476 end = p = beg + XSTRING_LENGTH (file); | 515 end = p = beg + XSTRING_LENGTH (file); |
477 | 516 |
478 while (p != beg && !IS_ANY_SEP (p[-1])) | 517 while (p != beg && !IS_ANY_SEP (p[-1]) |
479 p--; | 518 #ifdef DOS_NT |
519 /* only recognise drive specifier at beginning */ | |
520 && !(p[-1] == ':' && p == beg + 2) | |
521 #endif | |
522 ) p--; | |
480 | 523 |
481 return make_string (p, end - p); | 524 return make_string (p, end - p); |
482 } | 525 } |
483 | 526 |
484 DEFUN ("unhandled-file-name-directory", Funhandled_file_name_directory, 1, 1, 0, /* | 527 DEFUN ("unhandled-file-name-directory", Funhandled_file_name_directory, 1, 1, 0, /* |
549 (buf, (char *) XSTRING_DATA (file))); | 592 (buf, (char *) XSTRING_DATA (file))); |
550 } | 593 } |
551 | 594 |
552 /* | 595 /* |
553 * Convert from directory name to filename. | 596 * Convert from directory name to filename. |
554 * On UNIX, it's simple: just make sure there is a terminating / | 597 * On UNIX, it's simple: just make sure there isn't a terminating / |
555 | 598 |
556 * Value is nonzero if the string output is different from the input. | 599 * Value is nonzero if the string output is different from the input. |
557 */ | 600 */ |
558 | 601 |
559 static int | 602 static int |
573 #else | 616 #else |
574 if (slen > 1 | 617 if (slen > 1 |
575 && IS_DIRECTORY_SEP (dst[slen - 1]) | 618 && IS_DIRECTORY_SEP (dst[slen - 1]) |
576 #ifdef DOS_NT | 619 #ifdef DOS_NT |
577 && !IS_ANY_SEP (dst[slen - 2]) | 620 && !IS_ANY_SEP (dst[slen - 2]) |
578 #endif | 621 #endif /* DOS_NT */ |
579 ) | 622 ) |
580 dst[slen - 1] = 0; | 623 dst[slen - 1] = 0; |
581 #endif | 624 #endif /* APOLLO */ |
625 #ifdef DOS_NT | |
626 CORRECT_DIR_SEPS (dst); | |
627 #endif /* DOS_NT */ | |
582 return 1; | 628 return 1; |
583 } | 629 } |
584 | 630 |
585 DEFUN ("directory-file-name", Fdirectory_file_name, 1, 1, 0, /* | 631 DEFUN ("directory-file-name", Fdirectory_file_name, 1, 1, 0, /* |
586 Return the file name of the directory named DIR. | 632 Return the file name of the directory named DIR. |
631 memcpy (data, XSTRING_DATA (prefix), len); | 677 memcpy (data, XSTRING_DATA (prefix), len); |
632 memcpy (data + len, suffix, countof (suffix)); | 678 memcpy (data + len, suffix, countof (suffix)); |
633 /* !!#### does mktemp() Mule-encapsulate? */ | 679 /* !!#### does mktemp() Mule-encapsulate? */ |
634 mktemp ((char *) data); | 680 mktemp ((char *) data); |
635 | 681 |
682 #ifdef DOS_NT | |
683 CORRECT_DIR_SEPS (XSTRING_DATA (val)); | |
684 #endif /* DOS_NT */ | |
636 return val; | 685 return val; |
637 } | 686 } |
638 | 687 |
639 DEFUN ("expand-file-name", Fexpand_file_name, 1, 2, 0, /* | 688 DEFUN ("expand-file-name", Fexpand_file_name, 1, 2, 0, /* |
640 Convert FILENAME to absolute, and canonicalize it. | 689 Convert FILENAME to absolute, and canonicalize it. |
657 Bufbyte *newdir, *p, *o; | 706 Bufbyte *newdir, *p, *o; |
658 int tlen; | 707 int tlen; |
659 Bufbyte *target; | 708 Bufbyte *target; |
660 struct passwd *pw; | 709 struct passwd *pw; |
661 #ifdef DOS_NT | 710 #ifdef DOS_NT |
662 /* Demacs 1.1.2 91/10/20 Manabu Higashida */ | 711 int drive = 0; |
663 int drive = -1; | 712 int collapse_newdir = 1; |
664 int relpath = 0; | 713 int length; |
665 Bufbyte *tmp, *defdir; | |
666 #endif /* DOS_NT */ | 714 #endif /* DOS_NT */ |
667 Lisp_Object handler; | 715 Lisp_Object handler; |
668 | 716 |
669 CHECK_STRING (name); | 717 CHECK_STRING (name); |
670 | 718 |
710 the code and forget to adjust them, resulting in intermittent bugs. | 758 the code and forget to adjust them, resulting in intermittent bugs. |
711 Putting this call here avoids all that crud. | 759 Putting this call here avoids all that crud. |
712 | 760 |
713 The EQ test avoids infinite recursion. */ | 761 The EQ test avoids infinite recursion. */ |
714 if (! NILP(default_) && !EQ (default_, name) | 762 if (! NILP(default_) && !EQ (default_, name) |
715 /* This saves time in a common case. */ | 763 /* Save time in some common cases - as long as default_directory |
764 is not relative, it can be canonicalized with name below (if it | |
765 is needed at all) without requiring it to be expanded now. */ | |
716 && ! (XSTRING_LENGTH (default_) >= 3 | 766 && ! (XSTRING_LENGTH (default_) >= 3 |
767 #ifdef DOS_NT | |
768 /* Detect MSDOS file names with drive specifiers. */ | |
769 && (IS_DRIVE (XSTRING_BYTE (default_, 0)) | |
770 && (IS_DEVICE_SEP (XSTRING_BYTE (default_, 1)) | |
771 IS_DIRECTORY_SEP (XSTRING_BYTE (default_, 2))))) | |
772 #ifdef WINDOWSNT | |
773 /* Detect Windows file names in UNC format. */ | |
774 && ! (XSTRING_LENGTH (default_) >= 2 | |
775 && IS_DIRECTORY_SEP (XSTRING_BYTE (default_, 0)) | |
776 && IS_DIRECTORY_SEP (XSTRING_BYTE (default_, 1))) | |
777 #endif | |
778 #else /* not DOS_NT */ | |
779 /* Detect Unix absolute file names (/... alone is not absolute on | |
780 DOS or Windows). */ | |
717 && (IS_DIRECTORY_SEP (XSTRING_BYTE (default_, 0)) | 781 && (IS_DIRECTORY_SEP (XSTRING_BYTE (default_, 0)) |
718 || IS_DEVICE_SEP (XSTRING_BYTE (default_, 1))))) | 782 || IS_DEVICE_SEP (XSTRING_BYTE (default_, 1)))) |
783 #endif /* not DOS_NT */ | |
784 ) | |
719 { | 785 { |
720 struct gcpro gcpro1; | 786 struct gcpro gcpro1; |
721 | 787 |
722 GCPRO1 (default_); /* may be current_buffer->directory */ | 788 GCPRO1 (default_); /* may be current_buffer->directory */ |
723 default_ = Fexpand_file_name (default_, Qnil); | 789 default_ = Fexpand_file_name (default_, Qnil); |
730 | 796 |
731 /* #### dmoore - this is ugly, clean this up. Looks like nm | 797 /* #### dmoore - this is ugly, clean this up. Looks like nm |
732 pointing into name should be safe during all of this, though. */ | 798 pointing into name should be safe during all of this, though. */ |
733 nm = XSTRING_DATA (name); | 799 nm = XSTRING_DATA (name); |
734 | 800 |
735 #ifdef MSDOS | |
736 /* First map all backslashes to slashes. */ | |
737 dostounix_filename (nm = strcpy (alloca (strlen (nm) + 1), nm)); | |
738 #endif | |
739 | |
740 #ifdef DOS_NT | 801 #ifdef DOS_NT |
741 /* Now strip drive name. */ | 802 /* We will force directory separators to be either all \ or /, so make |
803 a local copy to modify, even if there ends up being no change. */ | |
804 nm = strcpy (alloca (strlen (nm) + 1), nm); | |
805 | |
806 /* Find and remove drive specifier if present; this makes nm absolute | |
807 even if the rest of the name appears to be relative. */ | |
742 { | 808 { |
743 Bufbyte *colon = strrchr (nm, ':'); | 809 Bufbyte *colon = strrchr (nm, ':'); |
744 if (colon) | 810 if (colon) |
811 /* Only recognize colon as part of drive specifier if there is a | |
812 single alphabetic character preceeding the colon (and if the | |
813 character before the drive letter, if present, is a directory | |
814 separator); this is to support the remote system syntax used by | |
815 ange-ftp, and the "po:username" syntax for POP mailboxes. */ | |
816 look_again: | |
745 if (nm == colon) | 817 if (nm == colon) |
746 nm++; | 818 nm++; |
747 else | 819 else if (IS_DRIVE (colon[-1]) |
820 && (colon == nm + 1 || IS_DIRECTORY_SEP (colon[-2]))) | |
748 { | 821 { |
749 drive = colon[-1]; | 822 drive = colon[-1]; |
750 nm = colon + 1; | 823 nm = colon + 1; |
751 if (!IS_DIRECTORY_SEP (*nm)) | 824 } |
752 { | 825 else |
753 defdir = alloca (MAXPATHLEN + 1); | 826 { |
754 relpath = getdefdir (tolower (drive) - 'a' + 1, defdir); | 827 while (--colon >= nm) |
755 } | 828 if (colon[0] == ':') |
829 goto look_again; | |
756 } | 830 } |
757 } | 831 } |
832 | |
833 #ifdef WINDOWSNT | |
834 /* If we see "c://somedir", we want to strip the first slash after the | |
835 colon when stripping the drive letter. Otherwise, this expands to | |
836 "//somedir". */ | |
837 if (drive && IS_DIRECTORY_SEP (nm[0]) && IS_DIRECTORY_SEP (nm[1])) | |
838 nm++; | |
839 #endif /* WINDOWSNT */ | |
758 #endif /* DOS_NT */ | 840 #endif /* DOS_NT */ |
759 | 841 |
760 /* We *don't* want to handle // and /~ that way. */ | 842 /* We *don't* want to handle // and /~ that way. */ |
761 #if 0 | 843 #if 0 |
762 /* Handle // and /~ in middle of file name | 844 /* Handle // and /~ in middle of file name |
782 if (IS_DIRECTORY_SEP (p[0]) && p[1] == '~') | 864 if (IS_DIRECTORY_SEP (p[0]) && p[1] == '~') |
783 nm = p + 1; | 865 nm = p + 1; |
784 | 866 |
785 p++; | 867 p++; |
786 } | 868 } |
869 | |
870 #endif /* 0 */ | |
871 | |
872 #ifdef WINDOWSNT | |
873 /* Discard any previous drive specifier if nm is now in UNC format. */ | |
874 if (IS_DIRECTORY_SEP (nm[0]) && IS_DIRECTORY_SEP (nm[1])) | |
875 { | |
876 drive = 0; | |
877 } | |
878 #endif /* WINDOWSNT */ | |
879 | |
880 /* If nm is absolute, look for /./ or /../ sequences; if none are | |
881 found, we can probably return right away. We will avoid allocating | |
882 a new string if name is already fully expanded. */ | |
883 if (IS_DIRECTORY_SEP (nm[0]) | |
884 #ifdef WINDOWSNT | |
885 && (drive || IS_DIRECTORY_SEP (nm[1])) | |
787 #endif | 886 #endif |
788 | 887 ) |
789 /* If nm is absolute, flush ...// and detect /./ and /../. | |
790 If no /./ or /../ we can return right away. */ | |
791 if (IS_DIRECTORY_SEP (nm[0])) | |
792 { | 888 { |
793 /* If it turns out that the filename we want to return is just a | 889 /* If it turns out that the filename we want to return is just a |
794 suffix of FILENAME, we don't need to go through and edit | 890 suffix of FILENAME, we don't need to go through and edit |
795 things; we just need to construct a new string using data | 891 things; we just need to construct a new string using data |
796 starting at the middle of FILENAME. If we set lose to a | 892 starting at the middle of FILENAME. If we set lose to a |
814 lose = 1; | 910 lose = 1; |
815 p++; | 911 p++; |
816 } | 912 } |
817 if (!lose) | 913 if (!lose) |
818 { | 914 { |
819 #ifndef DOS_NT | 915 #ifdef DOS_NT |
916 /* Make sure directories are all separated with / or \ as | |
917 desired, but avoid allocation of a new string when not | |
918 required. */ | |
919 CORRECT_DIR_SEPS (nm); | |
920 #ifdef WINDOWSNT | |
921 if (IS_DIRECTORY_SEP (nm[1])) | |
922 { | |
923 if (strcmp (nm, XSTRING_DATA (name)) != 0) | |
924 name = build_string (nm); | |
925 } | |
926 else | |
927 #endif | |
928 /* drive must be set, so this is okay */ | |
929 if (strcmp (nm - 2, XSTRING_DATA (name)) != 0) | |
930 { | |
931 name = make_string (nm - 2, p - nm + 2); | |
932 XSTRING_DATA (name)[0] = DRIVE_LETTER (drive); | |
933 XSTRING_DATA (name)[1] = ':'; | |
934 } | |
935 return name; | |
936 #else /* not DOS_NT */ | |
937 /* Unix */ | |
820 if (nm == XSTRING_DATA (name)) | 938 if (nm == XSTRING_DATA (name)) |
821 return name; | 939 return name; |
822 return build_string ((char *) nm); | 940 return build_string ((char *) nm); |
823 #endif /* not DOS_NT */ | 941 #endif /* DOS_NT */ |
824 } | 942 } |
825 } | 943 } |
826 | 944 |
827 /* Now determine directory to start with and put it in newdir */ | 945 /* At this point, nm might or might not be an absolute file name. We |
946 need to expand ~ or ~user if present, otherwise prefix nm with | |
947 default_directory if nm is not absolute, and finally collapse /./ | |
948 and /foo/../ sequences. | |
949 | |
950 We set newdir to be the appropriate prefix if one is needed: | |
951 - the relevant user directory if nm starts with ~ or ~user | |
952 - the specified drive's working dir (DOS/NT only) if nm does not | |
953 start with / | |
954 - the value of default_directory. | |
955 | |
956 Note that these prefixes are not guaranteed to be absolute (except | |
957 for the working dir of a drive). Therefore, to ensure we always | |
958 return an absolute name, if the final prefix is not absolute we | |
959 append it to the current working directory. */ | |
828 | 960 |
829 newdir = 0; | 961 newdir = 0; |
830 | 962 |
831 if (nm[0] == '~') /* prefix ~ */ | 963 if (nm[0] == '~') /* prefix ~ */ |
832 { | 964 { |
833 if (IS_DIRECTORY_SEP (nm[1]) | 965 if (IS_DIRECTORY_SEP (nm[1]) |
834 || nm[1] == 0) /* ~ by itself */ | 966 || nm[1] == 0) /* ~ by itself */ |
835 { | 967 { |
836 if (!(newdir = (Bufbyte *) egetenv ("HOME"))) | 968 if (!(newdir = (Bufbyte *) egetenv ("HOME"))) |
837 newdir = (Bufbyte *) ""; | 969 newdir = (Bufbyte *) ""; |
970 /* Syncing with FSF 19.34.6 note: this is not in FSF. Since it is dated 1995, | |
971 I doubt it is coming from XEmacs. I (#if 0) it but let the code | |
972 stay there just in case. --marcpa */ | |
973 #if 0 | |
838 #ifdef DOS_NT | 974 #ifdef DOS_NT |
839 /* Problem when expanding "~\" if HOME is not on current drive. | 975 /* Problem when expanding "~\" if HOME is not on current drive. |
840 Ulrich Leodolter, Wed Jan 11 10:20:35 1995 */ | 976 Ulrich Leodolter, Wed Jan 11 10:20:35 1995 */ |
841 if (newdir[1] == ':') | 977 if (newdir[1] == ':') |
842 drive = newdir[0]; | 978 drive = newdir[0]; |
843 dostounix_filename (newdir); | 979 dostounix_filename (newdir); |
844 #endif /* DOS_NT */ | 980 #endif /* DOS_NT */ |
981 #endif /* 0 */ | |
845 nm++; | 982 nm++; |
983 #ifdef DOS_NT | |
984 collapse_newdir = 0; | |
985 #endif /* DOS_NT */ | |
846 } | 986 } |
847 else /* ~user/filename */ | 987 else /* ~user/filename */ |
848 { | 988 { |
849 for (p = nm; *p && (!IS_DIRECTORY_SEP (*p)); p++); | 989 for (p = nm; *p && (!IS_DIRECTORY_SEP (*p)); p++); |
850 o = (Bufbyte *) alloca (p - nm + 1); | 990 o = (Bufbyte *) alloca (p - nm + 1); |
851 memcpy (o, (char *) nm, p - nm); | 991 memcpy (o, (char *) nm, p - nm); |
852 o [p - nm] = 0; | 992 o [p - nm] = 0; |
853 | 993 |
994 /* Syncing with FSF 19.34.6 note: FSF uses getpwnam even on NT, which does | |
995 not work. The following works only if ~USER names the user who runs | |
996 this instance of XEmacs. While NT is single-user (for the moment) you | |
997 still can have multiple user profiles users defined, each with its | |
998 HOME. Therefore, the following should be reworked to handle this case. | |
999 --marcpa */ | |
854 #ifdef WINDOWSNT | 1000 #ifdef WINDOWSNT |
855 /* | 1001 /* |
856 ** Now if the file given is "~foo/file" and HOME="c:/", then we | 1002 ** Now if the file given is "~foo/file" and HOME="c:/", then we |
857 ** want the file to be named "c:/file" ("~foo" becomes "c:/"). | 1003 ** want the file to be named "c:/file" ("~foo" becomes "c:/"). |
858 ** The variable o has "~foo", so we can use the length of | 1004 ** The variable o has "~foo", so we can use the length of |
859 ** that string to offset nm. August Hill, 31 Aug 1998. | 1005 ** that string to offset nm. August Hill, 31 Aug 1998. |
860 */ | 1006 */ |
861 newdir = (unsigned char *) egetenv ("HOME"); | 1007 newdir = (Bufbyte *) egetenv ("HOME"); |
862 dostounix_filename (newdir); | 1008 dostounix_filename (newdir); |
863 nm += strlen(o) + 1; | 1009 nm += strlen(o) + 1; |
864 #else /* not WINDOWSNT */ | 1010 #else /* not WINDOWSNT */ |
865 /* Jamie reports that getpwnam() can get wedged by SIGIO/SIGALARM | 1011 /* Jamie reports that getpwnam() can get wedged by SIGIO/SIGALARM |
866 occurring in it. (It can call select()). */ | 1012 occurring in it. (It can call select()). */ |
877 /* If we don't find a user of that name, leave the name | 1023 /* If we don't find a user of that name, leave the name |
878 unchanged; don't move nm forward to p. */ | 1024 unchanged; don't move nm forward to p. */ |
879 } | 1025 } |
880 } | 1026 } |
881 | 1027 |
882 if (!IS_ANY_SEP (nm[0]) | |
883 #ifdef DOS_NT | 1028 #ifdef DOS_NT |
884 && drive == -1 | 1029 /* On DOS and Windows, nm is absolute if a drive name was specified; |
1030 use the drive's current directory as the prefix if needed. */ | |
1031 if (!newdir && drive) | |
1032 { | |
1033 /* Get default directory if needed to make nm absolute. */ | |
1034 if (!IS_DIRECTORY_SEP (nm[0])) | |
1035 { | |
1036 newdir = alloca (MAXPATHLEN + 1); | |
1037 if (!getdefdir (toupper (drive) - 'A' + 1, newdir)) | |
1038 newdir = NULL; | |
1039 } | |
1040 if (!newdir) | |
1041 { | |
1042 /* Either nm starts with /, or drive isn't mounted. */ | |
1043 newdir = alloca (4); | |
1044 newdir[0] = DRIVE_LETTER (drive); | |
1045 newdir[1] = ':'; | |
1046 newdir[2] = '/'; | |
1047 newdir[3] = 0; | |
1048 } | |
1049 } | |
885 #endif /* DOS_NT */ | 1050 #endif /* DOS_NT */ |
1051 | |
1052 /* Finally, if no prefix has been specified and nm is not absolute, | |
1053 then it must be expanded relative to default_directory. */ | |
1054 if (1 | |
1055 #ifndef DOS_NT | |
1056 && !IS_ANY_SEP (nm[0]) | |
1057 #endif /* not DOS_NT */ | |
1058 #ifdef WINDOWSNT | |
1059 && !(IS_DIRECTORY_SEP (nm[0]) && IS_DIRECTORY_SEP (nm[1])) | |
1060 #endif | |
886 && !newdir | 1061 && !newdir |
887 && STRINGP (default_)) | 1062 && STRINGP (default_)) |
888 { | 1063 { |
889 newdir = XSTRING_DATA (default_); | 1064 newdir = XSTRING_DATA (default_); |
890 } | 1065 } |
891 | 1066 |
892 #ifdef DOS_NT | 1067 #ifdef DOS_NT |
893 if (newdir == 0 && relpath) | 1068 if (newdir) |
894 newdir = defdir; | 1069 { |
1070 /* First ensure newdir is an absolute name. */ | |
1071 if ( | |
1072 /* Detect MSDOS file names with drive specifiers. */ | |
1073 ! (IS_DRIVE (newdir[0]) | |
1074 && IS_DEVICE_SEP (newdir[1]) && IS_DIRECTORY_SEP (newdir[2])) | |
1075 #ifdef WINDOWSNT | |
1076 /* Detect Windows file names in UNC format. */ | |
1077 && ! (IS_DIRECTORY_SEP (newdir[0]) && IS_DIRECTORY_SEP (newdir[1])) | |
1078 #endif | |
1079 ) | |
1080 { | |
1081 /* Effectively, let newdir be (expand-file-name newdir cwd). | |
1082 Because of the admonition against calling expand-file-name | |
1083 when we have pointers into lisp strings, we accomplish this | |
1084 indirectly by prepending newdir to nm if necessary, and using | |
1085 cwd (or the wd of newdir's drive) as the new newdir. */ | |
1086 | |
1087 if (IS_DRIVE (newdir[0]) && newdir[1] == ':') | |
1088 { | |
1089 drive = newdir[0]; | |
1090 newdir += 2; | |
1091 } | |
1092 if (!IS_DIRECTORY_SEP (nm[0])) | |
1093 { | |
1094 char * tmp = alloca (strlen (newdir) + strlen (nm) + 2); | |
1095 file_name_as_directory (tmp, newdir); | |
1096 strcat (tmp, nm); | |
1097 nm = tmp; | |
1098 } | |
1099 newdir = alloca (MAXPATHLEN + 1); | |
1100 if (drive) | |
1101 { | |
1102 if (!getdefdir (toupper (drive) - 'A' + 1, newdir)) | |
1103 newdir = "/"; | |
1104 } | |
1105 else | |
1106 getwd (newdir); | |
1107 } | |
1108 | |
1109 /* Strip off drive name from prefix, if present. */ | |
1110 if (IS_DRIVE (newdir[0]) && newdir[1] == ':') | |
1111 { | |
1112 drive = newdir[0]; | |
1113 newdir += 2; | |
1114 } | |
1115 | |
1116 /* Keep only a prefix from newdir if nm starts with slash | |
1117 (//server/share for UNC, nothing otherwise). */ | |
1118 if (IS_DIRECTORY_SEP (nm[0]) && collapse_newdir) | |
1119 { | |
1120 #ifdef WINDOWSNT | |
1121 if (IS_DIRECTORY_SEP (newdir[0]) && IS_DIRECTORY_SEP (newdir[1])) | |
1122 { | |
1123 newdir = strcpy (alloca (strlen (newdir) + 1), newdir); | |
1124 p = newdir + 2; | |
1125 while (*p && !IS_DIRECTORY_SEP (*p)) p++; | |
1126 p++; | |
1127 while (*p && !IS_DIRECTORY_SEP (*p)) p++; | |
1128 *p = 0; | |
1129 } | |
1130 else | |
1131 #endif | |
1132 newdir = ""; | |
1133 } | |
1134 } | |
895 #endif /* DOS_NT */ | 1135 #endif /* DOS_NT */ |
896 if (newdir != 0) | 1136 if (newdir != 0) |
897 { | 1137 { |
898 /* Get rid of any slash at the end of newdir. */ | 1138 /* Get rid of any slash at the end of newdir, unless newdir is |
1139 just // (an incomplete UNC name). */ | |
899 int length = strlen ((char *) newdir); | 1140 int length = strlen ((char *) newdir); |
900 /* Adding `length > 1 &&' makes ~ expand into / when homedir | 1141 /* Adding `length > 1 &&' makes ~ expand into / when homedir |
901 is the root dir. People disagree about whether that is right. | 1142 is the root dir. People disagree about whether that is right. |
902 Anyway, we can't take the risk of this change now. */ | 1143 Anyway, we can't take the risk of this change now. */ |
903 #ifdef DOS_NT | 1144 /* Syncing with FSF 19.34.6 note: FSF does the above. */ |
904 if (newdir[1] != ':' && length > 1) | 1145 if (IS_DIRECTORY_SEP (newdir[length - 1]) |
1146 #ifdef WINDOWSNT | |
1147 && !(length == 2 && IS_DIRECTORY_SEP (newdir[0])) | |
905 #endif | 1148 #endif |
906 if (IS_DIRECTORY_SEP (newdir[length - 1])) | 1149 ) |
907 { | 1150 { |
908 Bufbyte *temp = (Bufbyte *) alloca (length); | 1151 Bufbyte *temp = (Bufbyte *) alloca (length); |
909 memcpy (temp, newdir, length - 1); | 1152 memcpy (temp, newdir, length - 1); |
910 temp[length - 1] = 0; | 1153 temp[length - 1] = 0; |
911 newdir = temp; | 1154 newdir = temp; |
922 produces incorrect code if the following two lines are combined.) */ | 1165 produces incorrect code if the following two lines are combined.) */ |
923 target = (Bufbyte *) alloca (tlen + 2); | 1166 target = (Bufbyte *) alloca (tlen + 2); |
924 target += 2; | 1167 target += 2; |
925 #else /* not DOS_NT */ | 1168 #else /* not DOS_NT */ |
926 target = (Bufbyte *) alloca (tlen); | 1169 target = (Bufbyte *) alloca (tlen); |
927 #endif /* not DOS_NT */ | 1170 #endif /* DOS_NT */ |
928 *target = 0; | 1171 *target = 0; |
929 | 1172 |
930 if (newdir) | 1173 if (newdir) |
931 { | 1174 { |
932 if (nm[0] == 0 || IS_DIRECTORY_SEP (nm[0])) | 1175 if (nm[0] == 0 || IS_DIRECTORY_SEP (nm[0])) |
951 else if (IS_DIRECTORY_SEP (p[0]) && IS_DIRECTORY_SEP (p[1]) | 1194 else if (IS_DIRECTORY_SEP (p[0]) && IS_DIRECTORY_SEP (p[1]) |
952 #if defined (APOLLO) || defined (WINDOWSNT) | 1195 #if defined (APOLLO) || defined (WINDOWSNT) |
953 /* // at start of filename is meaningful in Apollo | 1196 /* // at start of filename is meaningful in Apollo |
954 and WindowsNT systems */ | 1197 and WindowsNT systems */ |
955 && o != target | 1198 && o != target |
956 #endif /* APOLLO */ | 1199 #endif /* APOLLO || WINDOWSNT */ |
957 ) | 1200 ) |
958 { | 1201 { |
959 o = target; | 1202 o = target; |
960 p++; | 1203 p++; |
961 } | 1204 } |
975 && o != target | 1218 && o != target |
976 && (IS_DIRECTORY_SEP (p[3]) || p[3] == 0)) | 1219 && (IS_DIRECTORY_SEP (p[3]) || p[3] == 0)) |
977 { | 1220 { |
978 while (o != target && (--o) && !IS_DIRECTORY_SEP (*o)) | 1221 while (o != target && (--o) && !IS_DIRECTORY_SEP (*o)) |
979 ; | 1222 ; |
980 #if defined (APOLLO) || defined (WINDOWSNT) | 1223 if (o == target && IS_ANY_SEP (*o) |
981 if (o == target + 1 | 1224 #ifdef DOS_NT |
982 && IS_DIRECTORY_SEP (o[-1]) && IS_DIRECTORY_SEP (o[0])) | 1225 && p[3] == 0 |
983 ++o; | 1226 #endif |
984 else | 1227 ) |
985 #endif /* APOLLO || WINDOWSNT */ | |
986 if (o == target && IS_ANY_SEP (*o)) | |
987 ++o; | 1228 ++o; |
988 p += 3; | 1229 p += 3; |
989 } | 1230 } |
990 else | 1231 else |
991 { | 1232 { |
992 *o++ = *p++; | 1233 *o++ = *p++; |
993 } | 1234 } |
994 } | 1235 } |
995 | 1236 |
996 #ifdef DOS_NT | 1237 #ifdef DOS_NT |
997 /* at last, set drive name. */ | 1238 /* At last, set drive name. */ |
998 if (target[1] != ':' | |
999 #ifdef WINDOWSNT | 1239 #ifdef WINDOWSNT |
1000 /* Allow network paths that look like "\\foo" */ | 1240 /* Except for network file name. */ |
1001 && !(IS_DIRECTORY_SEP (target[0]) && IS_DIRECTORY_SEP (target[1])) | 1241 if (!(IS_DIRECTORY_SEP (target[0]) && IS_DIRECTORY_SEP (target[1]))) |
1002 #endif /* WINDOWSNT */ | 1242 #endif /* WINDOWSNT */ |
1003 ) | 1243 { |
1004 { | 1244 if (!drive) abort (); |
1005 target -= 2; | 1245 target -= 2; |
1006 target[0] = (drive < 0 ? getdisk () + 'A' : drive); | 1246 target[0] = DRIVE_LETTER (drive); |
1007 target[1] = ':'; | 1247 target[1] = ':'; |
1008 } | 1248 } |
1249 CORRECT_DIR_SEPS (target); | |
1009 #endif /* DOS_NT */ | 1250 #endif /* DOS_NT */ |
1010 | 1251 |
1011 return make_string (target, o - target); | 1252 return make_string (target, o - target); |
1012 } | 1253 } |
1013 | 1254 |
1163 if (!NILP (handler)) | 1404 if (!NILP (handler)) |
1164 return call2_check_string_or_nil (handler, Qsubstitute_in_file_name, | 1405 return call2_check_string_or_nil (handler, Qsubstitute_in_file_name, |
1165 string); | 1406 string); |
1166 | 1407 |
1167 nm = XSTRING_DATA (string); | 1408 nm = XSTRING_DATA (string); |
1168 #ifdef MSDOS | 1409 #ifdef DOS_NT |
1169 dostounix_filename (nm = strcpy (alloca (strlen (nm) + 1), nm)); | 1410 nm = strcpy (alloca (strlen (nm) + 1), nm); |
1170 substituted = !strcmp (nm, XSTRING_DATA (string)); | 1411 CORRECT_DIR_SEPS (nm); |
1412 substituted = (strcmp (nm, XSTRING_DATA (string)) != 0); | |
1171 #endif | 1413 #endif |
1172 endp = nm + XSTRING_LENGTH (string); | 1414 endp = nm + XSTRING_LENGTH (string); |
1173 | 1415 |
1174 /* If /~ or // appears, discard everything through first slash. */ | 1416 /* If /~ or // appears, discard everything through first slash. */ |
1175 | 1417 |
1176 for (p = nm; p != endp; p++) | 1418 for (p = nm; p != endp; p++) |
1177 { | 1419 { |
1178 if ((p[0] == '~' || | 1420 if ((p[0] == '~' |
1179 #ifdef APOLLO | 1421 #if defined (APOLLO) || defined (WINDOWSNT) |
1180 /* // at start of file name is meaningful in Apollo system */ | 1422 /* // at start of file name is meaningful in Apollo and |
1181 (p[0] == '/' && p - 1 != nm) | 1423 WindowsNT systems */ |
1182 #else /* not APOLLO */ | 1424 || (IS_DIRECTORY_SEP (p[0]) && p - 1 != nm) |
1183 #ifdef WINDOWSNT | 1425 #else /* not (APOLLO || WINDOWSNT) */ |
1184 (IS_DIRECTORY_SEP (p[0]) && p - 1 != nm) | 1426 || IS_DIRECTORY_SEP (p[0]) |
1185 #else /* not WINDOWSNT */ | 1427 #endif /* not (APOLLO || WINDOWSNT) */ |
1186 p[0] == '/' | |
1187 #endif /* not WINDOWSNT */ | |
1188 #endif /* not APOLLO */ | |
1189 ) | 1428 ) |
1190 && p != nm | 1429 && p != nm |
1191 && (IS_DIRECTORY_SEP (p[-1]))) | 1430 && (IS_DIRECTORY_SEP (p[-1]))) |
1192 { | 1431 { |
1193 nm = p; | 1432 nm = p; |
1194 substituted = 1; | 1433 substituted = 1; |
1195 } | 1434 } |
1196 #ifdef DOS_NT | 1435 #ifdef DOS_NT |
1197 if (p[0] && p[1] == ':') | 1436 /* see comment in expand-file-name about drive specifiers */ |
1437 else if (IS_DRIVE (p[0]) && p[1] == ':' | |
1438 && p > nm && IS_DIRECTORY_SEP (p[-1])) | |
1198 { | 1439 { |
1199 nm = p; | 1440 nm = p; |
1200 substituted = 1; | 1441 substituted = 1; |
1201 } | 1442 } |
1202 #endif /* DOS_NT */ | 1443 #endif /* DOS_NT */ |
1307 | 1548 |
1308 /* If /~ or // appears, discard everything through first slash. */ | 1549 /* If /~ or // appears, discard everything through first slash. */ |
1309 | 1550 |
1310 for (p = xnm; p != x; p++) | 1551 for (p = xnm; p != x; p++) |
1311 if ((p[0] == '~' | 1552 if ((p[0] == '~' |
1312 #ifdef APOLLO | 1553 #if defined (APOLLO) || defined (WINDOWSNT) |
1313 /* // at start of file name is meaningful in Apollo system */ | |
1314 || (p[0] == '/' && p - 1 != xnm) | |
1315 #else /* not APOLLO */ | |
1316 #ifdef WINDOWSNT | |
1317 || (IS_DIRECTORY_SEP (p[0]) && p - 1 != xnm) | 1554 || (IS_DIRECTORY_SEP (p[0]) && p - 1 != xnm) |
1318 #else /* not WINDOWSNT */ | 1555 #else /* not (APOLLO || WINDOWSNT) */ |
1319 || p[0] == '/' | 1556 || IS_DIRECTORY_SEP (p[0]) |
1320 #endif /* not WINDOWSNT */ | 1557 #endif /* APOLLO || WINDOWSNT */ |
1321 #endif /* not APOLLO */ | |
1322 ) | 1558 ) |
1323 /* don't do p[-1] if that would go off the beginning --jwz */ | 1559 /* don't do p[-1] if that would go off the beginning --jwz */ |
1324 && p != nm && p > xnm && IS_DIRECTORY_SEP (p[-1])) | 1560 && p != nm && p > xnm && IS_DIRECTORY_SEP (p[-1])) |
1325 xnm = p; | 1561 xnm = p; |
1326 #ifdef DOS_NT | 1562 #ifdef DOS_NT |
1327 else if (p[0] && p[1] == ':') | 1563 else if (IS_DRIVE (p[0]) && p[1] == ':' |
1564 && p > nm && IS_DIRECTORY_SEP (p[-1])) | |
1328 xnm = p; | 1565 xnm = p; |
1329 #endif | 1566 #endif |
1330 | 1567 |
1331 return make_string (xnm, x - xnm); | 1568 return make_string (xnm, x - xnm); |
1332 | 1569 |
1340 | 1577 |
1341 /* NOTREACHED */ | 1578 /* NOTREACHED */ |
1342 return Qnil; /* suppress compiler warning */ | 1579 return Qnil; /* suppress compiler warning */ |
1343 } | 1580 } |
1344 | 1581 |
1345 /* (directory-file-name (expand-file-name FOO)) */ | 1582 /* A slightly faster and more convenient way to get |
1583 (directory-file-name (expand-file-name FOO)). */ | |
1346 | 1584 |
1347 Lisp_Object | 1585 Lisp_Object |
1348 expand_and_dir_to_file (Lisp_Object filename, Lisp_Object defdir) | 1586 expand_and_dir_to_file (Lisp_Object filename, Lisp_Object defdir) |
1349 { | 1587 { |
1350 /* This function can call lisp */ | 1588 /* This function can call lisp */ |
1750 if (NILP (ok_if_already_exists) | 1988 if (NILP (ok_if_already_exists) |
1751 || INTP (ok_if_already_exists)) | 1989 || INTP (ok_if_already_exists)) |
1752 barf_or_query_if_file_exists (newname, "rename to it", | 1990 barf_or_query_if_file_exists (newname, "rename to it", |
1753 INTP (ok_if_already_exists), 0); | 1991 INTP (ok_if_already_exists), 0); |
1754 | 1992 |
1755 #ifdef WINDOWSNT | 1993 /* Syncing with FSF 19.34.6 note: FSF does not have conditional code for |
1756 if (!MoveFile (XSTRING (filename)->_data, XSTRING (newname)->_data)) | 1994 WINDOWSNT here; I've removed it. --marcpa */ |
1757 #else /* not WINDOWSNT */ | 1995 |
1758 /* FSFmacs only calls rename() here under BSD 4.1, and calls | 1996 /* FSFmacs only calls rename() here under BSD 4.1, and calls |
1759 link() and unlink() otherwise, but that's bogus. Sometimes | 1997 link() and unlink() otherwise, but that's bogus. Sometimes |
1760 rename() succeeds where link()/unlink() fail, and we have | 1998 rename() succeeds where link()/unlink() fail, and we have |
1761 configure check for rename() and emulate using link()/unlink() | 1999 configure check for rename() and emulate using link()/unlink() |
1762 if necessary. */ | 2000 if necessary. */ |
1763 if (0 > rename ((char *) XSTRING_DATA (filename), | 2001 if (0 > rename ((char *) XSTRING_DATA (filename), |
1764 (char *) XSTRING_DATA (newname))) | 2002 (char *) XSTRING_DATA (newname))) |
1765 #endif /* not WINDOWSNT */ | 2003 { |
1766 { | |
1767 #ifdef WINDOWSNT | |
1768 /* Why two? And why doesn't MS document what MoveFile will return? */ | |
1769 if (GetLastError () == ERROR_FILE_EXISTS | |
1770 || GetLastError () == ERROR_ALREADY_EXISTS) | |
1771 #else /* not WINDOWSNT */ | |
1772 if (errno == EXDEV) | 2004 if (errno == EXDEV) |
1773 #endif /* not WINDOWSNT */ | |
1774 { | 2005 { |
1775 Fcopy_file (filename, newname, | 2006 Fcopy_file (filename, newname, |
1776 /* We have already prompted if it was an integer, | 2007 /* We have already prompted if it was an integer, |
1777 so don't have copy-file prompt again. */ | 2008 so don't have copy-file prompt again. */ |
1778 ((NILP (ok_if_already_exists)) ? Qnil : Qt), | 2009 ((NILP (ok_if_already_exists)) ? Qnil : Qt), |
1824 | 2055 |
1825 if (NILP (ok_if_already_exists) | 2056 if (NILP (ok_if_already_exists) |
1826 || INTP (ok_if_already_exists)) | 2057 || INTP (ok_if_already_exists)) |
1827 barf_or_query_if_file_exists (newname, "make it a new name", | 2058 barf_or_query_if_file_exists (newname, "make it a new name", |
1828 INTP (ok_if_already_exists), 0); | 2059 INTP (ok_if_already_exists), 0); |
1829 #ifdef WINDOWSNT | 2060 /* Syncing with FSF 19.34.6 note: FSF does not report a file error |
2061 on NT here. --marcpa */ | |
2062 #if 0 /* defined(WINDOWSNT) */ | |
1830 /* Windows does not support this operation. */ | 2063 /* Windows does not support this operation. */ |
1831 report_file_error ("Adding new name", Flist (2, &filename)); | 2064 report_file_error ("Adding new name", Flist (2, &filename)); |
1832 #else /* not WINDOWSNT */ | 2065 #else /* not 0 -- defined(WINDOWSNT) */ |
1833 | 2066 |
1834 unlink ((char *) XSTRING_DATA (newname)); | 2067 unlink ((char *) XSTRING_DATA (newname)); |
1835 if (0 > link ((char *) XSTRING_DATA (filename), | 2068 if (0 > link ((char *) XSTRING_DATA (filename), |
1836 (char *) XSTRING_DATA (newname))) | 2069 (char *) XSTRING_DATA (newname))) |
1837 { | 2070 { |
1838 report_file_error ("Adding new name", | 2071 report_file_error ("Adding new name", |
1839 list2 (filename, newname)); | 2072 list2 (filename, newname)); |
1840 } | 2073 } |
1841 #endif /* not WINDOWSNT */ | 2074 #endif /* 0 -- defined(WINDOWSNT) */ |
1842 | 2075 |
1843 UNGCPRO; | 2076 UNGCPRO; |
1844 return Qnil; | 2077 return Qnil; |
1845 } | 2078 } |
1846 | 2079 |
1863 CHECK_STRING (filename); | 2096 CHECK_STRING (filename); |
1864 CHECK_STRING (linkname); | 2097 CHECK_STRING (linkname); |
1865 /* If the link target has a ~, we must expand it to get | 2098 /* If the link target has a ~, we must expand it to get |
1866 a truly valid file name. Otherwise, do not expand; | 2099 a truly valid file name. Otherwise, do not expand; |
1867 we want to permit links to relative file names. */ | 2100 we want to permit links to relative file names. */ |
1868 if (XSTRING_BYTE (filename, 0) == '~') /* #### Un*x-specific */ | 2101 if (XSTRING_BYTE (filename, 0) == '~') |
1869 filename = Fexpand_file_name (filename, Qnil); | 2102 filename = Fexpand_file_name (filename, Qnil); |
1870 linkname = Fexpand_file_name (linkname, Qnil); | 2103 linkname = Fexpand_file_name (linkname, Qnil); |
1871 | 2104 |
1872 /* If the file name has special constructs in it, | 2105 /* If the file name has special constructs in it, |
1873 call the corresponding file handler. */ | 2106 call the corresponding file handler. */ |
1942 | 2175 |
1943 CHECK_STRING (filename); | 2176 CHECK_STRING (filename); |
1944 ptr = XSTRING_DATA (filename); | 2177 ptr = XSTRING_DATA (filename); |
1945 if (IS_DIRECTORY_SEP (*ptr) || *ptr == '~' | 2178 if (IS_DIRECTORY_SEP (*ptr) || *ptr == '~' |
1946 #ifdef DOS_NT | 2179 #ifdef DOS_NT |
1947 || (*ptr != 0 && ptr[1] == ':' && (ptr[2] == '/' || ptr[2] == '\\')) | 2180 || (IS_DRIVE (*ptr) && ptr[1] == ':' && IS_DIRECTORY_SEP (ptr[2])) |
1948 #endif | 2181 #endif |
1949 ) | 2182 ) |
1950 return Qt; | 2183 return Qt; |
1951 else | 2184 else |
1952 return Qnil; | 2185 return Qnil; |
1961 int len = strlen (filename); | 2194 int len = strlen (filename); |
1962 char *suffix; | 2195 char *suffix; |
1963 struct stat st; | 2196 struct stat st; |
1964 if (stat (filename, &st) < 0) | 2197 if (stat (filename, &st) < 0) |
1965 return 0; | 2198 return 0; |
2199 #if defined (WINDOWSNT) | |
2200 return ((st.st_mode & S_IEXEC) != 0); | |
2201 #else | |
1966 return (S_ISREG (st.st_mode) | 2202 return (S_ISREG (st.st_mode) |
1967 && len >= 5 | 2203 && len >= 5 |
1968 && (stricmp ((suffix = filename + len-4), ".com") == 0 | 2204 && (stricmp ((suffix = filename + len-4), ".com") == 0 |
1969 || stricmp (suffix, ".exe") == 0 | 2205 || stricmp (suffix, ".exe") == 0 |
1970 || stricmp (suffix, ".bat") == 0) | 2206 || stricmp (suffix, ".bat") == 0) |
1971 || (st.st_mode & S_IFMT) == S_IFDIR); | 2207 || (st.st_mode & S_IFMT) == S_IFDIR); |
2208 #endif /* not WINDOWSNT */ | |
1972 #else /* not DOS_NT */ | 2209 #else /* not DOS_NT */ |
1973 #ifdef HAVE_EACCESS | 2210 #ifdef HAVE_EACCESS |
1974 return eaccess (filename, 1) >= 0; | 2211 return eaccess (filename, 1) >= 0; |
1975 #else | 2212 #else |
1976 /* Access isn't quite right because it uses the real uid | 2213 /* Access isn't quite right because it uses the real uid |
2082 handler = Ffind_file_name_handler (abspath, Qfile_readable_p); | 2319 handler = Ffind_file_name_handler (abspath, Qfile_readable_p); |
2083 UNGCPRO; | 2320 UNGCPRO; |
2084 if (!NILP (handler)) | 2321 if (!NILP (handler)) |
2085 return call2 (handler, Qfile_readable_p, abspath); | 2322 return call2 (handler, Qfile_readable_p, abspath); |
2086 | 2323 |
2324 #ifdef DOS_NT | |
2325 /* Under MS-DOS and Windows, open does not work for directories. */ | |
2326 if (access (XSTRING_DATA (abspath), 0) == 0) | |
2327 return Qt; | |
2328 return Qnil; | |
2329 #else /* not DOS_NT */ | |
2087 desc = open ((char *) XSTRING_DATA (abspath), O_RDONLY, 0); | 2330 desc = open ((char *) XSTRING_DATA (abspath), O_RDONLY, 0); |
2088 if (desc < 0) | 2331 if (desc < 0) |
2089 return Qnil; | 2332 return Qnil; |
2090 close (desc); | 2333 close (desc); |
2091 return Qt; | 2334 return Qt; |
2335 #endif /* not DOS_NT */ | |
2092 } | 2336 } |
2093 | 2337 |
2094 /* Having this before file-symlink-p mysteriously caused it to be forgotten | 2338 /* Having this before file-symlink-p mysteriously caused it to be forgotten |
2095 on the RT/PC. */ | 2339 on the RT/PC. */ |
2096 DEFUN ("file-writable-p", Ffile_writable_p, 1, 1, 0, /* | 2340 DEFUN ("file-writable-p", Ffile_writable_p, 1, 1, 0, /* |
2236 handler = Ffind_file_name_handler (filename, Qfile_accessible_directory_p); | 2480 handler = Ffind_file_name_handler (filename, Qfile_accessible_directory_p); |
2237 if (!NILP (handler)) | 2481 if (!NILP (handler)) |
2238 return call2 (handler, Qfile_accessible_directory_p, | 2482 return call2 (handler, Qfile_accessible_directory_p, |
2239 filename); | 2483 filename); |
2240 | 2484 |
2485 #if !defined(DOS_NT) | |
2241 if (NILP (Ffile_directory_p (filename))) | 2486 if (NILP (Ffile_directory_p (filename))) |
2242 return (Qnil); | 2487 return (Qnil); |
2243 else | 2488 else |
2244 return Ffile_executable_p (filename); | 2489 return Ffile_executable_p (filename); |
2490 #else | |
2491 { | |
2492 int tem; | |
2493 struct gcpro gcpro1; | |
2494 /* It's an unlikely combination, but yes we really do need to gcpro: | |
2495 Suppose that file-accessible-directory-p has no handler, but | |
2496 file-directory-p does have a handler; this handler causes a GC which | |
2497 relocates the string in `filename'; and finally file-directory-p | |
2498 returns non-nil. Then we would end up passing a garbaged string | |
2499 to file-executable-p. */ | |
2500 GCPRO1 (filename); | |
2501 tem = (NILP (Ffile_directory_p (filename)) | |
2502 || NILP (Ffile_executable_p (filename))); | |
2503 UNGCPRO; | |
2504 return tem ? Qnil : Qt; | |
2505 } | |
2506 #endif /* !defined(DOS_NT) */ | |
2245 } | 2507 } |
2246 | 2508 |
2247 DEFUN ("file-regular-p", Ffile_regular_p, 1, 1, 0, /* | 2509 DEFUN ("file-regular-p", Ffile_regular_p, 1, 1, 0, /* |
2248 "Return t if file FILENAME is the name of a regular file. | 2510 "Return t if file FILENAME is the name of a regular file. |
2249 This is the sort of file that holds an ordinary stream of data bytes. | 2511 This is the sort of file that holds an ordinary stream of data bytes. |
2297 if (!NILP (handler)) | 2559 if (!NILP (handler)) |
2298 return call2 (handler, Qfile_modes, abspath); | 2560 return call2 (handler, Qfile_modes, abspath); |
2299 | 2561 |
2300 if (stat ((char *) XSTRING_DATA (abspath), &st) < 0) | 2562 if (stat ((char *) XSTRING_DATA (abspath), &st) < 0) |
2301 return Qnil; | 2563 return Qnil; |
2564 /* Syncing with FSF 19.34.6 note: not in FSF, #if 0'ed out here. */ | |
2565 #if 0 | |
2302 #ifdef DOS_NT | 2566 #ifdef DOS_NT |
2303 if (check_executable (XSTRING (abspath)->_data)) | 2567 if (check_executable (XSTRING (abspath)->_data)) |
2304 st.st_mode |= S_IEXEC; | 2568 st.st_mode |= S_IEXEC; |
2305 #endif /* DOS_NT */ | 2569 #endif /* DOS_NT */ |
2570 #endif /* 0 */ | |
2306 | 2571 |
2307 return make_int (st.st_mode & 07777); | 2572 return make_int (st.st_mode & 07777); |
2308 } | 2573 } |
2309 | 2574 |
2310 DEFUN ("set-file-modes", Fset_file_modes, 2, 2, 0, /* | 2575 DEFUN ("set-file-modes", Fset_file_modes, 2, 2, 0, /* |
2428 } | 2693 } |
2429 | 2694 |
2430 | 2695 |
2431 #ifdef DOS_NT | 2696 #ifdef DOS_NT |
2432 Lisp_Object Qfind_buffer_file_type; | 2697 Lisp_Object Qfind_buffer_file_type; |
2698 | |
2699 /* Return 1 if buffer is text, 0 if binary. */ | |
2700 static int | |
2701 decide_buffer_type (unsigned char * buffer, int nbytes) | |
2702 { | |
2703 /* Buffer is binary if we find any LF chars not preceeded by CR or if | |
2704 the buffer doesn't contain at least 1 line. */ | |
2705 unsigned lines = 0; | |
2706 unsigned char *p, *q; | |
2707 | |
2708 for (p = buffer; nbytes > 0 && (q = memchr (p, '\n', nbytes)) != NULL; | |
2709 p = q + 1 ) | |
2710 { | |
2711 nbytes -= (q + 1 - p); | |
2712 lines++; | |
2713 if (q > buffer && q[-1] != '\r') | |
2714 return 0; | |
2715 } | |
2716 | |
2717 /* If we haven't seen any line endings yet, return -1 (meaning type is | |
2718 undecided) so we can examine the next bufferful as well. */ | |
2719 return (lines > 0) ? 1 : -1; | |
2720 } | |
2721 | |
2722 /* XEmacs addition: like decide_buffer_type(), but working on a XEmacs buffer: | |
2723 first arg is a byte index position instead of a char pointer; | |
2724 we check each char sequentially. --marcpa */ | |
2725 static int | |
2726 buf_decide_buffer_type (struct buffer *buf, Bytind start, int nbytes) | |
2727 { | |
2728 /* Buffer is binary if we find any LF chars not preceeded by CR or if | |
2729 the buffer doesn't contain at least 1 line. */ | |
2730 unsigned lines = 0; | |
2731 Bytind cur = start; | |
2732 | |
2733 while (nbytes) | |
2734 { | |
2735 if (BI_BUF_FETCH_CHAR(buf, cur) == '\n') | |
2736 { | |
2737 lines++; | |
2738 if (cur != start && BI_BUF_FETCH_CHAR(buf, cur - 1) != '\r') | |
2739 return 0; | |
2740 } | |
2741 nbytes--; | |
2742 } | |
2743 | |
2744 /* If we haven't seen any line endings yet, return -1 (meaning type is | |
2745 undecided) so we can examine the next bufferful as well. */ | |
2746 return (lines > 0) ? 1 : -1; | |
2747 } | |
2433 #endif /* DOS_NT */ | 2748 #endif /* DOS_NT */ |
2434 | 2749 |
2435 /* Stack sizes > 2**16 is a good way to elicit compiler bugs */ | 2750 /* Stack sizes > 2**16 is a good way to elicit compiler bugs */ |
2436 /* #define READ_BUF_SIZE (2 << 16) */ | 2751 /* #define READ_BUF_SIZE (2 << 16) */ |
2437 #define READ_BUF_SIZE (1 << 15) | 2752 #define READ_BUF_SIZE (1 << 15) |
2468 Bufbyte read_buf[READ_BUF_SIZE]; | 2783 Bufbyte read_buf[READ_BUF_SIZE]; |
2469 int mc_count; | 2784 int mc_count; |
2470 struct buffer *buf = current_buffer; | 2785 struct buffer *buf = current_buffer; |
2471 Lisp_Object curbuf; | 2786 Lisp_Object curbuf; |
2472 int not_regular = 0; | 2787 int not_regular = 0; |
2788 #ifdef DOS_NT | |
2789 int crlf_conversion_required = 0; | |
2790 unsigned crlf_count = 0; | |
2791 unsigned lf_count = 0; | |
2792 #endif | |
2473 | 2793 |
2474 if (buf->base_buffer && ! NILP (visit)) | 2794 if (buf->base_buffer && ! NILP (visit)) |
2475 error ("Cannot do file visiting in an indirect buffer"); | 2795 error ("Cannot do file visiting in an indirect buffer"); |
2476 | 2796 |
2477 /* No need to call Fbarf_if_buffer_read_only() here. | 2797 /* No need to call Fbarf_if_buffer_read_only() here. |
2584 { | 2904 { |
2585 end = make_int (st.st_size); | 2905 end = make_int (st.st_size); |
2586 if (XINT (end) != st.st_size) | 2906 if (XINT (end) != st.st_size) |
2587 error ("Maximum buffer size exceeded"); | 2907 error ("Maximum buffer size exceeded"); |
2588 } | 2908 } |
2909 | |
2910 #ifdef DOS_NT | |
2911 /* Permit old behaviour if desired. */ | |
2912 if (NILP (Vinsert_file_contents_allow_replace) && !NILP (replace)) | |
2913 { | |
2914 replace = Qnil; | |
2915 /* Surely this was never right! */ | |
2916 /* XSETFASTINT (beg, 0); | |
2917 XSETFASTINT (end, st.st_size); */ | |
2918 buffer_delete_range (buf, BUF_BEGV(buf), BUF_ZV(buf), | |
2919 !NILP (visit) ? INSDEL_NO_LOCKING : 0); | |
2920 } | |
2921 #endif /* DOS_NT */ | |
2589 } | 2922 } |
2590 | 2923 |
2591 /* If requested, replace the accessible part of the buffer | 2924 /* If requested, replace the accessible part of the buffer |
2592 with the file contents. Avoid replacing text at the | 2925 with the file contents. Avoid replacing text at the |
2593 beginning or end of the buffer that matches the file contents; | 2926 beginning or end of the buffer that matches the file contents; |
2594 that preserves markers pointing to the unchanged parts. */ | 2927 that preserves markers pointing to the unchanged parts. */ |
2595 #if !defined (DOS_NT) && !defined (MULE) | 2928 #if !defined (MULE) |
2596 /* The replace-mode code currently only works when the assumption | 2929 /* The replace-mode code currently only works when the assumption |
2597 'one byte == one char' holds true. This fails under MSDOS and | 2930 'one byte == one char' holds true. This fails Mule because |
2598 Windows NT (because newlines are represented as CR-LF in text | 2931 files may contain multibyte characters. It holds under Windows NT |
2599 files) and under Mule because files may contain multibyte characters. */ | 2932 provided we convert CRLF into LF. */ |
2600 # define FSFMACS_SPEEDY_INSERT | 2933 # define FSFMACS_SPEEDY_INSERT |
2601 #endif | 2934 #endif |
2602 #ifndef FSFMACS_SPEEDY_INSERT | 2935 #ifndef FSFMACS_SPEEDY_INSERT |
2603 if (!NILP (replace)) | 2936 if (!NILP (replace)) |
2604 { | 2937 { |
2610 { | 2943 { |
2611 char buffer[1 << 14]; | 2944 char buffer[1 << 14]; |
2612 Bufpos same_at_start = BUF_BEGV (buf); | 2945 Bufpos same_at_start = BUF_BEGV (buf); |
2613 Bufpos same_at_end = BUF_ZV (buf); | 2946 Bufpos same_at_end = BUF_ZV (buf); |
2614 int overlap; | 2947 int overlap; |
2948 #ifdef DOS_NT | |
2949 /* Syncing with 19.34.6 note: same_at_start_in_file and | |
2950 same_at_end_in_file are not in XEmacs 20.4. | |
2951 First try to introduce them as-is and see what happens. | |
2952 Might be necessary to use constructs like | |
2953 st.st_size - (BUF_ZV (buf) - same_at_end) | |
2954 instead. | |
2955 --marcpa | |
2956 */ | |
2957 /* Offset into the file where discrepancy begins. */ | |
2958 int same_at_start_in_file = 0; | |
2959 /* Offset into the file where discrepancy ends. */ | |
2960 int same_at_end_in_file = st.st_size; | |
2961 /* DOS_NT only: is there a `\r' character left in the buffer? */ | |
2962 int cr_left_in_buffer = 0; | |
2963 /* DOS_NT only: was `\n' the first character in previous bufferful? */ | |
2964 int last_was_lf = 0; | |
2965 | |
2966 /* Demacs 1.1.1 91/10/16 HIRANO Satoshi, MW July 1993 */ | |
2967 /* Determine file type (text/binary) from its name. | |
2968 Note that the buffer_file_type changes here when the file | |
2969 being inserted is not of the same type as the original buffer. */ | |
2970 current_buffer->buffer_file_type = call1 (Qfind_buffer_file_type, filename); | |
2971 if (NILP (current_buffer->buffer_file_type)) | |
2972 crlf_conversion_required = 1; | |
2973 else if (current_buffer->buffer_file_type != Qt) | |
2974 /* Use heuristic to decide whether file is text or binary (based | |
2975 on the first bufferful) if buffer-file-type is not nil or t. | |
2976 If no decision is made (because no line endings were ever | |
2977 seen) then let buffer-file-type default to nil. */ | |
2978 crlf_conversion_required = -1; | |
2979 #endif /* DOS_NT */ | |
2615 | 2980 |
2616 /* Count how many chars at the start of the file | 2981 /* Count how many chars at the start of the file |
2617 match the text at the beginning of the buffer. */ | 2982 match the text at the beginning of the buffer. */ |
2618 while (1) | 2983 while (1) |
2619 { | 2984 { |
2620 int nread; | 2985 int nread; |
2621 Bufpos bufpos; | 2986 Bufpos bufpos; |
2622 | 2987 #ifdef DOS_NT |
2988 if (cr_left_in_buffer) | |
2989 { | |
2990 nread = read_allowing_quit (fd, buffer + 1, sizeof(buffer) - 1); | |
2991 cr_left_in_buffer = 0; | |
2992 if (nread >= 0) | |
2993 nread++; | |
2994 } | |
2995 else | |
2996 #endif /* DOS_NT */ | |
2623 nread = read_allowing_quit (fd, buffer, sizeof buffer); | 2997 nread = read_allowing_quit (fd, buffer, sizeof buffer); |
2624 if (nread < 0) | 2998 if (nread < 0) |
2625 error ("IO error reading %s: %s", | 2999 error ("IO error reading %s: %s", |
2626 XSTRING_DATA (filename), strerror (errno)); | 3000 XSTRING_DATA (filename), strerror (errno)); |
2627 else if (nread == 0) | 3001 else if (nread == 0) |
2628 break; | 3002 break; |
2629 bufpos = 0; | 3003 bufpos = 0; |
3004 #ifdef DOS_NT | |
3005 /* If requested, we do a simple check on the first bufferful | |
3006 to decide whether the file is binary or text. (If text, we | |
3007 count LF and CRLF occurences to determine whether the file | |
3008 was in Unix or DOS format.) */ | |
3009 if (crlf_conversion_required < 0) | |
3010 { | |
3011 crlf_conversion_required = decide_buffer_type (buffer, nread); | |
3012 current_buffer->buffer_file_type = | |
3013 crlf_conversion_required ? Qnil : Qt; | |
3014 } | |
3015 | |
3016 /* DOS_NT text files require that we ignore a `\r' before a `\n'. */ | |
3017 if (crlf_conversion_required > 0) | |
3018 while (bufpos < nread && same_at_start < BUF_ZV (buf)) | |
3019 { | |
3020 int filec = buffer[bufpos]; | |
3021 int bufc = BUF_FETCH_CHAR (buf, same_at_start); | |
3022 | |
3023 if (filec == '\n') | |
3024 lf_count++; | |
3025 | |
3026 if (filec == bufc) | |
3027 same_at_start++, bufpos++, same_at_start_in_file++; | |
3028 else if (filec == '\r' && bufc == '\n') | |
3029 { | |
3030 /* If the `\r' is the last character in this buffer, | |
3031 it will be examined with the next bufferful. */ | |
3032 if (bufpos == nread) | |
3033 { | |
3034 buffer[0] = filec; | |
3035 cr_left_in_buffer = 1; | |
3036 } | |
3037 else if (buffer[bufpos + 1] == bufc) | |
3038 { | |
3039 bufpos += 2; | |
3040 same_at_start_in_file += 2; | |
3041 same_at_start++; | |
3042 crlf_count++; | |
3043 lf_count++; | |
3044 } | |
3045 else | |
3046 break; | |
3047 } | |
3048 else | |
3049 break; | |
3050 } | |
3051 else | |
3052 #endif /* DOS_NT */ | |
2630 while (bufpos < nread && same_at_start < BUF_ZV (buf) | 3053 while (bufpos < nread && same_at_start < BUF_ZV (buf) |
2631 && BUF_FETCH_CHAR (buf, same_at_start) == buffer[bufpos]) | 3054 && BUF_FETCH_CHAR (buf, same_at_start) == buffer[bufpos]) |
3055 #ifdef DOS_NT | |
3056 same_at_start_in_file++, | |
3057 #endif | |
2632 same_at_start++, bufpos++; | 3058 same_at_start++, bufpos++; |
2633 /* If we found a discrepancy, stop the scan. | 3059 /* If we found a discrepancy, stop the scan. |
2634 Otherwise loop around and scan the next bufferfull. */ | 3060 Otherwise loop around and scan the next bufferful. */ |
2635 if (bufpos != nread) | 3061 if (bufpos != nread) |
2636 break; | 3062 break; |
2637 } | 3063 } |
2638 /* If the file matches the buffer completely, | 3064 /* If the file matches the buffer completely, |
2639 there's no need to replace anything. */ | 3065 there's no need to replace anything. */ |
3066 #ifdef DOS_NT | |
3067 if (same_at_start_in_file == st.st_size) | |
3068 #else | |
2640 if (same_at_start - BUF_BEGV (buf) == st.st_size) | 3069 if (same_at_start - BUF_BEGV (buf) == st.st_size) |
3070 #endif /* DOS_NT */ | |
2641 { | 3071 { |
2642 close (fd); | 3072 close (fd); |
2643 unbind_to (speccount, Qnil); | 3073 unbind_to (speccount, Qnil); |
2644 /* Truncate the buffer to the size of the file. */ | 3074 /* Truncate the buffer to the size of the file. */ |
2645 buffer_delete_range (buf, same_at_start, same_at_end, | 3075 buffer_delete_range (buf, same_at_start, same_at_end, |
2652 { | 3082 { |
2653 int total_read, nread; | 3083 int total_read, nread; |
2654 Bufpos bufpos, curpos, trial; | 3084 Bufpos bufpos, curpos, trial; |
2655 | 3085 |
2656 /* At what file position are we now scanning? */ | 3086 /* At what file position are we now scanning? */ |
3087 #ifdef DOS_NT | |
3088 curpos = same_at_end_in_file; | |
3089 #else | |
2657 curpos = st.st_size - (BUF_ZV (buf) - same_at_end); | 3090 curpos = st.st_size - (BUF_ZV (buf) - same_at_end); |
3091 #endif /* DOS_NT */ | |
2658 /* If the entire file matches the buffer tail, stop the scan. */ | 3092 /* If the entire file matches the buffer tail, stop the scan. */ |
2659 if (curpos == 0) | 3093 if (curpos == 0) |
2660 break; | 3094 break; |
2661 /* How much can we scan in the next step? */ | 3095 /* How much can we scan in the next step? */ |
2662 trial = min (curpos, sizeof buffer); | 3096 trial = min (curpos, sizeof buffer); |
2672 if (nread <= 0) | 3106 if (nread <= 0) |
2673 error ("IO error reading %s: %s", | 3107 error ("IO error reading %s: %s", |
2674 XSTRING_DATA (filename), strerror (errno)); | 3108 XSTRING_DATA (filename), strerror (errno)); |
2675 total_read += nread; | 3109 total_read += nread; |
2676 } | 3110 } |
2677 /* Scan this bufferfull from the end, comparing with | 3111 /* Scan this bufferful from the end, comparing with |
2678 the Emacs buffer. */ | 3112 the Emacs buffer. */ |
2679 bufpos = total_read; | 3113 bufpos = total_read; |
3114 #ifdef DOS_NT | |
3115 /* DOS_NT text files require that we ignore a `\r' before a `\n'. */ | |
3116 if (crlf_conversion_required) | |
3117 #endif /* DOS_NT */ | |
2680 /* Compare with same_at_start to avoid counting some buffer text | 3118 /* Compare with same_at_start to avoid counting some buffer text |
2681 as matching both at the file's beginning and at the end. */ | 3119 as matching both at the file's beginning and at the end. */ |
3120 #if !defined(DOS_NT) | |
2682 while (bufpos > 0 && same_at_end > same_at_start | 3121 while (bufpos > 0 && same_at_end > same_at_start |
2683 && BUF_FETCH_CHAR (buf, same_at_end - 1) == | 3122 && BUF_FETCH_CHAR (buf, same_at_end - 1) == |
2684 buffer[bufpos - 1]) | 3123 buffer[bufpos - 1]) |
2685 same_at_end--, bufpos--; | 3124 same_at_end--, bufpos--; |
3125 #else /* DOS_NT */ | |
3126 while (bufpos > 0 && same_at_end > same_at_start | |
3127 && same_at_end_in_file > same_at_start_in_file) | |
3128 { | |
3129 int filec = buffer[bufpos - 1]; | |
3130 int bufc = BUF_FETCH_CHAR (buf, same_at_end - 1); | |
3131 | |
3132 /* Account for `\n' in previous bufferful. */ | |
3133 if (last_was_lf && filec == '\r') | |
3134 { | |
3135 same_at_end_in_file--, bufpos--; | |
3136 last_was_lf = 0; | |
3137 crlf_count++; | |
3138 } | |
3139 else if (filec == bufc) | |
3140 { | |
3141 last_was_lf = 0; | |
3142 same_at_end--, same_at_end_in_file--, bufpos--; | |
3143 if (bufc == '\n') | |
3144 { | |
3145 lf_count++; | |
3146 if (bufpos <= 0) | |
3147 last_was_lf = 1; | |
3148 else if (same_at_end_in_file <= same_at_start_in_file) | |
3149 break; | |
3150 else if (buffer[bufpos - 1] == '\r') | |
3151 same_at_end_in_file--, bufpos--, crlf_count++; | |
3152 } | |
3153 } | |
3154 else | |
3155 { | |
3156 last_was_lf = 0; | |
3157 break; | |
3158 } | |
3159 } | |
3160 else | |
3161 while (bufpos > 0 && same_at_end > same_at_start | |
3162 && same_at_end_in_file > same_at_start_in_file | |
3163 && BUF_FETCH_CHAR (buf, same_at_end - 1) == | |
3164 buffer[bufpos - 1]) | |
3165 same_at_end--, same_at_end_in_file--, bufpos--; | |
3166 #endif /* !defined(DOS_NT) */ | |
2686 /* If we found a discrepancy, stop the scan. | 3167 /* If we found a discrepancy, stop the scan. |
2687 Otherwise loop around and scan the preceding bufferfull. */ | 3168 Otherwise loop around and scan the preceding bufferful. */ |
2688 if (bufpos != 0) | 3169 if (bufpos != 0) |
2689 break; | 3170 break; |
2690 /* If display current starts at beginning of line, | 3171 /* If display current starts at beginning of line, |
2691 keep it that way. */ | 3172 keep it that way. */ |
2692 if (XBUFFER (XWINDOW (Fselected_window (Qnil))->buffer) == buf) | 3173 if (XBUFFER (XWINDOW (Fselected_window (Qnil))->buffer) == buf) |
2699 (same_at_end + st.st_size - BUF_ZV (buf)); | 3180 (same_at_end + st.st_size - BUF_ZV (buf)); |
2700 if (overlap > 0) | 3181 if (overlap > 0) |
2701 same_at_end += overlap; | 3182 same_at_end += overlap; |
2702 | 3183 |
2703 /* Arrange to read only the nonmatching middle part of the file. */ | 3184 /* Arrange to read only the nonmatching middle part of the file. */ |
3185 #ifdef DOS_NT | |
3186 beg = make_int (same_at_start_in_file); | |
3187 end = make_int (same_at_end_in_file); | |
3188 #else | |
2704 beg = make_int (same_at_start - BUF_BEGV (buf)); | 3189 beg = make_int (same_at_start - BUF_BEGV (buf)); |
2705 end = make_int (st.st_size - (BUF_ZV (buf) - same_at_end)); | 3190 end = make_int (st.st_size - (BUF_ZV (buf) - same_at_end)); |
3191 #endif /* DOS_NT */ | |
2706 | 3192 |
2707 buffer_delete_range (buf, same_at_start, same_at_end, | 3193 buffer_delete_range (buf, same_at_start, same_at_end, |
2708 !NILP (visit) ? INSDEL_NO_LOCKING : 0); | 3194 !NILP (visit) ? INSDEL_NO_LOCKING : 0); |
2709 /* Insert from the file at the proper position. */ | 3195 /* Insert from the file at the proper position. */ |
2710 BUF_SET_PT (buf, same_at_start); | 3196 BUF_SET_PT (buf, same_at_start); |
2773 { | 3259 { |
2774 if (this_len < 0) | 3260 if (this_len < 0) |
2775 saverrno = errno; | 3261 saverrno = errno; |
2776 break; | 3262 break; |
2777 } | 3263 } |
3264 #ifdef DOS_NT | |
3265 /* XEmacs (--marcpa) change: FSF does buffer_insert_raw_string_1() first | |
3266 then checks if conversion is needed, calling lisp | |
3267 (find-buffer-file-type) which can call a user-function that | |
3268 might look at the unconverted buffer to decide if | |
3269 conversion is needed. | |
3270 I removed the possibility for lisp functions called from | |
3271 find-buffer-file-type to look at the buffer's content, for | |
3272 simplicity reasons: it is easier to do the CRLF -> LF | |
3273 conversion on read_buf than on buffer contents because | |
3274 BUF_FETCH_CHAR does not return a pointer to an unsigned | |
3275 char memory location, and because we must cope with bytind | |
3276 VS bufpos in XEmacs, thus complicating crlf_to_lf(). | |
3277 This decision (of doing Lstream_read(), crlf_to_lf() then | |
3278 buffer_insert_raw_string_1()) is debatable. | |
3279 --marcpa | |
3280 */ | |
3281 /* Following FSF note no longer apply now. See comment above. | |
3282 --marcpa*/ | |
3283 /* For compatability with earlier versions that did not support the | |
3284 REPLACE funtionality, we call find-buffer-file-type after inserting | |
3285 the contents to allow it to inspect the inserted data. (This was | |
3286 not intentional usage, but proved to be quite useful.) */ | |
3287 if (NILP (replace)) | |
3288 { | |
3289 /* Demacs 1.1.1 91/10/16 HIRANO Satoshi, MW July 1993 */ | |
3290 /* Determine file type (text/binary) from its name. | |
3291 Note that the buffer_file_type changes here when the file | |
3292 being inserted is not of the same type as the original buffer. */ | |
3293 current_buffer->buffer_file_type = call1 (Qfind_buffer_file_type, filename); | |
3294 if (NILP (current_buffer->buffer_file_type)) | |
3295 crlf_conversion_required = 1; | |
3296 else if (current_buffer->buffer_file_type != Qt) | |
3297 /* Use heuristic to decide whether file is text or binary (based | |
3298 on the first bufferful) if buffer-file-type is not nil or t. | |
3299 If no decision is made (because no line endings were ever | |
3300 seen) then let buffer-file-type default to nil. */ | |
3301 crlf_conversion_required = -1; | |
3302 } | |
3303 | |
3304 /* If requested, we check the inserted data to decide whether the file | |
3305 is binary or text. (If text, we count LF and CRLF occurences to | |
3306 determine whether the file was in Unix or DOS format.) */ | |
3307 if (crlf_conversion_required < 0) | |
3308 { | |
3309 crlf_conversion_required = | |
3310 decide_buffer_type (read_buf, this_len); | |
3311 current_buffer->buffer_file_type = | |
3312 crlf_conversion_required ? Qnil : Qt; | |
3313 } | |
3314 | |
3315 /* Demacs 1.1.1 91/10/16 HIRANO Satoshi, MW July 1993 */ | |
3316 /* Remove CRs from CR-LFs if the file is deemed to be a text file. */ | |
3317 if (crlf_conversion_required) | |
3318 { | |
3319 int reduced_size | |
3320 = this_len - crlf_to_lf (this_len, read_buf, | |
3321 &lf_count); | |
3322 crlf_count += reduced_size; | |
3323 /* XEmacs (--marcpa) change: No need for this since we havent | |
3324 inserted in buffer yet. */ | |
3325 #if 0 | |
3326 ZV -= reduced_size; | |
3327 Z -= reduced_size; | |
3328 GPT -= reduced_size; | |
3329 GAP_SIZE += reduced_size; | |
3330 inserted -= reduced_size; | |
3331 #endif | |
3332 this_len -= reduced_size; | |
3333 | |
3334 /* Change buffer_file_type back to binary if Unix eol format. */ | |
3335 if (crlf_count == 0 && lf_count > 0) | |
3336 current_buffer->buffer_file_type = Qt; | |
3337 } | |
3338 | |
3339 /* Make crlf_count and lf_count available for inspection. */ | |
3340 Fset (intern ("buffer-file-lines"), make_int (lf_count)); | |
3341 Fset (intern ("buffer-file-dos-lines"), make_int (crlf_count)); | |
3342 #endif /* DOS_NT */ | |
2778 | 3343 |
2779 cc_inserted = buffer_insert_raw_string_1 (buf, cur_point, read_buf, | 3344 cc_inserted = buffer_insert_raw_string_1 (buf, cur_point, read_buf, |
2780 this_len, | 3345 this_len, |
2781 !NILP (visit) | 3346 !NILP (visit) |
2782 ? INSDEL_NO_LOCKING : 0); | 3347 ? INSDEL_NO_LOCKING : 0); |
2790 XCODING_SYSTEM_NAME (decoding_stream_coding_system (XLSTREAM (stream)))); | 3355 XCODING_SYSTEM_NAME (decoding_stream_coding_system (XLSTREAM (stream)))); |
2791 } | 3356 } |
2792 #endif /* MULE */ | 3357 #endif /* MULE */ |
2793 NUNGCPRO; | 3358 NUNGCPRO; |
2794 } | 3359 } |
2795 | |
2796 #if 0 | |
2797 /* XXXX Why the #### ? Bogus anyway. If they are there, display em! */ | |
2798 #ifdef DOS_NT | |
2799 /* Determine file type from name and remove LFs from CR-LFs if the file | |
2800 is deemed to be a text file. */ | |
2801 { | |
2802 struct gcpro gcpro1; | |
2803 GCPRO1 (filename); | |
2804 buf->buffer_file_type | |
2805 = call1_in_buffer (buf, Qfind_buffer_file_type, filename); | |
2806 UNGCPRO; | |
2807 if (NILP (buf->buffer_file_type)) | |
2808 { | |
2809 buffer_do_msdos_crlf_to_lf (buf, ####); | |
2810 } | |
2811 } | |
2812 #endif | |
2813 #endif /* 0 */ | |
2814 | 3360 |
2815 /* Close the file/stream */ | 3361 /* Close the file/stream */ |
2816 unbind_to (speccount, Qnil); | 3362 unbind_to (speccount, Qnil); |
2817 | 3363 |
2818 if (saverrno != 0) | 3364 if (saverrno != 0) |
2956 we should signal an error rather than blissfully continuing | 3502 we should signal an error rather than blissfully continuing |
2957 along. ARGH, this function is going to lose lose lose. We need | 3503 along. ARGH, this function is going to lose lose lose. We need |
2958 to protect the current_buffer from being destroyed, but the | 3504 to protect the current_buffer from being destroyed, but the |
2959 multiple return points make this a pain in the butt. */ | 3505 multiple return points make this a pain in the butt. */ |
2960 | 3506 |
2961 #if 0 | |
2962 #ifdef DOS_NT | 3507 #ifdef DOS_NT |
2963 int buffer_file_type | 3508 int buffer_file_type |
2964 = NILP (current_buffer->buffer_file_type) ? O_TEXT : O_BINARY; | 3509 = NILP (current_buffer->buffer_file_type) ? O_TEXT : O_BINARY; |
2965 #endif /* DOS_NT */ | 3510 #endif /* DOS_NT */ |
2966 #endif /* 0 */ | |
2967 | 3511 |
2968 #ifdef MULE | 3512 #ifdef MULE |
2969 codesys = Fget_coding_system (codesys); | 3513 codesys = Fget_coding_system (codesys); |
2970 #endif /* MULE */ | 3514 #endif /* MULE */ |
2971 | 3515 |
3048 fn = filename; | 3592 fn = filename; |
3049 desc = -1; | 3593 desc = -1; |
3050 if (!NILP (append)) | 3594 if (!NILP (append)) |
3051 #ifdef DOS_NT | 3595 #ifdef DOS_NT |
3052 desc = open ((char *) XSTRING_DATA (fn), | 3596 desc = open ((char *) XSTRING_DATA (fn), |
3053 (O_WRONLY | O_BINARY), 0); | 3597 (O_WRONLY | buffer_file_type), 0); |
3054 #else /* not DOS_NT */ | 3598 #else /* not DOS_NT */ |
3055 desc = open ((char *) XSTRING_DATA (fn), O_WRONLY, 0); | 3599 desc = open ((char *) XSTRING_DATA (fn), O_WRONLY, 0); |
3056 #endif /* not DOS_NT */ | 3600 #endif /* not DOS_NT */ |
3057 | 3601 |
3058 if (desc < 0) | 3602 if (desc < 0) |
3059 { | 3603 { |
3060 #ifdef DOS_NT | 3604 #ifdef DOS_NT |
3061 desc = open ((char *) XSTRING_DATA (fn), | 3605 desc = open ((char *) XSTRING_DATA (fn), |
3062 (O_WRONLY | O_TRUNC | O_CREAT | O_BINARY), | 3606 (O_WRONLY | O_TRUNC | O_CREAT | buffer_file_type), |
3063 (S_IREAD | S_IWRITE)); | 3607 (S_IREAD | S_IWRITE)); |
3064 #else /* not DOS_NT */ | 3608 #else /* not DOS_NT */ |
3065 desc = creat ((char *) XSTRING_DATA (fn), | 3609 desc = creat ((char *) XSTRING_DATA (fn), |
3066 ((auto_saving) ? auto_save_mode_bits : 0666)); | 3610 ((auto_saving) ? auto_save_mode_bits : 0666)); |
3067 #endif /* DOS_NT */ | 3611 #endif /* DOS_NT */ |
4219 This is to prevent you from losing your edits if you accidentally | 4763 This is to prevent you from losing your edits if you accidentally |
4220 delete a large chunk of the buffer and don't notice it until too late. | 4764 delete a large chunk of the buffer and don't notice it until too late. |
4221 Saving the buffer normally turns auto-save back on. | 4765 Saving the buffer normally turns auto-save back on. |
4222 */ ); | 4766 */ ); |
4223 disable_auto_save_when_buffer_shrinks = 1; | 4767 disable_auto_save_when_buffer_shrinks = 1; |
4224 } | 4768 #ifdef DOS_NT |
4769 DEFVAR_LISP ("directory-sep-char", &Vdirectory_sep_char /* | |
4770 *Directory separator character for built-in functions that return file names. | |
4771 The value should be either ?/ or ?\\ (any other value is treated as ?\\). | |
4772 This variable affects the built-in functions only on Windows, | |
4773 on other platforms, it is initialized so that Lisp code can find out | |
4774 what the normal separator is. | |
4775 */ ); | |
4776 Vdirectory_sep_char = '/'; | |
4777 | |
4778 DEFVAR_LISP ("insert-file-contents-allow-replace", &Vinsert_file_contents_allow_replace /* | |
4779 *Allow REPLACE option of insert-file-contents to preserve markers. | |
4780 If non-nil, the REPLACE option works as described, preserving markers. | |
4781 If nil, the REPLACE option is implemented by deleting the visible region | |
4782 then inserting the file contents as if REPLACE was nil. | |
4783 | |
4784 This option is only meaningful on Windows. | |
4785 */ ); | |
4786 Vinsert_file_contents_allow_replace = Qt; | |
4787 #endif | |
4788 } |