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);