2018-12-18 15:13:35 +03:00
// SPDX-License-Identifier: GPL-2.0+
2005-04-17 02:20:36 +04:00
/*
* textbox . c - - implements the text box
*
* ORIGINAL AUTHOR : Savio Lam ( lam836 @ cs . cuhk . hk )
* MODIFIED FOR LINUX KERNEL CONFIG BY : William Roadcap ( roadcap @ cfw . com )
*/
# include "dialog.h"
2005-11-19 21:13:34 +03:00
static void back_lines ( int n ) ;
2012-08-23 22:55:08 +04:00
static void print_page ( WINDOW * win , int height , int width , update_text_fn
update_text , void * data ) ;
static void print_line ( WINDOW * win , int row , int width ) ;
2005-11-19 21:13:34 +03:00
static char * get_line ( void ) ;
2006-07-30 00:48:57 +04:00
static void print_position ( WINDOW * win ) ;
2005-04-17 02:20:36 +04:00
2006-07-28 00:10:27 +04:00
static int hscroll ;
static int begin_reached , end_reached , page_length ;
2012-08-23 22:55:08 +04:00
static char * buf ;
static char * page ;
2005-04-17 02:20:36 +04:00
2006-07-30 00:48:57 +04:00
/*
* refresh window content
*/
static void refresh_text_box ( WINDOW * dialog , WINDOW * box , int boxh , int boxw ,
2012-08-23 22:55:08 +04:00
int cur_y , int cur_x , update_text_fn update_text ,
void * data )
2006-07-30 00:48:57 +04:00
{
2012-08-23 22:55:08 +04:00
print_page ( box , boxh , boxw , update_text , data ) ;
2006-07-30 00:48:57 +04:00
print_position ( dialog ) ;
wmove ( dialog , cur_y , cur_x ) ; /* Restore cursor position */
wrefresh ( dialog ) ;
}
2005-04-17 02:20:36 +04:00
/*
* Display text from a file in a dialog box .
2012-08-23 22:55:04 +04:00
*
* keys is a null - terminated array
2012-08-23 22:55:08 +04:00
* update_text ( ) may not add or remove any ' \n ' or ' \0 ' in tbuf
2005-04-17 02:20:36 +04:00
*/
2012-08-23 22:55:08 +04:00
int dialog_textbox ( const char * title , char * tbuf , int initial_height ,
int initial_width , int * keys , int * _vscroll , int * _hscroll ,
update_text_fn update_text , void * data )
2005-04-17 02:20:36 +04:00
{
2006-07-28 00:10:27 +04:00
int i , x , y , cur_x , cur_y , key = 0 ;
2006-07-30 00:48:57 +04:00
int height , width , boxh , boxw ;
WINDOW * dialog , * box ;
2012-08-23 22:55:04 +04:00
bool done = false ;
2005-11-19 21:13:34 +03:00
2006-07-28 00:10:27 +04:00
begin_reached = 1 ;
end_reached = 0 ;
page_length = 0 ;
hscroll = 0 ;
buf = tbuf ;
page = buf ; /* page is pointer to start of page to be displayed */
2005-11-19 21:13:34 +03:00
2012-08-23 22:55:05 +04:00
if ( _vscroll & & * _vscroll ) {
begin_reached = 0 ;
for ( i = 0 ; i < * _vscroll ; i + + )
get_line ( ) ;
}
if ( _hscroll )
hscroll = * _hscroll ;
2006-07-30 00:48:57 +04:00
do_resize :
getmaxyx ( stdscr , height , width ) ;
2013-06-15 13:07:35 +04:00
if ( height < TEXTBOX_HEIGTH_MIN | | width < TEXTBOX_WIDTH_MIN )
2006-07-30 00:48:57 +04:00
return - ERRDISPLAYTOOSMALL ;
if ( initial_height ! = 0 )
height = initial_height ;
else
if ( height > 4 )
height - = 4 ;
else
height = 0 ;
if ( initial_width ! = 0 )
width = initial_width ;
else
if ( width > 5 )
width - = 5 ;
else
width = 0 ;
2005-11-19 21:13:34 +03:00
/* center dialog box on screen */
2013-05-12 14:30:49 +04:00
x = ( getmaxx ( stdscr ) - width ) / 2 ;
y = ( getmaxy ( stdscr ) - height ) / 2 ;
2005-11-19 21:13:34 +03:00
draw_shadow ( stdscr , y , x , height , width ) ;
dialog = newwin ( height , width , y , x ) ;
keypad ( dialog , TRUE ) ;
2006-07-30 00:48:57 +04:00
/* Create window for box region, used for scrolling text */
boxh = height - 4 ;
boxw = width - 2 ;
box = subwin ( dialog , boxh , boxw , y + 1 , x + 1 ) ;
wattrset ( box , dlg . dialog . atr ) ;
wbkgdset ( box , dlg . dialog . atr & A_COLOR ) ;
2005-11-19 21:13:34 +03:00
2006-07-30 00:48:57 +04:00
keypad ( box , TRUE ) ;
2005-11-19 21:13:34 +03:00
/* register the new window, along with its borders */
2006-07-24 23:40:46 +04:00
draw_box ( dialog , 0 , 0 , height , width ,
dlg . dialog . atr , dlg . border . atr ) ;
2005-11-19 21:13:34 +03:00
2006-07-24 23:40:46 +04:00
wattrset ( dialog , dlg . border . atr ) ;
2005-11-19 21:13:34 +03:00
mvwaddch ( dialog , height - 3 , 0 , ACS_LTEE ) ;
for ( i = 0 ; i < width - 2 ; i + + )
waddch ( dialog , ACS_HLINE ) ;
2006-07-24 23:40:46 +04:00
wattrset ( dialog , dlg . dialog . atr ) ;
wbkgdset ( dialog , dlg . dialog . atr & A_COLOR ) ;
2005-11-19 21:13:34 +03:00
waddch ( dialog , ACS_RTEE ) ;
2005-11-20 01:38:06 +03:00
print_title ( dialog , title , width ) ;
2005-04-17 02:20:36 +04:00
2018-05-22 22:36:12 +03:00
print_button ( dialog , " Exit " , height - 2 , width / 2 - 4 , TRUE ) ;
2005-11-19 21:13:34 +03:00
wnoutrefresh ( dialog ) ;
getyx ( dialog , cur_y , cur_x ) ; /* Save cursor position */
/* Print first page of text */
2006-07-30 00:48:57 +04:00
attr_clear ( box , boxh , boxw , dlg . dialog . atr ) ;
2012-08-23 22:55:08 +04:00
refresh_text_box ( dialog , box , boxh , boxw , cur_y , cur_x , update_text ,
data ) ;
2005-11-19 21:13:34 +03:00
2012-08-23 22:55:04 +04:00
while ( ! done ) {
2005-11-19 21:13:34 +03:00
key = wgetch ( dialog ) ;
switch ( key ) {
case ' E ' : /* Exit */
case ' e ' :
case ' X ' :
case ' x ' :
2012-07-25 00:12:02 +04:00
case ' q ' :
2012-08-23 22:55:04 +04:00
case ' \n ' :
done = true ;
break ;
2005-11-19 21:13:34 +03:00
case ' g ' : /* First page */
case KEY_HOME :
if ( ! begin_reached ) {
begin_reached = 1 ;
page = buf ;
2006-07-30 00:48:57 +04:00
refresh_text_box ( dialog , box , boxh , boxw ,
2012-08-23 22:55:08 +04:00
cur_y , cur_x , update_text ,
data ) ;
2005-11-19 21:13:34 +03:00
}
break ;
case ' G ' : /* Last page */
case KEY_END :
end_reached = 1 ;
2006-07-28 00:10:27 +04:00
/* point to last char in buf */
page = buf + strlen ( buf ) ;
2006-07-30 00:48:57 +04:00
back_lines ( boxh ) ;
2012-08-23 22:55:08 +04:00
refresh_text_box ( dialog , box , boxh , boxw , cur_y ,
cur_x , update_text , data ) ;
2005-11-19 21:13:34 +03:00
break ;
case ' K ' : /* Previous line */
case ' k ' :
case KEY_UP :
2012-08-23 22:55:07 +04:00
if ( begin_reached )
break ;
2005-11-19 21:13:34 +03:00
2012-08-23 22:55:07 +04:00
back_lines ( page_length + 1 ) ;
refresh_text_box ( dialog , box , boxh , boxw , cur_y ,
2012-08-23 22:55:08 +04:00
cur_x , update_text , data ) ;
2005-11-19 21:13:34 +03:00
break ;
case ' B ' : /* Previous page */
case ' b ' :
2012-07-25 00:12:02 +04:00
case ' u ' :
2005-11-19 21:13:34 +03:00
case KEY_PPAGE :
if ( begin_reached )
break ;
2006-07-30 00:48:57 +04:00
back_lines ( page_length + boxh ) ;
2012-08-23 22:55:08 +04:00
refresh_text_box ( dialog , box , boxh , boxw , cur_y ,
cur_x , update_text , data ) ;
2005-11-19 21:13:34 +03:00
break ;
case ' J ' : /* Next line */
case ' j ' :
case KEY_DOWN :
2012-08-23 22:55:07 +04:00
if ( end_reached )
break ;
back_lines ( page_length - 1 ) ;
refresh_text_box ( dialog , box , boxh , boxw , cur_y ,
2012-08-23 22:55:08 +04:00
cur_x , update_text , data ) ;
2005-11-19 21:13:34 +03:00
break ;
case KEY_NPAGE : /* Next page */
case ' ' :
2012-07-25 00:12:02 +04:00
case ' d ' :
2005-11-19 21:13:34 +03:00
if ( end_reached )
break ;
begin_reached = 0 ;
2012-08-23 22:55:08 +04:00
refresh_text_box ( dialog , box , boxh , boxw , cur_y ,
cur_x , update_text , data ) ;
2005-11-19 21:13:34 +03:00
break ;
case ' 0 ' : /* Beginning of line */
case ' H ' : /* Scroll left */
case ' h ' :
case KEY_LEFT :
if ( hscroll < = 0 )
break ;
if ( key = = ' 0 ' )
hscroll = 0 ;
else
hscroll - - ;
/* Reprint current page to scroll horizontally */
back_lines ( page_length ) ;
2012-08-23 22:55:08 +04:00
refresh_text_box ( dialog , box , boxh , boxw , cur_y ,
cur_x , update_text , data ) ;
2005-11-19 21:13:34 +03:00
break ;
case ' L ' : /* Scroll right */
case ' l ' :
case KEY_RIGHT :
if ( hscroll > = MAX_LEN )
break ;
hscroll + + ;
/* Reprint current page to scroll horizontally */
back_lines ( page_length ) ;
2012-08-23 22:55:08 +04:00
refresh_text_box ( dialog , box , boxh , boxw , cur_y ,
cur_x , update_text , data ) ;
2005-11-19 21:13:34 +03:00
break ;
2006-07-29 01:57:48 +04:00
case KEY_ESC :
2012-08-23 22:55:04 +04:00
if ( on_key_esc ( dialog ) = = KEY_ESC )
done = true ;
2005-11-19 21:13:34 +03:00
break ;
2006-07-30 00:48:57 +04:00
case KEY_RESIZE :
back_lines ( height ) ;
delwin ( box ) ;
delwin ( dialog ) ;
on_key_resize ( ) ;
goto do_resize ;
2012-08-23 22:55:04 +04:00
default :
for ( i = 0 ; keys [ i ] ; i + + ) {
if ( key = = keys [ i ] ) {
done = true ;
break ;
}
}
2005-11-19 21:13:34 +03:00
}
2005-04-17 02:20:36 +04:00
}
2006-07-30 00:48:57 +04:00
delwin ( box ) ;
2005-11-19 21:13:34 +03:00
delwin ( dialog ) ;
2012-08-23 22:55:05 +04:00
if ( _vscroll ) {
const char * s ;
s = buf ;
* _vscroll = 0 ;
back_lines ( page_length ) ;
while ( s < page & & ( s = strchr ( s , ' \n ' ) ) ) {
( * _vscroll ) + + ;
s + + ;
}
}
if ( _hscroll )
* _hscroll = hscroll ;
2012-08-23 22:55:04 +04:00
return key ;
2005-04-17 02:20:36 +04:00
}
/*
2006-07-28 00:10:27 +04:00
* Go back ' n ' lines in text . Called by dialog_textbox ( ) .
2005-04-17 02:20:36 +04:00
* ' page ' will be updated to point to the desired line in ' buf ' .
*/
2005-11-19 21:13:34 +03:00
static void back_lines ( int n )
2005-04-17 02:20:36 +04:00
{
2006-07-28 00:10:27 +04:00
int i ;
2005-11-19 21:13:34 +03:00
begin_reached = 0 ;
2006-07-28 00:10:27 +04:00
/* Go back 'n' lines */
for ( i = 0 ; i < n ; i + + ) {
if ( * page = = ' \0 ' ) {
if ( end_reached ) {
end_reached = 0 ;
continue ;
2005-11-19 21:13:34 +03:00
}
2005-04-17 02:20:36 +04:00
}
2006-07-28 00:10:27 +04:00
if ( page = = buf ) {
begin_reached = 1 ;
return ;
2005-04-17 02:20:36 +04:00
}
2006-07-28 00:10:27 +04:00
page - - ;
2005-11-19 21:13:34 +03:00
do {
if ( page = = buf ) {
2006-07-28 00:10:27 +04:00
begin_reached = 1 ;
return ;
2005-04-17 02:20:36 +04:00
}
2006-07-28 00:10:27 +04:00
page - - ;
} while ( * page ! = ' \n ' ) ;
page + + ;
}
2005-04-17 02:20:36 +04:00
}
/*
2012-08-23 22:55:08 +04:00
* Print a new page of text .
2005-04-17 02:20:36 +04:00
*/
2012-08-23 22:55:08 +04:00
static void print_page ( WINDOW * win , int height , int width , update_text_fn
update_text , void * data )
2005-04-17 02:20:36 +04:00
{
2005-11-19 21:13:34 +03:00
int i , passed_end = 0 ;
2012-08-23 22:55:08 +04:00
if ( update_text ) {
char * end ;
for ( i = 0 ; i < height ; i + + )
get_line ( ) ;
end = page ;
back_lines ( height ) ;
update_text ( buf , page - buf , end - buf , data ) ;
}
2005-11-19 21:13:34 +03:00
page_length = 0 ;
for ( i = 0 ; i < height ; i + + ) {
print_line ( win , i , width ) ;
if ( ! passed_end )
page_length + + ;
if ( end_reached & & ! passed_end )
passed_end = 1 ;
}
wnoutrefresh ( win ) ;
2005-04-17 02:20:36 +04:00
}
/*
2012-08-23 22:55:08 +04:00
* Print a new line of text .
2005-04-17 02:20:36 +04:00
*/
2005-11-19 21:13:34 +03:00
static void print_line ( WINDOW * win , int row , int width )
2005-04-17 02:20:36 +04:00
{
2005-11-19 21:13:34 +03:00
char * line ;
2005-04-17 02:20:36 +04:00
2005-11-19 21:13:34 +03:00
line = get_line ( ) ;
line + = MIN ( strlen ( line ) , hscroll ) ; /* Scroll horizontally */
wmove ( win , row , 0 ) ; /* move cursor to correct line */
waddch ( win , ' ' ) ;
waddnstr ( win , line , MIN ( strlen ( line ) , width - 2 ) ) ;
2005-04-17 02:20:36 +04:00
2005-11-19 21:13:34 +03:00
/* Clear 'residue' of previous line */
2005-04-17 02:20:36 +04:00
# if OLD_NCURSES
2005-11-19 21:13:34 +03:00
{
2011-08-20 09:28:53 +04:00
int x = getcurx ( win ) ;
2005-11-19 21:13:34 +03:00
int i ;
for ( i = 0 ; i < width - x ; i + + )
waddch ( win , ' ' ) ;
}
2005-04-17 02:20:36 +04:00
# else
2005-11-19 21:13:34 +03:00
wclrtoeol ( win ) ;
2005-04-17 02:20:36 +04:00
# endif
}
/*
* Return current line of text . Called by dialog_textbox ( ) and print_line ( ) .
* ' page ' should point to start of current line before calling , and will be
* updated to point to start of next line .
*/
2005-11-19 21:13:34 +03:00
static char * get_line ( void )
2005-04-17 02:20:36 +04:00
{
2006-07-28 00:10:27 +04:00
int i = 0 ;
2005-11-19 21:13:34 +03:00
static char line [ MAX_LEN + 1 ] ;
end_reached = 0 ;
while ( * page ! = ' \n ' ) {
if ( * page = = ' \0 ' ) {
2012-08-23 22:55:03 +04:00
end_reached = 1 ;
break ;
2005-11-19 21:13:34 +03:00
} else if ( i < MAX_LEN )
line [ i + + ] = * ( page + + ) ;
else {
/* Truncate lines longer than MAX_LEN characters */
if ( i = = MAX_LEN )
line [ i + + ] = ' \0 ' ;
page + + ;
2005-04-17 02:20:36 +04:00
}
}
2005-11-19 21:13:34 +03:00
if ( i < = MAX_LEN )
line [ i ] = ' \0 ' ;
if ( ! end_reached )
2012-08-23 22:55:03 +04:00
page + + ; /* move past '\n' */
2005-04-17 02:20:36 +04:00
2005-11-19 21:13:34 +03:00
return line ;
2005-04-17 02:20:36 +04:00
}
/*
* Print current position
*/
2006-07-30 00:48:57 +04:00
static void print_position ( WINDOW * win )
2005-04-17 02:20:36 +04:00
{
2006-07-28 00:10:27 +04:00
int percent ;
2005-11-19 21:13:34 +03:00
2006-07-24 23:40:46 +04:00
wattrset ( win , dlg . position_indicator . atr ) ;
wbkgdset ( win , dlg . position_indicator . atr & A_COLOR ) ;
2006-07-28 00:10:27 +04:00
percent = ( page - buf ) * 100 / strlen ( buf ) ;
2006-07-30 00:48:57 +04:00
wmove ( win , getmaxy ( win ) - 3 , getmaxx ( win ) - 9 ) ;
2005-11-19 21:13:34 +03:00
wprintw ( win , " (%3d%%) " , percent ) ;
2005-04-17 02:20:36 +04:00
}