libyui-ncurses  2.44.1
 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 KEY_BACKSPACE:
376 
377  if ( bufferFull() && curpos == maxCursor() )
378  {
379  // if we're on the last char in a full buffer delete this char
380  // and not the previous one.
381  buffer.erase( curpos, 1 );
382  }
383  else if ( curpos )
384  {
385  buffer.erase( --curpos, 1 );
386  }
387  else
388  {
389  update = false;
390  beep = true;
391  }
392 
393  break;
394 
395  case KEY_DC:
396 
397  if ( curpos < buffer.length() )
398  {
399  buffer.erase( curpos, 1 );
400  }
401  else
402  {
403  update = false;
404  beep = true;
405  }
406 
407  break;
408 
409  case KEY_HOME:
410 
411  if ( curpos )
412  {
413  curpos = 0;
414  }
415  else
416  {
417  update = false;
418  beep = true;
419  }
420 
421  break;
422 
423  case KEY_END:
424 
425  if ( curpos < maxCursor() )
426  {
427  curpos = maxCursor();
428  }
429  else
430  {
431  update = false;
432  beep = true;
433  }
434 
435  break;
436 
437  case KEY_LEFT:
438 
439  if ( curpos )
440  {
441  --curpos;
442  }
443  else
444  {
445  update = false;
446  beep = true;
447  }
448 
449  break;
450 
451  case KEY_RIGHT:
452 
453  if ( curpos < maxCursor() )
454  {
455  ++curpos;
456  }
457  else
458  {
459  update = false;
460  beep = true;
461  }
462 
463  break;
464 
465  case KEY_RETURN:
466  update = false;
467 
468  if ( notify() || returnOnReturn_b )
469  ret = NCursesEvent::Activated;
470 
471  break;
472 
473  case KEY_HOTKEY:
474  update = false;
475 
476  break;
477 
478  default:
479  bool is_special = false;
480 
481  if ( key > 0xFFFF )
482  {
483  is_special = true;
484  key -= 0xFFFF;
485  }
486 
487  if (( !is_special && KEY_MIN < key && KEY_MAX > key )
488  ||
489  !iswprint( key )
490  ||
491  // if we are at limit of input
492  ( InputMaxLength >= 0 && InputMaxLength <= ( int )buffer.length() ) )
493  {
494  update = false;
495  beep = true;
496  }
497  else if ( fldtype == NUMBER )
498  {
499  if ( bufferFull() && key != L'+' )
500  {
501  update = false;
502  beep = true;
503  }
504  else
505  {
506  switch ( key )
507  {
508  case L'0':
509  case L'1':
510  case L'2':
511  case L'3':
512  case L'4':
513  case L'5':
514  case L'6':
515  case L'7':
516  case L'8':
517  case L'9':
518 
519  if ( curpos || buffer.empty() || buffer[0] != L'-' )
520  {
521  buffer.insert( std::wstring::size_type( curpos ), 1, key );
522 
523  if ( curpos < maxCursor() )
524  ++curpos;
525  }
526  else
527  {
528  update = false;
529  beep = true;
530  }
531 
532  break;
533 
534  case L'+':
535 
536  if ( !buffer.empty() && buffer[0] == L'-' )
537  {
538  buffer.erase( std::wstring::size_type( 0 ), 1 );
539 
540  if ( curpos )
541  --curpos;
542  }
543  else
544  {
545  update = false;
546  }
547 
548  break;
549 
550  case L'-':
551 
552  if ( buffer.empty() || buffer[0] != L'-' )
553  {
554  buffer.insert( std::wstring::size_type( 0 ), 1, L'-' );
555 
556  if ( curpos < maxCursor() )
557  ++curpos;
558  }
559  else
560  {
561  update = false;
562  }
563 
564  break;
565 
566  default:
567  update = false;
568  beep = true;
569  break;
570  }
571  }
572 
573  }
574  else // PLAIN
575  {
576 
577  if ( bufferFull() || !validKey( key ) )
578  {
579  update = false;
580  beep = true;
581  }
582  else
583  {
584  buffer.insert( std::wstring::size_type( curpos ), 1, key );
585 
586  if ( curpos < maxCursor() )
587  ++curpos;
588  }
589 
590  }
591 
592  break;
593  }
594 
595  if ( update )
596  {
597  tUpdate();
598 
599  if ( notify() )
600  ret = NCursesEvent::ValueChanged;
601  }
602 
603  if ( beep )
604  ::beep();
605 
606  return ret;
607 
608 }
609 
610 
611 void NCInputField::setInputMaxLength( int numberOfChars )
612 {
613  int nr = numberOfChars;
614 
615  // if there is more text then the maximum number of chars,
616  // truncate the text and update the buffer
617 
618  if ( nr >= 0 && ( int )buffer.length() > nr )
619  {
620  buffer.erase( nr, maxCursor() - nr );
621  tUpdate();
622  curpos = buffer.length();
623  }
624 
625  InputMaxLength = nr;
626 
627  YInputField::setInputMaxLength( numberOfChars );
628 }
C++ class for windows.
Definition: ncursesw.h:904
virtual void setEnabled(bool do_bv)
Definition: NCInputField.cc:94
int bkgd(const chtype ch)
Definition: ncursesw.h:1443
void bkgdset(chtype ch)
Definition: ncursesw.h:1448
Definition: position.h:109
int addwstr(const wchar_t *str, int n=-1)
Definition: ncursesw.cc:123
int add_attr_char(int y, int x)
Definition: ncursesw.cc:166
int addch(const char ch)
Definition: ncursesw.h:1228
int move(int y, int x)
Definition: ncursesw.h:1155
virtual void setEnabled(bool do_bv)=0
Definition: NCWidget.cc:391
Definition: position.h:154