1
/**************************************************************************
2
* Waitbar function -- displays progress of lengthy calculations
3
* -------------------------------------------------------------
4
* Copyright (c) 2002 Quentin Spencer <qspencer@ieee.org>
6
* This library is free software; you can redistribute it and/or
7
* modify it under the terms of the GNU Library General Public
8
* License as published by the Free Software Foundation; either
9
* version 2 of the License, or (at your option) any later version.
11
* This library is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14
* Library General Public License for more details.
16
* You should have received a copy of the GNU Library General Public
17
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
19
*************************************************************************/
21
#include <octave/oct.h>
23
// Note the extern "C" is need for mingw with a version of termcap.h
24
// without the extern "C" explicitly included. Doing it twice should be
27
#if defined (HAVE_TERM_H)
29
#elif defined (HAVE_TERMCAP_H)
36
#define DEFAULT_LEN 50
40
static bool no_terminal=false;
42
DEFUN_DLD(waitbar, args, nargout,
44
WAITBAR displays a text-based wait bar. This function\n\
45
is similar to the Matlab waitbar command, but it is\n\
46
a text, rather than graphical function.\n\n\
47
A typical usage of WAITBAR in a lengthy computation\n\
48
(inside a FOR loop, for example) is as follows:\n\n\
53
WAITBAR(X,TITLE), where 0 <= X <= 1, sets the position of\n\
54
the waitbar to the fractional length X. Values of X exactly\n\
55
equal to 0 or 1 clear the waitbar. The optional second\n\
56
argument TITLE sets the waitbar caption to TITLE.\n\n\
57
If Octave is running in a smart terminal, the width is\n\
58
automatically detected, and the title is displayed in the\n\
59
waitbar (and truncated if it is too long). Otherwise, the\n\
60
title is not displayed and the width is initialized to a\n\
61
default of 50 characters, or it can be set to N characters\n\
62
with WAITBAR(0,N). If no terminal is detected (such as when\n\
63
Octave is run in batch mode and output is redirected), no\n\
64
output is generated.\n\n\
65
For compatibility with the Matlab version of this function\n\
66
(which is graphical rather than text-based), additional\n\
67
arguments are ignored, but there are no guarantees of perfect\n\
70
static char print_buf[BUF_SIZE];
71
static int n_chars_old;
72
static int pct_int_old;
75
static char term_buffer[1024];
76
static char *begin_rv, *end_rv;
77
static int brvlen, ervlen, pct_pos;
78
static bool smart_term;
79
static bool newtitle = false;
80
static charMatrix title;
89
octave_value_list retval;
90
retval(0) = Matrix(0,0);
91
int nargin = args.length();
100
pct = args(0).double_value();
101
if(pct>1.0) pct = 1.0; // to prevent overflow
103
#if defined(USE_TERM)
104
if(nargin==2 && args(1).is_string())
107
title = args(1).string_value();
112
title = args(2).string_value();
116
if(pct==0.0 || pct==1.0)
119
term = getenv("TERM");
125
#if defined (USE_TERM)
127
smart_term = i ? true : false;
128
if(nargin==1 || args(1).is_string())
129
length = smart_term ? i-1 : DEFAULT_LEN;
132
length = DEFAULT_LEN;
135
if(nargin==2 && !(args(1).is_string()))
137
length = args(1).int_value();
138
if(length>MAX_LEN) length = MAX_LEN;
139
if(length<=0) length = DEFAULT_LEN;
141
#if defined (USE_TERM)
142
pct_pos = length/2-2;
145
// get terminal strings ("rv"="reverse video")
146
char* buf_ptr = term_buffer;
147
begin_rv = tgetstr("so", &buf_ptr);
148
end_rv = tgetstr("se", &buf_ptr);
150
// Display a progress bar, but only if the current terminal has a
152
if (begin_rv && end_rv)
156
while(buf_ptr[++brvlen]);
157
ervlen = 0; buf_ptr = end_rv;
158
while(buf_ptr[++ervlen]);
161
// initialize print buffer
162
for(i=0; i<BUF_SIZE; ++i)
164
print_buf[length+brvlen+ervlen+1] = '\r';
165
print_buf[length+brvlen+ervlen+2] = '\0';
166
for(i=0; i<brvlen; ++i)
167
print_buf[i] = begin_rv[i];
168
for(i=0; i<ervlen; ++i)
169
print_buf[i+brvlen] = end_rv[i];
170
fputs(print_buf,stdout);
177
for(i=0; i<BUF_SIZE; ++i)
179
print_buf[length+8] = '\r';
180
print_buf[length+9] = '\0';
181
fputs(print_buf,stdout);
183
print_buf[length+1] = ']';
184
#if defined (USE_TERM)
193
// calculate position
194
int n_chars=(int)(pct*length+0.5);
195
int pct_int=(int)(pct*100.0+0.5);
197
// check to see if we got this far without initialization
200
Fwaitbar(octave_value(0.0),0);
201
fputs(print_buf,stdout);
205
// check to see of output needs to be updated
206
#if !defined (USE_TERM)
207
if(n_chars!=n_chars_old || pct_int!=pct_int_old)
210
if(n_chars!=n_chars_old || pct_int!=pct_int_old || newtitle)
214
static char pct_str[5];
215
sprintf(pct_str,"%3i%%",pct_int);
220
pct_pos = length-SPACING*2;
221
for(i=SPACING+brvlen; i<pct_pos+brvlen-SPACING; ++i)
222
print_buf[ i>=n_chars_old+brvlen ? i+ervlen : i ] = ' ';
223
for(i=SPACING+brvlen, j=0; j<title.length(); ++i, ++j)
224
if(i<pct_pos+brvlen-SPACING)
225
print_buf[ i>=n_chars_old ? i+ervlen : i ] = title(0,j);
229
// Insert the percentage string
230
for(i=pct_pos+brvlen, j=0; j<4; ++i, ++j)
231
print_buf[ i>=n_chars_old+brvlen ? i+ervlen : i ] = pct_str[j];
233
// Move print_buf characters
234
if(n_chars_old<n_chars)
235
for(i=n_chars_old+brvlen; i<n_chars+brvlen; ++i)
236
print_buf[i] = print_buf[i+ervlen];
238
for(i=n_chars_old+brvlen-1; i>=n_chars+brvlen; --i)
239
print_buf[i+ervlen] = print_buf[i];
241
// Insert end of reverse video
242
for(i=n_chars+brvlen, j=0; j<ervlen; ++i, ++j)
243
print_buf[i] = end_rv[j];
248
if(n_chars>=n_chars_old)
249
for(int i=n_chars_old+1; i<=n_chars; ++i)
250
print_buf[i] = BAR_CHAR;
252
for(int i=n_chars+1; i<=n_chars_old; ++i)
254
sprintf(&(print_buf[length+3])," %3i%%\r",pct_int);
255
#if defined (USE_TERM)
258
fputs(print_buf,stdout);
260
n_chars_old = n_chars;
261
pct_int_old = pct_int;