summaryrefslogtreecommitdiff
path: root/src/ui_readline.c
diff options
context:
space:
mode:
authorLars-Dominik Braun <lars@6xq.net>2011-01-06 16:25:40 +0100
committerLars-Dominik Braun <lars@6xq.net>2011-02-02 16:48:53 +0100
commitce8503f859345990a14be90bf89dadf7f73d7613 (patch)
tree6a2c7b572ba76bdbda3bbe4bff21f484e848f0e5 /src/ui_readline.c
parent58398e4b2a9666a94aacced30453c1fc46b4a2e8 (diff)
downloadpianobar-ce8503f859345990a14be90bf89dadf7f73d7613.tar.gz
pianobar-ce8503f859345990a14be90bf89dadf7f73d7613.tar.bz2
pianobar-ce8503f859345990a14be90bf89dadf7f73d7613.zip
BarReadline rewrite
Doesn't use c streams any more, allows multiplexing of fifo/stdin in all situations.
Diffstat (limited to 'src/ui_readline.c')
-rw-r--r--src/ui_readline.c110
1 files changed, 79 insertions, 31 deletions
diff --git a/src/ui_readline.c b/src/ui_readline.c
index 98af5ea..8e6ecb4 100644
--- a/src/ui_readline.c
+++ b/src/ui_readline.c
@@ -1,5 +1,5 @@
/*
-Copyright (c) 2008-2010
+Copyright (c) 2008-2011
Lars-Dominik Braun <lars@6xq.net>
Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -24,6 +24,10 @@ THE SOFTWARE.
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
+#include <unistd.h>
+#include <assert.h>
+
+#include "ui_readline.h"
static inline void BarReadlineMoveLeft (char *buf, size_t *bufPos,
size_t *bufLen) {
@@ -52,33 +56,73 @@ static inline char BarReadlineIsUtf8Content (char b) {
* @param buffer
* @param buffer size
* @param accept these characters
- * @param return if buffer full (otherwise more characters are not accepted)
- * @param don't echo anything (for passwords)
- * @param read from this fd
+ * @param input fds
+ * @param flags
+ * @param timeout (seconds) or -1 (no timeout)
* @return number of bytes read from stdin
*/
-size_t BarReadline (char *buf, size_t bufSize, const char *mask,
- char fullReturn, char noEcho, FILE *fd) {
- int chr = 0;
+size_t BarReadline (char *buf, const size_t bufSize, const char *mask,
+ BarReadlineFds_t *input, const BarReadlineFlags_t flags, int timeout) {
size_t bufPos = 0;
size_t bufLen = 0;
unsigned char escapeState = 0;
+ fd_set set;
+ const bool echo = !(flags & BAR_RL_NOECHO);
+
+ assert (buf != NULL);
+ assert (bufSize > 0);
+ assert (input != NULL);
memset (buf, 0, bufSize);
/* if fd is a fifo fgetc will always return EOF if nobody writes to
* it, stdin will block */
- while ((chr = fgetc (fd)) != EOF) {
+ while (1) {
+ int curFd = -1;
+ char chr;
+ struct timeval timeoutstruct;
+
+ /* select modifies set and timeout */
+ memcpy (&set, &input->set, sizeof (set));
+ timeoutstruct.tv_sec = timeout;
+ timeoutstruct.tv_usec = 0;
+
+ if (select (input->maxfd, &set, NULL, NULL,
+ (timeout == -1) ? NULL : &timeoutstruct) <= 0) {
+ /* fail or timeout */
+ break;
+ }
+
+ assert (sizeof (input->fds) / sizeof (*input->fds) == 2);
+ if (FD_ISSET(input->fds[0], &set)) {
+ curFd = input->fds[0];
+ } else if (input->fds[1] != -1 && FD_ISSET(input->fds[1], &set)) {
+ curFd = input->fds[1];
+ }
+ if (read (curFd, &chr, sizeof (chr)) <= 0) {
+ /* select() is going wild if fdset contains EOFed stdin, only check
+ * for stdin, fifo is "reopened" as soon as another writer is
+ * available
+ * FIXME: ugly */
+ if (curFd == STDIN_FILENO) {
+ FD_CLR (curFd, &input->set);
+ }
+ continue;
+ }
switch (chr) {
/* EOT */
case 4:
- printf ("\n");
+ if (echo) {
+ fputs ("\n", stdout);
+ }
return bufLen;
break;
/* return */
case 10:
- printf ("\n");
+ if (echo) {
+ fputs ("\n", stdout);
+ }
return bufLen;
break;
@@ -109,15 +153,15 @@ size_t BarReadline (char *buf, size_t bufSize, const char *mask,
}
}
/* move caret back and delete last character */
- if (!noEcho) {
- printf ("\033[D\033[K");
+ if (echo) {
+ fputs ("\033[D\033[K", stdout);
fflush (stdout);
}
} else if (bufPos == 0 && buf[bufPos] != '\0') {
/* delete char at position 0 but don't move cursor any further */
buf[bufPos] = '\0';
- if (!noEcho) {
- printf ("\033[K");
+ if (echo) {
+ fputs ("\033[K", stdout);
fflush (stdout);
}
}
@@ -145,18 +189,21 @@ size_t BarReadline (char *buf, size_t bufSize, const char *mask,
buf[bufPos] = chr;
++bufPos;
++bufLen;
- if (!noEcho) {
- fputc (chr, stdout);
+ if (echo) {
+ putchar (chr);
+ fflush (stdout);
}
/* buffer full => return if requested */
- if (fullReturn && bufPos >= bufSize-1) {
- printf ("\n");
+ if (bufPos >= bufSize-1 && (flags & BAR_RL_FULLRETURN)) {
+ if (echo) {
+ fputs ("\n", stdout);
+ }
return bufLen;
}
}
break;
- }
- }
+ } /* end switch */
+ } /* end while */
return 0;
}
@@ -165,35 +212,36 @@ size_t BarReadline (char *buf, size_t bufSize, const char *mask,
* @param buffer size
* @return number of bytes read from stdin
*/
-size_t BarReadlineStr (char *buf, size_t bufSize, char noEcho,
- FILE *fd) {
- return BarReadline (buf, bufSize, NULL, 0, noEcho, fd);
+size_t BarReadlineStr (char *buf, const size_t bufSize,
+ BarReadlineFds_t *input, const BarReadlineFlags_t flags) {
+ return BarReadline (buf, bufSize, NULL, input, flags, -1);
}
/* Read int from stdin
* @param write result into this variable
* @return number of bytes read from stdin
*/
-size_t BarReadlineInt (int *ret, FILE *fd) {
+size_t BarReadlineInt (int *ret, BarReadlineFds_t *input) {
int rlRet = 0;
char buf[16];
- rlRet = BarReadline (buf, sizeof (buf), "0123456789", 0, 0, fd);
+ rlRet = BarReadline (buf, sizeof (buf), "0123456789", input,
+ BAR_RL_DEFAULT, -1);
*ret = atoi ((char *) buf);
return rlRet;
}
/* Yes/No?
- * @param defaul (user presses enter)
+ * @param default (user presses enter)
*/
-int BarReadlineYesNo (char def, FILE *fd) {
+bool BarReadlineYesNo (bool def, BarReadlineFds_t *input) {
char buf[2];
- BarReadline (buf, sizeof (buf), "yYnN", 1, 0, fd);
- if (*buf == 'y' || *buf == 'Y' || (def == 1 && *buf == '\0')) {
- return 1;
+ BarReadline (buf, sizeof (buf), "yYnN", input, BAR_RL_FULLRETURN, -1);
+ if (*buf == 'y' || *buf == 'Y' || (def == true && *buf == '\0')) {
+ return true;
} else {
- return 0;
+ return false;
}
}