]> git.lyx.org Git - lyx.git/blob - src/frontends/xforms/XMiniBuffer.C
Compilation fix: give C_read_callback extern "C" linkage.
[lyx.git] / src / frontends / xforms / XMiniBuffer.C
1 // -*- C++ -*-
2 /**
3  * \file XMiniBuffer.C
4  * Copyright 1995-2002 the LyX Team
5  * Read the file COPYING
6  *
7  * \author Lars
8  * \author Asger and Juergen
9  */
10
11 #include <config.h>
12
13 #ifdef __GNUG__
14 #pragma implementation
15 #endif
16
17 #include "frontends/xforms/DropDown.h"
18 #include "frontends/xforms/XFormsView.h"
19 #include "frontends/Timeout.h"
20
21 #include "XMiniBuffer.h"
22 #include "BufferView.h"
23 #include "LyXAction.h"
24 #include "gettext.h"
25 #include "support/lyxalgo.h"
26 #include "support/lstrings.h"
27
28 #include <boost/bind.hpp>
29
30 #include <vector>
31 #include <cctype>
32
33 #ifndef CXX_GLOBAL_CSTD
34 using std::isprint;
35 #endif
36
37 using std::vector;
38
39
40 namespace {
41
42 struct prefix {
43         string p;
44         prefix(string const & s)
45                 : p(s) {}
46         bool operator()(string const & s) const {
47                 return prefixIs(s, p);
48         }
49 };
50
51 } // end of anon namespace
52
53
54 XMiniBuffer::XMiniBuffer(LyXView * o, FL_Coord x, FL_Coord y,
55                          FL_Coord h, FL_Coord w)
56         : MiniBuffer(o)
57 {
58         create_input_box(FL_NORMAL_INPUT, x, y, h, w);
59         messageMode();
60 }
61
62
63 // thanks for nothing, xforms (recursive creation not allowed)
64 void XMiniBuffer::dd_init()
65 {
66         dropdown_ = new DropDown(owner_, the_buffer);
67         dropdown_->result.connect(boost::bind(&XMiniBuffer::set_complete_input, this, _1));
68         dropdown_->keypress.connect(boost::bind(&XMiniBuffer::append_char, this, _1));
69 }
70
71
72 XMiniBuffer::~XMiniBuffer()
73 {
74         delete dropdown_;
75 }
76
77
78 int XMiniBuffer::peek_event(FL_OBJECT * ob, int event,
79                             int key, XEvent * /*xev*/)
80 {
81 #if 0
82         if (dropdown_->isVisible()) {
83                 return dropdown_->peek(xev);
84         }
85 #endif
86
87         switch (event) {
88         case FL_UNFOCUS:
89                 messageMode();
90                 break;
91         case FL_KEYBOARD:
92         {
93                 string input;
94                 if (information_displayed_) {
95                         information_timer_->stop();
96                         input = stored_input;
97                         restore_input();
98                 } else {
99                         char const * tmp = fl_get_input(ob);
100                         input = tmp ? tmp : "";
101                 }
102
103
104                 switch (key) {
105                 case XK_Down:
106 #ifdef XK_KP_Down
107                 case XK_KP_Down:
108 #endif
109                         if (hist_iter != history_->end()) {
110                                 ++hist_iter;
111                         }
112                         if (hist_iter == history_->end()) {
113                                 // no further history
114                                 show_information(_("[End of history]"), input);
115                         } else {
116                                 set_input((*hist_iter));
117                         }
118                         return 1;
119                 case XK_Up:
120 #ifdef XK_KP_Up
121                 case XK_KP_Up:
122 #endif
123                         if (hist_iter == history_->begin()) {
124                                 // no further history
125                                 show_information(_("[Beginning of history]"),
126                                                  input);
127                         } else {
128                                 --hist_iter;
129                                 set_input((*hist_iter));
130                         }
131                         return 1;
132                 case 9:
133                 case XK_Tab:
134                 {
135                         // Completion handling.
136
137                         vector<string> comp;
138                         lyx::copy_if(completion_.begin(),
139                                      completion_.end(),
140                                      back_inserter(comp), prefix(input));
141
142                         if (comp.empty()) {
143                                 // No matches
144                                 string const tmp = input + _(" [no match]");
145                                 show_information(tmp, input);
146                         } else if (comp.size() == 1) {
147                                 // Perfect match
148                                 string const tmp =
149                                         comp[0] + _(" [sole completion]");
150                                 show_information(tmp, comp[0] + " ");
151                         } else {
152                                 // More that one match
153                                 // Find maximal avaliable prefix
154                                 string const tmp = comp[0];
155                                 string test(input);
156                                 if (tmp.length() > test.length())
157                                         test += tmp[test.length()];
158                                 while (test.length() < tmp.length()) {
159                                         vector<string> vtmp;
160                                         lyx::copy_if(comp.begin(),
161                                                      comp.end(),
162                                                      back_inserter(vtmp),
163                                                      prefix(test));
164                                         if (vtmp.size() != comp.size()) {
165                                                 test.erase(test.length() - 1);
166                                                 break;
167                                         }
168                                         test += tmp[test.length()];
169                                 }
170                                 set_input(test);
171
172                                 int x,y,w,h;
173                                 fl_get_wingeometry(fl_get_real_object_window(the_buffer),
174                                                    &x, &y, &w, &h);
175
176                                 // asynchronous completion
177                                 int const air = the_buffer->x;
178                                 x += air;
179                                 y += h - (the_buffer->h + air);
180                                 w = the_buffer->w;
181                                 dropdown_->select(comp, x, y, w);
182                         }
183                         return 1;
184                 }
185                 case 27:
186                 case XK_Escape:
187                         // Abort
188 #if 0
189                         owner_->view()->focus(true);
190 #endif
191                         message_timeout();
192                         messageMode();
193                         //escape.emit();
194                         return 1;
195                 case 13:
196                 case XK_Return:
197 #ifdef XK_KP_Enter
198                 case XK_KP_Enter:
199 #endif
200                 {
201 #if 0
202                         // This will go in again in a little while
203                         // we need to be able to declare what types
204                         // of argumetns LFUN's should have first. (Lgb)
205                         // First check for match
206                         vector<string>::const_iterator cit =
207                                 find(completion_.begin(),
208                                      completion_.end(),
209                                      input);
210                         if (cit == completion_.end()) {
211                                 // no such func/item
212                                 string const tmp = input + _(" [no match]");
213                                 show_information(tmp, input);
214                         } else {
215 #endif
216                                 // Return the inputted string
217                                 messageMode();
218 #if 0
219                                 owner_->view()->focus(true);
220 #endif
221                                 if (!input.empty()) {
222                                         history_->push_back(input);
223                                 }
224                                 inputReady(input);
225 # if 0
226                         }
227 #endif
228                         return 1;
229                 }
230                 default:
231                         return 0;
232                 }
233         }
234         default:
235                 //lyxerr << "Unhandled minibuffer event!" << endl;
236                 break;
237         }
238
239         return 0;
240 }
241
242
243 extern "C" {
244
245         static
246         int C_XMiniBuffer_peek_event(FL_OBJECT * ob, int event,
247                                      FL_Coord, FL_Coord,
248                                      int key, void * xev)
249         {
250                 XMiniBuffer * mini = static_cast<XMiniBuffer*>(ob->u_vdata);
251                 return mini->peek_event(ob, event, key,
252                                         static_cast<XEvent *>(xev));
253         }
254
255 }
256
257
258 FL_OBJECT * XMiniBuffer::create_input_box(int type, FL_Coord x, FL_Coord y,
259                                           FL_Coord w, FL_Coord h)
260 {
261         FL_OBJECT * obj;
262
263         the_buffer = obj = fl_add_input(type, x, y, w, h, text.c_str());
264         fl_set_object_boxtype(obj, FL_DOWN_BOX);
265         fl_set_object_resize(obj, FL_RESIZE_ALL);
266         fl_set_object_gravity(obj, SouthWestGravity, SouthEastGravity);
267         fl_set_object_color(obj, FL_MCOL, FL_MCOL);
268         fl_set_object_lsize(obj, FL_NORMAL_SIZE);
269
270         // To intercept Up, Down, Table for history
271         fl_set_object_prehandler(obj, C_XMiniBuffer_peek_event);
272         obj->u_vdata = this;
273         obj->wantkey = FL_KEY_TAB;
274
275         set_input(text);
276
277         return obj;
278 }
279
280
281 bool XMiniBuffer::isEditingMode() const
282 {
283         return the_buffer->focus;
284 }
285
286
287 void XMiniBuffer::editingMode()
288 {
289         fl_activate_object(the_buffer);
290         fl_set_focus_object(static_cast<XFormsView *>(owner_)->getForm(),
291                             the_buffer);
292         redraw();
293 }
294
295
296 void XMiniBuffer::messageMode()
297 {
298         fl_deactivate_object(the_buffer);
299         redraw();
300 }
301
302
303 void XMiniBuffer::redraw()
304 {
305         fl_redraw_object(the_buffer);
306         XFlush(fl_display);
307 }
308
309
310 void XMiniBuffer::append_char(char c)
311 {
312         if (!c || !isprint(c))
313                 return;
314
315         char const * tmp = fl_get_input(the_buffer);
316         string str = tmp ? tmp : "";
317
318         str += c;
319
320         fl_set_input(the_buffer, str.c_str());
321 }
322
323
324 void XMiniBuffer::set_input(string const & str)
325 {
326         fl_set_input(the_buffer, str.c_str());
327 }