]> git.lyx.org Git - lyx.git/blob - src/minibuffer.C
Remove unused font variable which caused a warning.
[lyx.git] / src / minibuffer.C
1 /* ###########################################################################
2  *
3  *                 The MiniBuffer Class
4  *                 read minibuffer.h for more
5  *                 information.
6  * 
7  *           Copyright 1995 Matthias Ettrich
8  *           Copyright 1995-2001 The LyX Team.  
9  * 
10  * ###########################################################################
11  */
12
13 #include <config.h>
14
15 #include <iostream>
16
17 #ifdef __GNUG__
18 #pragma implementation
19 #endif
20
21 #include "minibuffer.h"
22
23 #include "support/lyxalgo.h"
24 #include "support/filetools.h"
25 #include "LyXView.h"
26 #include "XFormsView.h"
27 #include "gettext.h"
28 #include "LyXAction.h"
29 #include "BufferView.h"
30
31
32 using SigC::slot;
33 using std::vector;
34
35 extern LyXAction lyxaction;
36
37
38 namespace {
39
40 struct prefix {
41         string p;
42         prefix(string const & s) 
43                 : p(s) {}
44         bool operator()(string const & s) const {
45                 return prefixIs(s, p);
46         }
47 };
48
49 } // end of anon namespace
50
51
52 MiniBuffer::MiniBuffer(LyXView * o, FL_Coord x, FL_Coord y,
53                        FL_Coord h, FL_Coord w)
54         : stored_(false), owner_(o), state_(spaces)
55 {
56         add(FL_NORMAL_INPUT, x, y, h, w);
57         timer.setTimeout(6000);
58         timer.timeout.connect(slot(this, &MiniBuffer::init));
59         stored_timer.setTimeout(1500);
60         stored_timer.timeout.connect(slot(this, &MiniBuffer::stored_slot));
61         deactivate();
62 }
63
64
65 void MiniBuffer::stored_slot() 
66 {
67         if (stored_) {
68                 stored_ = false;
69                 fl_set_input(the_buffer, stored_input.c_str());
70         }
71 }
72
73
74 void MiniBuffer::stored_set(string const & str) 
75 {
76         stored_input = str;
77         stored_ = true;
78         stored_timer.start();
79 }
80
81
82 int MiniBuffer::peek_event(FL_OBJECT * ob, int event, int key)
83 {
84         switch (event) {
85         case FL_KEYBOARD:
86         {
87                 char const * tmp = fl_get_input(ob);
88                 string input = tmp ? tmp : "";
89                 if (stored_) {
90                         stored_timer.stop();
91                         input = stored_input;
92                         fl_set_input(ob, input.c_str());
93                         stored_ = false;
94                 }
95                 
96                 switch (key) {
97                 case XK_Down:
98                         if (hist_iter != history_->end()) {
99                                 ++hist_iter;
100                         }
101                         if (hist_iter == history_->end()) {
102                                 // no further history
103                                 stored_set(input);
104                                 fl_set_input(ob, _("[End of history]"));
105                         } else {
106                                 fl_set_input(ob, hist_iter->c_str());
107                         }
108                         return 1; 
109                 case XK_Up:
110                         if (hist_iter == history_->begin()) {
111                                 // no further history
112                                 stored_set(input);
113                                 fl_set_input(ob, _("[Beginning of history]"));
114                         } else {
115                                 --hist_iter;
116                                 fl_set_input(ob, hist_iter->c_str());
117                         }
118                         return 1; 
119                 case 9:
120                 case XK_Tab:
121                 {
122                         // Completion handling.
123                         
124                         vector<string> comp;
125                         lyx::copy_if(completion_.begin(),
126                                      completion_.end(),
127                                      std::back_inserter(comp), prefix(input));
128
129                         if (comp.empty()) {
130                                 // No matches
131                                 string const tmp = input + _(" [no match]");
132                                 stored_set(input);
133                                 fl_set_input(ob, tmp.c_str());
134                         } else if (comp.size() == 1) {
135                                 // Perfect match
136                                 string const tmp =
137                                         comp[0] + _(" [sole completion]");
138                                 stored_set(comp[0]);
139                                 fl_set_input(ob, tmp.c_str());
140                         } else {
141                                 // More that one match
142                                 // Find maximal avaliable prefix
143                                 string const tmp = comp[0];
144                                 string test(input);
145                                 test += tmp[test.length()];
146                                 while (test.length() < tmp.length()) {
147                                         vector<string> vtmp;
148                                         lyx::copy_if(comp.begin(),
149                                                      comp.end(),
150                                                      std::back_inserter(vtmp),
151                                                      prefix(test));
152                                         if (vtmp.size() != comp.size()) {
153                                                 test.erase(test.length() - 1);
154                                                 break;
155                                         }
156                                         test += tmp[test.length()];
157                                 }
158                                 fl_set_input(ob, test.c_str());
159                                 
160                                 // How should the possible matches
161                                 // be visualized?
162                                 std::copy(comp.begin(), comp.end(),
163                                           std::ostream_iterator<string>(std::cerr, "\n"));
164                         }
165                         return 1; 
166                 }
167                 case 27:
168                 case XK_Escape:
169                         // Abort
170                         owner_->view()->focus(true);
171                         init();
172                         deactivate();
173                         //escape.emit();
174                         return 1; 
175                 case 13:
176                 case XK_Return:
177                 {
178 #if 0
179                         // This will go in again in a little while
180                         // we need to be able to declare what types
181                         // of argumetns LFUN's should have first. (Lgb)
182                         // First check for match
183                         vector<string>::const_iterator cit =
184                                 std::find(completion_.begin(),
185                                           completion_.end(),
186                                           input);
187                         if (cit == completion_.end()) {
188                                 // no such func/item
189                                 stored_set(input);
190                                 string const tmp = input + _(" [no match]");
191                                 fl_set_input(ob, tmp.c_str());
192                         } else {
193 #endif
194                                 // Return the inputted string
195                                 deactivate();
196                                 owner_->view()->focus(true);
197                                 history_->push_back(input);
198                                 stringReady.emit(input);
199 # if 0
200                         }
201 #endif
202                         return 1;
203                 }
204                 case XK_space:
205                 {
206                         // Depending on the input state spaces might not
207                         // be allowed.
208                         switch (state_) {
209                         case spaces:
210                                 return 0;
211                         case nospaces:
212                         {
213                                 stored_set(input);
214                                 string const tmp = input + _(" [no match]");
215                                 fl_set_input(ob, tmp.c_str());
216                                 return 1;
217                         }
218                         }
219                         
220                 }
221                 
222                 default:
223                         return 0;
224                 }
225         }
226         default:
227                 //lyxerr << "Unhandled minibuffer event!" << endl;
228                 break;
229         }
230         
231         return 0;
232 }
233
234
235 extern "C"
236 int C_MiniBuffer_peek_event(FL_OBJECT * ob, int event, 
237                             FL_Coord, FL_Coord,
238                             int key, void * /*xev*/)
239 {
240         MiniBuffer * mini = static_cast<MiniBuffer*>(ob->u_vdata);
241         return mini->peek_event(ob, event, key);
242 }
243
244
245 void MiniBuffer::prepare()
246 {
247         text.erase();
248         fl_set_input(the_buffer, "");
249         activate();
250         fl_set_focus_object(static_cast<XFormsView *>(owner_)->getForm(),
251                             the_buffer);
252 }
253
254
255 FL_OBJECT * MiniBuffer::add(int type, FL_Coord x, FL_Coord y,
256                            FL_Coord w, FL_Coord h)
257 {
258         FL_OBJECT * obj;
259         
260         the_buffer = obj = fl_add_input(type, x, y, w, h, text.c_str());
261         fl_set_object_boxtype(obj, FL_DOWN_BOX);
262         fl_set_object_resize(obj, FL_RESIZE_ALL);
263         fl_set_object_gravity(obj, SouthWestGravity, SouthEastGravity);
264         fl_set_object_color(obj, FL_MCOL, FL_MCOL);
265         fl_set_object_lsize(obj, FL_NORMAL_SIZE);
266         
267         // To intercept Up, Down, Table for history
268         fl_set_object_prehandler(obj, C_MiniBuffer_peek_event);
269         obj->u_vdata = this;
270         obj->wantkey = FL_KEY_TAB;
271
272         fl_set_input(the_buffer, text.c_str());
273         
274         return obj;
275 }
276
277
278 void MiniBuffer::message(string const & str) 
279 {
280         timer.restart();
281         string const ntext = strip(str);
282         if (!the_buffer->focus) {
283                 fl_set_input(the_buffer, ntext.c_str());
284                 text = ntext;
285         }
286 }
287
288
289 void MiniBuffer::messagePush(string const & str) 
290 {
291         text_stored = text;
292         message(str);
293 }
294
295
296 void MiniBuffer::messagePop()
297 {
298         if (!text_stored.empty()) {
299                 message(text_stored);
300                 text_stored.erase();
301         }
302 }
303
304
305 void MiniBuffer::addSet(string const & s1, string const & s2)
306 {
307         string const str = text + ' ' +  s1 + ' ' + s2;
308         message(str);
309 }
310
311
312 void MiniBuffer::getString(State spaces,
313                            vector<string> const & completion,
314                            vector<string> & history)
315 {
316         state_ = spaces;
317         completion_ = completion;
318         history_ = &history;
319         hist_iter = history_->end();
320         prepare();
321 }
322
323
324 void MiniBuffer::init()
325 {
326         // If we have focus, we don't want to change anything.
327         if (the_buffer->focus)
328                 return;
329
330         timeout.emit();
331         timer.stop();
332 }
333
334
335 void MiniBuffer::activate()
336 {
337         fl_activate_object(the_buffer);
338         fl_redraw_object(the_buffer);
339 }
340
341
342 void MiniBuffer::deactivate()
343 {
344         fl_redraw_object(the_buffer);
345         fl_deactivate_object(the_buffer);
346 }
347
348
349 void MiniBuffer::redraw() 
350 {
351         fl_redraw_object(the_buffer);
352 }