33 #include <yui/Libyui_config.h>
35 #define YUILogComponent "ncurses"
36 #include <yui/YUILog.h>
43 #include <sys/types.h>
52 std::set<NCDialog*> NCurses::_knownDlgs;
53 const NCursesEvent NCursesEvent::Activated( NCursesEvent::button, YEvent::Activated );
54 const NCursesEvent NCursesEvent::SelectionChanged( NCursesEvent::button, YEvent::SelectionChanged );
55 const NCursesEvent NCursesEvent::ValueChanged( NCursesEvent::button, YEvent::ValueChanged );
60 #define CONVERR(n,p) \
66 errmsg_t = vform( p, ap, ap1 ); \
70 NCursesError::NCursesError(
const char * msg, ... )
76 NCursesError::NCursesError(
int val,
const char * msg, ... )
82 NCursesError & NCursesError::NCError(
const char * msg, ... )
88 NCursesError & NCursesError::NCError(
int val,
const char * msg, ... )
97 std::ostream & operator<<( std::ostream & STREAM,
const NCursesError & OBJ )
99 STREAM << form(
"%s: (%d) %s"
102 , OBJ.errmsg_t.c_str() );
107 std::ostream & operator<<( std::ostream & STREAM,
const NCursesEvent & OBJ )
109 #define ENUM_OUT(v) case NCursesEvent::v: return STREAM << "Ev::" << #v
123 return STREAM <<
"Ev::unknown";
135 const char * term = getenv(
"TERM" );
145 yuiMilestone() <<
"Shutdown NCurses..." << std::endl;
149 setenv(
"TERM", envTerm.c_str(), 1 );
157 ::delwin( status_w );
162 ::delscreen( theTerm );
164 yuiMilestone() <<
"NCurses down" << std::endl;
169 WINDOW * NCurses::ripped_w_top = 0;
170 WINDOW * NCurses::ripped_w_bottom = 0;
172 int NCurses::ripinit_top( WINDOW * w,
int c )
179 int NCurses::ripinit_bottom( WINDOW * w,
int c )
188 yuiMilestone() <<
"Launch NCurses..."
190 <<
"(ui-ncurses-" << VERSION <<
")"
193 yuiMilestone() <<
"TERM=" << envTerm << std::endl;
195 signal( SIGINT, SIG_IGN );
199 if ( title_line() && ::ripoffline( 1, ripinit_top ) != OK )
203 if ( ::ripoffline( -1, ripinit_bottom ) != OK )
206 yuiMilestone() <<
"isatty(stdin)" << ( isatty( 0 ) ?
"yes" :
"no" ) << std::endl;
210 char * mytty = ttyname( 0 );
214 yuiMilestone() <<
"mytty: " << mytty << std::endl;
215 FILE * fdi = fopen( mytty,
"r" );
219 yuiError() <<
"fdi: (" << errno <<
") " << strerror( errno ) << std::endl;
222 FILE * fdo = fopen( mytty,
"w" );
226 yuiError() <<
"fdo: (" << errno <<
") " << strerror( errno ) << std::endl;
231 theTerm = newterm( 0, fdo, fdi );
235 if ( theTerm == NULL )
241 std::string fallbackTerm =
"";
244 if ( ! fnmatch(
"xterm*", envTerm.c_str(), 0 ) )
245 fallbackTerm =
"xterm";
247 fallbackTerm =
"vt100";
249 yuiWarning() <<
"newterm() failed, using generic " << fallbackTerm <<
" as a fallback" << std::endl;
252 setenv(
"TERM", fallbackTerm.c_str(), 1 );
255 theTerm = newterm( 0, fdo, fdi );
257 if ( theTerm == NULL )
261 if ( set_term( theTerm ) == NULL )
271 stdout_save = dup( 1 );
272 stderr_save = dup( 2 );
278 yuiMilestone() <<
"no term so fall back to initscr" << std::endl;
280 if ( ::initscr() == NULL )
284 yuiMilestone() <<
"have color = " << ::has_colors() << std::endl;
286 if ( want_colors() && ::has_colors() )
288 if ( ::start_color() != OK )
291 NCattribute::init_colors();
299 title_w = ripped_w_top;
302 if ( !ripped_w_bottom )
305 status_w = ripped_w_bottom;
309 yuiMilestone() << form(
"screen size %d x %d\n", lines(), cols() );
312 styleset =
new NCstyle( envTerm );
314 stdpan->
bkgd( style()( NCstyle::AppText ) );
318 SetStatusLine( myself->status_line );
321 yuiMilestone() <<
"NCurses ready" << std::endl;
326 void NCurses::setup_screen()
330 ::keypad( ::stdscr,
true );
331 ::meta( ::stdscr,
true );
332 ::leaveok( ::stdscr,
true );
335 ::define_key(
"\e[Z", KEY_BTAB );
336 ::define_key(
"\e\t", KEY_BTAB );
337 ::define_key(
"\030\t", KEY_BTAB );
342 void NCurses::init_title()
344 ::wbkgd( title_w, style()( NCstyle::AppTitle ) );
345 ::wnoutrefresh( title_w );
346 ::wbkgd( status_w, style()( NCstyle::AppTitle ) );
347 ::wnoutrefresh( status_w );
352 void NCurses::init_screen()
354 bool redefine =
false;
356 char *value = getenv(
"Y2NCPSEUDO" );
363 if ( value != NULL && strcmp( value,
"1" ) == 0 )
372 NCattribute::setChar( cch,
'+' );
383 NCattribute::setChar( cch,
'|' );
386 NCattribute::setChar( cch,
'-' );
389 NCattribute::setChar( cch,
'#' );
394 NCattribute::setChar( cch,
'<' );
397 NCattribute::setChar( cch,
'>' );
400 NCattribute::setChar( cch,
'v' );
403 NCattribute::setChar( cch,
'^' );
409 const NCstyle & NCurses::style()
411 return *myself->styleset;
415 void NCurses::Update()
417 if ( myself && myself->initialized() )
425 void NCurses::Refresh()
427 if ( myself && myself->initialized() )
429 yuiMilestone() <<
"start refresh ..." << std::endl;
430 SetTitle( myself->title_t );
431 SetStatusLine( myself->status_line );
432 ::clearok( ::stdscr,
true );
434 yuiMilestone() <<
"done refresh ..." << std::endl;
439 void NCurses::Redraw()
441 if ( myself && myself->initialized() )
443 yuiMilestone() <<
"start redraw ..." << std::endl;
446 PANEL * pan = ::panel_above( NULL );
457 pan = ::panel_above( pan );
463 yuiMilestone() <<
"done redraw ..." << std::endl;
468 void NCurses::SetTitle(
const std::string & str )
470 if ( myself && myself->title_w )
472 myself->title_t = str;
473 ::wbkgd( myself->title_w, myself->style()( NCstyle::AppTitle ) );
474 ::wclear( myself->title_w );
476 yuiMilestone() <<
"Draw title called" << std::endl;
478 ::mvwaddstr( myself->title_w, 0, 1, myself->title_t.c_str() );
479 ::wnoutrefresh( myself->title_w );
484 void NCurses::SetStatusLine( std::map <int, NCstring> fkeys )
487 if ( myself && myself->status_w )
489 myself->status_line = fkeys;
490 ::wbkgd( myself->status_w, myself->style()( NCstyle::AppTitle ) );
491 ::werase( myself->status_w );
496 std::map<int, NCstring>::iterator it;
498 for ( it = fkeys.begin(); it != fkeys.end(); ++it )
500 sprintf( key,
" F%d ", ( *it ).first );
502 ::wattron( myself->status_w, A_REVERSE );
503 ::waddstr( myself->status_w, key );
504 ::wattroff( myself->status_w, A_REVERSE );
506 value = (*it ).second.str();
507 if ( NCstring::terminalEncoding() !=
"UTF-8" )
510 NCstring::RecodeFromWchar( value, NCstring::terminalEncoding(), &out );
511 ::waddstr( myself->status_w, (
char *)out.c_str() );
515 ::waddwstr( myself->status_w, (
wchar_t *)value.c_str() );
517 ::waddch( myself->status_w,
' ' );
520 ::wnoutrefresh( myself->status_w );
526 void NCurses::drawTitle()
528 if ( myself && myself->title_w )
530 SetTitle( myself->title_t );
536 void NCurses::RememberDlg(
NCDialog * dlg_r )
540 _knownDlgs.insert( dlg_r );
546 void NCurses::ForgetDlg(
NCDialog * dlg_r )
550 _knownDlgs.erase( dlg_r );
556 void NCurses::RedirectToLog()
558 std::string log =
"/dev/null";
560 yuiMilestone() <<
"isatty(stderr)" << ( isatty( 2 ) ?
"yes" :
"no" ) << std::endl;
562 if ( isatty( 2 ) && theTerm )
566 open( log.c_str(), O_APPEND | O_CREAT, 0666 );
569 yuiMilestone() <<
"isatty(stdout)" << ( isatty( 1 ) ?
"yes" :
"no" ) << std::endl;
571 if ( isatty( 1 ) && theTerm )
575 open( log.c_str(), O_APPEND | O_CREAT, 0666 );
581 void NCurses::ResizeEvent()
583 if ( myself && myself->initialized() )
585 yuiMilestone() <<
"start resize to " << NCurses::lines() <<
'x' << NCurses::cols() <<
"..." << std::endl;
589 std::list<NCDialog*> dlgStack;
591 for ( PANEL * pan = ::panel_above( NULL ); pan; pan = ::panel_above( pan ) )
597 dlgStack.push_back( dlg );
602 for ( std::list<NCDialog*>::iterator it = dlgStack.begin(); it != dlgStack.end(); ++it )
604 ( *it )->getInvisible();
612 for ( std::set<NCDialog*>::iterator it = _knownDlgs.begin(); it != _knownDlgs.end(); ++it )
614 ( *it )->resizeEvent();
618 for ( std::list<NCDialog*>::iterator it = dlgStack.begin(); it != dlgStack.end(); ++it )
620 ( *it )->getVisible();
627 ::mvwin( myself->status_w, NCurses::lines(), 0 );
628 SetStatusLine( myself->status_line );
630 ::touchwin( myself->status_w );
633 yuiMilestone() <<
"done resize ..." << std::endl;
639 void NCurses::ScreenShot(
const std::string & name )
645 std::ostream & out( yuiMilestone() );
647 int curscrlines = myself->title_line() ? lines() + 1 : lines();
649 for (
int l = 0; l < curscrlines; ++l )
651 for (
int c = 0; c < cols(); ++c )
654 chtype al = ::mvwinch( ::curscr, l, c ) & ( A_ALTCHARSET | A_CHARTEXT );
656 if ( al & A_ALTCHARSET )
658 if ( al == ACS_ULCORNER
659 || al == ACS_LLCORNER
660 || al == ACS_URCORNER
661 || al == ACS_LRCORNER
670 else if ( al == ACS_HLINE )
674 else if ( al == ACS_VLINE )
678 else if ( al == ACS_DIAMOND
684 else if ( al == ACS_LARROW )
688 else if ( al == ACS_RARROW )
692 else if ( al == ACS_DARROW )
696 else if ( al == ACS_UARROW )
702 out << ( char )( al & A_CHARTEXT );
707 out << ( char )( al & A_CHARTEXT );
717 std::ostream & operator<<( std::ostream & STREAM, const NCurses & OBJ )
719 STREAM << form( "NC - %d x %d - colors %d - pairs %d\n"
720 , OBJ.lines(), OBJ.cols()
721 , NCattribute::colors(), NCattribute::color_pairs() );
723 WINDOW * cw = ::stdscr;
724 STREAM << form( "NC - rootw %p", cw );
727 STREAM << form( " - (%2hd,%2hd)%2hdx%2hd - {%p - (%2d,%2d)}\n"
728 , cw->_begy, cw->_begx
729 , cw->_maxy, cw->_maxx
731 , cw->_pary, cw->_parx
738 STREAM << form( "NC - title %p", cw );
741 STREAM << form( " - (%2hd,%2hd)%2hdx%2hd - {%p - (%2d,%2d)}\n"
742 , cw->_begy, cw->_begx
743 , cw->_maxy, cw->_maxx
745 , cw->_pary, cw->_parx
static void redraw()
Redraw all panels.
int bkgd(const chtype ch)
Set the background property and apply it to the window.
virtual int refresh()
Propagate all panel changes to the virtual screen and update the physical screen. ...
static T * UserDataOf(const PANEL &pan)
Retrieve the user data if associated with the PANEL.