shellwindow: fix line reading code

In case of partially read lines, the last complete line before was
discarded. Fix this, simplify the code  and make it code work at all
for lines longer than 1023 bytes (went into endless loop before).
This commit is contained in:
Stefan Seyfried
2015-02-01 20:11:02 +01:00
committed by Jacek Jendrzej
parent e02972c81c
commit 27124e72e1

View File

@@ -82,27 +82,26 @@ CShellWindow::CShellWindow(const std::string &command, const int _mode, int *res
struct timeval tv; struct timeval tv;
gettimeofday(&tv,NULL); gettimeofday(&tv,NULL);
uint64_t lastPaint = (uint64_t) tv.tv_usec + (uint64_t)((uint64_t) tv.tv_sec * (uint64_t) 1000000); uint64_t lastPaint = (uint64_t) tv.tv_usec + (uint64_t)((uint64_t) tv.tv_sec * (uint64_t) 1000000);
bool ok = true, nlseen = false, dirty = false, pushed = false; bool ok = true, nlseen = false, dirty = false, incomplete = false;
char output[1024]; char output[1024];
int off = 0;
std::string txt = ""; std::string txt = "";
std::string line = "";
do { do {
uint64_t now; uint64_t now;
fds.revents = 0; fds.revents = 0;
int r = poll(&fds, 1, 300); int r = poll(&fds, 1, 300);
if (r > 0) { if (r > 0) {
if (!feof(f)) { if (!feof(f)) {
gettimeofday(&tv,NULL); gettimeofday(&tv,NULL);
now = (uint64_t) tv.tv_usec + (uint64_t)((uint64_t) tv.tv_sec * (uint64_t) 1000000); now = (uint64_t) tv.tv_usec + (uint64_t)((uint64_t) tv.tv_sec * (uint64_t) 1000000);
unsigned int lines_read = 0; unsigned int lines_read = 0;
while (fgets(output + off, sizeof(output) - off, f)) { while (fgets(output, sizeof(output), f)) {
char *outputp = output + off; char *outputp = output;
dirty = true; dirty = true;
for (int i = off; output[i] && !nlseen; i++) for (int i = 0; output[i] && !nlseen; i++)
switch (output[i]) { switch (output[i]) {
case '\b': case '\b':
if (outputp > output) if (outputp > output)
@@ -124,26 +123,26 @@ CShellWindow::CShellWindow(const std::string &command, const int _mode, int *res
if (outputp < output + sizeof(output)) if (outputp < output + sizeof(output))
*outputp = 0; *outputp = 0;
line += std::string(output);
if (incomplete)
lines.pop_back();
if (nlseen) { if (nlseen) {
pushed = false; lines.push_back(line);
line.clear();
nlseen = false; nlseen = false;
off = 0; incomplete = false;
} else { } else {
off = strlen(output); lines.push_back(line);
if (pushed) incomplete = true;
lines.pop_back();
} }
lines.push_back(std::string((output)));
pushed = true;
if (lines.size() > lines_max) if (lines.size() > lines_max)
lines.pop_front(); lines.pop_front();
txt = ""; txt = "";
bool first = true; bool first = true;
for (std::list<std::string>::const_iterator it = lines.begin(), end = lines.end(); it != end; ++it) { for (std::list<std::string>::const_iterator it = lines.begin(), end = lines.end(); it != end; ++it) {
if (first) if (!first)
first = false;
else
txt += '\n'; txt += '\n';
first = false;
txt += *it; txt += *it;
} }
if (((lines_read == lines_max) && (lastPaint + 100000 < now)) || (lastPaint + 250000 < now)) { if (((lines_read == lines_max) && (lastPaint + 100000 < now)) || (lastPaint + 250000 < now)) {