]> git.lyx.org Git - lyx.git/blob - src/minibuffer.C
merge from the string-switch branch and ready for a prelease.
[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-1999 The LyX Team.  
9  * 
10  * ###########################################################################
11  */
12
13 #include <config.h>
14
15 #ifdef __GNUG__
16 #pragma implementation "minibuffer.h"
17 #endif
18
19 #include "support/filetools.h"
20 #include "lyx_main.h" 
21 #include "lyxfunc.h"
22 #include FORMS_H_LOCATION
23 #include "minibuffer.h"  
24 #include "LyXView.h"
25 #include "error.h"
26 #include "gettext.h"
27
28 extern bool keyseqUncomplete();
29 extern string keyseqOptions(int l=190);
30 extern string keyseqStr(int l=190);
31 extern LyXAction lyxaction;
32
33 void MiniBuffer::TimerCB(FL_OBJECT *, long tmp)
34 {
35         MiniBuffer *obj= (MiniBuffer*)tmp;
36         obj->Init();
37 }
38
39
40 void MiniBuffer::ExecutingCB(FL_OBJECT *ob, long)
41 {
42         MiniBuffer *obj = (MiniBuffer*)ob->u_vdata;
43         lyxerr.debug("Getting ready to execute: " + obj->cur_cmd);
44         fl_set_focus_object(obj->owner->getForm(),
45                             obj->owner->currentView()->getWorkArea());
46         if (obj->cur_cmd.empty()) { 
47                 obj->Init();
48                 return ; 
49         }
50         obj->Set(_("Executing:"), obj->cur_cmd);
51         obj->addHistory(obj->cur_cmd);
52         
53         // Split command into function and argument
54         // This is done wrong Asger. Instead of <function argument>
55         // it ends up as <argument function> Queer solution:
56         string arg = obj->cur_cmd;
57         string function;
58         if (contains(arg, " ")) {
59                 arg = split(arg, function, ' ');
60                 function = strip(function);
61         } else {
62                 function = arg;
63                 arg.erase();
64         }
65         lyxerr.debug("Function: " + function);
66         lyxerr.debug("Arg     : " + arg);
67         // Check if the name is valid (ale)
68         // No, let the dispatch functions handle that.
69         //int action = lyxaction.LookupFunc(function.c_str());
70         //lyxerr.debug(string("minibuffer action: ") + action);
71         //if (action>=0) {
72             // Dispatch only returns requested data for a few commands (ale)
73         string res=obj->owner->getLyXFunc()->Dispatch(function.c_str(),
74                                                        arg.c_str());
75         lyxerr.debug(string("Minibuffer Res: ") + res);
76 /*      if (!res.empty())
77                 if(obj->owner->getLyXFunc()->errorStat())
78                         obj->Set(_("Error:"), _(res.c_str()), string(), 4);
79                 else
80                         obj->Set(_("Result:"), _(res.c_str()), string(), 4);
81         else
82                 obj->Init();
83 */
84         //} else {
85 #ifdef WITH_WARNINGS
86 #warning Look at this.
87 #endif
88         //obj->Set(_("Cannot find function"), function, "!");
89         obj->shows_no_match = false;
90         //}
91
92         return ;
93 }
94
95
96 void MiniBuffer::ExecCommand()
97 {
98         text.erase();
99         fl_set_input(the_buffer, "");
100         fl_set_focus_object(owner->getForm(),the_buffer);
101 }
102
103
104 FL_OBJECT *MiniBuffer::add(int type, FL_Coord x, FL_Coord y,
105                            FL_Coord w, FL_Coord h)
106 {
107         FL_OBJECT *obj;
108         
109         the_buffer = obj = fl_add_input(type,x,y,w,h,text.c_str());
110         fl_set_object_boxtype(obj,FL_DOWN_BOX);
111         fl_set_object_resize(obj, FL_RESIZE_ALL);
112         fl_set_object_gravity(obj, SouthWestGravity, SouthEastGravity);
113         fl_set_object_color(obj,FL_MCOL,FL_MCOL);
114         fl_set_object_lsize(obj,FL_NORMAL_SIZE);
115         fl_set_object_callback(obj,ExecutingCB, 0);
116
117         // To intercept Up, Down, Table for history
118         fl_set_object_prehandler(obj, peek_event);
119         obj->u_vdata = (void*)this;
120         obj->wantkey = FL_KEY_TAB;
121         
122         // timer
123         timer = fl_add_timer(FL_HIDDEN_TIMER, 0,0,0,0, "Timer");
124         fl_set_object_callback(timer, TimerCB, (long)this);
125         fl_set_input(the_buffer, text.c_str());
126
127         return obj;
128 }
129
130
131 // Added optional arg `delay_secs', defaults to 4.
132 //When 0, no timeout is done. RVDK_PATCH_5 
133 void MiniBuffer::Set(string const& s1, string const& s2,
134                      string const& s3, int delay_secs)
135 {
136         setTimer(delay_secs);
137
138         string ntext = strip(s1 + ' ' + s2 + ' ' + s3);
139
140         if (!the_buffer->focus) {
141                 fl_set_input(the_buffer, ntext.c_str());
142                 XFlush(fl_display);
143                 text = ntext;
144         }
145 }
146
147
148 void MiniBuffer::Init()
149 {
150         // If we have focus, we don't want to change anything.
151         if (the_buffer->focus)
152                 return;
153
154         // When meta-fake key is pressed, show the key sequence so far + "M-".
155         if (owner->getLyXFunc()->wasMetaKey()) {
156                 text = owner->getLyXFunc()->keyseqStr();
157                 text += " M-";
158         }
159
160         // Else, when a non-complete key sequence is pressed,
161         // show the available options.
162         else if (owner->getLyXFunc()->keyseqUncomplete()) 
163                 text = owner->getLyXFunc()->keyseqOptions();
164    
165         // Else, show the buffer state.
166         else if (owner->currentView()->available()) {
167                         string nicename =
168                                 MakeDisplayPath(owner->currentBuffer()->
169                                                 getFileName());
170                         // Should we do this instead? (kindo like emacs)
171                         // leaves more room for other information
172                         text = "LyX: ";
173                         text += nicename;
174                         if (owner->currentBuffer()->lyxvc.inUse()) {
175                                 text += " [RCS:";
176                                 text += owner->currentBuffer()->lyxvc.getVersion();
177                                 text += ' ';
178                                 text += owner->currentBuffer()->lyxvc.getLocker();
179                                 if (owner->currentBuffer()->isReadonly())
180                                         text += " (RO)";
181                                 text += ']';
182                         } else if (owner->currentBuffer()->isReadonly())
183                                 text += " [RO]";
184                         if (!owner->currentBuffer()->isLyxClean())
185                                 text += _(" (Changed)");
186         } else {
187                 if (text != "Welcome to LyX!") // this is a hack
188                         text = _("* No document open *");
189         }
190         
191
192         fl_set_input(the_buffer, text.c_str());
193         setTimer(0);
194         XFlush(fl_display);
195 }
196
197
198 // allows to store and reset the contents one time. Usefull for
199 // status messages like "load font" (Matthias)
200 void MiniBuffer::Store()
201 {
202         text_stored = fl_get_input(the_buffer);
203 }
204
205
206 void MiniBuffer::Reset()
207 {
208         if (!text_stored.empty()){
209                 Set(text_stored);
210                 text_stored.erase();
211         }
212 }
213
214 void MiniBuffer::Activate()
215 {
216         fl_activate_object(the_buffer);
217         fl_redraw_object(the_buffer);
218 }
219
220 void MiniBuffer::Deactivate()
221 {
222         fl_deactivate_object(the_buffer);
223 }
224
225
226 // This is not as dirty as it seems, the hidden buttons removed by this
227 // function were just kludges for an uncomplete keyboard callback (ale)
228 int MiniBuffer::peek_event(FL_OBJECT *ob, int event, FL_Coord, FL_Coord,
229                            int key, void */*xev*/)
230 {
231         MiniBuffer *mini = (MiniBuffer*)ob->u_vdata;
232         
233         if (event==FL_KEYBOARD){
234                 switch (key) {
235                 case XK_Down:
236                         mini->history_idx++;
237                         if (!mini->getHistory().empty()) {
238                                 fl_set_input(ob, mini->getHistory().c_str());
239                         } else
240                                 mini->history_idx--;
241                         return 1; 
242                 case XK_Up:
243                         if (mini->history_idx > 0) mini->history_idx--;
244                         fl_set_input(ob, mini->getHistory().c_str());
245                         return 1; 
246                 case 9:
247                 case XK_Tab:
248                 {
249                         // complete or increment the command
250                         const char *s = lyxaction.getApproxFuncName(fl_get_input(ob));
251                         if (s && s[0])
252                                 fl_set_input(ob, s);
253                         return 1; 
254                 }
255                 case 27:
256                 case XK_Escape:
257                         // Abort
258                         fl_set_focus_object(mini->owner->getForm(),
259                                             mini->owner->currentView()->getWorkArea());
260                         mini->Init();
261                         return 1; 
262                 case 13:
263                 case XK_Return:
264                         // Execute a command. 
265                         mini->cur_cmd = string(fl_get_input(ob));
266                         ExecutingCB(ob, 0);
267                         return 1;
268                 default:
269                         return 0;
270                 }
271         }
272         return 0;
273 }
274