Mercurial > hg > xemacs-beta
comparison src/dired.c @ 412:697ef44129c6 r21-2-14
Import from CVS: tag r21-2-14
author | cvs |
---|---|
date | Mon, 13 Aug 2007 11:20:41 +0200 |
parents | de805c49cfc1 |
children | 11054d720c21 |
comparison
equal
deleted
inserted
replaced
411:12e008d41344 | 412:697ef44129c6 |
---|---|
21 /* Synched up with: FSF 19.30. */ | 21 /* Synched up with: FSF 19.30. */ |
22 | 22 |
23 #include <config.h> | 23 #include <config.h> |
24 #include "lisp.h" | 24 #include "lisp.h" |
25 | 25 |
26 #include "buffer.h" | |
27 #include "commands.h" | |
28 #include "elhash.h" | |
29 #include "regex.h" | |
30 #include "opaque.h" | |
26 #include "sysfile.h" | 31 #include "sysfile.h" |
27 #include "sysdir.h" | 32 #include "sysdir.h" |
28 #include "systime.h" | 33 #include "systime.h" |
29 #include "sysdep.h" | 34 #include "sysdep.h" |
30 #include "syspwd.h" | 35 #include "syspwd.h" |
31 #include "buffer.h" | |
32 #include "commands.h" | |
33 #include "elhash.h" | |
34 #include "regex.h" | |
35 #include "opaque.h" | |
36 | 36 |
37 Lisp_Object Vcompletion_ignored_extensions; | 37 Lisp_Object Vcompletion_ignored_extensions; |
38 Lisp_Object Qdirectory_files; | 38 Lisp_Object Qdirectory_files; |
39 Lisp_Object Qfile_name_completion; | 39 Lisp_Object Qfile_name_completion; |
40 Lisp_Object Qfile_name_all_completions; | 40 Lisp_Object Qfile_name_all_completions; |
301 | 301 |
302 GCPRO3 (file, directory, bestmatch); | 302 GCPRO3 (file, directory, bestmatch); |
303 | 303 |
304 CHECK_STRING (file); | 304 CHECK_STRING (file); |
305 | 305 |
306 #ifdef WIN32_NATIVE | 306 #ifdef WINDOWSNT |
307 /* Filename completion on Windows ignores case, since Windows | 307 /* Filename completion on Windows ignores case, since Windows |
308 filesystems do. */ | 308 filesystems do. */ |
309 specbind (Qcompletion_ignore_case, Qt); | 309 specbind (Qcompletion_ignore_case, Qt); |
310 #endif /* WIN32_NATIVE */ | 310 #endif /* WINDOWSNT */ |
311 | 311 |
312 #ifdef FILE_SYSTEM_CASE | 312 #ifdef FILE_SYSTEM_CASE |
313 file = FILE_SYSTEM_CASE (file); | 313 file = FILE_SYSTEM_CASE (file); |
314 #endif | 314 #endif |
315 directory = Fexpand_file_name (directory, Qnil); | 315 directory = Fexpand_file_name (directory, Qnil); |
506 } | 506 } |
507 | 507 |
508 | 508 |
509 | 509 |
510 /* The *pwent() functions do not exist on NT */ | 510 /* The *pwent() functions do not exist on NT */ |
511 #ifndef WIN32_NATIVE | 511 #ifndef WINDOWSNT |
512 | 512 |
513 static Lisp_Object user_name_completion (Lisp_Object user, | 513 static Lisp_Object user_name_completion (Lisp_Object user, |
514 int all_flag, | 514 int all_flag, |
515 int *uniq); | 515 int *uniq); |
516 | 516 |
540 if and only if the completion returned in the car was unique. | 540 if and only if the completion returned in the car was unique. |
541 */ | 541 */ |
542 (user)) | 542 (user)) |
543 { | 543 { |
544 int uniq; | 544 int uniq; |
545 Lisp_Object completed = user_name_completion (user, 0, &uniq); | 545 Lisp_Object completed; |
546 | |
547 completed = user_name_completion (user, 0, &uniq); | |
546 return Fcons (completed, uniq ? Qt : Qnil); | 548 return Fcons (completed, uniq ? Qt : Qnil); |
547 } | 549 } |
548 | 550 |
549 DEFUN ("user-name-all-completions", Fuser_name_all_completions, 1, 1, 0, /* | 551 DEFUN ("user-name-all-completions", Fuser_name_all_completions, 1, 1, 0, /* |
550 Return a list of all completions of user name USER. | 552 Return a list of all completions of user name USER. |
553 (user)) | 555 (user)) |
554 { | 556 { |
555 return user_name_completion (user, 1, NULL); | 557 return user_name_completion (user, 1, NULL); |
556 } | 558 } |
557 | 559 |
558 struct user_name | 560 struct user_cache { |
559 { | 561 char **data; |
560 Bufbyte *ptr; | |
561 size_t len; | |
562 }; | |
563 | |
564 struct user_cache | |
565 { | |
566 struct user_name *user_names; | |
567 int length; | 562 int length; |
568 int size; | 563 int size; |
569 EMACS_TIME last_rebuild_time; | 564 EMACS_TIME last_rebuild_time; |
570 }; | 565 }; |
571 static struct user_cache user_cache; | 566 static struct user_cache user_cache; |
573 static void | 568 static void |
574 free_user_cache (struct user_cache *cache) | 569 free_user_cache (struct user_cache *cache) |
575 { | 570 { |
576 int i; | 571 int i; |
577 for (i = 0; i < cache->length; i++) | 572 for (i = 0; i < cache->length; i++) |
578 xfree (cache->user_names[i].ptr); | 573 xfree (cache->data[i]); |
579 xfree (cache->user_names); | 574 xfree (cache->data); |
580 xzero (*cache); | |
581 } | 575 } |
582 | 576 |
583 static Lisp_Object | 577 static Lisp_Object |
584 user_name_completion_unwind (Lisp_Object cache_incomplete_p) | 578 user_name_completion_unwind (Lisp_Object locative) |
585 { | 579 { |
586 endpwent (); | 580 int interrupted = !NILP (XCAR (locative)); |
587 speed_up_interrupts (); | 581 |
588 | 582 if (interrupted) |
589 if (! NILP (XCAR (cache_incomplete_p))) | 583 { |
590 free_user_cache (&user_cache); | 584 endpwent (); |
591 | 585 speed_up_interrupts (); |
592 free_cons (XCONS (cache_incomplete_p)); | 586 free_user_cache (&user_cache); |
587 } | |
588 free_cons (XCONS (locative)); | |
593 | 589 |
594 return Qnil; | 590 return Qnil; |
595 } | 591 } |
596 | 592 |
597 #define USER_CACHE_TTL (24*60*60) /* Time to live: 1 day, in seconds */ | 593 #define USER_CACHE_REBUILD (24*60*60) /* 1 day, in seconds */ |
598 | 594 |
599 static Lisp_Object | 595 static Lisp_Object |
600 user_name_completion (Lisp_Object user, int all_flag, int *uniq) | 596 user_name_completion (Lisp_Object user, int all_flag, int *uniq) |
601 { | 597 { |
602 /* This function can GC */ | 598 /* This function can GC */ |
603 int matchcount = 0; | 599 int matchcount = 0; |
604 Lisp_Object bestmatch = Qnil; | 600 Lisp_Object bestmatch = Qnil; |
605 Charcount bestmatchsize = 0; | 601 Charcount bestmatchsize = 0; |
602 int speccount = specpdl_depth (); | |
606 Charcount user_name_length; | 603 Charcount user_name_length; |
607 EMACS_TIME t; | 604 EMACS_TIME t; |
608 int i; | 605 int i; |
609 struct gcpro gcpro1, gcpro2; | 606 struct gcpro gcpro1, gcpro2; |
610 | 607 |
615 user_name_length = XSTRING_CHAR_LENGTH (user); | 612 user_name_length = XSTRING_CHAR_LENGTH (user); |
616 | 613 |
617 /* Cache user name lookups because it tends to be quite slow. | 614 /* Cache user name lookups because it tends to be quite slow. |
618 * Rebuild the cache occasionally to catch changes */ | 615 * Rebuild the cache occasionally to catch changes */ |
619 EMACS_GET_TIME (t); | 616 EMACS_GET_TIME (t); |
620 if (user_cache.user_names && | 617 if (user_cache.data && |
621 (EMACS_SECS (t) - EMACS_SECS (user_cache.last_rebuild_time) | 618 (EMACS_SECS (t) - EMACS_SECS (user_cache.last_rebuild_time) |
622 > USER_CACHE_TTL)) | 619 > USER_CACHE_REBUILD)) |
623 free_user_cache (&user_cache); | 620 { |
624 | 621 free_user_cache (&user_cache); |
625 if (!user_cache.user_names) | 622 xzero (user_cache); |
623 } | |
624 | |
625 if (!user_cache.data) | |
626 { | 626 { |
627 struct passwd *pwd; | 627 struct passwd *pwd; |
628 Lisp_Object cache_incomplete_p = noseeum_cons (Qt, Qnil); | 628 Lisp_Object locative = noseeum_cons (Qt, Qnil); |
629 int speccount = specpdl_depth (); | |
630 | |
631 slow_down_interrupts (); | 629 slow_down_interrupts (); |
632 setpwent (); | 630 setpwent (); |
633 record_unwind_protect (user_name_completion_unwind, cache_incomplete_p); | 631 record_unwind_protect (user_name_completion_unwind, locative); |
634 while ((pwd = getpwent ())) | 632 while ((pwd = getpwent ())) |
635 { | 633 { |
634 Bufbyte *pwuser; | |
636 QUIT; | 635 QUIT; |
637 DO_REALLOC (user_cache.user_names, user_cache.size, | 636 DO_REALLOC (user_cache.data, user_cache.size, |
638 user_cache.length + 1, struct user_name); | 637 user_cache.length + 1, char *); |
639 TO_INTERNAL_FORMAT (C_STRING, pwd->pw_name, | 638 GET_C_CHARPTR_INT_DATA_ALLOCA (pwd->pw_name, FORMAT_OS, pwuser); |
640 MALLOC, | 639 user_cache.data[user_cache.length++] = xstrdup (pwuser); |
641 (user_cache.user_names[user_cache.length].ptr, | |
642 user_cache.user_names[user_cache.length].len), | |
643 Qnative); | |
644 user_cache.length++; | |
645 } | 640 } |
646 XCAR (cache_incomplete_p) = Qnil; | 641 endpwent (); |
647 unbind_to (speccount, Qnil); | 642 speed_up_interrupts (); |
648 | 643 XCAR (locative) = Qnil; |
644 unbind_to (speccount, Qnil); /* free locative cons */ | |
649 EMACS_GET_TIME (user_cache.last_rebuild_time); | 645 EMACS_GET_TIME (user_cache.last_rebuild_time); |
650 } | 646 } |
651 | 647 |
652 for (i = 0; i < user_cache.length; i++) | 648 for (i = 0; i < user_cache.length; i++) |
653 { | 649 { |
654 Bufbyte *u_name = user_cache.user_names[i].ptr; | 650 Bufbyte *u_name = user_cache.data[i]; |
655 Bytecount len = user_cache.user_names[i].len; | 651 Bytecount len = strlen ((char *) u_name); |
656 /* scmp() works in chars, not bytes, so we have to compute this: */ | 652 /* scmp() works in chars, not bytes, so we have to compute this: */ |
657 Charcount cclen = bytecount_to_charcount (u_name, len); | 653 Charcount cclen = bytecount_to_charcount (u_name, len); |
658 | 654 |
659 QUIT; | 655 QUIT; |
660 | 656 |
705 return bestmatch; | 701 return bestmatch; |
706 if (matchcount == 1 && bestmatchsize == user_name_length) | 702 if (matchcount == 1 && bestmatchsize == user_name_length) |
707 return Qt; | 703 return Qt; |
708 return Fsubstring (bestmatch, Qzero, make_int (bestmatchsize)); | 704 return Fsubstring (bestmatch, Qzero, make_int (bestmatchsize)); |
709 } | 705 } |
710 #endif /* ! defined WIN32_NATIVE */ | 706 #endif /* ! defined WINDOWSNT */ |
711 | 707 |
712 | 708 |
713 Lisp_Object | 709 Lisp_Object |
714 make_directory_hash_table (const char *path) | 710 make_directory_hash_table (CONST char *path) |
715 { | 711 { |
716 DIR *d; | 712 DIR *d; |
717 if ((d = opendir (path))) | 713 if ((d = opendir (path))) |
718 { | 714 { |
719 DIRENTRY *dp; | 715 DIRENTRY *dp; |
794 | 790 |
795 #ifdef BSD4_2 | 791 #ifdef BSD4_2 |
796 directory = Ffile_name_directory (filename); | 792 directory = Ffile_name_directory (filename); |
797 #endif | 793 #endif |
798 | 794 |
799 #if 0 /* #### shouldn't this apply to WIN32_NATIVE and maybe CYGWIN? */ | 795 #ifdef MSDOS |
800 { | 796 { |
801 char *tmpnam = (char *) XSTRING_DATA (Ffile_name_nondirectory (filename)); | 797 char *tmpnam = (char *) XSTRING_DATA (Ffile_name_nondirectory (filename)); |
802 int l = strlen (tmpnam); | 798 int l = strlen (tmpnam); |
803 | 799 |
804 if (l >= 5 | 800 if (l >= 5 |
808 stricmp (&tmpnam[l - 4], ".bat") == 0)) | 804 stricmp (&tmpnam[l - 4], ".bat") == 0)) |
809 { | 805 { |
810 s.st_mode |= S_IEXEC; | 806 s.st_mode |= S_IEXEC; |
811 } | 807 } |
812 } | 808 } |
813 #endif | 809 #endif /* MSDOS */ |
814 | 810 |
815 switch (s.st_mode & S_IFMT) | 811 switch (s.st_mode & S_IFMT) |
816 { | 812 { |
817 default: | 813 default: |
818 values[0] = Qnil; | 814 values[0] = Qnil; |
871 defsymbol (&Qfile_attributes, "file-attributes"); | 867 defsymbol (&Qfile_attributes, "file-attributes"); |
872 | 868 |
873 DEFSUBR (Fdirectory_files); | 869 DEFSUBR (Fdirectory_files); |
874 DEFSUBR (Ffile_name_completion); | 870 DEFSUBR (Ffile_name_completion); |
875 DEFSUBR (Ffile_name_all_completions); | 871 DEFSUBR (Ffile_name_all_completions); |
876 #ifndef WIN32_NATIVE | 872 #ifndef WINDOWSNT |
877 DEFSUBR (Fuser_name_completion); | 873 DEFSUBR (Fuser_name_completion); |
878 DEFSUBR (Fuser_name_completion_1); | 874 DEFSUBR (Fuser_name_completion_1); |
879 DEFSUBR (Fuser_name_all_completions); | 875 DEFSUBR (Fuser_name_all_completions); |
880 #endif | 876 #endif |
881 DEFSUBR (Ffile_attributes); | 877 DEFSUBR (Ffile_attributes); |