libyui-ncurses  2.47.6
 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 
381 NCursesWindow::NCursesWindow( WINDOW *win, int cols )
382 {
383  w = win;
384  assert(( w->_maxx + 1 ) == cols );
385  alloced = FALSE;
386  subwins = par = sib = 0;
387 }
388 
389 int NCursesWindow::ripoff_init( WINDOW *w, int cols )
390 {
391  int res = ERR;
392 
393  RIPOFFINIT init = *prip++;
394 
395  if ( init )
396  {
397  NCursesWindow* W = new NCursesWindow( w, cols );
398  res = init( *W );
399  }
400 
401  return res;
402 }
403 
404 int NCursesWindow::ripoffline( int ripoff_lines,
405  int ( *init )( NCursesWindow& win ) )
406 {
407  int code = ::ripoffline( ripoff_lines, ripoff_init );
408 
409  if ( code == OK && init && ripoff_lines )
410  {
411  R_INIT[r_init_idx++] = init;
412  }
413 
414  return code;
415 }
416 
417 bool
419 {
420  for ( NCursesWindow* p = subwins; p != NULL; p = p->sib )
421  {
422  if ( p == &win )
423  return TRUE;
424  else
425  {
426  if ( p->isDescendant( win ) )
427  return TRUE;
428  }
429  }
430 
431  return FALSE;
432 }
433 
434 void
436 {
437  for ( NCursesWindow* p = subwins; p != 0; p = p->sib )
438  {
439  p->kill_subwindows();
440 
441  if ( p->alloced )
442  {
443  if ( p->w != 0 )
444  ::delwin( p->w );
445 
446  p->alloced = FALSE;
447  }
448 
449  p->w = 0; // cause a run-time error if anyone attempts to use...
450  }
451 }
452 
453 
455 {
456  kill_subwindows();
457 
458  if ( par != 0 ) // Snip us from the parent's list of subwindows.
459  {
460  NCursesWindow * win = par->subwins;
461  NCursesWindow * trail = 0;
462 
463  for ( ;; )
464  {
465  if ( win == 0 )
466  break;
467  else if ( win == this )
468  {
469  if ( trail != 0 )
470  trail->sib = win->sib;
471  else
472  par->subwins = win->sib;
473 
474  break;
475  }
476  else
477  {
478  trail = win;
479  win = win->sib;
480  }
481  }
482  }
483 
484  if ( alloced && w != 0 )
485  delwin( w );
486 
487  if ( alloced )
488  {
489  --count;
490 
491  if ( count == 0 )
492  {
493  ::endwin();
494  }
495  else if ( count < 0 ) // cannot happen!
496  {
497  err_handler( "Too many windows destroyed" );
498  }
499  }
500 }
501 
502 // ---------------------------------------------------------------------
503 // Color stuff
504 int NCursesWindow::colorInitialized = COLORS_NOT_INITIALIZED;
505 
506 void
508 {
509  if ( colorInitialized == COLORS_NOT_INITIALIZED )
510  {
511  if ( b_initialized )
512  {
513  if ( ::has_colors() )
514  {
515  ::start_color();
516  colorInitialized = COLORS_ARE_REALLY_THERE;
517  }
518  else
519  colorInitialized = COLORS_MONOCHROME;
520  }
521  else
522  colorInitialized = COLORS_NEED_INITIALIZATION;
523  }
524 }
525 
526 short
527 NCursesWindow::getcolor( int getback ) const
528 {
529  short fore, back;
530 
531  if ( colorInitialized == COLORS_ARE_REALLY_THERE )
532  {
533  if ( pair_content( PAIR_NUMBER( w->_attrs ), &fore, &back ) )
534  err_handler( "Can't get color pair" );
535  }
536  else
537  {
538  // Monochrome means white on black
539  back = COLOR_BLACK;
540  fore = COLOR_WHITE;
541  }
542 
543  return getback ? back : fore;
544 }
545 
547 {
548  if ( colorInitialized == COLORS_ARE_REALLY_THERE )
549  return COLORS;
550  else
551  return 1; // monochrome (actually there are two ;-)
552 }
553 
554 short
556 {
557  if ( colorInitialized == COLORS_ARE_REALLY_THERE )
558  return PAIR_NUMBER( w->_attrs );
559  else
560  return 0; // we only have pair zero
561 }
562 
563 int
564 NCursesWindow::setpalette( short fore, short back, short pair )
565 {
566  if ( colorInitialized == COLORS_ARE_REALLY_THERE )
567  return init_pair( pair, fore, back );
568  else
569  return OK;
570 }
571 
572 int
573 NCursesWindow::setpalette( short fore, short back )
574 {
575  if ( colorInitialized == COLORS_ARE_REALLY_THERE )
576  return setpalette( fore, back, PAIR_NUMBER( w->_attrs ) );
577  else
578  return OK;
579 }
580 
581 int
583 {
584  if ( colorInitialized == COLORS_ARE_REALLY_THERE )
585  {
586  if (( pair < 1 ) || ( pair > COLOR_PAIRS ) )
587  err_handler( "Can't std::set color pair" );
588 
589  attroff( A_COLOR );
590 
591  attrset( COLOR_PAIR( pair ) );
592  }
593 
594  return OK;
595 }
596 
598 {
599  return (( ::has_key( KEY_MOUSE ) || ::has_mouse() )
600  ? TRUE : FALSE );
601 }
602 
603 NCursesPad::NCursesPad( int lines, int cols ) : NCursesWindow()
604 {
605  if ( lines <= 0 )
606  lines = 1;
607 
608  if ( cols <= 0 )
609  cols = 1;
610 
611  w = ::newpad( lines, cols );
612 
613  if ( w == ( WINDOW* )0 )
614  {
615  count--;
616  err_handler( "Cannot construct window" );
617  }
618 
619  alloced = TRUE;
620 }
621 
622 
623 
624 int NCursesWindow::box( const wrect & dim )
625 {
626  wrect box_area( dim.intersectRelTo( area() ) );
627 
628  if ( box_area.Sze > 0 )
629  {
630  hline( box_area.Pos.L, box_area.Pos.C, box_area.Sze.W );
631  hline( box_area.Pos.L + box_area.Sze.H - 1, box_area.Pos.C, box_area.Sze.W );
632  vline( box_area.Pos.L, box_area.Pos.C, box_area.Sze.H );
633  vline( box_area.Pos.L, box_area.Pos.C + box_area.Sze.W - 1, box_area.Sze.H );
634 
635  addch( box_area.Pos.L + box_area.Sze.H - 1, box_area.Pos.C, ACS_LLCORNER );
636  addch( box_area.Pos.L, box_area.Pos.C + box_area.Sze.W - 1, ACS_URCORNER );
637  addch( box_area.Pos.L + box_area.Sze.H - 1, box_area.Pos.C + box_area.Sze.W - 1, ACS_LRCORNER );
638  addch( box_area.Pos.L, box_area.Pos.C, ACS_ULCORNER );
639  }
640 
641  return OK;
642 }
643 
644 
645 
646 // move subwin tree inside parent
647 int NCursesWindow::mvsubwin( NCursesWindow * sub, int begin_y, int begin_x )
648 {
649  int ret = ERR;
650 
651  if ( sub && sub->parent() )
652  {
653  sub->w->_parx = -1; // force ncurses to actually move the child
654  ret = ::mvderwin( sub->w, begin_y, begin_x );
655 
656  for ( NCursesWindow * ch = sub->child(); ch && ret == OK; ch = ch->sibling() )
657  {
658  ret = mvsubwin( ch, ch->w->_pary, ch->w->_parx );
659  }
660  }
661 
662  return ret;
663 }
664 
665 
666 
667 int NCursesWindow::resize( int lines, int columns )
668 {
669  if ( lines <= 0 )
670  lines = 1;
671 
672  if ( columns <= 0 )
673  columns = 1;
674 
675  return ::wresize( w, lines, columns );
676 }
677 
678 
679 std::ostream & operator<<( std::ostream & Stream, const NCursesWindow * Obj_Cv )
680 {
681  if ( Obj_Cv )
682  return Stream << *Obj_Cv;
683 
684  return Stream << "(NoNCWin)";
685 }
686 
687 
688 std::ostream & operator<<( std::ostream & Stream, const NCursesWindow & Obj_Cv )
689 {
690  return Stream << "NCWin(" << Obj_Cv.w
691  << wrect( wpos( Obj_Cv.begy(), Obj_Cv.begx() ),
692  wsze( Obj_Cv.height(), Obj_Cv.width() ) ) << ')';
693 }
C++ class for windows.
Definition: ncursesw.h:904
void kill_subwindows()
Destroy all subwindows.
Definition: ncursesw.cc:435
int printw(const char *fmt,...)
Do a formatted print to the window.
Definition: ncursesw.cc:75
static int lines()
Number of lines on terminal, not window.
Definition: ncursesw.h:1042
short getcolor() const
Actual color pair.
Definition: ncursesw.cc:555
NCursesWindow * parent()
Get my parent.
Definition: ncursesw.h:1777
int vline(int len, chtype ch=0)
Draw a vertical line of len characters with the given character.
Definition: ncursesw.h:1499
NCursesWindow * par
parent, if subwindow
Definition: ncursesw.h:957
bool isDescendant(NCursesWindow &win)
Return TRUE if win is a descendant of this.
Definition: ncursesw.cc:418
static int cols()
Number of cols on terminal, not window.
Definition: ncursesw.h:1047
static int NumberOfColors()
Number of available colors.
Definition: ncursesw.cc:546
int box()
Draw a box around the window with the given vertical and horizontal drawing characters.
Definition: ncursesw.h:1462
int setcolor(short pair)
Set actually used palette entry.
Definition: ncursesw.cc:582
int hline(int len, chtype ch=0)
Draw a horizontal line of len characters with the given character.
Definition: ncursesw.h:1485
Definition: position.h:109
int attroff(chtype at)
Switch off the window attributes;.
Definition: ncursesw.h:1405
int addwstr(const wchar_t *str, int n=-1)
Write the wchar_t str to the window, stop writing if the terminating NUL or the limit n is reached...
Definition: ncursesw.cc:123
void err_handler(const char *) const THROWS(NCursesException)
Signal an error with the given message text.
Definition: ncursesw.cc:230
virtual ~NCursesWindow()
Destructor.
Definition: ncursesw.cc:454
int height() const
Number of lines in this window.
Definition: ncursesw.h:1070
int add_attr_char(int y, int x)
Put attributed character from given position to the window.
Definition: ncursesw.cc:166
int addch(const char ch)
Put attributed character to the window.
Definition: ncursesw.h:1228
int in_wchar(cchar_t *cchar)
Retrieve combined character under the current cursor position.
Definition: ncursesw.cc:153
static long count
count of all active windows
Definition: ncursesw.h:939
int begy() const
Line of top left corner relative to stdscr.
Definition: ncursesw.h:1085
NCursesWindow * sibling()
Get the next child of my parent.
Definition: ncursesw.h:1770
NCursesWindow()
Only for use by derived classes.
Definition: ncursesw.cc:255
int begx() const
Column of top left corner relative to stdscr.
Definition: ncursesw.h:1080
int keypad(bool bf)
If called with bf=TRUE, the application will interpret function keys.
Definition: ncursesw.h:1682
static void useColors(void)
Call this routine very early if you want to have colors.
Definition: ncursesw.cc:507
int leaveok(bool bf)
If bf is TRUE, curses will leave the cursor after an update whereever it is after the update...
Definition: ncursesw.h:1631
bool has_mouse() const
Return TRUE if terminal supports a mouse, FALSE otherwise.
Definition: ncursesw.cc:597
NCursesWindow * sib
next subwindow of parent
Definition: ncursesw.h:965
int attrset(chtype at)
Set the window attributes;.
Definition: ncursesw.h:1410
NCursesWindow Clone()
Make an exact copy of the window.
Definition: ncursesw.cc:364
NCursesWindow * subwins
head of subwindows std::list
Definition: ncursesw.h:961
Definition: position.h:154
int width() const
Number of columns in this window.
Definition: ncursesw.h:1075
WINDOW * w
the curses WINDOW
Definition: ncursesw.h:947
static int ripoffline(int ripoff_lines, int(*init)(NCursesWindow &win))
This function is used to generate a window of ripped-of lines.
Definition: ncursesw.cc:404
int meta(bool bf)
If called with bf=TRUE, keys may generate 8-Bit characters.
Definition: ncursesw.h:1688
NCursesWindow * child()
Get the first child window.
Definition: ncursesw.h:1763
int add_wch(const cchar_t *cch)
Put a combined character to the window.
Definition: ncursesw.h:1244
bool alloced
TRUE if we own the WINDOW.
Definition: ncursesw.h:952