comparison src/dired.c @ 373:6240c7796c7a r21-2b2

Import from CVS: tag r21-2b2
author cvs
date Mon, 13 Aug 2007 11:04:06 +0200
parents 7df0dd720c89
children d883f39b8495
comparison
equal deleted inserted replaced
372:49e1ed2d7ed8 373:6240c7796c7a
28 #include "elhash.h" 28 #include "elhash.h"
29 #include "regex.h" 29 #include "regex.h"
30 #include "opaque.h" 30 #include "opaque.h"
31 #include "sysfile.h" 31 #include "sysfile.h"
32 #include "sysdir.h" 32 #include "sysdir.h"
33 #include "systime.h"
34 #include "syspwd.h"
33 35
34 Lisp_Object Vcompletion_ignored_extensions; 36 Lisp_Object Vcompletion_ignored_extensions;
35 Lisp_Object Qdirectory_files; 37 Lisp_Object Qdirectory_files;
36 Lisp_Object Qfile_name_completion; 38 Lisp_Object Qfile_name_completion;
37 Lisp_Object Qfile_name_all_completions; 39 Lisp_Object Qfile_name_all_completions;
292 file_name_completion_unwind (Lisp_Object locative) 294 file_name_completion_unwind (Lisp_Object locative)
293 { 295 {
294 DIR *d; 296 DIR *d;
295 Lisp_Object obj = XCAR (locative); 297 Lisp_Object obj = XCAR (locative);
296 298
297 if (NILP (obj)) 299 if (!NILP (obj))
298 return Qnil; 300 {
299 d = (DIR *)get_opaque_ptr (obj); 301 d = (DIR *)get_opaque_ptr (obj);
300 closedir (d); 302 closedir (d);
301 free_opaque_ptr (obj); 303 free_opaque_ptr (obj);
304 }
302 free_cons (XCONS (locative)); 305 free_cons (XCONS (locative));
303 return Qnil; 306 return Qnil;
304 } 307 }
305 308
306 static Lisp_Object 309 static Lisp_Object
526 return Qt; 529 return Qt;
527 return Fsubstring (bestmatch, Qzero, make_int (bestmatchsize)); 530 return Fsubstring (bestmatch, Qzero, make_int (bestmatchsize));
528 } 531 }
529 532
530 533
534 static Lisp_Object user_name_completion (Lisp_Object user,
535 int all_flag,
536 int *uniq);
537
538 DEFUN ("user-name-completion", Fuser_name_completion, 1, 1, 0, /*
539 Complete user name USER.
540
541 Returns the longest string common to all user names that start
542 with USER. If there is only one and USER matches it exactly,
543 returns t. Returns nil if there is no user name starting with USER.
544 */
545 (user))
546 {
547 return user_name_completion (user, 0, NULL);
548 }
549
550 DEFUN ("user-name-completion-1", Fuser_name_completion_1, 1, 1, 0, /*
551 Complete user name USER.
552
553 This function is identical to `user-name-completion', except that
554 the cons of the completion and an indication of whether the
555 completion was unique is returned.
556
557 The car of the returned value is the longest string common to all
558 user names that start with USER. If there is only one and USER
559 matches it exactly, the car is t. The car is nil if there is no
560 user name starting with USER. The cdr of the result is non-nil
561 if and only if the completion returned in the car was unique.
562 */
563 (user))
564 {
565 int uniq;
566 Lisp_Object completed;
567
568 completed = user_name_completion (user, 0, &uniq);
569 return Fcons (completed, uniq ? Qt : Qnil);
570 }
571
572 DEFUN ("user-name-all-completions", Fuser_name_all_completions, 1, 1, 0, /*
573 Return a list of all completions of user name USER.
574 These are all user names which begin with USER.
575 */
576 (user))
577 {
578 return user_name_completion (user, 1, NULL);
579 }
580
581 static Lisp_Object
582 user_name_completion_unwind (Lisp_Object locative)
583 {
584 Lisp_Object obj1 = XCAR (locative);
585 Lisp_Object obj2 = XCDR (locative);
586 char **cache;
587 int clen, i;
588
589
590 if (!NILP (obj1) && !NILP (obj2))
591 {
592 /* clean up if interrupted building cache */
593 cache = *(char ***)get_opaque_ptr (obj1);
594 clen = *(int *)get_opaque_ptr (obj2);
595 free_opaque_ptr (obj1);
596 free_opaque_ptr (obj2);
597 for (i = 0; i < clen; i++)
598 free (cache[i]);
599 free (cache);
600 }
601
602 free_cons (XCONS (locative));
603 endpwent ();
604
605 return Qnil;
606 }
607
608 static char **user_cache;
609 static int user_cache_len;
610 static int user_cache_max;
611 static long user_cache_time;
612
613 #define USER_CACHE_REBUILD (24*60*60) /* 1 day, in seconds */
614
615 static Lisp_Object
616 user_name_completion (Lisp_Object user, int all_flag, int *uniq)
617 {
618 /* This function can GC */
619 struct passwd *pw;
620 int matchcount = 0;
621 Lisp_Object bestmatch = Qnil;
622 Charcount bestmatchsize = 0;
623 int speccount = specpdl_depth ();
624 int i, cmax, clen;
625 char **cache;
626 Charcount user_name_length;
627 Lisp_Object locative;
628 EMACS_TIME t;
629 struct gcpro gcpro1, gcpro2;
630
631 GCPRO2 (user, bestmatch);
632
633 CHECK_STRING (user);
634
635 user_name_length = XSTRING_CHAR_LENGTH (user);
636
637 /* Cache user name lookups because it tends to be quite slow.
638 * Rebuild the cache occasionally to catch changes */
639 EMACS_GET_TIME (t);
640 if (user_cache &&
641 EMACS_SECS (t) - user_cache_time > USER_CACHE_REBUILD)
642 {
643 for (i = 0; i < user_cache_len; i++)
644 free (user_cache[i]);
645 free (user_cache);
646 user_cache = NULL;
647 user_cache_len = 0;
648 user_cache_max = 0;
649 }
650
651 if (user_cache == NULL || user_cache_max <= 0)
652 {
653 cmax = 200;
654 clen = 0;
655 cache = (char **) malloc (cmax*sizeof (char *));
656
657 setpwent ();
658 locative = noseeum_cons (Qnil, Qnil);
659 XCAR (locative) = make_opaque_ptr ((void *) &cache);
660 XCDR (locative) = make_opaque_ptr ((void *) &clen);
661 record_unwind_protect (user_name_completion_unwind, locative);
662 /* #### may need to slow down interrupts around call to getpwent
663 * below. at least the call to getpwnam in Fuser_full_name
664 * is documented as needing it on irix. */
665 while ((pw = getpwent ()))
666 {
667 if (clen >= cmax)
668 {
669 cmax *= 2;
670 cache = (char **) realloc (cache, cmax*sizeof (char *));
671 }
672
673 QUIT;
674
675 cache[clen++] = strdup (pw->pw_name);
676 }
677 free_opaque_ptr (XCAR (locative));
678 free_opaque_ptr (XCDR (locative));
679 XCAR (locative) = Qnil;
680 XCDR (locative) = Qnil;
681
682 unbind_to (speccount, Qnil); /* free locative cons, endpwent() */
683
684 user_cache_max = cmax;
685 user_cache_len = clen;
686 user_cache = cache;
687 user_cache_time = EMACS_SECS (t);
688 }
689
690 for (i = 0; i < user_cache_len; i++)
691 {
692 Bytecount len;
693 /* scmp() works in chars, not bytes, so we have to compute this: */
694 Charcount cclen;
695 Bufbyte *d_name;
696
697 d_name = (Bufbyte *) user_cache[i];
698 len = strlen (d_name);
699 cclen = bytecount_to_charcount (d_name, len);
700
701 QUIT;
702
703 if (cclen < user_name_length ||
704 0 <= scmp (d_name, XSTRING_DATA (user), user_name_length))
705 continue;
706
707 matchcount++; /* count matching completions */
708
709 if (all_flag || NILP (bestmatch))
710 {
711 Lisp_Object name = Qnil;
712 struct gcpro ngcpro1;
713 NGCPRO1 (name);
714 /* This is a possible completion */
715 name = make_string (d_name, len);
716 if (all_flag)
717 {
718 bestmatch = Fcons (name, bestmatch);
719 }
720 else
721 {
722 bestmatch = name;
723 bestmatchsize = XSTRING_CHAR_LENGTH (name);
724 }
725 NUNGCPRO;
726 }
727 else
728 {
729 Charcount compare = min (bestmatchsize, cclen);
730 Bufbyte *p1 = XSTRING_DATA (bestmatch);
731 Bufbyte *p2 = d_name;
732 Charcount matchsize = scmp (p1, p2, compare);
733
734 if (matchsize < 0)
735 matchsize = compare;
736 if (completion_ignore_case)
737 {
738 /* If this is an exact match except for case,
739 use it as the best match rather than one that is not
740 an exact match. This way, we get the case pattern
741 of the actual match. */
742 if ((matchsize == cclen
743 && matchsize < XSTRING_CHAR_LENGTH (bestmatch))
744 ||
745 /* If there is no exact match ignoring case,
746 prefer a match that does not change the case
747 of the input. */
748 (((matchsize == cclen)
749 ==
750 (matchsize == XSTRING_CHAR_LENGTH (bestmatch)))
751 /* If there is more than one exact match aside from
752 case, and one of them is exact including case,
753 prefer that one. */
754 && 0 > scmp_1 (p2, XSTRING_DATA (user),
755 user_name_length, 0)
756 && 0 <= scmp_1 (p1, XSTRING_DATA (user),
757 user_name_length, 0)))
758 {
759 bestmatch = make_string (d_name, len);
760 }
761 }
762
763 bestmatchsize = matchsize;
764 }
765 }
766
767 UNGCPRO;
768
769 if (uniq)
770 *uniq = (matchcount == 1);
771
772 if (all_flag || NILP (bestmatch))
773 return bestmatch;
774 if (matchcount == 1 && bestmatchsize == user_name_length)
775 return Qt;
776 return Fsubstring (bestmatch, Qzero, make_int (bestmatchsize));
777 }
778
779
531 Lisp_Object 780 Lisp_Object
532 make_directory_hash_table (CONST char *path) 781 make_directory_hash_table (CONST char *path)
533 { 782 {
534 DIR *d; 783 DIR *d;
535 Lisp_Object hash = make_lisp_hashtable (100, HASHTABLE_NONWEAK, 784 Lisp_Object hash = make_lisp_hashtable (100, HASHTABLE_NONWEAK,
687 defsymbol (&Qfile_attributes, "file-attributes"); 936 defsymbol (&Qfile_attributes, "file-attributes");
688 937
689 DEFSUBR (Fdirectory_files); 938 DEFSUBR (Fdirectory_files);
690 DEFSUBR (Ffile_name_completion); 939 DEFSUBR (Ffile_name_completion);
691 DEFSUBR (Ffile_name_all_completions); 940 DEFSUBR (Ffile_name_all_completions);
941 DEFSUBR (Fuser_name_completion);
942 DEFSUBR (Fuser_name_completion_1);
943 DEFSUBR (Fuser_name_all_completions);
692 DEFSUBR (Ffile_attributes); 944 DEFSUBR (Ffile_attributes);
693 } 945 }
694 946
695 void 947 void
696 vars_of_dired (void) 948 vars_of_dired (void)
701 but does affect the commands that actually do completions. 953 but does affect the commands that actually do completions.
702 It is used by the functions `file-name-completion' and 954 It is used by the functions `file-name-completion' and
703 `file-name-all-completions'. 955 `file-name-all-completions'.
704 */ ); 956 */ );
705 Vcompletion_ignored_extensions = Qnil; 957 Vcompletion_ignored_extensions = Qnil;
706 } 958
959 user_cache = NULL;
960 user_cache_len = 0;
961 user_cache_max = 0;
962 }