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