33 #include <yui/Libyui_config.h>
35 #define YUILogComponent "ncurses"
36 #include <yui/YUILog.h>
44 #include <sys/types.h>
57 std::set<NCDialog*> NCurses::_knownDlgs;
58 const NCursesEvent NCursesEvent::Activated( NCursesEvent::button, YEvent::Activated );
59 const NCursesEvent NCursesEvent::SelectionChanged( NCursesEvent::button, YEvent::SelectionChanged );
60 const NCursesEvent NCursesEvent::ValueChanged( NCursesEvent::button, YEvent::ValueChanged );
65 #define CONVERR(n,p) \
71 errmsg_t = vform( p, ap, ap1 ); \
75 NCursesError::NCursesError(
const char * msg, ... )
81 NCursesError::NCursesError(
int val,
const char * msg, ... )
87 NCursesError & NCursesError::NCError(
const char * msg, ... )
93 NCursesError & NCursesError::NCError(
int val,
const char * msg, ... )
102 std::ostream & operator<<( std::ostream & STREAM,
const NCursesError & OBJ )
104 STREAM << form(
"%s: (%d) %s"
107 , OBJ.errmsg_t.c_str() );
112 std::ostream & operator<<( std::ostream & STREAM,
const NCursesEvent & OBJ )
114 #define ENUM_OUT(v) case NCursesEvent::v: return STREAM << "Ev::" << #v
128 return STREAM <<
"Ev::unknown";
140 const char * term = getenv(
"TERM" );
150 yuiMilestone() <<
"Shutdown NCurses..." << std::endl;
154 setenv(
"TERM", envTerm.c_str(), 1 );
162 ::delwin( status_w );
167 ::delscreen( theTerm );
169 yuiMilestone() <<
"NCurses down" << std::endl;
174 WINDOW * NCurses::ripped_w_top = 0;
175 WINDOW * NCurses::ripped_w_bottom = 0;
177 int NCurses::ripinit_top( WINDOW * w,
int c )
184 int NCurses::ripinit_bottom( WINDOW * w,
int c )
193 yuiMilestone() <<
"Launch NCurses..."
195 <<
"(ui-ncurses-" << VERSION <<
")"
198 yuiMilestone() <<
"TERM=" << envTerm << std::endl;
200 signal( SIGINT, SIG_IGN );
204 if ( title_line() && ::ripoffline( 1, ripinit_top ) != OK )
208 if ( ::ripoffline( -1, ripinit_bottom ) != OK )
211 yuiMilestone() <<
"isatty(stdin)" << ( isatty( 0 ) ?
"yes" :
"no" ) << std::endl;
215 char * mytty = ttyname( 0 );
219 yuiMilestone() <<
"mytty: " << mytty << std::endl;
220 FILE * fdi = fopen( mytty,
"r" );
224 yuiError() <<
"fdi: (" << errno <<
") " << strerror( errno ) << std::endl;
227 FILE * fdo = fopen( mytty,
"w" );
231 yuiError() <<
"fdo: (" << errno <<
") " << strerror( errno ) << std::endl;
236 theTerm = newterm( 0, fdo, fdi );
240 if ( theTerm == NULL )
246 std::string fallbackTerm =
"";
249 if ( ! fnmatch(
"xterm*", envTerm.c_str(), 0 ) )
250 fallbackTerm =
"xterm";
252 fallbackTerm =
"vt100";
254 yuiWarning() <<
"newterm() failed, using generic " << fallbackTerm <<
" as a fallback" << std::endl;
257 setenv(
"TERM", fallbackTerm.c_str(), 1 );
260 theTerm = newterm( 0, fdo, fdi );
262 if ( theTerm == NULL )
266 if ( set_term( theTerm ) == NULL )
276 stdout_save = dup( 1 );
277 stderr_save = dup( 2 );
283 yuiMilestone() <<
"no term so fall back to initscr" << std::endl;
285 if ( ::initscr() == NULL )
289 yuiMilestone() <<
"have color = " << ::has_colors() << std::endl;
291 if ( want_colors() && ::has_colors() )
293 if ( ::start_color() != OK )
296 NCattribute::init_colors();
304 title_w = ripped_w_top;
307 if ( !ripped_w_bottom )
310 status_w = ripped_w_bottom;
314 yuiMilestone() << form(
"screen size %d x %d\n", lines(), cols() );
317 styleset =
new NCstyle( envTerm );
319 stdpan->
bkgd( style()( NCstyle::AppText ) );
323 SetStatusLine( myself->status_line );
326 yuiMilestone() <<
"NCurses ready" << std::endl;
331 void NCurses::setup_screen()
335 ::keypad( ::stdscr,
true );
336 ::meta( ::stdscr,
true );
337 ::leaveok( ::stdscr,
true );
340 ::define_key(
"\e[Z", KEY_BTAB );
341 ::define_key(
"\e\t", KEY_BTAB );
342 ::define_key(
"\030\t", KEY_BTAB );
347 void NCurses::init_title()
349 ::wbkgd( title_w, style()( NCstyle::AppTitle ) );
350 ::wnoutrefresh( title_w );
351 ::wbkgd( status_w, style()( NCstyle::AppTitle ) );
352 ::wnoutrefresh( status_w );
357 void NCurses::init_screen()
359 bool redefine =
false;
361 char *value = getenv(
"Y2NCPSEUDO" );
368 if ( value != NULL && strcmp( value,
"1" ) == 0 )
377 NCattribute::setChar( cch,
'+' );
388 NCattribute::setChar( cch,
'|' );
391 NCattribute::setChar( cch,
'-' );
394 NCattribute::setChar( cch,
'#' );
399 NCattribute::setChar( cch,
'<' );
402 NCattribute::setChar( cch,
'>' );
405 NCattribute::setChar( cch,
'v' );
408 NCattribute::setChar( cch,
'^' );
414 const NCstyle & NCurses::style()
416 return *myself->styleset;
420 void NCurses::Update()
422 if ( myself && myself->initialized() )
430 void NCurses::Refresh()
432 if ( myself && myself->initialized() )
434 yuiMilestone() <<
"start refresh ..." << std::endl;
435 SetTitle( myself->title_t );
436 SetStatusLine( myself->status_line );
437 ::clearok( ::stdscr,
true );
439 yuiMilestone() <<
"done refresh ..." << std::endl;
444 void NCurses::Redraw()
446 if ( myself && myself->initialized() )
448 yuiMilestone() <<
"start redraw ..." << std::endl;
451 PANEL * pan = ::panel_above( NULL );
462 pan = ::panel_above( pan );
468 yuiMilestone() <<
"done redraw ..." << std::endl;
473 void NCurses::SetTitle(
const std::string & str )
475 if ( myself && myself->title_w )
477 myself->title_t = str;
478 ::wbkgd( myself->title_w, myself->style()( NCstyle::AppTitle ) );
479 ::wclear( myself->title_w );
481 yuiMilestone() <<
"Draw title called" << std::endl;
484 setTextdomain(
"ncurses" );
486 NCstring helpF1( _(
"Press F1 for Help" ) );
489 int s = myself->title_w->_maxx - textF1.Columns();
491 if ( NCstring::terminalEncoding() !=
"UTF-8" )
494 NCstring::RecodeFromWchar( helpF1.str(), NCstring::terminalEncoding(), &out );
495 ::mvwaddstr( myself->title_w, 0, s, out.c_str() );
499 ::mvwaddwstr( myself->title_w, 0, s, (
wchar_t * )helpF1.str().c_str() );
504 ::mvwaddstr( myself->title_w, 0, 1, myself->title_t.c_str() );
505 ::wnoutrefresh( myself->title_w );
510 void NCurses::SetStatusLine( std::map <int, std::string> fkeys )
513 if ( myself && myself->status_w )
515 myself->status_line = fkeys;
516 ::wbkgd( myself->status_w, myself->style()( NCstyle::AppTitle ) );
517 ::werase( myself->status_w );
522 std::map<int, std::string>::iterator it;
524 for ( it = fkeys.begin(); it != fkeys.end(); ++it )
526 sprintf( key,
" F%d ", ( *it ).first );
528 ::wattron( myself->status_w, A_REVERSE );
529 ::waddstr( myself->status_w, key );
530 ::wattroff( myself->status_w, A_REVERSE );
532 sprintf( value,
"%s ", ( *it ).second.c_str() );
533 ::waddstr( myself->status_w, value );
536 ::wnoutrefresh( myself->status_w );
542 void NCurses::drawTitle()
544 if ( myself && myself->title_w )
546 SetTitle( myself->title_t );
552 void NCurses::RememberDlg(
NCDialog * dlg_r )
556 _knownDlgs.insert( dlg_r );
562 void NCurses::ForgetDlg(
NCDialog * dlg_r )
566 _knownDlgs.erase( dlg_r );
572 void NCurses::RedirectToLog()
574 std::string log =
"/dev/null";
576 yuiMilestone() <<
"isatty(stderr)" << ( isatty( 2 ) ?
"yes" :
"no" ) << std::endl;
578 if ( isatty( 2 ) && theTerm )
582 open( log.c_str(), O_APPEND | O_CREAT, 0666 );
585 yuiMilestone() <<
"isatty(stdout)" << ( isatty( 1 ) ?
"yes" :
"no" ) << std::endl;
587 if ( isatty( 1 ) && theTerm )
591 open( log.c_str(), O_APPEND | O_CREAT, 0666 );
597 void NCurses::ResizeEvent()
599 if ( myself && myself->initialized() )
601 yuiMilestone() <<
"start resize to " << NCurses::lines() <<
'x' << NCurses::cols() <<
"..." << std::endl;
605 std::list<NCDialog*> dlgStack;
607 for ( PANEL * pan = ::panel_above( NULL ); pan; pan = ::panel_above( pan ) )
613 dlgStack.push_back( dlg );
618 for ( std::list<NCDialog*>::iterator it = dlgStack.begin(); it != dlgStack.end(); ++it )
620 ( *it )->getInvisible();
628 for ( std::set<NCDialog*>::iterator it = _knownDlgs.begin(); it != _knownDlgs.end(); ++it )
630 ( *it )->resizeEvent();
634 for ( std::list<NCDialog*>::iterator it = dlgStack.begin(); it != dlgStack.end(); ++it )
636 ( *it )->getVisible();
643 ::mvwin( myself->status_w, NCurses::lines(), 0 );
644 SetStatusLine( myself->status_line );
646 ::touchwin( myself->status_w );
649 yuiMilestone() <<
"done resize ..." << std::endl;
655 void NCurses::ScreenShot(
const std::string & name )
661 std::ostream & out( yuiMilestone() );
663 int curscrlines = myself->title_line() ? lines() + 1 : lines();
665 for (
int l = 0; l < curscrlines; ++l )
667 for (
int c = 0; c < cols(); ++c )
670 chtype al = ::mvwinch( ::curscr, l, c ) & ( A_ALTCHARSET | A_CHARTEXT );
672 if ( al & A_ALTCHARSET )
674 if ( al == ACS_ULCORNER
675 || al == ACS_LLCORNER
676 || al == ACS_URCORNER
677 || al == ACS_LRCORNER
686 else if ( al == ACS_HLINE )
690 else if ( al == ACS_VLINE )
694 else if ( al == ACS_DIAMOND
700 else if ( al == ACS_LARROW )
704 else if ( al == ACS_RARROW )
708 else if ( al == ACS_DARROW )
712 else if ( al == ACS_UARROW )
718 out << ( char )( al & A_CHARTEXT );
723 out << ( char )( al & A_CHARTEXT );
733 std::ostream & operator<<( std::ostream & STREAM, const NCurses & OBJ )
735 STREAM << form( "NC - %d x %d - colors %d - pairs %d\n"
736 , OBJ.lines(), OBJ.cols()
737 , NCattribute::colors(), NCattribute::color_pairs() );
739 WINDOW * cw = ::stdscr;
740 STREAM << form( "NC - rootw %p", cw );
743 STREAM << form( " - (%2hd,%2hd)%2hdx%2hd - {%p - (%2d,%2d)}\n"
744 , cw->_begy, cw->_begx
745 , cw->_maxy, cw->_maxx
747 , cw->_pary, cw->_parx
754 STREAM << form( "NC - title %p", cw );
757 STREAM << form( " - (%2hd,%2hd)%2hdx%2hd - {%p - (%2d,%2d)}\n"
758 , cw->_begy, cw->_begx
759 , cw->_maxy, cw->_maxx
761 , cw->_pary, cw->_parx
int bkgd(const chtype ch)
static T * UserDataOf(const PANEL &pan)