From e225bbd75ef5c66bc94a51aad19cef66c6a3d671 Mon Sep 17 00:00:00 2001 From: John Levon Date: Fri, 19 Jul 2002 20:56:31 +0000 Subject: [PATCH] I fixed the two bugs (Very shallow in fact) Please test the minibuffer, and report things that are broken. I think things should still be working the same ... git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@4713 a592a061-630c-0410-9148-cb99ea01b6c8 --- src/ChangeLog | 4 + src/frontends/ChangeLog | 9 + src/frontends/LyXView.C | 23 +- src/frontends/LyXView.h | 16 +- src/frontends/Makefile.am | 2 - src/frontends/MiniBuffer.C | 116 -------- src/frontends/MiniBuffer.h | 133 --------- src/frontends/controllers/ChangeLog | 7 + .../controllers/ControlCommandBuffer.C | 114 ++++++++ .../controllers/ControlCommandBuffer.h | 63 +++++ src/frontends/controllers/Makefile.am | 2 + src/frontends/qt2/ChangeLog | 4 + src/frontends/qt2/QWorkArea.C | 1 - src/frontends/xforms/ChangeLog | 14 + src/frontends/xforms/DropDown.C | 4 +- src/frontends/xforms/DropDown.h | 7 +- src/frontends/xforms/XFormsView.C | 32 +-- src/frontends/xforms/XFormsView.h | 9 +- src/frontends/xforms/XMiniBuffer.C | 263 +++++++++--------- src/frontends/xforms/XMiniBuffer.h | 81 ++++-- src/frontends/xforms/lyx_gui.C | 2 +- src/lyxfunc.C | 15 +- 22 files changed, 451 insertions(+), 470 deletions(-) delete mode 100644 src/frontends/MiniBuffer.C delete mode 100644 src/frontends/MiniBuffer.h create mode 100644 src/frontends/controllers/ControlCommandBuffer.C create mode 100644 src/frontends/controllers/ControlCommandBuffer.h diff --git a/src/ChangeLog b/src/ChangeLog index bf8c6b26aa..4c1a25c06b 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,7 @@ +2002-07-19 John Levon + + * lyxfunc.C: move minibuffer completion handling out of here + 2002-07-19 John Levon * BufferView_pimpl.C: diff --git a/src/frontends/ChangeLog b/src/frontends/ChangeLog index a80f967f48..5298981301 100644 --- a/src/frontends/ChangeLog +++ b/src/frontends/ChangeLog @@ -1,3 +1,12 @@ +2002-07-19 John Levon + + * LyXView.h: + * LyXView.C: use ControlCommandBuffer, related + cleanup + + * MiniBuffer.h: + * MiniBuffer.C: remove + 2002-07-18 John Levon * LyXView.h: diff --git a/src/frontends/LyXView.C b/src/frontends/LyXView.C index 8241995589..e5be0f2833 100644 --- a/src/frontends/LyXView.C +++ b/src/frontends/LyXView.C @@ -14,7 +14,6 @@ #endif #include "LyXView.h" -#include "MiniBuffer.h" #include "debug.h" #include "intl.h" #include "lyxrc.h" @@ -28,10 +27,11 @@ #include "bufferview_funcs.h" #include "lyxtextclasslist.h" -#include "frontends/Dialogs.h" -#include "frontends/Toolbar.h" -#include "frontends/Timeout.h" -#include "frontends/Menubar.h" +#include "Dialogs.h" +#include "Toolbar.h" +#include "Timeout.h" +#include "Menubar.h" +#include "controllers/ControlCommandBuffer.h" #include "support/filetools.h" // OnlyFilename() @@ -56,6 +56,7 @@ LyXView::LyXView() autosave_timeout_.reset(new Timeout(5000)); dialogs_.reset(new Dialogs(this)); + controlcommand_.reset(new ControlCommandBuffer(*getLyXFunc())); } @@ -115,18 +116,6 @@ LyXFunc * LyXView::getLyXFunc() const } -MiniBuffer * LyXView::getMiniBuffer() const -{ - return minibuffer_.get(); -} - - -void LyXView::message(string const & str) -{ - minibuffer_->message(str); -} - - Menubar * LyXView::getMenubar() const { return menubar_.get(); diff --git a/src/frontends/LyXView.h b/src/frontends/LyXView.h index b6ed972ab5..24fb6c952f 100644 --- a/src/frontends/LyXView.h +++ b/src/frontends/LyXView.h @@ -26,9 +26,9 @@ class Buffer; class Toolbar; -class MiniBuffer; class Intl; class Menubar; +class ControlCommandBuffer; class BufferView; class Dialogs; @@ -85,11 +85,6 @@ public: /// return the menubar for this view Menubar * getMenubar() const; - /// return the minibuffer for this view - /// FIXME: I'm not at all sure that LyXFunc should be - /// aware of a mini buffer as such - MiniBuffer * getMiniBuffer() const; - /// get access to the dialogs Dialogs * getDialogs() { return dialogs_.get(); } @@ -108,11 +103,14 @@ public: /// update the menubar void updateMenubar(); + /// focus the command buffer (minibuffer) + boost::signal0 focus_command_buffer; + /// view state string changed boost::signal0 view_state_changed; /// display a message in the view - void message(string const &); + virtual void message(string const &) = 0; /// updates the title of the window void updateWindowTitle(); @@ -128,8 +126,8 @@ protected: boost::scoped_ptr menubar_; /// view's toolbar boost::scoped_ptr toolbar_; - /// view's minibuffer - boost::scoped_ptr minibuffer_; + /// view's command buffer controller + boost::scoped_ptr controlcommand_; /// keyboard mapping object boost::scoped_ptr intl_; diff --git a/src/frontends/Makefile.am b/src/frontends/Makefile.am index 3bc6960fa6..a33b0048e3 100644 --- a/src/frontends/Makefile.am +++ b/src/frontends/Makefile.am @@ -30,8 +30,6 @@ libfrontends_la_SOURCES = \ LyXView.h \ Menubar.C \ Menubar.h \ - MiniBuffer.C \ - MiniBuffer.h \ Painter.C \ Painter.h \ Timeout.C \ diff --git a/src/frontends/MiniBuffer.C b/src/frontends/MiniBuffer.C deleted file mode 100644 index e571748e9c..0000000000 --- a/src/frontends/MiniBuffer.C +++ /dev/null @@ -1,116 +0,0 @@ -// -*- C++ -*- -/** - * \file MiniBuffer.C - * Copyright 1995-2002 the LyX Team - * Read the file COPYING - * - * \author Lars - * \author Asger and Juergen - */ - -#include - -#ifdef __GNUG__ -#pragma implementation -#endif - -#include "MiniBuffer.h" - -#include "support/lyxalgo.h" -#include "support/filetools.h" -#include "support/lstrings.h" -#include "frontends/LyXView.h" -#include "gettext.h" -#include "LyXAction.h" -#include "BufferView.h" -#include "frontends/Timeout.h" - -#include - -using std::vector; -using std::back_inserter; -using std::find; - -extern LyXAction lyxaction; - - -MiniBuffer::MiniBuffer(LyXView * o) - : information_displayed_(false), owner_(o) -{ - timer = new Timeout(6000); - timer->timeout.connect(boost::bind(&MiniBuffer::message_timeout, this)); - - information_timer_ = new Timeout(1500); - information_timer_->timeout.connect(boost::bind(&MiniBuffer::restore_input, this)); -} - - -MiniBuffer::~MiniBuffer() -{ - delete timer; - delete information_timer_; -} - - -void MiniBuffer::show_information(string const & info, string const & input) -{ - stored_input = input; - information_displayed_ = true; - information_timer_->start(); - set_input(info); -} - - -void MiniBuffer::restore_input() -{ - if (information_displayed_) { - information_displayed_ = false; - set_input(stored_input); - } -} - - -void MiniBuffer::message(string const & str) -{ - timer->restart(); - string const ntext = strip(str); - if (! isEditingMode()) { - set_input(ntext); - text = ntext; - } -} - - -void MiniBuffer::prepareForInput(vector const & completion, - vector & history) -{ - completion_ = completion; - history_ = &history; - hist_iter = history_->end(); - text.erase(); - set_input(""); - editingMode(); -} - - -void MiniBuffer::message_timeout() -{ - // If we have focus, we don't want to change anything. - if (isEditingMode()) - return; - - timeout(); - // we have redraw problems therefor we don't stop the - // timer as so we force a redraw every 6 seconds. - // timer->stop(); -} - - -void MiniBuffer::set_complete_input(string const & str) -{ - if (!str.empty()) { - // add a space so the user can type - // an argument immediately - set_input(str + " "); - } -} diff --git a/src/frontends/MiniBuffer.h b/src/frontends/MiniBuffer.h deleted file mode 100644 index 49b4f2c8cc..0000000000 --- a/src/frontends/MiniBuffer.h +++ /dev/null @@ -1,133 +0,0 @@ -// -*- C++ -*- -/** - * \file MiniBuffer.h - * Copyright 1995-2002 the LyX Team - * Read the file COPYING - * - * \author Lars - * \author Asger and Juergen - */ - -#ifndef MINIBUFFER_H -#define MINIBUFFER_H - -#include "LString.h" - -#include -#include -#include - -#include - -#ifdef __GNUG__ -#pragma interface -#endif - -class LyXView; -class Timeout; - -/// -class MiniBuffer : public boost::signals::trackable { -public: - /// - MiniBuffer(LyXView *); - - /// destructor - virtual ~MiniBuffer(); - - /// Displays a text for 6 seconds - void message(string const & str); - - /** Makes the minibuffer wait for a string to be inserted. - Waits for a string to be inserted into the minibuffer, when - the string has been inserted the signal stringReady is - emitted. - */ - void prepareForInput(std::vector const & completion, - std::vector & history); - - /// This is signalled when the user has input a string - boost::signal1 inputReady; - - /// This is signalled 6 seconds after a message has been displayed - boost::signal0 timeout; - -protected: - /// Are we in editing mode? - virtual bool isEditingMode() const = 0; - /// enter editing mode - virtual void editingMode() = 0; - /// enter message display mode - virtual void messageMode() = 0; - - /** - * This will show the info string for 1.5 seconds, after - * which it will revert to the input string. - * Use this in editing mode only. If the user presses a - * key in the 1.5 second interval, the information will - * disappear. - */ - void show_information(string const & info, string const & input); - - /** - * This is called after information has been shown for 1.5 seconds - * to restore the input as given in the show_information call. - */ - void restore_input(); - - /** - * This is called when we tab-completed a command and it adds - * a space to the input so that we're ready to input any arguments. - */ - void set_complete_input(string const &); - - /// set the minibuffer content in editing mode - virtual void set_input(string const &) = 0; - - /** - * This when a message has been displayed for 6 seconds and - * it will emit the timeout signal. - */ - void message_timeout(); - - /** - * This will be the input after the information will timeout - * in 1.5 seconds or we press a key and force the information - * to disappear. - */ - string stored_input; - - /** - * This is true for 1.5 seconds while information is shown in - * editing mode. If the user presses a key while information - * is shown, the info will disappear. - */ - bool information_displayed_; - - /// - LyXView * owner_; - - /// This is the text for the message display - string text; - - /** - * This will emit the timeout signal after a message has been - * displayed for 6 seconds. - */ - Timeout * timer; - - /** - * This will call restore_input after 1.5 seconds to restore - * the input after an information display. - */ - Timeout * information_timer_; - - /// - std::vector completion_; - /// - std::vector * history_; - /// - std::vector::iterator hist_iter; -}; - -#endif // MINIBUFFER_H diff --git a/src/frontends/controllers/ChangeLog b/src/frontends/controllers/ChangeLog index cb9d00401b..2b62ad73a0 100644 --- a/src/frontends/controllers/ChangeLog +++ b/src/frontends/controllers/ChangeLog @@ -1,3 +1,10 @@ +2002-07-19 John Levon + + * Makefile.am: + * ControlCommandBuffer.h: + * ControlCommandBuffer.C: add controller for command (mini) buffer + handling + 2002-07-19 John Levon * ControlRef.C: fix dispatch call diff --git a/src/frontends/controllers/ControlCommandBuffer.C b/src/frontends/controllers/ControlCommandBuffer.C new file mode 100644 index 0000000000..7ed0871eb3 --- /dev/null +++ b/src/frontends/controllers/ControlCommandBuffer.C @@ -0,0 +1,114 @@ +/** + * \file ControlCommandBuffer.C + * Copyright 1995-2002 the LyX Team + * Read the file COPYING + * + * \author Lars + * \author Asger and Juergen + * \author John Levon + */ + +#ifdef __GNUG__ +#pragma implementation +#endif + +#include "ControlCommandBuffer.h" +#include "support/lyxalgo.h" +#include "support/lstrings.h" +#include "LyXAction.h" +#include "lyxfunc.h" +#include "debug.h" + +using std::vector; +using std::back_inserter; +using std::transform; +using std::endl; + +extern LyXAction lyxaction; + +namespace { + +struct prefix_p { + string p; + prefix_p(string const & s) + : p(s) {} + bool operator()(string const & s) const { + return prefixIs(s, p); + } +}; + +} // end of anon namespace + + +ControlCommandBuffer::ControlCommandBuffer(LyXFunc & lf) + : lyxfunc_(lf), history_pos_(history_.end()) +{ + transform(lyxaction.func_begin(), lyxaction.func_end(), + back_inserter(commands_), lyx::firster()); +} + + +string const ControlCommandBuffer::historyUp() +{ + if (history_pos_ == history_.begin()) + return ""; + + return *(--history_pos_); +} + + +string const ControlCommandBuffer::historyDown() +{ + if (history_pos_ == history_.end()) + return ""; + if (history_pos_ + 1 == history_.end()) + return ""; + + return *(++history_pos_); +} + + +vector const ControlCommandBuffer::completions(string const & prefix, string & new_prefix) +{ + vector comp; + + lyx::copy_if(commands_.begin(), commands_.end(), + back_inserter(comp), prefix_p(prefix)); + + if (comp.empty()) { + new_prefix = prefix; + return comp; + } + + if (comp.size() == 1) { + new_prefix = comp[0]; + return vector(); + } + + // find maximal avaliable prefix + string const tmp = comp[0]; + string test(prefix); + if (tmp.length() > test.length()) + test += tmp[test.length()]; + while (test.length() < tmp.length()) { + vector vtmp; + lyx::copy_if(comp.begin(), comp.end(), + back_inserter(vtmp), prefix_p(test)); + if (vtmp.size() != comp.size()) { + test.erase(test.length() - 1); + break; + } + test += tmp[test.length()]; + } + + new_prefix = test; + return comp; +} + + +void ControlCommandBuffer::dispatch(string const & str) +{ + history_.push_back(str); + history_pos_ = history_.end(); + lyxfunc_.dispatch(str, true); +} diff --git a/src/frontends/controllers/ControlCommandBuffer.h b/src/frontends/controllers/ControlCommandBuffer.h new file mode 100644 index 0000000000..000786a1c4 --- /dev/null +++ b/src/frontends/controllers/ControlCommandBuffer.h @@ -0,0 +1,63 @@ +// -*- C++ -*- +/** + * \file ControlCommandBuffer.h + * Copyright 1995-2002 the LyX Team + * Read the file COPYING + * + * \author Lars + * \author Asger and Juergen + * \author John Levon + */ + +#ifndef CONTROLCOMMANDBUFFER_H +#define CONTROLCOMMANDBUFFER_H + +#include + +#include "LString.h" + +#include + +#ifdef __GNUG__ +#pragma interface +#endif + +class LyXFunc; + +/** + * ControlCommandBuffer + * + * This provides methods for the use of a toolkit's + * minibuffer/command buffer + */ +class ControlCommandBuffer { +public: + ControlCommandBuffer(LyXFunc & lf); + + /// return the previous history entry if any + string const historyUp(); + + /// return the next history entry if any + string const historyDown(); + + /// return the possible completions + std::vector const completions(string const & prefix, string & new_prefix); + + /// dispatch a command + void dispatch(string const & str); + +private: + /// controlling lyxfunc + LyXFunc & lyxfunc_; + + /// available command names + std::vector commands_; + + /// command history + std::vector history_; + + /// current position in command history + std::vector::const_iterator history_pos_; +}; + +#endif // CONTROLCOMMANDBUFFER_H diff --git a/src/frontends/controllers/Makefile.am b/src/frontends/controllers/Makefile.am index 0310f37bab..1639786496 100644 --- a/src/frontends/controllers/Makefile.am +++ b/src/frontends/controllers/Makefile.am @@ -36,6 +36,8 @@ libcontrollers_la_SOURCES= \ ControlCitation.h \ ControlCommand.C \ ControlCommand.h \ + ControlCommandBuffer.C \ + ControlCommandBuffer.h \ ControlConnections.C \ ControlConnections.h \ ControlDialog.h \ diff --git a/src/frontends/qt2/ChangeLog b/src/frontends/qt2/ChangeLog index a0de850626..3f75f43b0a 100644 --- a/src/frontends/qt2/ChangeLog +++ b/src/frontends/qt2/ChangeLog @@ -1,3 +1,7 @@ +2002-07-19 John Levon + + * QWorkArea.C: remove unnecessary include + 2002-07-18 John Levon * QtView.C: diff --git a/src/frontends/qt2/QWorkArea.C b/src/frontends/qt2/QWorkArea.C index b14372c1c0..37a83d54a8 100644 --- a/src/frontends/qt2/QWorkArea.C +++ b/src/frontends/qt2/QWorkArea.C @@ -14,7 +14,6 @@ #include "debug.h" #include "LyXView.h" -#include "lyxrc.h" // lyxrc.show_banner #include "version.h" // lyx_version #include "support/filetools.h" // LibFileSearch diff --git a/src/frontends/xforms/ChangeLog b/src/frontends/xforms/ChangeLog index 10645e7831..3ec1c34e3b 100644 --- a/src/frontends/xforms/ChangeLog +++ b/src/frontends/xforms/ChangeLog @@ -1,3 +1,17 @@ +2002-07-19 John Levon + + * DropDown.h: + * DropDown.C: remove unneeded LyXView * + + * XFormsView.h: + * XFormsView.C: changes for minibuffer rework + + * XMiniBuffer.h: + * XMiniBuffer.C: use ControlCommandBuffer. Move relevant + old code to here + + * lyx_gui.C: add FIXME + 2002-07-19 John Levon * FormMathsDelim.C: diff --git a/src/frontends/xforms/DropDown.C b/src/frontends/xforms/DropDown.C index 837cbea2d4..6fe29e7788 100644 --- a/src/frontends/xforms/DropDown.C +++ b/src/frontends/xforms/DropDown.C @@ -20,7 +20,6 @@ #include #include - #ifndef CXX_GLOBAL_CSTD using std::isprint; #endif @@ -46,8 +45,7 @@ extern "C" int C_PeekCB(FL_FORM * form, void *xev) } // namespace anon -DropDown::DropDown(LyXView * lv, FL_OBJECT * ob) - : lv_(lv) +DropDown::DropDown(FL_OBJECT * ob) { form_ = fl_bgn_form(FL_NO_BOX, ob->w, 100); fl_add_box(FL_UP_BOX, 0, 0, ob->w, 100, ""); diff --git a/src/frontends/xforms/DropDown.h b/src/frontends/xforms/DropDown.h index fd332c55a8..fb8b35d885 100644 --- a/src/frontends/xforms/DropDown.h +++ b/src/frontends/xforms/DropDown.h @@ -22,12 +22,10 @@ #include "LString.h" #include -class LyXView; - class DropDown { public: /// constructor - DropDown(LyXView * lv, FL_OBJECT * ob); + DropDown(FL_OBJECT * ob); /// destructor ~DropDown(); @@ -56,9 +54,6 @@ private: /// move down a browser line void line_down(); - /// owning lyxview - LyXView * lv_; - /// our form FL_FORM * form_; diff --git a/src/frontends/xforms/XFormsView.C b/src/frontends/xforms/XFormsView.C index 6c1ee6c847..88251fc5b2 100644 --- a/src/frontends/xforms/XFormsView.C +++ b/src/frontends/xforms/XFormsView.C @@ -19,7 +19,6 @@ #if FL_VERSION < 1 && (FL_REVISION < 89 || (FL_REVISION == 89 && FL_FIXLEVEL < 5)) #include "frontends/xforms/lyxlookup.h" #endif -#include "frontends/MiniBuffer.h" #include "frontends/xforms/XMiniBuffer.h" #include "debug.h" #include "intl.h" @@ -63,11 +62,8 @@ XFormsView::XFormsView(int width, int height) create_form_form_main(*getDialogs(), width, height); fl_set_form_atclose(getForm(), C_XFormsView_atCloseMainFormCB, 0); - // Connect the minibuffer signals - minibuffer_->inputReady.connect(boost::bind(&XFormsView::dispatch, this, _1)); - view_state_changed.connect(boost::bind(&XFormsView::show_view_state, this)); - minibuffer_->timeout.connect(boost::bind(&XFormsView::show_view_state, this)); + focus_command_buffer.connect(boost::bind(&XMiniBuffer::focus, minibuffer_.get())); // Make sure the buttons are disabled if needed. updateToolbar(); @@ -77,25 +73,18 @@ XFormsView::XFormsView(int width, int height) XFormsView::~XFormsView() { + minibuffer_->freeze(); fl_hide_form(form_); fl_free_form(form_); } -void XFormsView::dispatch(string const & arg) -{ - getLyXFunc()->dispatch(arg, true); -} - - /// Redraw the main form. void XFormsView::redraw() { lyxerr[Debug::INFO] << "XFormsView::redraw()" << endl; fl_redraw_form(getForm()); - // This is dangerous, but we know it is safe - XMiniBuffer * m = static_cast(minibuffer_.get()); - m->redraw(); + minibuffer_->redraw(); } @@ -168,8 +157,8 @@ void XFormsView::create_form_form_main(Dialogs & dia, int width, int height) width - 3 * air, workheight)); ::current_view = bufferview_.get(); - minibuffer_.reset(new XMiniBuffer(this, air, height - (25 + air), - width - (2 * air), 25)); + minibuffer_.reset(new XMiniBuffer(this, *controlcommand_, + air, height - (25 + air), width - (2 * air), 25)); // FIXME: why do this in xforms/ ? autosave_timeout_->timeout.connect(boost::bind(&XFormsView::autoSave, this)); @@ -195,8 +184,7 @@ void XFormsView::create_form_form_main(Dialogs & dia, int width, int height) fl_end_form(); - // This is dangerous, but we know it is safe in this situation - static_cast(minibuffer_.get())->dd_init(); + minibuffer_->dd_init(); } @@ -207,9 +195,15 @@ void XFormsView::setWindowTitle(string const & title, string const & icon_title) } +void XFormsView::message(string const & str) +{ + minibuffer_->message(str); +} + + void XFormsView::show_view_state() { - minibuffer_->message(getLyXFunc()->view_status_message()); + message(getLyXFunc()->view_status_message()); } diff --git a/src/frontends/xforms/XFormsView.h b/src/frontends/xforms/XFormsView.h index c41276cdc9..81c9e52139 100644 --- a/src/frontends/xforms/XFormsView.h +++ b/src/frontends/xforms/XFormsView.h @@ -21,6 +21,7 @@ #include "frontends/LyXView.h" class Dialogs; +class XMiniBuffer; /** * XFormsView - xforms implementation of LyXView @@ -54,9 +55,9 @@ public: /// callback for close event from window manager static int atCloseMainFormCB(FL_FORM *, void *); - /// dispatch an action - void dispatch(string const & arg); - + /// display a status message + virtual void message(string const & str); + private: /** * setWindowTitle - set title of window @@ -70,6 +71,8 @@ private: /// makes the main form. void create_form_form_main(Dialogs & d, int width, int height); + /// the minibuffer + boost::scoped_ptr minibuffer_; /// the main form. FL_FORM * form_; }; diff --git a/src/frontends/xforms/XMiniBuffer.C b/src/frontends/xforms/XMiniBuffer.C index 790a16234e..e9e1f4f4dc 100644 --- a/src/frontends/xforms/XMiniBuffer.C +++ b/src/frontends/xforms/XMiniBuffer.C @@ -16,46 +16,37 @@ #include "frontends/xforms/DropDown.h" #include "frontends/xforms/XFormsView.h" +#include "frontends/controllers/ControlCommandBuffer.h" #include "frontends/Timeout.h" #include "XMiniBuffer.h" -#include "BufferView.h" -#include "LyXAction.h" #include "gettext.h" -#include "support/lyxalgo.h" -#include "support/lstrings.h" +#include "debug.h" +#include "bufferview_funcs.h" #include #include -#include #ifndef CXX_GLOBAL_CSTD using std::isprint; #endif +using std::endl; using std::vector; -namespace { - -struct prefix { - string p; - prefix(string const & s) - : p(s) {} - bool operator()(string const & s) const { - return prefixIs(s, p); - } -}; - -} // end of anon namespace - - -XMiniBuffer::XMiniBuffer(LyXView * o, FL_Coord x, FL_Coord y, - FL_Coord h, FL_Coord w) - : MiniBuffer(o) +XMiniBuffer::XMiniBuffer(XFormsView * v, ControlCommandBuffer & control, + FL_Coord x, FL_Coord y, FL_Coord h, FL_Coord w) + : controller_(control), view_(v), + info_suffix_shown_(false) { - create_input_box(FL_NORMAL_INPUT, x, y, h, w); + input_obj_ = create_input_box(FL_NORMAL_INPUT, x, y, h, w); + suffix_timer_.reset(new Timeout(1500)); + idle_timer_.reset(new Timeout(6000)); + suffix_timer_->timeout.connect(boost::bind(&XMiniBuffer::suffix_timeout, this)); + idle_timer_->timeout.connect(boost::bind(&XMiniBuffer::idle_timeout, this)); + idle_timer_->start(); messageMode(); } @@ -63,7 +54,7 @@ XMiniBuffer::XMiniBuffer(LyXView * o, FL_Coord x, FL_Coord y, // thanks for nothing, xforms (recursive creation not allowed) void XMiniBuffer::dd_init() { - dropdown_ = new DropDown(owner_, the_buffer); + dropdown_.reset(new DropDown(the_buffer_)); dropdown_->result.connect(boost::bind(&XMiniBuffer::set_complete_input, this, _1)); dropdown_->keypress.connect(boost::bind(&XMiniBuffer::append_char, this, _1)); } @@ -71,7 +62,6 @@ void XMiniBuffer::dd_init() XMiniBuffer::~XMiniBuffer() { - delete dropdown_; } @@ -85,112 +75,86 @@ int XMiniBuffer::peek_event(FL_OBJECT * ob, int event, #endif switch (event) { + case FL_FOCUS: + messageMode(false); + break; case FL_UNFOCUS: messageMode(); break; case FL_KEYBOARD: { string input; - if (information_displayed_) { - information_timer_->stop(); - input = stored_input; - restore_input(); - } else { - char const * tmp = fl_get_input(ob); - input = tmp ? tmp : ""; + if (info_suffix_shown_) { + suffix_timer_->stop(); + suffix_timeout(); } - + + char const * tmp = fl_get_input(ob); + input = tmp ? tmp : ""; switch (key) { case XK_Down: #ifdef XK_KP_Down case XK_KP_Down: #endif - if (hist_iter != history_->end()) { - ++hist_iter; - } - if (hist_iter == history_->end()) { - // no further history - show_information(_("[End of history]"), input); + { + string const h(controller_.historyDown()); + if (h.empty()) { + show_info_suffix(_("[End of history]"), input); } else { - set_input((*hist_iter)); + set_input(h); } return 1; + } + case XK_Up: #ifdef XK_KP_Up case XK_KP_Up: #endif - if (hist_iter == history_->begin()) { - // no further history - show_information(_("[Beginning of history]"), - input); + { + string const h(controller_.historyUp()); + if (h.empty()) { + show_info_suffix(_("[Beginning of history]"), input); } else { - --hist_iter; - set_input((*hist_iter)); + set_input(h); } return 1; + } + case 9: case XK_Tab: { - // Completion handling. - - vector comp; - lyx::copy_if(completion_.begin(), - completion_.end(), - back_inserter(comp), prefix(input)); + string new_input; + vector comp = controller_.completions(input, new_input); + + if (comp.empty() && new_input == input) { + show_info_suffix(_("[no match]"), input); + break; + } if (comp.empty()) { - // No matches - string const tmp = input + _(" [no match]"); - show_information(tmp, input); - } else if (comp.size() == 1) { - // Perfect match - string const tmp = - comp[0] + _(" [sole completion]"); - show_information(tmp, comp[0] + " "); - } else { - // More that one match - // Find maximal avaliable prefix - string const tmp = comp[0]; - string test(input); - if (tmp.length() > test.length()) - test += tmp[test.length()]; - while (test.length() < tmp.length()) { - vector vtmp; - lyx::copy_if(comp.begin(), - comp.end(), - back_inserter(vtmp), - prefix(test)); - if (vtmp.size() != comp.size()) { - test.erase(test.length() - 1); - break; - } - test += tmp[test.length()]; - } - set_input(test); - - int x,y,w,h; - fl_get_wingeometry(fl_get_real_object_window(the_buffer), - &x, &y, &w, &h); - - // asynchronous completion - int const air = the_buffer->x; - x += air; - y += h - (the_buffer->h + air); - w = the_buffer->w; - dropdown_->select(comp, x, y, w); + set_input(new_input); + show_info_suffix(("[only completion]"), new_input + " "); + break; } + + set_input(new_input); + + int x,y,w,h; + fl_get_wingeometry(fl_get_real_object_window(the_buffer_), + &x, &y, &w, &h); + + // asynchronous completion + int const air = the_buffer_->x; + x += air; + y += h - (the_buffer_->h + air); + w = the_buffer_->w; + dropdown_->select(comp, x, y, w); return 1; } case 27: case XK_Escape: - // Abort -#if 0 - owner_->view()->focus(true); -#endif - message_timeout(); messageMode(); - //escape.emit(); return 1; case 13: case XK_Return: @@ -210,18 +174,12 @@ int XMiniBuffer::peek_event(FL_OBJECT * ob, int event, if (cit == completion_.end()) { // no such func/item string const tmp = input + _(" [no match]"); - show_information(tmp, input); + show_info_suffix(tmp, input); } else { #endif - // Return the inputted string - messageMode(); -#if 0 - owner_->view()->focus(true); -#endif - if (!input.empty()) { - history_->push_back(input); - } - inputReady(input); + messageMode(); + redraw(); + controller_.dispatch(input); # if 0 } #endif @@ -232,7 +190,6 @@ int XMiniBuffer::peek_event(FL_OBJECT * ob, int event, } } default: - //lyxerr << "Unhandled minibuffer event!" << endl; break; } @@ -251,7 +208,6 @@ extern "C" { return mini->peek_event(ob, event, key, static_cast(xev)); } - } @@ -260,7 +216,7 @@ FL_OBJECT * XMiniBuffer::create_input_box(int type, FL_Coord x, FL_Coord y, { FL_OBJECT * obj; - the_buffer = obj = fl_add_input(type, x, y, w, h, text.c_str()); + the_buffer_ = obj = fl_add_input(type, x, y, w, h, ""); fl_set_object_boxtype(obj, FL_DOWN_BOX); fl_set_object_resize(obj, FL_RESIZE_ALL); fl_set_object_gravity(obj, SouthWestGravity, SouthEastGravity); @@ -272,37 +228,67 @@ FL_OBJECT * XMiniBuffer::create_input_box(int type, FL_Coord x, FL_Coord y, obj->u_vdata = this; obj->wantkey = FL_KEY_TAB; - set_input(text); - return obj; } +void XMiniBuffer::freeze() +{ + // we must prevent peek_event, or we get an unfocus() when the + // containing form gets destroyed + fl_set_object_prehandler(input_obj_, 0); +} + + +void XMiniBuffer::show_info_suffix(string const & suffix, string const & input) +{ + stored_input_ = input; + info_suffix_shown_ = true; + set_input(input + " " + suffix); + suffix_timer_->start(); +} + + +void XMiniBuffer::idle_timeout() +{ + set_input(currentState(view_->view())); +} + + +void XMiniBuffer::suffix_timeout() +{ + info_suffix_shown_ = false; + set_input(stored_input_); +} + + bool XMiniBuffer::isEditingMode() const { - return the_buffer->focus; + return the_buffer_->focus; } -void XMiniBuffer::editingMode() +void XMiniBuffer::messageMode(bool on) { - fl_activate_object(the_buffer); - fl_set_focus_object(static_cast(owner_)->getForm(), - the_buffer); - redraw(); -} - - -void XMiniBuffer::messageMode() -{ - fl_deactivate_object(the_buffer); - redraw(); + set_input(""); + if (!on) { + fl_activate_object(the_buffer_); + fl_set_focus_object(view_->getForm(), the_buffer_); + redraw(); + idle_timer_->stop(); + } else { + if (isEditingMode()) { + // focus back to the workarea + fl_set_focus_object(view_->getForm(), 0); + idle_timer_->start(); + } + } } void XMiniBuffer::redraw() { - fl_redraw_object(the_buffer); + fl_redraw_object(the_buffer_); XFlush(fl_display); } @@ -312,16 +298,33 @@ void XMiniBuffer::append_char(char c) if (!c || !isprint(c)) return; - char const * tmp = fl_get_input(the_buffer); + char const * tmp = fl_get_input(the_buffer_); string str = tmp ? tmp : ""; str += c; - fl_set_input(the_buffer, str.c_str()); + fl_set_input(the_buffer_, str.c_str()); +} + + +void XMiniBuffer::set_complete_input(string const & str) +{ + if (!str.empty()) { + // add a space so the user can type + // an argument immediately + set_input(str + " "); + } +} + + +void XMiniBuffer::message(string const & str) +{ + if (!isEditingMode()) + set_input(str); } - + void XMiniBuffer::set_input(string const & str) { - fl_set_input(the_buffer, str.c_str()); + fl_set_input(the_buffer_, str.c_str()); } diff --git a/src/frontends/xforms/XMiniBuffer.h b/src/frontends/xforms/XMiniBuffer.h index eb75980db4..f48ada3a0c 100644 --- a/src/frontends/xforms/XMiniBuffer.h +++ b/src/frontends/xforms/XMiniBuffer.h @@ -6,64 +6,107 @@ * * \author Lars * \author Asger and Juergen + * \author John Levon */ #ifndef XMINIBUFFER_H #define XMINIBUFFER_H -#include "frontends/MiniBuffer.h" - #include FORMS_H_LOCATION +#include + #ifdef __GNUG__ #pragma interface #endif class DropDown; +class ControlCommandBuffer; +class Timeout; -/// -class XMiniBuffer : public MiniBuffer { +/// in xforms, the minibuffer is both a status bar and a command buffer +class XMiniBuffer { public: - /// - XMiniBuffer(LyXView * o, + XMiniBuffer(XFormsView * o, ControlCommandBuffer & control, FL_Coord x, FL_Coord y, FL_Coord h, FL_Coord w); - /// destructor ~XMiniBuffer(); /// create drop down void dd_init(); - /// + /// repaint the minibuffer void redraw(); - /// + /// command completion, history, etc. management int peek_event(FL_OBJECT *, int, int, XEvent * xev); + /// show a message + void message(string const & str); + + /// focus the buffer for editing mode + void focus() { messageMode(false); } + + /// disable event management + void freeze(); + protected: /// Are we in editing mode? - virtual bool isEditingMode() const; - /// enter editing mode - virtual void editingMode(); - /// enter message display mode - virtual void messageMode(); + bool isEditingMode() const; + /// reset buffer to stored input text + void suffix_timeout(); + + /// go back to "at rest" message + void idle_timeout(); + /** * Append "c" to the current input contents when the completion * list is displayed and has focus. */ void append_char(char c); + + /// completion selection callback + void set_complete_input(string const & str); /// set the minibuffer content in editing mode - virtual void set_input(string const &); + void set_input(string const &); /// This creates the input widget for the minibuffer FL_OBJECT * create_input_box(int, FL_Coord, FL_Coord, FL_Coord, FL_Coord); - /// the dropdown menu - DropDown * dropdown_; + /// go into message mode + void messageMode(bool on = true); + + /// show a temporary message whilst in edit mode + void show_info_suffix(string const & suffix, string const & input); + /// the dropdown menu + boost::scoped_ptr dropdown_; + + /// info suffix timer + boost::scoped_ptr suffix_timer_; + + /// idle timer + boost::scoped_ptr idle_timer_; + /// This is the input widget object - FL_OBJECT * the_buffer; + FL_OBJECT * the_buffer_; + + /// the input box + FL_OBJECT * input_obj_; + + /// the controller we use + ControlCommandBuffer & controller_; + + /// the lyx view + XFormsView * view_; + + /// stored input when showing suffix info + string stored_input_; + + /// are we showing an informational suffix of the mesage ? + bool info_suffix_shown_; }; -#endif + +#endif // XMINIBUFFER_H diff --git a/src/frontends/xforms/lyx_gui.C b/src/frontends/xforms/lyx_gui.C index 614c02622b..7d5139fb9a 100644 --- a/src/frontends/xforms/lyx_gui.C +++ b/src/frontends/xforms/lyx_gui.C @@ -304,7 +304,7 @@ void lyx_gui::start(string const & batch, vector files) } } - // FIXME + // FIXME: breaks emergencyCleanup delete lyxserver; } diff --git a/src/lyxfunc.C b/src/lyxfunc.C index 74b7baf41a..e658408d1a 100644 --- a/src/lyxfunc.C +++ b/src/lyxfunc.C @@ -33,7 +33,6 @@ #include "trans_mgr.h" #include "layout.h" #include "bufferview_funcs.h" -#include "frontends/MiniBuffer.h" #include "frontends/LyXView.h" #include "frontends/lyx_gui.h" #include "vspace.h" @@ -914,14 +913,8 @@ void LyXFunc::dispatch(kb_action action, string argument, bool verbose) // --- Misc ------------------------------------------- case LFUN_EXEC_COMMAND: - { - vector allCmds; - transform(lyxaction.func_begin(), lyxaction.func_end(), - back_inserter(allCmds), lyx::firster()); - static vector hist; - owner->getMiniBuffer()->prepareForInput(allCmds, hist); - } - break; + owner->focus_command_buffer(); + break; case LFUN_CANCEL: // RVDK_PATCH_5 keyseq.reset(); @@ -1370,10 +1363,10 @@ void LyXFunc::dispatch(kb_action action, string argument, bool verbose) // passthrough hat and underscore outside mathed: case LFUN_SUBSCRIPT: - dispatch(LFUN_SELFINSERT, "_"); + dispatch(LFUN_SELFINSERT, string("_")); break; case LFUN_SUPERSCRIPT: - dispatch(LFUN_SELFINSERT, "^"); + dispatch(LFUN_SELFINSERT, string("^")); break; case LFUN_MATH_PANEL: