33#endif
44
55#include <sys/ioctl.h>
6+ #include <sys/types.h>
67
78#include <ctype.h>
89#include <err.h>
@@ -70,13 +71,15 @@ struct choice {
7071 double score ;
7172};
7273
74+ int tty_getc_peek = -1 ;
75+
7376static int choice_cmp (const void * , const void * );
7477static const char * choice_description (const struct choice * );
7578static const char * choice_string (const struct choice * );
7679static void delete_between (char * , size_t , size_t , size_t );
7780static char * eager_strpbrk (const char * , const char * );
7881static int filter_choices (size_t );
79- static size_t get_choices (int , size_t );
82+ static size_t get_choices (int , ssize_t );
8083static enum key get_key (const char * * );
8184static void handle_sigwinch (int );
8285static int isu8cont (unsigned char );
@@ -224,7 +227,7 @@ usage(int status)
224227}
225228
226229size_t
227- get_choices (int fd , size_t insert )
230+ get_choices (int fd , ssize_t insert )
228231{
229232 static const char * ifs ;
230233 static char * buf ;
@@ -291,7 +294,7 @@ get_choices(int fd, size_t insert)
291294 }
292295 offset = start - buf ;
293296 dchoices = choices .length - nchoices ;
294- if (dchoices == 0 || nchoices == 0 )
297+ if (dchoices == 0 || nchoices == 0 || insert == -1 )
295298 return n ;
296299
297300 /* Move new choices after the given insert index. */
@@ -325,11 +328,12 @@ selected_choice(void)
325328{
326329 struct pollfd fds [2 ];
327330 const char * buf ;
331+ ssize_t insert ;
328332 size_t cursor_position , i , j , length , nfds , xscroll ;
329333 size_t choices_count = 0 ;
330334 size_t selection = 0 ;
331335 size_t yscroll = 0 ;
332- int dokey , doread , timo ;
336+ int dokey , doread , nready , timo ;
333337 int choices_reset = 1 ;
334338 int dochoices = 0 ;
335339 int dofilter = 1 ;
@@ -346,7 +350,8 @@ selected_choice(void)
346350 for (;;) {
347351 dokey = doread = 0 ;
348352 toggle_sigwinch (1 );
349- if (poll (fds , nfds , timo ) == -1 && errno != EINTR )
353+ nready = xpoll (fds , nfds , timo );
354+ if (nready == -1 && errno != EINTR )
350355 err (1 , "poll" );
351356 toggle_sigwinch (0 );
352357 if (gotsigwinch ) {
@@ -355,33 +360,33 @@ selected_choice(void)
355360 }
356361 timo = -1 ;
357362 for (i = 0 ; i < nfds ; i ++ ) {
358- if (fds [i ].revents & (POLLERR | POLLNVAL ))
359- errx (1 , "%d: bad file descriptor" , fds [i ].fd );
363+ if (fds [i ].revents & (POLLERR | POLLNVAL )) {
364+ errno = EBADF ;
365+ err (1 , "poll" );
366+ }
360367 if ((fds [i ].revents & (POLLIN | POLLHUP )) == 0 )
361368 continue ;
362369
363- if (fds [i ].fd == fds [0 ].fd )
364- dokey = 1 ;
365- else if (fds [i ].fd == fds [1 ].fd )
370+ if (fds [i ].fd == STDIN_FILENO )
366371 doread = 1 ;
372+ else if (fds [i ].fd == fileno (tty_in ))
373+ dokey = 1 ;
367374 }
368375
369376 length = choices .length ;
370377 if (doread ) {
371- if ( get_choices ( STDIN_FILENO , query_length > 0 ?
372- choices_count : 0 )) {
378+ insert = query_length > 0 ? ( ssize_t ) choices_count : -1 ;
379+ if ( get_choices ( fds [ 1 ]. fd , insert )) {
373380 if (query_length > 0 ) {
374381 dofilter = 1 ;
375382 choices_reset = 0 ;
376383 choices_count += choices .length -
377384 length ;
378385 }
379386 } else {
380- nfds = 1 ; /* EOF */
387+ nfds -- ; /* EOF */
381388 }
382389 }
383- if (!dokey && query_length == 0 && length >= choices_lines )
384- continue ; /* prevent redundant rendering */
385390 if (!dokey )
386391 goto render ;
387392
@@ -589,8 +594,8 @@ selected_choice(void)
589594int
590595filter_choices (size_t nchoices )
591596{
592- struct choice * c ;
593597 struct pollfd pfd ;
598+ struct choice * c ;
594599 size_t i , match_length ;
595600 int nready ;
596601
@@ -610,7 +615,7 @@ filter_choices(size_t nchoices)
610615 if (i > 0 && i % 50 == 0 ) {
611616 pfd .fd = fileno (tty_in );
612617 pfd .events = POLLIN ;
613- if ((nready = poll (& pfd , 1 , 0 )) == -1 )
618+ if ((nready = xpoll (& pfd , 1 , 0 )) == -1 )
614619 err (1 , "poll" );
615620 if (nready == 1 && pfd .revents & (POLLIN | POLLHUP ))
616621 return 0 ;
@@ -1116,6 +1121,12 @@ tty_getc(void)
11161121 ssize_t n ;
11171122 unsigned char c ;
11181123
1124+ if (tty_getc_peek != -1 ) {
1125+ c = tty_getc_peek ;
1126+ tty_getc_peek = -1 ;
1127+ return c ;
1128+ }
1129+
11191130 n = read (fileno (tty_in ), & c , sizeof (c ));
11201131 if (n == -1 )
11211132 err (1 , "read" );
0 commit comments