1
// Copyright (C) 2002 Quentin Spencer <qspencer@ieee.org>
3
// This program is free software; you can redistribute it and/or modify it under
4
// the terms of the GNU General Public License as published by the Free Software
5
// Foundation; either version 3 of the License, or (at your option) any later
8
// This program is distributed in the hope that it will be useful, but WITHOUT
9
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
13
// You should have received a copy of the GNU General Public License along with
14
// this program; if not, see <http://www.gnu.org/licenses/>.
16
#include <octave/oct.h>
18
// Note the extern "C" is need for mingw with a version of termcap.h
19
// without the extern "C" explicitly included. Doing it twice should be
22
#if defined (HAVE_TERM_H)
24
#elif defined (HAVE_TERMCAP_H)
31
#define DEFAULT_LEN 50
35
static bool no_terminal=false;
37
DEFUN_DLD(text_waitbar, args, nargout,
39
@deftypefn {Loadable Function} {} text_waitbar (@var{frac})\n\
40
@deftypefnx {Loadable Function} {} text_waitbar (@var{frac}, @var{msg})\n\
41
@deftypefnx {Loadable Function} {} text_waitbar (0, @var{n})\n\
42
Display text-based waitbar/progress bar.\n\
44
This function is similar to the @code{waitbar} function but is a text, rather\n\
45
than graphical bar. The waitbar is filled to fraction @var{frac} which must\n\
46
be in the range [0, 1]. Values exactly equal to 0 or 1 clear the waitbar.\n\
48
The optional message @var{msg} sets the waitbar caption. If Octave is running\n\
49
in a smart terminal, the width is automatically detected, and @var{msg} is\n\
50
displayed in the waitbar (and truncated if it is too long). Otherwise,\n\
51
@var{msg} is not displayed and the width is initialized to a default of 50\n\
52
characters, or it can be set to @var{n} characters with\n\
53
@code{text_waitbar (0, @var{n})}. If no terminal is detected (such as when\n\
54
Octave is run in batch mode and output is redirected), no output is\n\
57
Additional arguments are ignored for compatibility with the graphical\n\
58
counterpart of this function but there are no guarantees of perfect\n\
64
static char print_buf[BUF_SIZE];
65
static int n_chars_old;
66
static int pct_int_old;
69
static char term_buffer[1024];
70
static char *begin_rv, *end_rv;
71
static int brvlen, ervlen, pct_pos;
72
static bool smart_term;
73
static bool newtitle = false;
74
static charMatrix title;
83
octave_value_list retval;
84
retval(0) = Matrix(0,0);
85
int nargin = args.length();
94
pct = args(0).double_value();
95
if(pct>1.0) pct = 1.0; // to prevent overflow
98
if(nargin==2 && args(1).is_string())
101
title = args(1).string_value();
106
title = args(2).string_value();
110
if(pct==0.0 || pct==1.0)
113
term = getenv("TERM");
119
#if defined (USE_TERM)
121
smart_term = i ? true : false;
122
if(nargin==1 || args(1).is_string())
123
length = smart_term ? i-1 : DEFAULT_LEN;
126
length = DEFAULT_LEN;
129
if(nargin==2 && !(args(1).is_string()))
131
length = args(1).int_value();
132
if(length>MAX_LEN) length = MAX_LEN;
133
if(length<=0) length = DEFAULT_LEN;
135
#if defined (USE_TERM)
136
pct_pos = length/2-2;
139
// get terminal strings ("rv"="reverse video")
140
char* buf_ptr = term_buffer;
141
begin_rv = tgetstr("so", &buf_ptr);
142
end_rv = tgetstr("se", &buf_ptr);
144
// Display a progress bar, but only if the current terminal has a
146
if (begin_rv && end_rv)
150
while(buf_ptr[++brvlen]);
151
ervlen = 0; buf_ptr = end_rv;
152
while(buf_ptr[++ervlen]);
154
// initialize print buffer
155
for(i=0; i<BUF_SIZE; ++i)
157
print_buf[length+brvlen+ervlen+1] = '\r';
158
print_buf[length+brvlen+ervlen+2] = '\0';
159
for(i=0; i<brvlen; ++i)
160
print_buf[i] = begin_rv[i];
161
for(i=0; i<ervlen; ++i)
162
print_buf[i+brvlen] = end_rv[i];
163
fputs(print_buf,stdout);
170
for(i=0; i<BUF_SIZE; ++i)
172
print_buf[length+8] = '\r';
173
print_buf[length+9] = '\0';
174
fputs(print_buf,stdout);
176
print_buf[length+1] = ']';
177
#if defined (USE_TERM)
186
// calculate position
187
int n_chars=(int)(pct*length+0.5);
188
int pct_int=(int)(pct*100.0+0.5);
190
// check to see if we got this far without initialization
193
Ftext_waitbar(octave_value(0.0),0);
194
fputs(print_buf,stdout);
198
// check to see of output needs to be updated
199
#if !defined (USE_TERM)
200
if(n_chars!=n_chars_old || pct_int!=pct_int_old)
203
if(n_chars!=n_chars_old || pct_int!=pct_int_old || newtitle)
207
static char pct_str[5];
208
sprintf(pct_str,"%3i%%",pct_int);
213
pct_pos = length-SPACING*2;
214
for(i=SPACING+brvlen; i<pct_pos+brvlen-SPACING; ++i)
215
print_buf[ i>=n_chars_old+brvlen ? i+ervlen : i ] = ' ';
216
for(i=SPACING+brvlen, j=0; j<title.length(); ++i, ++j)
217
if(i<pct_pos+brvlen-SPACING)
218
print_buf[ i>=n_chars_old ? i+ervlen : i ] = title(0,j);
222
// Insert the percentage string
223
for(i=pct_pos+brvlen, j=0; j<4; ++i, ++j)
224
print_buf[ i>=n_chars_old+brvlen ? i+ervlen : i ] = pct_str[j];
226
// Move print_buf characters
227
if(n_chars_old<n_chars)
228
for(i=n_chars_old+brvlen; i<n_chars+brvlen; ++i)
229
print_buf[i] = print_buf[i+ervlen];
231
for(i=n_chars_old+brvlen-1; i>=n_chars+brvlen; --i)
232
print_buf[i+ervlen] = print_buf[i];
234
// Insert end of reverse video
235
for(i=n_chars+brvlen, j=0; j<ervlen; ++i, ++j)
236
print_buf[i] = end_rv[j];
241
if(n_chars>=n_chars_old)
242
for(int i=n_chars_old+1; i<=n_chars; ++i)
243
print_buf[i] = BAR_CHAR;
245
for(int i=n_chars+1; i<=n_chars_old; ++i)
247
sprintf(&(print_buf[length+3])," %3i%%\r",pct_int);
248
#if defined (USE_TERM)
251
fputs(print_buf,stdout);
253
n_chars_old = n_chars;
254
pct_int_old = pct_int;