ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/dclient/src/backend/ndk/edit.cpp
Revision: 1.2
Committed: Mon Oct 18 14:11:48 2010 UTC (13 years, 8 months ago) by sf-pippijn
Branch: MAIN
Changes since 1.1: +2 -1 lines
Log Message:
check and log but do not die when ncurses stuff fails

File Contents

# User Rev Content
1 sf-pippijn 1.1 /* edit.cc
2     * This file is part of NDK++ library
3     * Copyright (c) 2003,2004 by Stanislav Ievlev
4     *
5     * This file is covered by the GNU Library General Public License,
6     * which should be included with libndk++ as the file COPYING.
7     */
8     #include <ndk++/application.hh>
9     #include <ndk++/edit.hh>
10     #include <ndk++/packer.hh>
11     #include <ndk++/palette.hh>
12    
13 sf-pippijn 1.2 #include <ncurses/assert.hh>
14 sf-pippijn 1.1 #include <ncurses/pen.hh>
15    
16     #include <cctype>
17    
18    
19     using ndk::edit;
20    
21     edit::edit (const std::string &str, panel *parent, bool accept)
22     : button (str, parent, accept)
23     , current_ (0)
24     , begin_ (0)
25     , mode_ (normal)
26     {
27     events ()->on_keyboard (slot (&edit::at_keyboard, this));
28     events ()->on_system (slot (&edit::at_system, this));
29     }
30    
31     void
32     edit::resize (int size)
33     {
34     button::resize (size, 1);
35     }
36    
37     void
38     edit::set_text (const std::string &str)
39     {
40     label::set_text (str);
41     current_ = text_.length ();
42     draw ();
43     }
44    
45     void
46     edit::set_mode (echo_mode mode)
47     {
48     mode_ = mode;
49     }
50    
51     void
52     edit::change_color ()
53     {
54     ncurses::pen (*this).set_color (palette::instance ()
55     [
56     state_ == engine::enter_focus
57     ? colors::edit_active
58     : colors::edit_inactive
59     ]);
60     }
61    
62     void
63     edit::draw ()
64     {
65     /* first process flags */
66     std::string out;
67    
68     switch (mode_)
69     {
70     case normal:
71     out.assign (text ());
72     break;
73     case no_echo:
74     out.assign ("");
75     break;
76     case password:
77     out.assign (std::string (text ().size (), '*'));
78     break;
79     default:
80     break;
81     }
82    
83     label::draw (out, begin_); /* and draw */
84     set_cursor (); /* and finally update cursor position */
85     ncurses::pen (*this).commit (); /* commit changes to the screen */
86     }
87    
88     ndk::event::result
89     edit::at_system (const event &ev)
90     {
91     event::result res = event::ignored;
92    
93     if (!ev.sender_)
94     {
95     if (engine::enter_focus == ev.type_)
96     {
97     app ().cursor_on ();
98     set_cursor (); /* only set cursor position, don't need full redraw */
99     res = event::accepted;
100     }
101     else if (engine::leave_focus == ev.type_)
102     {
103     app ().cursor_off ();
104     res = event::accepted;
105     }
106     }
107     return res;
108     }
109    
110     ndk::event::result
111     edit::at_keyboard (const keyboard &ev)
112     {
113     event::result res = event::ignored;
114     unsigned int pos = current_;
115    
116     switch (ev.code ())
117     {
118     case key::right:
119     (scroll_right ()) ? draw () : set_cursor ();
120     res = event::accepted;
121     break;
122     case key::left:
123     (scroll_left ()) ? draw () : set_cursor ();
124     res = event::accepted;
125     break;
126     case key::backspace:
127     --pos; /* try to go to previous position */
128     if (pos < text_.length ())
129     {
130     erase (pos);
131     scroll_left (); /* scroll all view to the left */
132     draw (); /* we always need full redraw */
133     res = event::accepted;
134     }
135     break;
136     case key::dc:
137     if (pos < text_.length ())
138     {
139     erase (pos);
140     draw (); /* we always need full redraw */
141     res = event::accepted;
142     }
143     break;
144     case key::home:
145     begin_ = 0;
146     current_ = 0;
147     draw ();
148     res = event::accepted;
149     break;
150     case key::end:
151     current_ = text_.length ();
152     (recalibrate ()) ? draw () : set_cursor ();
153     res = event::accepted;
154     break;
155     case '\r':
156     on_commit_ (text_);
157     break;
158     case '\t': /* don't beep on tab */
159     break;
160     default: /* enter key to the string */
161     if (std::isprint (int (ev.code ())))
162     {
163     insert (pos, char (ev.code ()));
164     scroll_right ();
165     draw (); /* we always need full redraw */
166     res = event::accepted;
167     }
168     #if 0
169     else
170     throw ev.code ();
171     #endif
172     break;
173     }
174    
175     return res;
176     }
177    
178     bool
179     edit::scroll_right ()
180     {
181     if (current_ < int (text_.length ()))
182     ++current_; /* increase current */
183     /* recalibrate begin, decide are we need to redraw */
184     return recalibrate ();
185     }
186    
187     bool
188     edit::scroll_left ()
189     {
190     if (current_ > 0)
191     --current_; /* decrease current */
192     /* recalibrate begin, decide are we need to redraw */
193     return recalibrate ();
194     }
195    
196     bool
197     edit::recalibrate ()
198     {
199     bool res = false;
200    
201     if ((begin_ < current_) && ((current_ - begin_) > (width () - 1)))
202     {
203     /* may be cursor is over(after) edit screen? */
204     begin_ = current_ - width () + 1;
205     res = true;
206     }
207     else if (begin_ > current_)
208     {
209     /* may be cursor is over(before) edit screen? */
210     begin_ = current_;
211     res = true;
212     }
213     return res;
214     }
215    
216     void
217     edit::set_cursor ()
218     {
219     /* always move to zero position in no_echo mode */
220 sf-pippijn 1.2 return_unless (ncurses::pen (*this).move (mode_ != no_echo ? current_ - begin_ : 0, 0));
221 sf-pippijn 1.1 ncurses::pen (*this).commit ();
222     }
223    
224     void
225     edit::insert (int pos, char sym)
226     {
227     text_.insert (text_.begin () + pos, sym); /* default mode is insert mode */
228     }
229    
230     void
231     edit::erase (int pos)
232     {
233     text_.erase (text_.begin () + pos);
234     }