From: Lars Gullik Bjønnes Date: Wed, 5 Apr 2006 22:56:18 +0000 (+0000) Subject: 2006-04-06 Bo Peng X-Git-Tag: 1.6.10~13401 X-Git-Url: https://git.lyx.org/gitweb/?a=commitdiff_plain;h=b2effebe209af199a591ee8666bf462b2a3b712b;p=lyx.git 2006-04-06 Bo Peng session support that * handle recent opened files (previously lastfile) * save/load bookmarks when quit lyx * save/load buffer cursor location whan a file is closed * save/load windows position and size when a file is closed * add rc entries load_session, use_lastfilepos, screen_geometry_height, screen_geometry_width, screen_geometry_xysaved. * trigger LFUN_QUIT when Alt-F4 or close-button is used to close lyx. * remove lastfile.h lastfile.C (merged in session.h, session.C) git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@13561 a592a061-630c-0410-9148-cb99ea01b6c8 --- diff --git a/src/BufferView.C b/src/BufferView.C index d5160a7420..aa4ff6fcb3 100644 --- a/src/BufferView.C +++ b/src/BufferView.C @@ -188,6 +188,10 @@ bool BufferView::isSavedPosition(unsigned int i) return pimpl_->isSavedPosition(i); } +void BufferView::saveSavedPositions() +{ + return pimpl_->saveSavedPositions(); +} void BufferView::switchKeyMap() { diff --git a/src/BufferView.h b/src/BufferView.h index 2940d77586..95910a97f1 100644 --- a/src/BufferView.h +++ b/src/BufferView.h @@ -120,6 +120,8 @@ public: void restorePosition(unsigned int i); /// does the given bookmark have a saved position ? bool isSavedPosition(unsigned int i); + /// save bookmarks to .lyx/session + void saveSavedPositions(); /// return the current change at the cursor Change const getCurrentChange(); diff --git a/src/BufferView_pimpl.C b/src/BufferView_pimpl.C index d75f1730bb..061f9385a9 100644 --- a/src/BufferView_pimpl.C +++ b/src/BufferView_pimpl.C @@ -42,7 +42,7 @@ #include "lyxfunc.h" #include "lyxtext.h" #include "lyxrc.h" -#include "lastfiles.h" +#include "session.h" #include "metricsinfo.h" #include "paragraph.h" #include "paragraph_funcs.h" @@ -170,6 +170,14 @@ BufferView::Pimpl::Pimpl(BufferView & bv, LyXView * owner, .connect(boost::bind(&BufferView::Pimpl::cursorToggle, this)); cursor_timeout.start(); saved_positions.resize(saved_positions_num); + // load saved bookmarks + lyx::Session::BookmarkList & bmList = LyX::ref().session().loadBookmarks(); + for (lyx::Session::BookmarkList::iterator bm = bmList.begin(); + bm != bmList.end(); ++bm) + if (bm->get<0>() < saved_positions_num) + saved_positions[bm->get<0>()] = Position( bm->get<1>(), bm->get<2>(), bm->get<3>() ); + // and then clear them + bmList.clear(); } @@ -294,9 +302,31 @@ bool BufferView::Pimpl::loadLyXFile(string const & filename, bool tolastfiles) setBuffer(b); bv_->showErrorList(_("Parse")); + + // scroll to the position when the file was last closed + if (lyxrc.use_lastfilepos) { + lyx::pit_type pit; + lyx::pos_type pos; + boost::tie(pit, pos) = LyX::ref().session().loadFilePosition(s); + // I am not sure how to separate the following part to a function + // so I will leave this to Lars. + // + // check pit since the document may be externally changed. + if ( static_cast(pit) < b->paragraphs().size() ) { + ParIterator it = b->par_iterator_begin(); + ParIterator const end = b->par_iterator_end(); + for (; it != end; ++it) + if (it.pit() == pit) { + // restored pos may be bigger than it->size + bv_->setCursor(makeDocIterator(it, min(pos, it->size()))); + bv_->update(Update::FitCursor); + break; + } + } + } if (tolastfiles) - LyX::ref().lastfiles().newFile(b->fileName()); + LyX::ref().session().addLastFile(b->fileName()); return true; } @@ -332,6 +362,9 @@ void BufferView::Pimpl::setBuffer(Buffer * b) // to this buffer later on. buffer_->saveCursor(cursor_.selectionBegin(), cursor_.selectionEnd()); + // current buffer is going to be switched-off, save cursor pos + LyX::ref().session().saveFilePosition(buffer_->fileName(), + boost::tie(cursor_.pit(), cursor_.pos()) ); } // If we are closing current buffer, switch to the first in @@ -812,6 +845,22 @@ bool BufferView::Pimpl::isSavedPosition(unsigned int i) } +void BufferView::Pimpl::saveSavedPositions() +{ + // save bookmarks. It is better to use the pit interface + // but I do not know how to effectively convert between + // par_id and pit. + for (unsigned int i=1; i < saved_positions_num; ++i) { + if ( isSavedPosition(i) ) + LyX::ref().session().saveBookmark( boost::tie( + i, + saved_positions[i].filename, + saved_positions[i].par_id, + saved_positions[i].par_pos) ); + } +} + + void BufferView::Pimpl::switchKeyMap() { if (!lyxrc.rtl_support) diff --git a/src/BufferView_pimpl.h b/src/BufferView_pimpl.h index c6ac78f6f7..8c4393516f 100644 --- a/src/BufferView_pimpl.h +++ b/src/BufferView_pimpl.h @@ -95,6 +95,8 @@ public: void restorePosition(unsigned int i); /// bool isSavedPosition(unsigned int i); + /// save bookmarks to .lyx/session + void saveSavedPositions(); /// void switchKeyMap(); /// diff --git a/src/Makefile.am b/src/Makefile.am index 58afae3063..4ed39157ff 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -190,8 +190,8 @@ lyx_SOURCES = \ kbsequence.h \ language.C \ language.h \ - lastfiles.C \ - lastfiles.h \ + session.C \ + session.h \ layout.h \ lengthcommon.C \ lengthcommon.h \ diff --git a/src/MenuBackend.C b/src/MenuBackend.C index 44789444a7..58e4b26683 100644 --- a/src/MenuBackend.C +++ b/src/MenuBackend.C @@ -30,7 +30,7 @@ #include "gettext.h" #include "importer.h" #include "kbmap.h" -#include "lastfiles.h" +#include "session.h" #include "LyXAction.h" #include "lyx_main.h" // for lastfiles #include "lyxfunc.h" @@ -428,13 +428,12 @@ string const limit_string_length(string const & str) void expandLastfiles(Menu & tomenu, LyXView const * view) { - LastFiles const & lastfiles = LyX::cref().lastfiles(); + lyx::Session::LastFiles const & lf = LyX::cref().session().lastFiles(); + lyx::Session::LastFiles::const_iterator lfit = lf.begin(); int ii = 1; - LastFiles::const_iterator lfit = lastfiles.begin(); - LastFiles::const_iterator end = lastfiles.end(); - for (; lfit != end && ii < 10; ++lfit, ++ii) { + for (; lfit != lf.end() && ii < 10; ++lfit, ++ii) { string const label = convert(ii) + ". " + MakeDisplayPath((*lfit), 30) + '|' + convert(ii); diff --git a/src/bufferlist.C b/src/bufferlist.C index da708c72e1..a4d2d6a0fd 100644 --- a/src/bufferlist.C +++ b/src/bufferlist.C @@ -17,7 +17,7 @@ #include "bufferparams.h" #include "debug.h" #include "gettext.h" -#include "lastfiles.h" +#include "session.h" #include "lyx_cb.h" #include "lyx_main.h" #include "output_latex.h" @@ -187,7 +187,7 @@ bool BufferList::close(Buffer * buf, bool const ask) if (!WriteAs(buf)) return false; } else if (buf->save()) { - LyX::ref().lastfiles().newFile(buf->fileName()); + LyX::ref().session().addLastFile(buf->fileName()); } else { return false; } diff --git a/src/frontends/gtk/GView.C b/src/frontends/gtk/GView.C index 6889516db3..8d41e47b40 100644 --- a/src/frontends/gtk/GView.C +++ b/src/frontends/gtk/GView.C @@ -24,12 +24,17 @@ #include "BufferView.h" #include "lyx_cb.h" +#include "lyxrc.h" +#include "lyx_main.h" +#include "session.h" #include "lyxfunc.h" #include "MenuBackend.h" +#include "funcrequest.h" #include "frontends/Toolbars.h" #include "support/filetools.h" +#include "support/convert.h" #include @@ -95,7 +100,24 @@ GView::GView() boost::bind(&GMiniBuffer::editMode, minibuffer_.get())); view_state_changed.connect(boost::bind(&GView::showViewState, this)); signal_focus_in_event().connect(sigc::mem_fun(*this, &GView::onFocusIn)); - set_default_size(750, 550); + // + int width = 750; + int height = 550; + // first try lyxrc + if (lyxrc.geometry_width != 0 && lyxrc.geometry_height != 0 ) { + width = lyxrc.geometry_width; + height = lyxrc.geometry_height; + } + // if lyxrc returns (0,0), then use session info + else { + string val = LyX::ref().session().loadSessionInfo("WindowWidth"); + if (val != "") + width = convert(val); + val = LyX::ref().session().loadSessionInfo("WindowHeight"); + if (val != "") + height = convert(val); + } + set_default_size(width, height); // Make sure the buttons are disabled if needed. updateToolbars(); string const iconName = @@ -117,7 +139,14 @@ Gtk::Box & GView::getBox(Position pos) bool GView::on_delete_event(GdkEventAny * /*event*/) { - QuitLyX(false); + // save windows size and position + Gtk::Requisition req = workArea_->size_request(); + LyX::ref().session().saveSessionInfo("WindowWidth", convert(req.width)); + LyX::ref().session().saveSessionInfo("WindowHeight", convert(req.height)); + // trigger LFUN_QUIT instead of quit directly + // since LFUN_QUIT may have more cleanup stuff + // + getLyXFunc().dispatch(FuncRequest(LFUN_QUIT)); return true; } diff --git a/src/frontends/qt2/QPrefs.C b/src/frontends/qt2/QPrefs.C index e6f97c8a85..8bdb6d0879 100644 --- a/src/frontends/qt2/QPrefs.C +++ b/src/frontends/qt2/QPrefs.C @@ -35,7 +35,7 @@ #include "ui/QPrefIdentityModule.h" #include "debug.h" -#include "lastfiles.h" +#include "session.h" #include "LColor.h" #include "lyxfont.h" diff --git a/src/frontends/qt2/QtView.C b/src/frontends/qt2/QtView.C index 7f7e98c490..b83a767e4b 100644 --- a/src/frontends/qt2/QtView.C +++ b/src/frontends/qt2/QtView.C @@ -13,12 +13,17 @@ #include "BufferView.h" #include "lyx_cb.h" +#include "lyxrc.h" +#include "lyx_main.h" +#include "session.h" #include "lyxfunc.h" #include "MenuBackend.h" +#include "funcrequest.h" #include "frontends/Toolbars.h" #include "support/filetools.h" +#include "support/convert.h" #include @@ -155,7 +160,16 @@ bool QtView::hasFocus() const void QtView::closeEvent(QCloseEvent *) { - QuitLyX(false); + // save windows size and position + LyX::ref().session().saveSessionInfo("WindowWidth", convert(width())); + LyX::ref().session().saveSessionInfo("WindowHeight", convert(height())); + if (lyxrc.geometry_xysaved) { + LyX::ref().session().saveSessionInfo("WindowPosX", convert(x())); + LyX::ref().session().saveSessionInfo("WindowPosY", convert(y())); + } + // trigger LFUN_QUIT instead of quit directly + // since LFUN_QUIT may have more cleanup stuff + getLyXFunc().dispatch(FuncRequest(LFUN_QUIT)); } diff --git a/src/frontends/qt2/lyx_gui.C b/src/frontends/qt2/lyx_gui.C index 360c8be666..e676c4a2fe 100644 --- a/src/frontends/qt2/lyx_gui.C +++ b/src/frontends/qt2/lyx_gui.C @@ -25,10 +25,12 @@ #include "lyxrc.h" #include "lyxserver.h" #include "lyxsocket.h" +#include "session.h" #include "graphics/LoaderQueue.h" #include "support/lstrings.h" +#include "support/convert.h" #include "support/os.h" #include "support/package.h" #include "debug.h" @@ -224,11 +226,37 @@ void start(string const & batch, vector const & files) // initial geometry unsigned int width = 690; unsigned int height = 510; + // first try lyxrc + if (lyxrc.geometry_width != 0 && lyxrc.geometry_height != 0 ) { + width = lyxrc.geometry_width; + height = lyxrc.geometry_height; + } + // if lyxrc returns (0,0), then use session info + else { + string val = LyX::ref().session().loadSessionInfo("WindowWidth"); + if (val != "") + width = convert(val); + val = LyX::ref().session().loadSessionInfo("WindowHeight"); + if (val != "") + height = convert(val); + } boost::shared_ptr view_ptr(new QtView(width, height)); LyX::ref().addLyXView(view_ptr); QtView & view = *view_ptr.get(); + + // if user wants to restore window position + if (lyxrc.geometry_xysaved) { + QPoint p = view.pos(); + string val = LyX::ref().session().loadSessionInfo("WindowPosX"); + if (val != "") + p.setX(convert(val)); + val = LyX::ref().session().loadSessionInfo("WindowPosY"); + if (val != "") + p.setY(convert(val)); + view.move(p); + } view.show(); view.init(); diff --git a/src/frontends/qt4/QPrefs.C b/src/frontends/qt4/QPrefs.C index 5499c3c1c3..5389b4ca02 100644 --- a/src/frontends/qt4/QPrefs.C +++ b/src/frontends/qt4/QPrefs.C @@ -18,7 +18,6 @@ #include "qt_helpers.h" #include "debug.h" -#include "lastfiles.h" #include "LColor.h" #include "lyxfont.h" diff --git a/src/frontends/qt4/QPrefsDialog.C b/src/frontends/qt4/QPrefsDialog.C index 6b7bfd01c1..c7ef7a4b9a 100644 --- a/src/frontends/qt4/QPrefsDialog.C +++ b/src/frontends/qt4/QPrefsDialog.C @@ -18,7 +18,7 @@ #include "qt_helpers.h" #include "debug.h" -#include "lastfiles.h" +#include "session.h" #include "LColor.h" #include "lyxfont.h" diff --git a/src/frontends/qt4/QtView.C b/src/frontends/qt4/QtView.C index ed8c628ec5..def0043f13 100644 --- a/src/frontends/qt4/QtView.C +++ b/src/frontends/qt4/QtView.C @@ -14,8 +14,13 @@ #include "BufferView.h" #include "lyx_cb.h" +#include "lyx_rc.h" +#include "lyx_main.h" +#include "session.h" #include "lyxfunc.h" #include "MenuBackend.h" +#include "funcrequest.h" +#include "funcrequest.h" #include "debug.h" @@ -23,6 +28,7 @@ #include "support/filetools.h" +#include "support/convert.h" #include #include "QtView.h" @@ -173,7 +179,16 @@ bool QtView::hasFocus() const void QtView::closeEvent(QCloseEvent *) { - QuitLyX(false); + // save windows size and position + LyX::ref().session().saveSessionInfo("WindowWidth", convert(width())); + LyX::ref().session().saveSessionInfo("WindowHeight", convert(height())); + if (lyxrc.geometry_xysaved) { + LyX::ref().session().saveSessionInfo("WindowPosX", convert(x())); + LyX::ref().session().saveSessionInfo("WindowPosY", convert(y())); + } + // trigger LFUN_QUIT instead of quit directly + // since LFUN_QUIT may have more cleanup stuff + getLyXFunc().dispatch(FuncRequest(LFUN_QUIT)); } diff --git a/src/frontends/qt4/lyx_gui.C b/src/frontends/qt4/lyx_gui.C index 60084c5ffc..c100257415 100644 --- a/src/frontends/qt4/lyx_gui.C +++ b/src/frontends/qt4/lyx_gui.C @@ -218,11 +218,37 @@ void start(string const & batch, vector const & files) // initial geometry unsigned int width = 690; unsigned int height = 510; + // first try lyxrc + if (lyxrc.geometry_width != 0 && lyxrc.geometry_height != 0 ) { + width = lyxrc.geometry_width; + height = lyxrc.geometry_height; + } + // if lyxrc returns (0,0), then use session info + else { + string val = LyX::ref().session().loadSessionInfo("WindowWidth"); + if (val != "") + width = convert(val); + val = LyX::ref().session().loadSessionInfo("WindowHeight"); + if (val != "") + height = convert(val); + } boost::shared_ptr view_ptr(new QtView(width, height)); LyX::ref().addLyXView(view_ptr); QtView & view = *view_ptr.get(); + + // if user wants to restore window position + if (lyxrc.geometry_xysaved) { + QPoint p = view.pos(); + string val = LyX::ref().session().loadSessionInfo("WindowPosX"); + if (val != "") + p.setX(convert(val)); + val = LyX::ref().session().loadSessionInfo("WindowPosY"); + if (val != "") + p.setY(convert(val)); + view.move(p); + } view.show(); view.init(); diff --git a/src/frontends/xforms/FormPreferences.C b/src/frontends/xforms/FormPreferences.C index 04f78aef1a..715f0cc109 100644 --- a/src/frontends/xforms/FormPreferences.C +++ b/src/frontends/xforms/FormPreferences.C @@ -24,7 +24,7 @@ #include "controllers/helper_funcs.h" // getSecond #include "buffer.h" -#include "lastfiles.h" +#include "session.h" #include "LColor.h" #include "lyxfont.h" #include "frontends/lyx_gui.h" @@ -2203,7 +2203,6 @@ void FormPreferences::Paths::apply(LyXRC & rc) if (!button) str.erase(); rc.check_lastfiles = button; - rc.lastfiles = str; rc.num_lastfiles = static_cast (fl_get_counter_value(dialog_->counter_lastfiles)); @@ -2261,8 +2260,6 @@ FormPreferences::Paths::feedback(FL_OBJECT const * const ob) const return LyXRC::getDescription(LyXRC::RC_TEMPDIRPATH); if (ob == dialog_->check_last_files) return LyXRC::getDescription(LyXRC::RC_CHECKLASTFILES); - if (ob == dialog_->input_lastfiles) - return LyXRC::getDescription(LyXRC::RC_LASTFILES); if (ob == dialog_->counter_lastfiles) return LyXRC::getDescription(LyXRC::RC_NUMLASTFILES); if (ob == dialog_->check_make_backups) @@ -2410,13 +2407,8 @@ void FormPreferences::Paths::update(LyXRC const & rc) fl_set_input(dialog_->input_temp_dir, rc.tempdir_path.c_str()); fl_set_input(dialog_->input_path_prefix, rc.path_prefix.c_str()); - str.erase(); - if (rc.check_lastfiles) - str = rc.lastfiles; - fl_set_button(dialog_->check_last_files, rc.check_lastfiles); - fl_set_input(dialog_->input_lastfiles, str.c_str()); fl_set_counter_value(dialog_->counter_lastfiles, rc.num_lastfiles); diff --git a/src/frontends/xforms/XFormsView.C b/src/frontends/xforms/XFormsView.C index 43f7058516..0206a6907b 100644 --- a/src/frontends/xforms/XFormsView.C +++ b/src/frontends/xforms/XFormsView.C @@ -17,13 +17,17 @@ #include "BufferView.h" #include "debug.h" +#include "lyx_main.h" +#include "session.h" #include "lyxfunc.h" #include "MenuBackend.h" +#include "funcrequest.h" #include "frontends/Dialogs.h" #include "frontends/Toolbars.h" #include "support/filetools.h" // OnlyFilename() +#include "support/convert.h" #include @@ -45,9 +49,13 @@ namespace frontend { extern "C" { static -int C_XFormsView_atCloseMainFormCB(FL_FORM * form, void * p) +int C_XFormsView_atCloseMainFormCB(FL_FORM * /*form*/, void * arg) { - return XFormsView::atCloseMainFormCB(form, p); + // For some reason u_vdata does not contain the pointer + // to the XFormsView that we need. We get it through arg instead. + //XFormsView * view = static_cast(form->u_vdata); + XFormsView * view = static_cast(arg); + return view->atCloseMainFormCB(); } } @@ -93,7 +101,7 @@ XFormsView::XFormsView(int width, int height) // dimensions. form_ = fl_bgn_form(FL_NO_BOX, width, height); form_->u_vdata = this; - fl_set_form_atclose(form_, C_XFormsView_atCloseMainFormCB, 0); + fl_set_form_atclose(form_, C_XFormsView_atCloseMainFormCB, this); FL_OBJECT * obj = fl_add_box(FL_FLAT_BOX, 0, 0, width, height, ""); fl_set_object_color(obj, FL_MCOL, FL_MCOL); @@ -171,9 +179,15 @@ FL_FORM * XFormsView::getForm() const // Callback for close main form from window manager -int XFormsView::atCloseMainFormCB(FL_FORM *, void *) +int XFormsView::atCloseMainFormCB() { - QuitLyX(false); + // save windows size + LyX::ref().session().saveSessionInfo("WindowWidth", convert(form_->w)); + LyX::ref().session().saveSessionInfo("WindowHeight", convert(form_->h)); + // trigger LFUN_QUIT instead of quit directly + // since LFUN_QUIT may have more cleanup stuff + // + getLyXFunc().dispatch(FuncRequest(LFUN_QUIT)); return FL_IGNORE; } diff --git a/src/frontends/xforms/XFormsView.h b/src/frontends/xforms/XFormsView.h index 7f77b76937..45e58ff870 100644 --- a/src/frontends/xforms/XFormsView.h +++ b/src/frontends/xforms/XFormsView.h @@ -66,7 +66,7 @@ public: virtual void busy(bool) const; /// callback for close event from window manager - static int atCloseMainFormCB(FL_FORM *, void *); + int atCloseMainFormCB(); /// display a status message virtual void message(std::string const & str); diff --git a/src/frontends/xforms/lyx_gui.C b/src/frontends/xforms/lyx_gui.C index bf562beded..809e834693 100644 --- a/src/frontends/xforms/lyx_gui.C +++ b/src/frontends/xforms/lyx_gui.C @@ -28,6 +28,7 @@ #include "LyXAction.h" #include "lyxfunc.h" #include "lyxrc.h" +#include "session.h" #include "lyxserver.h" #include "lyxsocket.h" @@ -37,6 +38,7 @@ #include "support/lyxlib.h" #include "support/os.h" #include "support/package.h" +#include "support/convert.h" #include "lyx_forms.h" @@ -259,6 +261,20 @@ void start(string const & batch, vector const & files) int ypos = -1; unsigned int width = 690; unsigned int height = 510; + // first try lyxrc + if (lyxrc.geometry_width != 0 && lyxrc.geometry_height != 0 ) { + width = lyxrc.geometry_width; + height = lyxrc.geometry_height; + } + // if lyxrc returns (0,0), then use session info + else { + string val = LyX::ref().session().loadSessionInfo("WindowWidth"); + if (val != "") + width = convert(val); + val = LyX::ref().session().loadSessionInfo("WindowHeight"); + if (val != "") + height = convert(val); + } int const geometryBitmask = XParseGeometry(geometry, diff --git a/src/lastfiles.C b/src/lastfiles.C deleted file mode 100644 index 537d611c61..0000000000 --- a/src/lastfiles.C +++ /dev/null @@ -1,99 +0,0 @@ -/** - * \file lastfiles.C - * This file is part of LyX, the document processor. - * Licence details can be found in the file COPYING. - * - * \author Lars Gullik Bjønnes - * - * Full author contact details are available in file CREDITS. - */ - -#include - -#include "lastfiles.h" -#include "debug.h" - -#include - -#include -#include -#include - -namespace fs = boost::filesystem; - -using std::copy; -using std::endl; -using std::find; -using std::getline; -using std::string; -using std::ifstream; -using std::ofstream; -using std::ostream_iterator; - - -LastFiles::LastFiles(string const & filename, bool st, unsigned int num) - : dostat(st) -{ - setNumberOfFiles(num); - readFile(filename); -} - - -void LastFiles::setNumberOfFiles(unsigned int no) -{ - if (0 < no && no <= ABSOLUTEMAXLASTFILES) - num_files = no; - else { - lyxerr << "LyX: lastfiles: too many files\n" - "\tdefault (=" << int(DEFAULTFILES) - << ") used." << endl; - num_files = DEFAULTFILES; - } -} - - -void LastFiles::readFile(string const & filename) -{ - // we will not complain if we can't find filename nor will - // we issue a warning. (Lgb) - ifstream ifs(filename.c_str()); - string tmp; - - while (getline(ifs, tmp) && files.size() < num_files) { - if (dostat && !fs::exists(tmp)) - continue; - files.push_back(tmp); - } -} - - -void LastFiles::writeFile(string const & filename) const -{ - ofstream ofs(filename.c_str()); - if (ofs) { - copy(files.begin(), files.end(), - ostream_iterator(ofs, "\n")); - } else - lyxerr << "LyX: Warning: unable to save LastFiles: " - << filename << endl; -} - - -void LastFiles::newFile(string const & file) -{ - // If file already exist, delete it and reinsert at front. - Files::iterator it = find(files.begin(), files.end(), file); - if (it != files.end()) - files.erase(it); - files.push_front(file); - if (files.size() > num_files) - files.pop_back(); -} - - -string const LastFiles::operator[](unsigned int i) const -{ - if (i < files.size()) - return files[i]; - return string(); -} diff --git a/src/lastfiles.h b/src/lastfiles.h deleted file mode 100644 index efe657e785..0000000000 --- a/src/lastfiles.h +++ /dev/null @@ -1,105 +0,0 @@ -// -*- C++ -*- -/** - * \file lastfiles.h - * This file is part of LyX, the document processor. - * Licence details can be found in the file COPYING. - * - * \author Lars Gullik Bjønnes - * - * Full author contact details are available in file CREDITS. - */ - -#ifndef LASTFILES_H -#define LASTFILES_H - -#include - -#include -#include - -const long maxlastfiles = 20; - -/** The latest documents loaded. - * This class takes care of the last .lyx files used by the LyX user. It - * both reads and writes this information to a file. The number of files - * kept are user defined, but defaults to four. - */ -class LastFiles : boost::noncopyable { -public: - /// - typedef std::deque Files; - - /// - typedef Files::const_iterator const_iterator; - - /** Read the lastfiles file. - @param file The file to read the lastfiles form. - @param dostat Whether to check for file existance. - @param num number of files to remember. - */ - explicit - LastFiles(std::string const & file, - bool dostat = true, unsigned int num = 4); - - /** Insert #file# into the list. - This funtion inserts #file# into the last files list. If the file - already exist it is moved to the top of the list, else exist it - is placed on the top of the list. If the list is full the last - file in the list is popped from the end. - @param file the file to insert in the list. - */ - void newFile(std::string const & file); - /** Writes the lastfiles table to disk. - Writes one file on each line, this way we can at least have - some special chars (e.g. space), but newline in filenames - are thus not allowed. - @param file the file we write the lastfiles list to. - */ - void writeFile(std::string const & file) const; - /** Return file #n# in the lastfiles list. - @param n number in the list to get - */ - std::string const operator[](unsigned int n) const; - /// Iterator to the beginning of the list. - Files::const_iterator begin() const { return files.begin(); } - /// Iterator to the end of the list. - Files::const_iterator end() const { return files.end(); } -private: - /** Local constants. - It is more portable among different C++ compilers to use - an enum instead of #int const XXX# - */ - enum local_constants { - /// Default number of lastfiles. - DEFAULTFILES = 4, - /** Max number of lastfiles. - There is no point in keeping more than this number - of files at the same time. However perhaps someday - someone finds use for more files and wants to - change it. Please do. But don't show the files in - a menu... - */ - ABSOLUTEMAXLASTFILES = 20 - }; - - /// a list of lastfiles - Files files; - /// number of files in the lastfiles list. - unsigned int num_files; - /// check for file existance or not. - bool dostat; - - /** Read the lastfiles file. - Reads the #.lyx_lastfiles# at the beginning of the LyX session. - This will read the lastfiles file (usually #.lyx_lastfiles#). It - will normally discard files that don't exist anymore, unless - LastFiles has been initialized with #dostat = false#. - @param file the file containing the lastfiles. - */ - void readFile(std::string const & file); - /** Used by the constructor to set the number of stored last files. - @param num the number of lastfiles to set. - */ - void setNumberOfFiles(unsigned int num); -}; -#endif diff --git a/src/lyx_cb.C b/src/lyx_cb.C index d69871edb7..5445ef21c9 100644 --- a/src/lyx_cb.C +++ b/src/lyx_cb.C @@ -22,7 +22,7 @@ #include "cursor.h" #include "debug.h" #include "gettext.h" -#include "lastfiles.h" +#include "session.h" #include "LaTeXFeatures.h" #include "lyx_main.h" #include "lyxlayout.h" @@ -101,7 +101,7 @@ bool quitting; // flag, that we are quitting the program bool MenuWrite(Buffer * buffer) { if (buffer->save()) { - LyX::ref().lastfiles().newFile(buffer->fileName()); + LyX::ref().session().addLastFile(buffer->fileName()); return true; } @@ -196,7 +196,7 @@ void QuitLyX(bool noask) if (!noask && !bufferlist.quitWriteAll()) return; - LyX::cref().lastfiles().writeFile(lyxrc.lastfiles); + LyX::cref().session().writeFile(); } // Set a flag that we do quitting from the program, diff --git a/src/lyx_main.C b/src/lyx_main.C index b7f54fdb74..a7fc41b277 100644 --- a/src/lyx_main.C +++ b/src/lyx_main.C @@ -28,7 +28,7 @@ #include "gettext.h" #include "kbmap.h" #include "language.h" -#include "lastfiles.h" +#include "session.h" #include "LColor.h" #include "lyxfunc.h" #include "lyxlex.h" @@ -163,17 +163,17 @@ LyX::LyX() {} -LastFiles & LyX::lastfiles() +lyx::Session & LyX::session() { - BOOST_ASSERT(lastfiles_.get()); - return *lastfiles_.get(); + BOOST_ASSERT(session_.get()); + return *session_.get(); } -LastFiles const & LyX::lastfiles() const +lyx::Session const & LyX::session() const { - BOOST_ASSERT(lastfiles_.get()); - return *lastfiles_.get(); + BOOST_ASSERT(session_.get()); + return *session_.get(); } @@ -238,6 +238,14 @@ void LyX::priv_exec(int & argc, char * argv[]) if (first_start) files.push_back(i18nLibFileSearch("examples", "splash.lyx")); + // if a file is specified, I assume that user wants to edit *that* file + if (files.empty() && lyxrc.load_session) { + vector const & lastopened = session_->lastOpenedFiles(); + files.insert(files.end(), lastopened.begin(), lastopened.end() ); + // clear this list to save a few bytes of RAM + session_->clearLastOpenedFiles(); + } + // Execute batch commands if available if (!batch_command.empty()) { @@ -425,10 +433,6 @@ void LyX::init(bool gui) "templates"); } - if (lyxrc.lastfiles.empty()) { - lyxrc.lastfiles = AddName(package().user_support(), "lastfiles"); - } - if (lyxrc.roman_font_name.empty()) lyxrc.roman_font_name = lyx_gui::roman_font_name(); if (lyxrc.sans_font_name.empty()) @@ -513,11 +517,8 @@ void LyX::init(bool gui) lyxerr << "LyX tmp dir: `" << package().temp_dir() << '\'' << endl; } - lyxerr[Debug::INIT] << "Reading lastfiles `" - << lyxrc.lastfiles << "'..." << endl; - lastfiles_.reset(new LastFiles(lyxrc.lastfiles, - lyxrc.check_lastfiles, - lyxrc.num_lastfiles)); + lyxerr[Debug::INIT] << "Reading session information '.lyx/session'..." << endl; + session_.reset(new lyx::Session(lyxrc.num_lastfiles)); } diff --git a/src/lyx_main.h b/src/lyx_main.h index a196e8909a..426a7810ee 100644 --- a/src/lyx_main.h +++ b/src/lyx_main.h @@ -24,9 +24,11 @@ class Buffer; class ErrorItem; class InsetBase; -class LastFiles; class LyXView; class kb_keymap; +namespace lyx { + class Session; +} /// initial startup @@ -39,8 +41,8 @@ public: /// in the case of failure void emergencyCleanup() const; - LastFiles & lastfiles(); - LastFiles const & lastfiles() const; + lyx::Session & session(); + lyx::Session const & session() const; void addLyXView(boost::shared_ptr const & lyxview); @@ -86,8 +88,8 @@ private: /// the parsed command line batch command if any std::string batch_command; - /// last files loaded - boost::scoped_ptr lastfiles_; + /// lyx session, containing lastfiles, lastfilepos, and lastopened + boost::scoped_ptr session_; /// typedef std::list > ViewList; ViewList views_; diff --git a/src/lyxfunc.C b/src/lyxfunc.C index 0f858e819e..d59fd1a8db 100644 --- a/src/lyxfunc.C +++ b/src/lyxfunc.C @@ -43,6 +43,8 @@ #include "kbmap.h" #include "language.h" #include "LColor.h" +#include "session.h" +#include "lyx_main.h" #include "lyx_cb.h" #include "LyXAction.h" #include "lyxfind.h" @@ -996,6 +998,15 @@ void LyXFunc::dispatch(FuncRequest const & cmd) break; case LFUN_QUIT: + if (view()->available()) { + // save cursor Position for opened files to .lyx/session + LyX::ref().session().saveFilePosition(owner->buffer()->fileName(), + boost::tie(view()->cursor().pit(), view()->cursor().pos()) ); + // save opened file name to .lyx/session + LyX::ref().session().setLastOpenedFiles( bufferlist.getFileNames()); + // save bookmarks to .lyx/session + view()->saveSavedPositions(); + } QuitLyX(argument == "force"); break; @@ -1880,6 +1891,9 @@ void LyXFunc::doImport(string const & argument) void LyXFunc::closeBuffer() { + // save current cursor position + LyX::ref().session().saveFilePosition(owner->buffer()->fileName(), + boost::tie(view()->cursor().pit(), view()->cursor().pos()) ); if (bufferlist.close(owner->buffer(), true) && !quitting) { if (bufferlist.empty()) { // need this otherwise SEGV may occur while @@ -1966,6 +1980,8 @@ void actOnUpdatedPrefs(LyXRC const & lyxrc_orig, LyXRC const & lyxrc_new) case LyXRC::RC_BIBTEX_COMMAND: case LyXRC::RC_BINDFILE: case LyXRC::RC_CHECKLASTFILES: + case LyXRC::RC_USELASTFILEPOS: + case LyXRC::RC_LOADSESSION: case LyXRC::RC_CHKTEX_COMMAND: case LyXRC::RC_CONVERTER: case LyXRC::RC_COPIER: @@ -2007,7 +2023,6 @@ void actOnUpdatedPrefs(LyXRC const & lyxrc_orig, LyXRC const & lyxrc_new) case LyXRC::RC_LANGUAGE_GLOBAL_OPTIONS: case LyXRC::RC_LANGUAGE_PACKAGE: case LyXRC::RC_LANGUAGE_USE_BABEL: - case LyXRC::RC_LASTFILES: case LyXRC::RC_MAKE_BACKUP: case LyXRC::RC_MARK_FOREIGN_LANGUAGE: case LyXRC::RC_NUMLASTFILES: @@ -2052,6 +2067,9 @@ void actOnUpdatedPrefs(LyXRC const & lyxrc_orig, LyXRC const & lyxrc_new) case LyXRC::RC_SCREEN_FONT_SIZES: case LyXRC::RC_SCREEN_FONT_TYPEWRITER: case LyXRC::RC_SCREEN_FONT_TYPEWRITER_FOUNDRY: + case LyXRC::RC_SCREEN_GEOMETRY_HEIGHT: + case LyXRC::RC_SCREEN_GEOMETRY_WIDTH: + case LyXRC::RC_SCREEN_GEOMETRY_XYSAVED: case LyXRC::RC_SCREEN_ZOOM: case LyXRC::RC_SERVERPIPE: case LyXRC::RC_SET_COLOR: diff --git a/src/lyxrc.C b/src/lyxrc.C index 36bc4fc70f..80ae63b770 100644 --- a/src/lyxrc.C +++ b/src/lyxrc.C @@ -25,7 +25,7 @@ #include "converter.h" #include "format.h" #include "gettext.h" -#include "lastfiles.h" +#include "session.h" #include "LColor.h" #include "lyxlex.h" #include "lyxfont.h" @@ -104,7 +104,7 @@ keyword_item lyxrcTags[] = { { "\\language_global_options", LyXRC::RC_LANGUAGE_GLOBAL_OPTIONS }, { "\\language_package", LyXRC::RC_LANGUAGE_PACKAGE }, { "\\language_use_babel", LyXRC::RC_LANGUAGE_USE_BABEL }, - { "\\lastfiles", LyXRC::RC_LASTFILES }, + { "\\load_session", LyXRC::RC_LOADSESSION }, { "\\make_backup", LyXRC::RC_MAKE_BACKUP }, { "\\mark_foreign_language", LyXRC::RC_MARK_FOREIGN_LANGUAGE }, { "\\num_lastfiles", LyXRC::RC_NUMLASTFILES }, @@ -152,6 +152,9 @@ keyword_item lyxrcTags[] = { { "\\screen_font_typewriter", LyXRC::RC_SCREEN_FONT_TYPEWRITER }, { "\\screen_font_typewriter_foundry", LyXRC::RC_SCREEN_FONT_TYPEWRITER_FOUNDRY }, { "\\screen_zoom", LyXRC::RC_SCREEN_ZOOM }, + { "\\screen_geometry_height", LyXRC::RC_SCREEN_GEOMETRY_HEIGHT }, + { "\\screen_geometry_width", LyXRC::RC_SCREEN_GEOMETRY_WIDTH }, + { "\\screen_geometry_xysaved", LyXRC::RC_SCREEN_GEOMETRY_XYSAVED }, { "\\serverpipe", LyXRC::RC_SERVERPIPE }, { "\\set_color", LyXRC::RC_SET_COLOR }, { "\\show_banner", LyXRC::RC_SHOW_BANNER }, @@ -163,6 +166,7 @@ keyword_item lyxrcTags[] = { { "\\use_alt_language", LyXRC::RC_USE_ALT_LANG }, { "\\use_escape_chars", LyXRC::RC_USE_ESC_CHARS }, { "\\use_input_encoding", LyXRC::RC_USE_INP_ENC }, + { "\\use_lastfilepos", LyXRC::RC_USELASTFILEPOS }, { "\\use_personal_dictionary", LyXRC::RC_USE_PERS_DICT }, // compatibility with versions older than 1.4.0 only { "\\use_pspell", LyXRC::RC_USE_SPELL_LIB }, @@ -219,6 +223,9 @@ void LyXRC::setDefaults() { dpi = 75; // Because a screen typically is wider than a piece of paper: zoom = 150; + geometry_width = 0; + geometry_height = 0; + geometry_xysaved = true; wheel_jump = 5; // Default LaTeX font size: font_sizes[LyXFont::SIZE_TINY] = "5.0"; @@ -246,6 +253,8 @@ void LyXRC::setDefaults() { ascii_linelen = 65; num_lastfiles = maxlastfiles; check_lastfiles = true; + use_lastfilepos = true; + load_session = true; make_backup = true; backupdir_path.erase(); display_graphics = lyx::graphics::ColorDisplay; @@ -629,6 +638,24 @@ int LyXRC::read(LyXLex & lexrc) } break; + case RC_SCREEN_GEOMETRY_HEIGHT: + if (lexrc.next()) { + geometry_height = lexrc.getInteger(); + } + break; + + case RC_SCREEN_GEOMETRY_WIDTH: + if (lexrc.next()) { + geometry_width = lexrc.getInteger(); + } + break; + + case RC_SCREEN_GEOMETRY_XYSAVED: + if (lexrc.next()) { + geometry_xysaved = lexrc.getBool(); + } + break; + case RC_WHEEL_JUMP: if (lexrc.next()) { wheel_jump = lexrc.getInteger(); @@ -717,9 +744,15 @@ int LyXRC::read(LyXLex & lexrc) } break; - case RC_LASTFILES: + case RC_USELASTFILEPOS: + if (lexrc.next()) { + use_lastfilepos = lexrc.getBool(); + } + break; + + case RC_LOADSESSION: if (lexrc.next()) { - lastfiles = ExpandPath(os::internal_path(lexrc.getString())); + load_session = lexrc.getBool(); } break; @@ -1427,7 +1460,7 @@ void LyXRC::write(ostream & os, bool ignore_system_lyxrc) const os << "\\preview_scale_factor " << preview_scale_factor << '\n'; } - + os << "\n#\n" << "# SCREEN & FONTS SECTION ############################\n" << "#\n\n"; @@ -1460,6 +1493,24 @@ void LyXRC::write(ostream & os, bool ignore_system_lyxrc) const zoom != system_lyxrc.zoom) { os << "\\screen_zoom " << zoom << '\n'; } + case RC_SCREEN_GEOMETRY_HEIGHT: + if (ignore_system_lyxrc || + geometry_height != system_lyxrc.geometry_height) { + os << "\\screen_geometry_height " << geometry_height + << '\n'; + } + case RC_SCREEN_GEOMETRY_WIDTH: + if (ignore_system_lyxrc || + geometry_width != system_lyxrc.geometry_width) { + os << "\\screen_geometry_width " << geometry_width + << '\n'; + } + case RC_SCREEN_GEOMETRY_XYSAVED: + if (ignore_system_lyxrc || + geometry_xysaved != system_lyxrc.geometry_xysaved) { + os << "\\screen_geometry_xysaved " << convert(geometry_xysaved) + << '\n'; + } case RC_WHEEL_JUMP: if (ignore_system_lyxrc || wheel_jump != system_lyxrc.wheel_jump) { @@ -1741,11 +1792,17 @@ void LyXRC::write(ostream & os, bool ignore_system_lyxrc) const string const path = os::external_path(document_path); os << "\\document_path \"" << path << "\"\n"; } - case RC_LASTFILES: + case RC_USELASTFILEPOS: + if (ignore_system_lyxrc || + use_lastfilepos != system_lyxrc.use_lastfilepos) { + os << "\\use_session " << convert(use_lastfilepos) + << '\n'; + } + case RC_LOADSESSION: if (ignore_system_lyxrc || - lastfiles != system_lyxrc.lastfiles) { - string const path = os::external_path(lastfiles); - os << "\\lastfiles \"" << path << "\"\n"; + load_session != system_lyxrc.load_session) { + os << "\\load_session " << convert(load_session) + << "\n"; } case RC_NUMLASTFILES: if (ignore_system_lyxrc || @@ -2225,8 +2282,12 @@ string const LyXRC::getDescription(LyXRCTags tag) str = _("De-select if you don't want babel to be used when the language of the document is the default language."); break; - case RC_LASTFILES: - str = _("The file where the last-files information should be stored."); + case RC_USELASTFILEPOS: + str = _("De-select if you do not want LyX to scroll to saved position."); + break; + + case RC_LOADSESSION: + str = _("De-select to prevent loading files opened from the last lyx session."); break; case RC_MAKE_BACKUP: @@ -2384,6 +2445,15 @@ string const LyXRC::getDescription(LyXRCTags tag) str = _("The zoom percentage for screen fonts. A setting of 100% will make the fonts roughly the same size as on paper."); break; + case RC_SCREEN_GEOMETRY_HEIGHT: + case RC_SCREEN_GEOMETRY_WIDTH: + str = _("Specify geometry of the main view in width x height (values from last session will not be used if non-zero values are specified)."); + break; + + case RC_SCREEN_GEOMETRY_XYSAVED: + str = _("Allow session manager to save and restore windows position."); + break; + case RC_SERVERPIPE: str = _("This starts the lyxserver. The pipes get an additional extension \".in\" and \".out\". Only for advanced users."); break; diff --git a/src/lyxrc.h b/src/lyxrc.h index 2b88a84f35..d84438e23b 100644 --- a/src/lyxrc.h +++ b/src/lyxrc.h @@ -75,7 +75,8 @@ public: RC_LANGUAGE_GLOBAL_OPTIONS, RC_LANGUAGE_PACKAGE, RC_LANGUAGE_USE_BABEL, - RC_LASTFILES, + RC_USELASTFILEPOS, + RC_LOADSESSION, RC_MAKE_BACKUP, RC_MARK_FOREIGN_LANGUAGE, RC_NUMLASTFILES, @@ -116,6 +117,9 @@ public: RC_SCREEN_FONT_SIZES, RC_SCREEN_FONT_TYPEWRITER, RC_SCREEN_FONT_TYPEWRITER_FOUNDRY, + RC_SCREEN_GEOMETRY_HEIGHT, + RC_SCREEN_GEOMETRY_WIDTH, + RC_SCREEN_GEOMETRY_XYSAVED, RC_SCREEN_ZOOM, RC_SERVERPIPE, RC_SET_COLOR, @@ -227,14 +231,22 @@ public: bool auto_reset_options; /// bool check_lastfiles; - /// filename for lastfiles file - std::string lastfiles; /// maximal number of lastfiles unsigned int num_lastfiles; + /// whether or not go to saved position when opening a file + bool use_lastfilepos; + /// load files from last session automatically + bool load_session; /// shall a backup file be created bool make_backup; /// A directory for storing backup files std::string backupdir_path; + /// Width of MainWindow. if 0, value from last session will be used + int geometry_width; + /// Height of MainWindow, if 0, value from last session will be used + int geometry_height; + /// Whether or not save/restore windows position as session info + bool geometry_xysaved; /// Zoom factor for screen fonts unsigned int zoom; /// parameter for button_4 and button_5 (scrollwheel) diff --git a/src/session.C b/src/session.C new file mode 100644 index 0000000000..a1781e4d01 --- /dev/null +++ b/src/session.C @@ -0,0 +1,279 @@ +/** + * \file session.C + * This file is part of LyX, the document processor. + * Licence details can be found in the file COPYING. + * + * \author Lars Gullik Bjønnes + * \author Bo Peng + * + * Full author contact details are available in file CREDITS. + */ + +#include + +#include "session.h" +#include "debug.h" +#include "support/package.h" +#include "support/filetools.h" + +#include + +#include +#include +#include +#include + +using lyx::support::AddName; +using lyx::support::package; + +namespace fs = boost::filesystem; + +using std::vector; +using std::getline; +using std::string; +using std::ifstream; +using std::ofstream; +using std::endl; +using std::istringstream; +using std::copy; +using std::find; +using std::ostream_iterator; + +namespace lyx{ + +namespace { + +string const sec_lastfiles = "[recent files]"; +string const sec_lastfilepos = "[cursor positions]"; +string const sec_lastopened = "[last opened files]"; +string const sec_bookmarks = "[bookmarks]"; +string const sec_session = "[session info]"; +int const id_lastfiles = 0; +int const id_lastfilepos = 1; +int const id_lastopened = 2; +int const id_bookmarks = 3; +int const id_session = 4; + +} // anon namespace + + +Session::Session(unsigned int num) : + default_num_last_files(4), + absolute_max_last_files(100), + num_lastfilepos(100) +{ + setNumberOfLastFiles(num); + // locate the session file + // note that the session file name 'session' is hard-coded + session_file = AddName(package().user_support(), "session"); + // + readFile(); +} + + +void Session::setNumberOfLastFiles(unsigned int no) +{ + if (0 < no && no <= absolute_max_last_files) + num_lastfiles = no; + else { + lyxerr << "LyX: session: too many last files\n" + << "\tdefault (=" << default_num_last_files + << ") used." << endl; + num_lastfiles = default_num_last_files; + } +} + + +void Session::readFile() +{ + // we will not complain if we can't find session_file nor will + // we issue a warning. (Lgb) + ifstream ifs(session_file.c_str()); + string tmp; + int section = -1; + + // the following is currently not implemented very + // robustly. (Manually editing of the session file may crash lyx) + // + while (getline(ifs, tmp)) { + // Ignore comments, empty line or line stats with ' ' + if (tmp == "" || tmp[0] == '#' || tmp[0] == ' ') + continue; + + // Determine section id + if (tmp == sec_lastfiles) { + section = id_lastfiles; + } else if (tmp == sec_lastfilepos) { + section = id_lastfilepos; + } else if (tmp == sec_lastopened) { + section = id_lastopened; + } else if (tmp == sec_bookmarks) { + section = id_bookmarks; + } else if (tmp == sec_session) { + section = id_session; + } else if (section == id_lastfiles) { + // read lastfiles + if (!fs::exists(tmp) || lastfiles.size() >= num_lastfiles) + continue; + lastfiles.push_back(tmp); + } else if (section == id_lastfilepos) { + // read lastfilepos + // pos, file\n + lyx::pit_type pit; + lyx::pos_type pos; + string fname; + istringstream itmp(tmp); + itmp >> pit; + itmp.ignore(2); // ignore ", " + itmp >> pos; + itmp.ignore(2); // ignore ", " + itmp >> fname; + if (!fs::exists(fname) || lastfilepos.size() >= num_lastfilepos) + continue; + lastfilepos[fname] = boost::tie(pit, pos); + } else if (section == id_lastopened) { + // read lastopened + // files + if (!fs::exists(tmp)) + continue; + lastopened.push_back(tmp); + } else if (section == id_bookmarks) { + // read bookmarks + // bookmarkid, id, pos, file\n + unsigned int num; + unsigned int id; + lyx::pos_type pos; + string fname; + istringstream itmp(tmp); + itmp >> num; + itmp.ignore(2); // ignore ", " + itmp >> id; + itmp.ignore(2); // ignore ", " + itmp >> pos; + itmp.ignore(2); // ignore ", " + itmp >> fname; + // only load valid bookmarks + if (fs::exists(fname)) + bookmarks.push_back(boost::tie(num, fname, id, pos)); + } else if (section == id_session) { + // Read session info, saved as key/value pairs + // would better yell if pos returns npos + string::size_type pos = tmp.find_first_of(" = "); + string key = tmp.substr(0, pos); + string value = tmp.substr(pos + 3); + sessioninfo[key] = value; + } + } +} + + +void Session::writeFile() const +{ + ofstream ofs(session_file.c_str()); + if (ofs) { + ofs << "## Automatically generated lyx session file \n" + << "## Editing this file manually may cause lyx to crash.\n"; + // first section + ofs << '\n' << sec_lastfiles << '\n'; + copy(lastfiles.begin(), lastfiles.end(), + ostream_iterator(ofs, "\n")); + // second section + ofs << '\n' << sec_lastfilepos << '\n'; + for (FilePosMap::const_iterator file = lastfilepos.begin(); + file != lastfilepos.end(); ++file) { + ofs << file->second.get<0>() << ", " + << file->second.get<1>() << ", " + << file->first << '\n'; + } + // third section + ofs << '\n' << sec_lastopened << '\n'; + copy(lastopened.begin(), lastopened.end(), + ostream_iterator(ofs, "\n")); + // fourth section + ofs << '\n' << sec_bookmarks << '\n'; + for (BookmarkList::const_iterator bm = bookmarks.begin(); + bm != bookmarks.end(); ++bm) { + // save bookmark number, id, pos, fname + ofs << bm->get<0>() << ", " + << bm->get<2>() << ", " + << bm->get<3>() << ", " + << bm->get<1>() << '\n'; + } + // fifth section + ofs << '\n' << sec_session << '\n'; + for (MiscInfo::const_iterator val = sessioninfo.begin(); + val != sessioninfo.end(); ++val) { + ofs << val->first << " = " << val->second << '\n'; + } + } else + lyxerr << "LyX: Warning: unable to save Session: " + << session_file << endl; +} + + +void Session::addLastFile(string const & file) +{ + // If file already exist, delete it and reinsert at front. + LastFiles::iterator it = find(lastfiles.begin(), lastfiles.end(), file); + if (it != lastfiles.end()) + lastfiles.erase(it); + lastfiles.push_front(file); + if (lastfiles.size() > num_lastfiles) + lastfiles.pop_back(); +} + + +void Session::saveFilePosition(string const & fname, FilePos pos) +{ + lastfilepos[fname] = pos; +} + + +Session::FilePos Session::loadFilePosition(string const & fname) const +{ + FilePosMap::const_iterator entry = lastfilepos.find(fname); + // Has position information, return it. + if (entry != lastfilepos.end()) + return entry->second; + // Not found, return the first paragraph + else + return 0; +} + + +void Session::clearLastOpenedFiles() +{ + lastopened.clear(); +} + + +void Session::setLastOpenedFiles(vector const & files) +{ + lastopened = files; +} + + +void Session::saveBookmark(Bookmark const & bookmark) +{ + bookmarks.push_back(bookmark); +} + + +void Session::saveSessionInfo(string const & key, string const & value) +{ + sessioninfo[key] = value; +} + + +string const Session::loadSessionInfo(string const & key, bool release) +{ + MiscInfo::const_iterator pos = sessioninfo.find(key); + string value; + if (pos != sessioninfo.end()) + value = pos->second; + if (release) + sessioninfo.erase(key); + return value; +} + +} diff --git a/src/session.h b/src/session.h new file mode 100644 index 0000000000..e4654a0de5 --- /dev/null +++ b/src/session.h @@ -0,0 +1,169 @@ +// -*- C++ -*- +/** + * \file session.h + * This file is part of LyX, the document processor. + * Licence details can be found in the file COPYING. + * + * \author Lars Gullik Bjønnes + * \author Bo Peng + * + * Full author contact details are available in file CREDITS. + */ + +#ifndef SESSION_H +#define SESSION_H + +#include + +#include +#include + +#include +#include +#include +#include + +// used by at least frontends/qt2/QPref.C +const long maxlastfiles = 20; + +/** This session file maintains + 1. the latest documents loaded (lastfiles) + 2. cursor positions of files closed (lastfilepos) + 3. opened files when a lyx session is closed (lastopened) + 4. bookmarks + 5. general purpose session info in the form of key/value pairs + */ +namespace lyx { + +class Session : boost::noncopyable { + +public: + /// + typedef boost::tuple FilePos; + /// + typedef std::map FilePosMap; + /// + typedef std::deque LastFiles; + /// + typedef std::vector LastOpened; + /// + typedef boost::tuple Bookmark; + /// + typedef std::vector BookmarkList; + /// + typedef std::map MiscInfo; + +public: + /** Read the session file. + @param num length of lastfiles + */ + explicit Session(unsigned int num = 4); + + /** Write the session file. + */ + void writeFile() const; + + /** Insert #file# into the lastfile dequeue. + This funtion inserts #file# into the last files list. If the file + already exists it is moved to the top of the list, else exist it + is placed on the top of the list. If the list is full the last + file in the list is popped from the end. + @param file the file to insert in the lastfile list. + */ + void addLastFile(std::string const & file); + + /** add cursor position to the fname entry in the filepos map + @param fname file entry for which to save position information + @param pos position of the cursor when the file is closed. + */ + void saveFilePosition(std::string const & fname, FilePos pos); + + /** clear lastopened file list + */ + void clearLastOpenedFiles(); + + /** set lastopened file list + @param files filenames of a list of opened files + */ + void setLastOpenedFiles(std::vector const & files); + + /** load saved cursor position from the fname entry in the filepos map + @param fname file entry for which to load position information + */ + FilePos loadFilePosition(std::string const & fname) const; + + /// Return lastfiles container (deque) + LastFiles const lastFiles() const { return lastfiles; } + + /// Return lastopened container (vector) + LastOpened const lastOpenedFiles() const { return lastopened; } + + /** save a bookmark + @bookmark bookmark to be saved + */ + void saveBookmark(Bookmark const & bookmark); + + /** return bookmark list. Non-const container is used since + bookmarks will be cleaned after use. + */ + BookmarkList & loadBookmarks() { return bookmarks; } + + /** set session info + @param key key of the value to store + @param value value, a string without newline ('\n') + */ + void saveSessionInfo(std::string const & key, std::string const & value); + + /** load session info + @param key a key to extract value from the session file + @param release whether or not clear the value. Default to true + since most of such values are supposed to be used only once. + */ + std::string const loadSessionInfo(std::string const & key, bool release = true); +private: + /// Default number of lastfiles. + unsigned int const default_num_last_files; + + /// Max number of lastfiles. + unsigned int const absolute_max_last_files; + + /// default number of lastfilepos to save */ + unsigned int const num_lastfilepos; + + /// file to save session, determined in the constructor. + std::string session_file; + + /// a list of lastfiles + LastFiles lastfiles; + + /// a list of bookmarks + BookmarkList bookmarks; + + /// a map to save session info + MiscInfo sessioninfo; + + /// number of files in the lastfiles list. + unsigned int num_lastfiles; + + /// a map of file positions + FilePosMap lastfilepos; + + /// a list of lastopened files + LastOpened lastopened; + + /** Read the session file. + Reads the #.lyx/session# at the beginning of the LyX session. + This will read the session file (usually #.lyx/session#). + @param file the file containing the session. + */ + void readFile(); + + /** Used by the constructor to set the number of stored last files. + @param num the number of lastfiles to set. + */ + void setNumberOfLastFiles(unsigned int num); +}; + +} + +#endif