Utils/Termlib: Implement terminfo format string interpretation
[senf.git] / Utils / Termlib / Editor.cc
1 // $Id$
2 //
3 // Copyright (C) 2009 
4 // Fraunhofer Institute for Open Communication Systems (FOKUS)
5 // Competence Center NETwork research (NET), St. Augustin, GERMANY
6 //     Stefan Bund <g0dil@berlios.de>
7 //
8 // This program is free software; you can redistribute it and/or modify
9 // it under the terms of the GNU General Public License as published by
10 // the Free Software Foundation; either version 2 of the License, or
11 // (at your option) any later version.
12 //
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 // GNU General Public License for more details.
17 //
18 // You should have received a copy of the GNU General Public License
19 // along with this program; if not, write to the
20 // Free Software Foundation, Inc.,
21 // 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22
23 /** \file
24     \brief Editor non-inline non-template implementation */
25
26 #include "Editor.hh"
27 //#include "Editor.ih"
28
29 // Custom includes
30 #include <senf/Utils/membind.hh>
31 #include <senf/Scheduler/Scheduler.hh>
32
33 //#include "Editor.mpp"
34 #define prefix_
35 ///////////////////////////////cc.p////////////////////////////////////////
36
37 prefix_ senf::term::BaseEditor::BaseEditor(AbstractTerminal & terminal)
38     : terminal_ (&terminal),
39       keyTimeout_ (senf::ClockService::milliseconds(DEFAULT_KEY_TIMEOUT_MS)),
40       timer_ ("senf::term::BaseEditor::keySequenceTimeout", 
41               senf::membind(&BaseEditor::keySequenceTimeout, this)),
42       column_ (0u)
43 {
44     terminal_->setCallbacks(*this);
45 }
46
47 prefix_ void senf::term::BaseEditor::newline()
48 {
49     write("\r\n");
50     write(tifo_.getString(Terminfo::properties::ClrEol));
51     column_ = 0;
52 }
53
54 prefix_ void senf::term::BaseEditor::toColumn(unsigned c)
55 {
56     if (c >= width())
57         c = width();
58     if (c > column_) {
59         if (tifo_.hasProperty(Terminfo::properties::ParmRightCursor)) {
60             write(tifo_.formatString(Terminfo::properties::ParmRightCursor, c - column_));
61             column_ = c;
62         }
63         else {
64             char const * cuf1 (tifo_.getString(Terminfo::properties::CursorRight));
65             while (c > column_) {
66                 write(cuf1);
67                 ++column_;
68             }
69         }
70     }
71     else if (c < column_) {
72         if (tifo_.hasProperty(Terminfo::properties::ParmLeftCursor)) {
73             write(tifo_.formatString(Terminfo::properties::ParmLeftCursor, column_ - c));
74             column_ = c;
75         }
76         else {
77             char const * cub1 (tifo_.getString(Terminfo::properties::CursorRight));
78             while (c < column_) {
79                 write(cub1);
80                 --column_;
81             }
82         }
83     }
84 }
85
86 prefix_ void senf::term::BaseEditor::insertChar(char ch)
87 {
88     if (column_+1 >= width())
89         return;
90     if (tifo_.hasProperty(Terminfo::properties::InsertCharacter))
91         write(tifo_.getString(Terminfo::properties::InsertCharacter));
92     else
93         write(tifo_.formatString(Terminfo::properties::ParmIch, 1));
94     write(ch);
95     ++ column_;
96 }
97
98 prefix_ void senf::term::BaseEditor::overwriteChar(char ch)
99 {
100     write(ch);
101     ++ column_;
102 }
103
104 prefix_ void senf::term::BaseEditor::deleteChar()
105 {
106     if (tifo_.hasProperty(Terminfo::properties::DeleteCharacter))
107         write(tifo_.getString(Terminfo::properties::DeleteCharacter));
108     else
109         write(tifo_.formatString(Terminfo::properties::ParmDch, 1));
110 }
111
112 prefix_ unsigned senf::term::BaseEditor::currentColumn()
113     const
114 {
115     return column_;
116 }
117
118 prefix_ void senf::term::BaseEditor::cb_init()
119 {
120     tifo_.load(terminal_->terminalType());
121     keyParser_.load(tifo_);
122     if (tifo_.hasProperty(Terminfo::properties::KeypadXmit))
123         write(tifo_.getString(Terminfo::properties::KeypadXmit));
124 }
125
126 prefix_ void senf::term::BaseEditor::cb_charReceived(char c)
127 {
128     inputBuffer_ += c;
129     timer_.timeout(senf::scheduler::eventTime() + keyTimeout_);
130     processKeys();
131 }
132
133 prefix_ void senf::term::BaseEditor::cb_windowSizeChanged()
134 {
135     if (column_ >= width())
136         column_ = width()-1;
137 }
138
139 prefix_ void senf::term::BaseEditor::keySequenceTimeout()
140 {
141     while (!inputBuffer_.empty()) {
142         processKeys();
143         v_keyReceived(keycode_t(inputBuffer_[0]));
144         inputBuffer_.erase(0, 1);
145     }
146 }
147
148 prefix_ void senf::term::BaseEditor::processKeys()
149 {
150     do {
151         std::pair<senf::term::KeyParser::keycode_t, std::string::size_type> result
152             (keyParser_.lookup(inputBuffer_));
153         if (result.first == senf::term::KeyParser::Incomplete)
154             return;
155         v_keyReceived(result.first);
156         inputBuffer_.erase(0, result.second);
157     } while (! inputBuffer_.empty());
158     timer_.disable();
159 }
160
161 prefix_ unsigned senf::term::BaseEditor::width()
162 {
163     return terminal_->width();
164 }
165
166 prefix_ void senf::term::BaseEditor::write(char ch)
167 {
168     terminal_->write(ch);
169 }
170
171 prefix_ void senf::term::BaseEditor::write(std::string const & s)
172 {
173     for (std::string::const_iterator i (s.begin()); i != s.end(); ++i)
174         write(*i);
175 }
176
177 ///////////////////////////////cc.e////////////////////////////////////////
178 #undef prefix_
179 //#include "Editor.mpp"
180
181 \f
182 // Local Variables:
183 // mode: c++
184 // fill-column: 100
185 // comment-column: 40
186 // c-file-style: "senf"
187 // indent-tabs-mode: nil
188 // ispell-local-dictionary: "american"
189 // compile-command: "scons -u test"
190 // End: