Mercurial > hg > xemacs-beta
comparison src/dired.c @ 440:8de8e3f6228a r21-2-28
Import from CVS: tag r21-2-28
author | cvs |
---|---|
date | Mon, 13 Aug 2007 11:33:38 +0200 |
parents | 3ecd8885ac67 |
children | abe6d1db359e |
comparison
equal
deleted
inserted
replaced
439:357dd071b03c | 440:8de8e3f6228a |
---|---|
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; | 545 Lisp_Object completed = user_name_completion (user, 0, &uniq); |
546 | |
547 completed = user_name_completion (user, 0, &uniq); | |
548 return Fcons (completed, uniq ? Qt : Qnil); | 546 return Fcons (completed, uniq ? Qt : Qnil); |
549 } | 547 } |
550 | 548 |
551 DEFUN ("user-name-all-completions", Fuser_name_all_completions, 1, 1, 0, /* | 549 DEFUN ("user-name-all-completions", Fuser_name_all_completions, 1, 1, 0, /* |
552 Return a list of all completions of user name USER. | 550 Return a list of all completions of user name USER. |
555 (user)) | 553 (user)) |
556 { | 554 { |
557 return user_name_completion (user, 1, NULL); | 555 return user_name_completion (user, 1, NULL); |
558 } | 556 } |
559 | 557 |
560 struct user_cache { | 558 struct user_name |
561 Bufbyte **data; | 559 { |
560 Bufbyte *ptr; | |
561 size_t len; | |
562 }; | |
563 | |
564 struct user_cache | |
565 { | |
566 struct user_name *user_names; | |
562 int length; | 567 int length; |
563 int size; | 568 int size; |
564 EMACS_TIME last_rebuild_time; | 569 EMACS_TIME last_rebuild_time; |
565 }; | 570 }; |
566 static struct user_cache user_cache; | 571 static struct user_cache user_cache; |
568 static void | 573 static void |
569 free_user_cache (struct user_cache *cache) | 574 free_user_cache (struct user_cache *cache) |
570 { | 575 { |
571 int i; | 576 int i; |
572 for (i = 0; i < cache->length; i++) | 577 for (i = 0; i < cache->length; i++) |
573 xfree (cache->data[i]); | 578 xfree (cache->user_names[i].ptr); |
574 xfree (cache->data); | 579 xfree (cache->user_names); |
580 xzero (*cache); | |
575 } | 581 } |
576 | 582 |
577 static Lisp_Object | 583 static Lisp_Object |
578 user_name_completion_unwind (Lisp_Object locative) | 584 user_name_completion_unwind (Lisp_Object cache_incomplete_p) |
579 { | 585 { |
580 int interrupted = !NILP (XCAR (locative)); | 586 endpwent (); |
581 | 587 speed_up_interrupts (); |
582 if (interrupted) | 588 |
583 { | 589 if (! NILP (XCAR (cache_incomplete_p))) |
584 endpwent (); | 590 free_user_cache (&user_cache); |
585 speed_up_interrupts (); | 591 |
586 free_user_cache (&user_cache); | 592 free_cons (XCONS (cache_incomplete_p)); |
587 } | |
588 free_cons (XCONS (locative)); | |
589 | 593 |
590 return Qnil; | 594 return Qnil; |
591 } | 595 } |
592 | 596 |
593 #define USER_CACHE_REBUILD (24*60*60) /* 1 day, in seconds */ | 597 #define USER_CACHE_TTL (24*60*60) /* Time to live: 1 day, in seconds */ |
594 | 598 |
595 static Lisp_Object | 599 static Lisp_Object |
596 user_name_completion (Lisp_Object user, int all_flag, int *uniq) | 600 user_name_completion (Lisp_Object user, int all_flag, int *uniq) |
597 { | 601 { |
598 /* This function can GC */ | 602 /* This function can GC */ |
599 int matchcount = 0; | 603 int matchcount = 0; |
600 Lisp_Object bestmatch = Qnil; | 604 Lisp_Object bestmatch = Qnil; |
601 Charcount bestmatchsize = 0; | 605 Charcount bestmatchsize = 0; |
602 int speccount = specpdl_depth (); | |
603 Charcount user_name_length; | 606 Charcount user_name_length; |
604 EMACS_TIME t; | 607 EMACS_TIME t; |
605 int i; | 608 int i; |
606 struct gcpro gcpro1, gcpro2; | 609 struct gcpro gcpro1, gcpro2; |
607 | 610 |
612 user_name_length = XSTRING_CHAR_LENGTH (user); | 615 user_name_length = XSTRING_CHAR_LENGTH (user); |
613 | 616 |
614 /* Cache user name lookups because it tends to be quite slow. | 617 /* Cache user name lookups because it tends to be quite slow. |
615 * Rebuild the cache occasionally to catch changes */ | 618 * Rebuild the cache occasionally to catch changes */ |
616 EMACS_GET_TIME (t); | 619 EMACS_GET_TIME (t); |
617 if (user_cache.data && | 620 if (user_cache.user_names && |
618 (EMACS_SECS (t) - EMACS_SECS (user_cache.last_rebuild_time) | 621 (EMACS_SECS (t) - EMACS_SECS (user_cache.last_rebuild_time) |
619 > USER_CACHE_REBUILD)) | 622 > USER_CACHE_TTL)) |
620 { | 623 free_user_cache (&user_cache); |
621 free_user_cache (&user_cache); | 624 |
622 xzero (user_cache); | 625 if (!user_cache.user_names) |
623 } | |
624 | |
625 if (!user_cache.data) | |
626 { | 626 { |
627 struct passwd *pwd; | 627 struct passwd *pwd; |
628 Lisp_Object locative = noseeum_cons (Qt, Qnil); | 628 Lisp_Object cache_incomplete_p = noseeum_cons (Qt, Qnil); |
629 int speccount = specpdl_depth (); | |
630 | |
629 slow_down_interrupts (); | 631 slow_down_interrupts (); |
630 setpwent (); | 632 setpwent (); |
631 record_unwind_protect (user_name_completion_unwind, locative); | 633 record_unwind_protect (user_name_completion_unwind, cache_incomplete_p); |
632 while ((pwd = getpwent ())) | 634 while ((pwd = getpwent ())) |
633 { | 635 { |
634 Bufbyte *pwuser; | |
635 QUIT; | 636 QUIT; |
636 DO_REALLOC (user_cache.data, user_cache.size, | 637 DO_REALLOC (user_cache.user_names, user_cache.size, |
637 user_cache.length + 1, Bufbyte *); | 638 user_cache.length + 1, struct user_name); |
638 GET_C_CHARPTR_INT_DATA_ALLOCA (pwd->pw_name, FORMAT_OS, pwuser); | 639 TO_INTERNAL_FORMAT (C_STRING, pwd->pw_name, |
639 user_cache.data[user_cache.length++] = | 640 MALLOC, |
640 (Bufbyte *) xstrdup ((char *) 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++; | |
641 } | 645 } |
642 endpwent (); | 646 XCAR (cache_incomplete_p) = Qnil; |
643 speed_up_interrupts (); | 647 unbind_to (speccount, Qnil); |
644 XCAR (locative) = Qnil; | 648 |
645 unbind_to (speccount, Qnil); /* free locative cons */ | |
646 EMACS_GET_TIME (user_cache.last_rebuild_time); | 649 EMACS_GET_TIME (user_cache.last_rebuild_time); |
647 } | 650 } |
648 | 651 |
649 for (i = 0; i < user_cache.length; i++) | 652 for (i = 0; i < user_cache.length; i++) |
650 { | 653 { |
651 Bufbyte *u_name = user_cache.data[i]; | 654 Bufbyte *u_name = user_cache.user_names[i].ptr; |
652 Bytecount len = strlen ((char *) u_name); | 655 Bytecount len = user_cache.user_names[i].len; |
653 /* scmp() works in chars, not bytes, so we have to compute this: */ | 656 /* scmp() works in chars, not bytes, so we have to compute this: */ |
654 Charcount cclen = bytecount_to_charcount (u_name, len); | 657 Charcount cclen = bytecount_to_charcount (u_name, len); |
655 | 658 |
656 QUIT; | 659 QUIT; |
657 | 660 |