libyui-ncurses  2.44.1
 All Classes Functions Variables
ncursesw.cc
1 /*
2  Copyright (C) 2000-2012 Novell, Inc
3  This library is free software; you can redistribute it and/or modify
4  it under the terms of the GNU Lesser General Public License as
5  published by the Free Software Foundation; either version 2.1 of the
6  License, or (at your option) version 3.0 of the License. This library
7  is distributed in the hope that it will be useful, but WITHOUT ANY
8  WARRANTY; without even the implied warranty of MERCHANTABILITY or
9  FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
10  License for more details. You should have received a copy of the GNU
11  Lesser General Public License along with this library; if not, write
12  to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
13  Floor, Boston, MA 02110-1301 USA
14 */
15 
16 
17 /*-/
18 
19  File: ncursesw.cc
20 
21  Author: Michael Andres <ma@suse.de>
22 
23 /-*/
24 
25 /*
26  Copyright (C) 1989 Free Software Foundation
27  written by Eric Newton (newton@rocky.oswego.edu)
28 
29  This file is part of the GNU C++ Library. This library is free
30  software; you can redistribute it and/or modify it under the terms of
31  the GNU Library General Public License as published by the Free
32  Software Foundation; either version 2 of the License, or (at your
33  option) any later version. This library is distributed in the hope
34  that it will be useful, but WITHOUT ANY WARRANTY; without even the
35  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
36  PURPOSE. See the GNU Library General Public License for more details.
37  You should have received a copy of the GNU Library General Public
38  License along with this library; if not, write to the Free Software
39  Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
40 
41  modified by Ulrich Drepper (drepper@karlsruhe.gmd.de)
42  and Anatoly Ivasyuk (anatoly@nick.csh.rit.edu)
43 
44  modified by Juergen Pfeifer (Juergen.Pfeifer@T-Online.de)
45 */
46 
47 #include <iostream>
48 #include <stdlib.h>
49 #include <string.h>
50 #include <ncursesw/term.h>
51 #undef line
52 #undef columns
53 
54 #define YUILogComponent "ncurses"
55 #include <yui/YUILog.h>
56 
57 #include "ncursesw.h"
58 #include "NCstring.h"
59 
60 
61 #define COLORS_NEED_INITIALIZATION -1
62 #define COLORS_NOT_INITIALIZED 0
63 #define COLORS_MONOCHROME 1
64 #define COLORS_ARE_REALLY_THERE 2
65 
66 //
67 // static class variables
68 //
69 long NCursesWindow::count = 0L;
70 bool NCursesWindow::b_initialized = FALSE;
71 
72 
73 
74 int
75 NCursesWindow::printw( const char * fmt, ... )
76 {
77  va_list args;
78  va_start( args, fmt );
79  char buf[BUFSIZ];
80  vsprintf( buf, fmt, args );
81  va_end( args );
82  return waddstr( w, buf );
83 }
84 
85 
86 int
87 NCursesWindow::printw( int y, int x, const char * fmt, ... )
88 {
89  va_list args;
90  va_start( args, fmt );
91  int result = wmove( w, y, x );
92 
93  if ( result == OK )
94  {
95  char buf[BUFSIZ];
96  vsprintf( buf, fmt, args );
97  result = waddstr( w, buf );
98  }
99 
100  va_end( args );
101 
102  return result;
103 }
104 
105 int
106 NCursesWindow::addwstr( int y, int x, const wchar_t * str, int n )
107 {
108  const std::wstring wstr( str );
109  std::string out;
110 
111  if ( NCstring::terminalEncoding() != "UTF-8" )
112  {
113  NCstring::RecodeFromWchar( wstr, NCstring::terminalEncoding(), &out );
114  return ::mvwaddnstr( w, y, x, out.c_str(), n );
115  }
116  else
117  return ::mvwaddnwstr( w, y, x, ( wchar_t* )str, n );
118 
119 }
120 
121 
122 int
123 NCursesWindow::addwstr( const wchar_t* str, int n )
124 {
125  const std::wstring wstr( str );
126  std::string out;
127 
128  if ( NCstring::terminalEncoding() != "UTF-8" )
129  {
130  NCstring::RecodeFromWchar( wstr, NCstring::terminalEncoding(), &out );
131  return ::waddnstr( w, out.c_str(), n );
132  }
133  else
134  return ::waddnwstr( w, ( wchar_t* )str, n );
135 }
136 
137 
138 int
139 NCursesWindow::in_wchar( int y, int x, cchar_t *combined )
140 {
141  int ret = mvwin_wch( w, y, x, combined );
142  combined->attr = combined->attr & ( A_CHARTEXT | A_ALTCHARSET );
143 
144 // libncurses6 enables ext_color from struct cchar_t (see curses.h).
145 // Set ext_color to 0 to respect the settings got from mvwin_wch (bnc#652240).
146 #ifdef NCURSES_EXT_COLORS
147  combined->ext_color = 0;
148 #endif
149  return ret;
150 }
151 
152 int
153 NCursesWindow::in_wchar( cchar_t *combined )
154 {
155  int ret = win_wch( w, combined );
156  combined->attr = combined->attr & ( A_CHARTEXT | A_ALTCHARSET );
157 // libncurses6 enables ext_color from struct cchar_t (see curses.h).
158 // Set ext_color to 0 to respect the settings got from win_wch (bnc#652240).
159 #ifdef NCURSES_EXT_COLORS
160  combined->ext_color = 0;
161 #endif
162  return ret;
163 }
164 
165 int
167 {
168  int ret = ERR;
169 
170  if ( NCstring::terminalEncoding() != "UTF-8" )
171  {
172  ret = addch( inchar( y, x ) );
173  }
174  else
175  {
176  cchar_t combined;
177  ret = in_wchar( y, x, &combined );
178 
179  if ( ret == OK )
180  {
181  ret = add_wch( &combined );
182  }
183  }
184 
185  return ret;
186 }
187 
188 int
189 NCursesWindow::add_attr_char( )
190 {
191  int ret = ERR;
192 
193  if ( NCstring::terminalEncoding() != "UTF-8" )
194  {
195  ret = addch( inchar() );
196  }
197  else
198  {
199  cchar_t combined;
200  ret = in_wchar( &combined );
201 
202  if ( ret == OK )
203  {
204  ret = add_wch( &combined );
205  }
206  }
207 
208  return ret;
209 }
210 
211 void
212 NCursesWindow::init( void )
213 {
214  // Setting back_color_erase to FALSE was added because of bug #418613.
215  // This isn't necessary any longer because the kernel patch which
216  // has caused the bug was reverted (in SLES11-GM).
217 #if 0
218  static char * env;
219  if (!env && (env = ::getenv("TERM"))) {
220  if (::strncmp(env, "linux", 5) == 0)
221  back_color_erase = FALSE;
222  }
223 #endif
224  leaveok( 0 );
225  keypad( 1 );
226  meta( 1 );
227 }
228 
229 void
230 NCursesWindow::err_handler( const char *msg ) const THROWS( NCursesException )
231 {
232  THROW( new NCursesException( msg ) );
233 }
234 
235 void
236 NCursesWindow::initialize()
237 {
238  if ( !b_initialized )
239  {
240  //::initscr();
241  b_initialized = TRUE;
242 
243  if ( colorInitialized == COLORS_NEED_INITIALIZATION )
244  {
245  colorInitialized = COLORS_NOT_INITIALIZED;
246  useColors();
247  }
248 
249  ::noecho();
250 
251  ::cbreak();
252  }
253 }
254 
256  : w(0), alloced(FALSE), par(0), subwins(0), sib(0)
257 {
258  if ( !b_initialized )
259  initialize();
260 
261  w = static_cast<WINDOW *>(0);
262 
263  init();
264 
265  count++;
266 }
267 
268 NCursesWindow::NCursesWindow( int lines, int cols, int begin_y, int begin_x )
269  : w(0), alloced(TRUE), par(0), subwins(0), sib(0)
270 {
271  if ( !b_initialized )
272  initialize();
273 
274  if ( lines <= 0 )
275  lines = 1;
276 
277  if ( cols <= 0 )
278  cols = 1;
279 
280  if ( lines + begin_y > NCursesWindow::lines() )
281  lines = NCursesWindow::lines() - begin_y;
282 
283  if ( cols + begin_x > NCursesWindow::cols() )
284  cols = NCursesWindow::cols() - begin_x;
285 
286  yuiDebug() << "Lines: " << lines << " Cols: " << cols << " y: " << begin_y << " x: " << begin_x << std::endl;
287 
288  w = ::newwin( lines, cols, begin_y, begin_x );
289 
290  if ( w == 0 )
291  {
292  err_handler( "Cannot construct window" );
293  }
294 
295  init();
296 
297  count++;
298 }
299 
301  : w(0), alloced(FALSE), par(0), subwins(0), sib(0)
302 {
303  if ( !b_initialized )
304  initialize();
305 
306  w = window ? window : ::stdscr;
307 
308  init();
309 
310  count++;
311 }
312 
314  int begin_y, int begin_x, char absrel )
315  : w(0), alloced(TRUE), par(0), subwins(0), sib(0)
316 {
317  if ( l <= 0 )
318  l = 1;
319 
320  if ( c <= 0 )
321  c = 1;
322 
323  if ( begin_y < 0 )
324  begin_y = 0;
325 
326  if ( begin_x < 0 )
327  begin_x = 0;
328 
329  if ( absrel == 'a' ) // absolute origin
330  {
331  begin_y -= win.begy();
332  begin_x -= win.begx();
333  }
334 
335  if ( l + begin_y > win.height() )
336  l = win.height() - begin_y;
337 
338  if ( c + begin_x > win.width() )
339  c = win.width() - begin_x;
340 
341  // Even though we treat subwindows as a tree, the standard curses
342  // library needs the `subwin' call to link to the parent in
343  // order to correctly perform refreshes, etc.
344  // Friendly enough, this also works for pads.
345  w = ::derwin( win.w, l, c, begin_y, begin_x );
346 
347  if ( w == 0 )
348  {
349  yuiError() << "Throw " << wpos( begin_y, begin_x ) << wsze( l, c ) << std::endl;
350  err_handler( "Cannot construct subwindow" );
351  }
352 
353  //yuiMilestone() << "created " << wpos(begin_y, begin_x) << wsze(l, c) << std::endl;
354 
355  par = &win;
356 
357  sib = win.subwins;
358 
359  win.subwins = this;
360 
361  count++;
362 }
363 
365 {
366  WINDOW *d = ::dupwin( w );
367  NCursesWindow W( d );
368  W.subwins = subwins;
369  W.sib = sib;
370  W.par = par;
371  W.alloced = alloced;
372  return W;
373 }
374 
375 typedef int ( *RIPOFFINIT )( NCursesWindow& );
376 static RIPOFFINIT R_INIT[5]; // There can't be more
377 static int r_init_idx = 0;
378 static RIPOFFINIT* prip = R_INIT;
379 
380 extern "C" int _nc_ripoffline( int, int ( *init )( WINDOW*, int ) );
381 
382 NCursesWindow::NCursesWindow( WINDOW *win, int cols )
383 {
384  w = win;
385  assert(( w->_maxx + 1 ) == cols );
386  alloced = FALSE;
387  subwins = par = sib = 0;
388 }
389 
390 int NCursesWindow::ripoff_init( WINDOW *w, int cols )
391 {
392  int res = ERR;
393 
394  RIPOFFINIT init = *prip++;
395 
396  if ( init )
397  {
398  NCursesWindow* W = new NCursesWindow( w, cols );
399  res = init( *W );
400  }
401 
402  return res;
403 }
404 
405 int NCursesWindow::ripoffline( int ripoff_lines,
406  int ( *init )( NCursesWindow& win ) )
407 {
408  int code = ::_nc_ripoffline( ripoff_lines, ripoff_init );
409 
410  if ( code == OK && init && ripoff_lines )
411  {
412  R_INIT[r_init_idx++] = init;
413  }
414 
415  return code;
416 }
417 
418 bool
420 {
421  for ( NCursesWindow* p = subwins; p != NULL; p = p->sib )
422  {
423  if ( p == &win )
424  return TRUE;
425  else
426  {
427  if ( p->isDescendant( win ) )
428  return TRUE;
429  }
430  }
431 
432  return FALSE;
433 }
434 
435 void
437 {
438  for ( NCursesWindow* p = subwins; p != 0; p = p->sib )
439  {
440  p->kill_subwindows();
441 
442  if ( p->alloced )
443  {
444  if ( p->w != 0 )
445  ::delwin( p->w );
446 
447  p->alloced = FALSE;
448  }
449 
450  p->w = 0; // cause a run-time error if anyone attempts to use...
451  }
452 }
453 
454 
456 {
457  kill_subwindows();
458 
459  if ( par != 0 ) // Snip us from the parent's list of subwindows.
460  {
461  NCursesWindow * win = par->subwins;
462  NCursesWindow * trail = 0;
463 
464  for ( ;; )
465  {
466  if ( win == 0 )
467  break;
468  else if ( win == this )
469  {
470  if ( trail != 0 )
471  trail->sib = win->sib;
472  else
473  par->subwins = win->sib;
474 
475  break;
476  }
477  else
478  {
479  trail = win;
480  win = win->sib;
481  }
482  }
483  }
484 
485  if ( alloced && w != 0 )
486  delwin( w );
487 
488  if ( alloced )
489  {
490  --count;
491 
492  if ( count == 0 )
493  {
494  ::endwin();
495  }
496  else if ( count < 0 ) // cannot happen!
497  {
498  err_handler( "Too many windows destroyed" );
499  }
500  }
501 }
502 
503 // ---------------------------------------------------------------------
504 // Color stuff
505 int NCursesWindow::colorInitialized = COLORS_NOT_INITIALIZED;
506 
507 void
509 {
510  if ( colorInitialized == COLORS_NOT_INITIALIZED )
511  {
512  if ( b_initialized )
513  {
514  if ( ::has_colors() )
515  {
516  ::start_color();
517  colorInitialized = COLORS_ARE_REALLY_THERE;
518  }
519  else
520  colorInitialized = COLORS_MONOCHROME;
521  }
522  else
523  colorInitialized = COLORS_NEED_INITIALIZATION;
524  }
525 }
526 
527 short
528 NCursesWindow::getcolor( int getback ) const
529 {
530  short fore, back;
531 
532  if ( colorInitialized == COLORS_ARE_REALLY_THERE )
533  {
534  if ( pair_content( PAIR_NUMBER( w->_attrs ), &fore, &back ) )
535  err_handler( "Can't get color pair" );
536  }
537  else
538  {
539  // Monochrome means white on black
540  back = COLOR_BLACK;
541  fore = COLOR_WHITE;
542  }
543 
544  return getback ? back : fore;
545 }
546 
548 {
549  if ( colorInitialized == COLORS_ARE_REALLY_THERE )
550  return COLORS;
551  else
552  return 1; // monochrome (actually there are two ;-)
553 }
554 
555 short
557 {
558  if ( colorInitialized == COLORS_ARE_REALLY_THERE )
559  return PAIR_NUMBER( w->_attrs );
560  else
561  return 0; // we only have pair zero
562 }
563 
564 int
565 NCursesWindow::setpalette( short fore, short back, short pair )
566 {
567  if ( colorInitialized == COLORS_ARE_REALLY_THERE )
568  return init_pair( pair, fore, back );
569  else
570  return OK;
571 }
572 
573 int
574 NCursesWindow::setpalette( short fore, short back )
575 {
576  if ( colorInitialized == COLORS_ARE_REALLY_THERE )
577  return setpalette( fore, back, PAIR_NUMBER( w->_attrs ) );
578  else
579  return OK;
580 }
581 
582 
583 int
585 {
586  if ( colorInitialized == COLORS_ARE_REALLY_THERE )
587  {
588  if (( pair < 1 ) || ( pair > COLOR_PAIRS ) )
589  err_handler( "Can't std::set color pair" );
590 
591  attroff( A_COLOR );
592 
593  attrset( COLOR_PAIR( pair ) );
594  }
595 
596  return OK;
597 }
598 
599 extern "C" int _nc_has_mouse( void );
600 
602 {
603  return (( ::has_key( KEY_MOUSE ) || ::_nc_has_mouse() )
604  ? TRUE : FALSE );
605 }
606 
607 NCursesPad::NCursesPad( int lines, int cols ) : NCursesWindow()
608 {
609  if ( lines <= 0 )
610  lines = 1;
611 
612  if ( cols <= 0 )
613  cols = 1;
614 
615  w = ::newpad( lines, cols );
616 
617  if ( w == ( WINDOW* )0 )
618  {
619  count--;
620  err_handler( "Cannot construct window" );
621  }
622 
623  alloced = TRUE;
624 }
625 
626 
627 
628 int NCursesWindow::box( const wrect & dim )
629 {
630  wrect box_area( dim.intersectRelTo( area() ) );
631 
632  if ( box_area.Sze > 0 )
633  {
634  hline( box_area.Pos.L, box_area.Pos.C, box_area.Sze.W );
635  hline( box_area.Pos.L + box_area.Sze.H - 1, box_area.Pos.C, box_area.Sze.W );
636  vline( box_area.Pos.L, box_area.Pos.C, box_area.Sze.H );
637  vline( box_area.Pos.L, box_area.Pos.C + box_area.Sze.W - 1, box_area.Sze.H );
638 
639  addch( box_area.Pos.L + box_area.Sze.H - 1, box_area.Pos.C, ACS_LLCORNER );
640  addch( box_area.Pos.L, box_area.Pos.C + box_area.Sze.W - 1, ACS_URCORNER );
641  addch( box_area.Pos.L + box_area.Sze.H - 1, box_area.Pos.C + box_area.Sze.W - 1, ACS_LRCORNER );
642  addch( box_area.Pos.L, box_area.Pos.C, ACS_ULCORNER );
643  }
644 
645  return OK;
646 }
647 
648 
649 
650 // move subwin tree inside parent
651 int NCursesWindow::mvsubwin( NCursesWindow * sub, int begin_y, int begin_x )
652 {
653  int ret = ERR;
654 
655  if ( sub && sub->parent() )
656  {
657  sub->w->_parx = -1; // force ncurses to actually move the child
658  ret = ::mvderwin( sub->w, begin_y, begin_x );
659 
660  for ( NCursesWindow * ch = sub->child(); ch && ret == OK; ch = ch->sibling() )
661  {
662  ret = mvsubwin( ch, ch->w->_pary, ch->w->_parx );
663  }
664  }
665 
666  return ret;
667 }
668 
669 
670 
671 int NCursesWindow::resize( int lines, int columns )
672 {
673  if ( lines <= 0 )
674  lines = 1;
675 
676  if ( columns <= 0 )
677  columns = 1;
678 
679  return ::wresize( w, lines, columns );
680 }
681 
682 
683 std::ostream & operator<<( std::ostream & Stream, const NCursesWindow * Obj_Cv )
684 {
685  if ( Obj_Cv )
686  return Stream << *Obj_Cv;
687 
688  return Stream << "(NoNCWin)";
689 }
690 
691 
692 std::ostream & operator<<( std::ostream & Stream, const NCursesWindow & Obj_Cv )
693 {
694  return Stream << "NCWin(" << Obj_Cv.w
695  << wrect( wpos( Obj_Cv.begy(), Obj_Cv.begx() ),
696  wsze( Obj_Cv.height(), Obj_Cv.width() ) ) << ')';
697 }
C++ class for windows.
Definition: ncursesw.h:904
void kill_subwindows()
Definition: ncursesw.cc:436
int printw(const char *fmt,...)
Definition: ncursesw.cc:75
static int lines()
Definition: ncursesw.h:1042
short getcolor() const
Definition: ncursesw.cc:556
NCursesWindow * parent()
Definition: ncursesw.h:1777
int vline(int len, chtype ch=0)
Definition: ncursesw.h:1499
NCursesWindow * par
Definition: ncursesw.h:957
bool isDescendant(NCursesWindow &win)
Definition: ncursesw.cc:419
static int cols()
Definition: ncursesw.h:1047
static int NumberOfColors()
Definition: ncursesw.cc:547
int setcolor(short pair)
Definition: ncursesw.cc:584
int hline(int len, chtype ch=0)
Definition: ncursesw.h:1485
Definition: position.h:109
int attroff(chtype at)
Definition: ncursesw.h:1405
int addwstr(const wchar_t *str, int n=-1)
Definition: ncursesw.cc:123
void err_handler(const char *) const THROWS(NCursesException)
Definition: ncursesw.cc:230
virtual ~NCursesWindow()
Definition: ncursesw.cc:455
int height() const
Definition: ncursesw.h:1070
int add_attr_char(int y, int x)
Definition: ncursesw.cc:166
int addch(const char ch)
Definition: ncursesw.h:1228
int in_wchar(cchar_t *cchar)
Definition: ncursesw.cc:153
static long count
Definition: ncursesw.h:939
int begy() const
Definition: ncursesw.h:1085
NCursesWindow * sibling()
Definition: ncursesw.h:1770
int begx() const
Definition: ncursesw.h:1080
int keypad(bool bf)
Definition: ncursesw.h:1682
static void useColors(void)
Definition: ncursesw.cc:508
int leaveok(bool bf)
Definition: ncursesw.h:1631
bool has_mouse() const
Definition: ncursesw.cc:601
NCursesWindow * sib
Definition: ncursesw.h:965
int attrset(chtype at)
Definition: ncursesw.h:1410
NCursesWindow Clone()
Definition: ncursesw.cc:364
NCursesWindow * subwins
Definition: ncursesw.h:961
Definition: position.h:154
int width() const
Definition: ncursesw.h:1075
WINDOW * w
Definition: ncursesw.h:947
static int ripoffline(int ripoff_lines, int(*init)(NCursesWindow &win))
Definition: ncursesw.cc:405
int meta(bool bf)
Definition: ncursesw.h:1688
NCursesWindow * child()
Definition: ncursesw.h:1763
int add_wch(const cchar_t *cch)
Definition: ncursesw.h:1244
bool alloced
Definition: ncursesw.h:952