libyui-ncurses  2.46.6
 All Classes Functions Variables
NCInputField.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: NCInputField.cc
20 
21  Author: Michael Andres <ma@suse.de>
22 
23 /-*/
24 #include <climits>
25 
26 
27 #define YUILogComponent "ncurses"
28 #include <yui/YUILog.h>
29 #include "NCurses.h"
30 #include "NCInputField.h"
31 
32 #include <wctype.h> // iswalnum()
33 
34 
35 NCInputField::NCInputField( YWidget * parent,
36  const std::string & nlabel,
37  bool passwordMode,
38  unsigned maxInput,
39  unsigned maxFld )
40  : YInputField( parent, nlabel, passwordMode )
41  , NCWidget( parent )
42  , passwd( passwordMode )
43  , lwin( 0 )
44  , twin( 0 )
45  , maxFldLength( maxFld )
46  , maxInputLength( maxInput )
47  , fldstart( 0 )
48  , fldlength( 0 )
49  , curpos( 0 )
50  , fldtype( PLAIN )
51  , returnOnReturn_b( false )
52  , InputMaxLength( -1 )
53 {
54  yuiDebug() << std::endl;
55 
56  if ( maxInputLength &&
57  ( !maxFldLength || maxFldLength > maxInputLength ) )
58  {
59  maxFldLength = maxInputLength;
60  }
61 
62  setLabel( nlabel );
63 
64  hotlabel = &label;
65  // initial text isn't an argument any longer
66  //setText( ntext );
67 }
68 
69 
70 
71 NCInputField::~NCInputField()
72 {
73  delete lwin;
74  delete twin;
75  yuiDebug() << std::endl;
76 }
77 
78 
79 
80 int NCInputField::preferredWidth()
81 {
82  return wGetDefsze().W;
83 }
84 
85 
86 
87 int NCInputField::preferredHeight()
88 {
89  return wGetDefsze().H;
90 }
91 
92 
93 
94 void NCInputField::setEnabled( bool do_bv )
95 {
96  NCWidget::setEnabled( do_bv );
97  YInputField::setEnabled( do_bv );
98 }
99 
100 
101 
102 void NCInputField::setSize( int newwidth, int newheight )
103 {
104  wRelocate( wpos( 0 ), wsze( newheight, newwidth ) );
105 }
106 
107 
108 
109 void NCInputField::setDefsze()
110 {
111  unsigned defwidth = maxFldLength ? maxFldLength : 5;
112 
113  if ( label.width() > defwidth )
114  defwidth = label.width();
115 
116  defsze = wsze( label.height() + 1, defwidth );
117 }
118 
119 
120 
121 void NCInputField::wCreate( const wrect & newrect )
122 {
123  NCWidget::wCreate( newrect );
124 
125  if ( !win )
126  return;
127 
128  wrect lrect( 0, wsze::min( newrect.Sze,
129  wsze( label.height(), newrect.Sze.W ) ) );
130 
131  if ( lrect.Sze.H == newrect.Sze.H )
132  lrect.Sze.H -= 1;
133 
134  wrect trect( 0, wsze( 1, newrect.Sze.W ) );
135 
136  trect.Pos.L = lrect.Sze.H > 0 ? lrect.Sze.H : 0;
137 
138  lwin = new NCursesWindow( *win,
139  lrect.Sze.H, lrect.Sze.W,
140  lrect.Pos.L, lrect.Pos.C,
141  'r' );
142 
143  twin = new NCursesWindow( *win,
144  trect.Sze.H, trect.Sze.W,
145  trect.Pos.L, trect.Pos.C,
146  'r' );
147 
148  if ( maxFldLength && maxFldLength < ( unsigned )newrect.Sze.W )
149  trect.Sze.W = maxFldLength;
150 
151  fldlength = trect.Sze.W;
152 }
153 
154 
155 
156 void NCInputField::wDelete()
157 {
158  delete lwin;
159  delete twin;
160  lwin = 0;
161  twin = 0;
162  NCWidget::wDelete();
163 }
164 
165 
166 
167 void NCInputField::setLabel( const std::string & nlabel )
168 {
169  label = NCstring( nlabel );
170  label.stripHotkey();
171  YInputField::setLabel( nlabel );
172  setDefsze();
173  Redraw();
174 }
175 
176 
177 
178 void NCInputField::setValue( const std::string & ntext )
179 {
180  buffer = NCstring( ntext ).str();
181 
182  if ( maxInputLength && buffer.length() > maxInputLength )
183  {
184  buffer = buffer.erase( maxInputLength );
185  }
186 
187  fldstart = 0;
188 
189  curpos = buffer.length();
190  tUpdate();
191 }
192 
193 
194 
195 std::string NCInputField::value( )
196 {
197  NCstring text( buffer );
198 
199  return text.Str();
200 }
201 
202 
203 
204 void NCInputField::setValidChars( const std::string & validchars )
205 {
206  validChars = NCstring( validchars );
207  YInputField::setValidChars( validchars );
208 }
209 
210 
211 
212 bool NCInputField::validKey( wint_t key ) const
213 {
214  // private: NCstring validChars;
215  const std::wstring vwch( validChars.str() );
216 
217  if ( vwch.empty() )
218  return true;
219 
220  if ( key < 0 || WCHAR_MAX < key )
221  return false;
222 
223  return( vwch.find(( wchar_t )key ) != std::wstring::npos );
224 }
225 
226 
227 
228 void NCInputField::wRedraw()
229 {
230  if ( !win )
231  return;
232 
233  // label
234  const NCstyle::StWidget & style( widgetStyle( true ) );
235 
236  lwin->bkgd( style.plain );
237 
238  lwin->clear();
239 
240  label.drawAt( *lwin, style );
241 
242  tUpdate();
243 }
244 
245 
246 
247 inline bool NCInputField::bufferFull() const
248 {
249  return( maxInputLength && buffer.length() == maxInputLength );
250 }
251 
252 
253 
254 inline unsigned NCInputField::maxCursor() const
255 {
256  return( bufferFull() ? buffer.length() - 1 : buffer.length() );
257 }
258 
259 
260 
261 void NCInputField::tUpdate()
262 {
263  if ( !win )
264  return;
265 
266  unsigned maxc = maxCursor();
267 
268  // adjust cursor
269  if ( curpos > maxc )
270  {
271  curpos = maxc;
272  }
273 
274  // adjust fldstart that cursor is visible
275  if ( maxc < fldlength )
276  {
277  fldstart = 0;
278  }
279  else
280  {
281  if ( curpos <= fldstart )
282  {
283  fldstart = curpos ? curpos - 1 : 0;
284  }
285 
286  if ( curpos >= fldstart + fldlength - 1 )
287  {
288  fldstart = curpos + ( curpos == maxc ? 1 : 2 ) - fldlength;
289  }
290  }
291 
292  const NCstyle::StWidget & style( widgetStyle() );
293 
294  twin->bkgd( widgetStyle( true ).plain );
295 
296  twin->move( 0, 0 );
297 
298  unsigned i = 0;
299 
300  unsigned end = fldlength;
301 
302  const wchar_t * cp = buffer.data() + fldstart;
303 
304  // draw left scrollhint if
305  if ( *cp && fldstart )
306  {
307  twin->bkgdset( style.scrl );
308  twin->addch( ACS_LARROW );
309  ++i;
310  ++cp;
311  }
312 
313  // check for right scrollhint
314  if ( fldstart + fldlength <= maxc )
315  {
316  --end;
317  }
318 
319  // draw field
320  twin->bkgdset( style.data );
321 
322  for ( /*adjusted i*/; *cp && i < end; ++i )
323  {
324  if ( passwd )
325  {
326  twin->addwstr( L"*" );
327  }
328  else
329  {
330  twin->addwstr( cp, 1 );
331  }
332 
333  ++cp;
334  }
335 
336  twin->bkgdset( style.plain );
337 
338  for ( /*adjusted i*/; i < end; ++i )
339  {
340  twin->addch( ACS_CKBOARD );
341  }
342 
343  // draw right scrollhint if
344  if ( end < fldlength )
345  {
346  twin->bkgdset( style.scrl );
347  twin->addch( ACS_RARROW );
348  }
349 
350  // reverse curpos
351  if ( GetState() == NC::WSactive )
352  {
353  twin->move( 0, curpos - fldstart );
354  twin->bkgdset( wStyle().cursor );
355 
356  if ( curpos < buffer.length() )
357  twin->add_attr_char( );
358  else
359  twin->addch( ACS_CKBOARD );
360  }
361 
362  Update();
363 }
364 
365 
366 
367 NCursesEvent NCInputField::wHandleInput( wint_t key )
368 {
369  NCursesEvent ret = NCursesEvent::none;
370  bool beep = false;
371  bool update = true;
372 
373  switch ( key )
374  {
375  case '\b': //ctrl-h
376  case 0x7f: //del
377  case KEY_BACKSPACE:
378 
379  if ( bufferFull() && curpos == maxCursor() )
380  {
381  // if we're on the last char in a full buffer delete this char
382  // and not the previous one.
383  buffer.erase( curpos, 1 );
384  }
385  else if ( curpos )
386  {
387  buffer.erase( --curpos, 1 );
388  }
389  else
390  {
391  update = false;
392  beep = true;
393  }
394 
395  break;
396 
397  case KEY_DC:
398 
399  if ( curpos < buffer.length() )
400  {
401  buffer.erase( curpos, 1 );
402  }
403  else
404  {
405  update = false;
406  beep = true;
407  }
408 
409  break;
410 
411  case KEY_HOME:
412 
413  if ( curpos )
414  {
415  curpos = 0;
416  }
417  else
418  {
419  update = false;
420  beep = true;
421  }
422 
423  break;
424 
425  case KEY_END:
426 
427  if ( curpos < maxCursor() )
428  {
429  curpos = maxCursor();
430  }
431  else
432  {
433  update = false;
434  beep = true;
435  }
436 
437  break;
438 
439  case KEY_LEFT:
440 
441  if ( curpos )
442  {
443  --curpos;
444  }
445  else
446  {
447  update = false;
448  beep = true;
449  }
450 
451  break;
452 
453  case KEY_RIGHT:
454 
455  if ( curpos < maxCursor() )
456  {
457  ++curpos;
458  }
459  else
460  {
461  update = false;
462  beep = true;
463  }
464 
465  break;
466 
467  case KEY_RETURN:
468  update = false;
469 
470  if ( notify() || returnOnReturn_b )
471  ret = NCursesEvent::Activated;
472 
473  break;
474 
475  case KEY_HOTKEY:
476  update = false;
477 
478  break;
479 
480  default:
481  bool is_special = false;
482 
483  if ( key > 0xFFFF )
484  {
485  is_special = true;
486  key -= 0xFFFF;
487  }
488 
489  if (( !is_special && KEY_MIN < key && KEY_MAX > key )
490  ||
491  !iswprint( key )
492  ||
493  // if we are at limit of input
494  ( InputMaxLength >= 0 && InputMaxLength <= ( int )buffer.length() ) )
495  {
496  update = false;
497  beep = true;
498  }
499  else if ( fldtype == NUMBER )
500  {
501  if ( bufferFull() && key != L'+' )
502  {
503  update = false;
504  beep = true;
505  }
506  else
507  {
508  switch ( key )
509  {
510  case L'0':
511  case L'1':
512  case L'2':
513  case L'3':
514  case L'4':
515  case L'5':
516  case L'6':
517  case L'7':
518  case L'8':
519  case L'9':
520 
521  if ( curpos || buffer.empty() || buffer[0] != L'-' )
522  {
523  buffer.insert( std::wstring::size_type( curpos ), 1, key );
524 
525  if ( curpos < maxCursor() )
526  ++curpos;
527  }
528  else
529  {
530  update = false;
531  beep = true;
532  }
533 
534  break;
535 
536  case L'+':
537 
538  if ( !buffer.empty() && buffer[0] == L'-' )
539  {
540  buffer.erase( std::wstring::size_type( 0 ), 1 );
541 
542  if ( curpos )
543  --curpos;
544  }
545  else
546  {
547  update = false;
548  }
549 
550  break;
551 
552  case L'-':
553 
554  if ( buffer.empty() || buffer[0] != L'-' )
555  {
556  buffer.insert( std::wstring::size_type( 0 ), 1, L'-' );
557 
558  if ( curpos < maxCursor() )
559  ++curpos;
560  }
561  else
562  {
563  update = false;
564  }
565 
566  break;
567 
568  default:
569  update = false;
570  beep = true;
571  break;
572  }
573  }
574 
575  }
576  else // PLAIN
577  {
578 
579  if ( bufferFull() || !validKey( key ) )
580  {
581  update = false;
582  beep = true;
583  }
584  else
585  {
586  buffer.insert( std::wstring::size_type( curpos ), 1, key );
587 
588  if ( curpos < maxCursor() )
589  ++curpos;
590  }
591 
592  }
593 
594  break;
595  }
596 
597  if ( update )
598  {
599  tUpdate();
600 
601  if ( notify() )
602  ret = NCursesEvent::ValueChanged;
603  }
604 
605  if ( beep )
606  ::beep();
607 
608  return ret;
609 
610 }
611 
612 
613 void NCInputField::setInputMaxLength( int numberOfChars )
614 {
615  int nr = numberOfChars;
616 
617  // if there is more text then the maximum number of chars,
618  // truncate the text and update the buffer
619 
620  if ( nr >= 0 && ( int )buffer.length() > nr )
621  {
622  buffer.erase( nr, maxCursor() - nr );
623  tUpdate();
624  curpos = buffer.length();
625  }
626 
627  InputMaxLength = nr;
628 
629  YInputField::setInputMaxLength( numberOfChars );
630 }
C++ class for windows.
Definition: ncursesw.h:904
virtual void setEnabled(bool do_bv)
Pure virtual to make sure every widget implements it.
Definition: NCInputField.cc:94
int clear()
Clear the window.
Definition: ncursesw.h:1522
int bkgd(const chtype ch)
Set the background property and apply it to the window.
Definition: ncursesw.h:1443
void bkgdset(chtype ch)
Set the background property.
Definition: ncursesw.h:1448
Definition: position.h:109
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
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 move(int y, int x)
Move cursor the this position.
Definition: ncursesw.h:1155
virtual void setEnabled(bool do_bv)=0
Pure virtual to make sure every widget implements it.
Definition: NCWidget.cc:391
Definition: position.h:154