> > If not for anything else that the code gets easier to read. > > (I do not quite see how removal of id plays into this.) > > (And no; operator[pit] on paragraphs won't solve it, just make the > > cursor placement even more coarse grained)
Now, a separate void BufferView::Pimpl::scrollToPosition(Buffer* buffer, lyx::pit_type pit, lyx::pos_type pos) { // check pit if ( static_cast<size_t>(pit) >= buffer->paragraphs().size() ) return; ParIterator it = buffer->par_iterator_begin(); ParIterator const end = buffer->par_iterator_end(); for (; it != end; ++it) if (it.pit() == pit) { bv_->setCursor(makeDocIterator(it, pos)); bv_->update(Update::FitCursor); return; } } More GUI (xform, gtk) code added to the patch. May not compile at all. Bo
Index: src/lyx_cb.C =================================================================== --- src/lyx_cb.C (revision 13495) +++ src/lyx_cb.C (working copy) @@ -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 MenuWrite(Buffer * buffer) { if (buffer->save()) { - LyX::ref().lastfiles().newFile(buffer->fileName()); + LyX::ref().session().addLastFile(buffer->fileName()); return true; } @@ -196,7 +196,7 @@ 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, Index: src/bufferlist.C =================================================================== --- src/bufferlist.C (revision 13495) +++ src/bufferlist.C (working copy) @@ -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 @@ if (!WriteAs(buf)) return false; } else if (buf->save()) { - LyX::ref().lastfiles().newFile(buf->fileName()); + LyX::ref().session().addLastFile(buf->fileName()); } else { return false; } Index: src/BufferView_pimpl.C =================================================================== --- src/BufferView_pimpl.C (revision 13495) +++ src/BufferView_pimpl.C (working copy) @@ -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" @@ -169,6 +169,16 @@ .connect(boost::bind(&BufferView::Pimpl::cursorToggle, this)); cursor_timeout.start(); saved_positions.resize(saved_positions_num); + // load saved bookmarks, emtpy bookmarks will be returned + // if bookmark was not saved. + for (unsigned int i=1; i < saved_positions_num; ++i) { + string fname; + unsigned int id; + lyx::pos_type pos; + boost::tie(fname, id, pos) = LyX::ref().session().loadBookmark(i); + saved_positions[i] = Position( fname, id, pos ); + } + LyX::ref().session().clearBookmarks(); } @@ -293,9 +303,17 @@ 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); + scrollToPosition(b, pit, pos); + } if (tolastfiles) - LyX::ref().lastfiles().newFile(b->fileName()); + LyX::ref().session().addLastFile(b->fileName()); return true; } @@ -331,6 +349,9 @@ // 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 @@ -804,13 +825,41 @@ owner_->message(bformat(_("Moved to bookmark %1$d"), i)); } - bool BufferView::Pimpl::isSavedPosition(unsigned int i) { return i < saved_positions_num && !saved_positions[i].filename.empty(); } +void BufferView::Pimpl::scrollToPosition(Buffer* buffer, lyx::pit_type pit, lyx::pos_type pos) +{ + // check pit + if ( static_cast<size_t>(pit) >= buffer->paragraphs().size() ) + return; + + ParIterator it = buffer->par_iterator_begin(); + ParIterator const end = buffer->par_iterator_end(); + for (; it != end; ++it) + if (it.pit() == pit) { + bv_->setCursor(makeDocIterator(it, pos)); + bv_->update(Update::FitCursor); + return; + } +} +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) { + // to preserve bookmark order, save invalid bookmarks as well + LyX::ref().session().saveBookmark( boost::tie( + saved_positions[i].filename, + saved_positions[i].par_id, + saved_positions[i].par_pos) ); + } +} + void BufferView::Pimpl::switchKeyMap() { if (!lyxrc.rtl_support) Index: src/BufferView_pimpl.h =================================================================== --- src/BufferView_pimpl.h (revision 13495) +++ src/BufferView_pimpl.h (working copy) @@ -96,6 +96,10 @@ /// bool isSavedPosition(unsigned int i); /// + void scrollToPosition(Buffer* buffer, lyx::pit_type pit, lyx::pos_type pos); + /// save bookmarks to .lyx/session + void saveSavedPositions(); + /// void switchKeyMap(); /// void center(); Index: src/session.C =================================================================== --- src/session.C (revision 0) +++ src/session.C (revision 0) @@ -0,0 +1,280 @@ +/** + * \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 <config.h> + +#include "session.h" +#include "debug.h" +#include "support/package.h" +#include "support/filetools.h" + +#include <boost/filesystem/operations.hpp> + +#include <fstream> +#include <sstream> +#include <algorithm> +#include <iterator> + +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 fs = boost::filesystem; +using lyx::support::AddName; +using lyx::support::package; + +namespace lyx{ + +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_misc = "[misc info]"; +int const id_lastfiles = 0; +int const id_lastfilepos = 1; +int const id_lastopened = 2; +int const id_bookmarks = 3; +int const id_misc = 4; + +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: lastfiles: too many 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[0] == '#' || tmp[0] == '\n' || tmp[0] == ' ') + continue; + // lastfiles section + if (tmp == sec_lastfiles) { + section = id_lastfiles; + continue; + } + else if (tmp == sec_lastfilepos) { + section = id_lastfilepos; + continue; + } + else if (tmp == sec_lastopened) { + section = id_lastopened; + continue; + } + else if (tmp == sec_bookmarks) { + section = id_bookmarks; + } + else if (tmp == sec_misc) { + section = id_misc; + continue; + } + // read lastfiles + else if (section == id_lastfiles) { + if (!fs::exists(tmp) || lastfiles.size() >= num_lastfiles) + continue; + lastfiles.push_back(tmp); + } + // read lastfilepos + else if (section == id_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); + } + // read lastopened + else if (section == id_lastopened) { + // files + if (!fs::exists(tmp)) + continue; + lastopened.push_back(tmp); + } + // read bookmars + else if (section == id_bookmarks) { + // pos, file\n + unsigned int id; + lyx::pos_type pos; + string fname; + istringstream itmp(tmp); + itmp >> id; + itmp.ignore(2); // ignore ", " + itmp >> pos; + itmp.ignore(2); // ignore ", " + itmp >> fname; + // fname is allowed to be empty (for empty bookmark) + bookmarks.push_back(boost::tie(fname, id, pos)); + } + // read misc info + else if (section == id_misc) { + // 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); + miscinfo[key] = value; + } + } + ifs.close(); +} + +void Session::writeFile() const +{ + ofstream ofs(session_file.c_str()); + if (ofs) { + // + ofs << "## Automatically generated lyx session file " << endl; + ofs << "## Editing this file manually may cause lyx to crash. " << endl; + // first section + ofs << endl << sec_lastfiles << endl; + copy(lastfiles.begin(), lastfiles.end(), + ostream_iterator<string>(ofs, "\n")); + // second section + ofs << endl << sec_lastfilepos << endl; + for (FilePosMap::const_iterator file = lastfilepos.begin(); + file != lastfilepos.end(); ++file) { + ofs << file->second.get<0>() << ", " + << file->second.get<1>() << ", " + << file->first << endl; + } + // third section + ofs << endl << sec_lastopened << endl; + copy(lastopened.begin(), lastopened.end(), + ostream_iterator<string>(ofs, "\n")); + // fourth section + ofs << endl << sec_bookmarks << endl; + for (BookmarkList::const_iterator bm = bookmarks.begin(); + bm != bookmarks.end(); ++bm) { + ofs << bm->get<1>() << ", " + << bm->get<2>() << ", " + << bm->get<0>() << endl; + } + // fifth section + ofs << endl << sec_misc << endl; + for (MiscInfo::const_iterator val = miscinfo.begin(); + val != miscinfo.end(); ++val) { + ofs << val->first << " = " << val->second << endl; + } + ofs.close(); + } 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<string> const & files) +{ + lastopened = files; +} + +void Session::saveBookmark( Bookmark const & bookmark) +{ + bookmarks.push_back( bookmark ); +} + +Session::Bookmark const Session::loadBookmark(unsigned int idx) const +{ + // idx is 1 based + if ( idx == 0 || idx >= bookmarks.size() ) + return Bookmark("", 0, 0); + else + return bookmarks[idx-1]; +} + +void Session::saveMiscInfo(string const & key, string const & value) +{ + miscinfo[key] = value; +} + +string const Session::loadMiscInfo(string const & key, bool release) +{ + MiscInfo::const_iterator pos = miscinfo.find(key); + string value=""; + if (pos != miscinfo.end()) + value = pos->second; + if (release) + miscinfo.erase(key); + return value; +} + +} Index: src/lastfiles.C =================================================================== --- src/lastfiles.C (revision 13495) +++ src/lastfiles.C (working copy) @@ -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 <config.h> - -#include "lastfiles.h" -#include "debug.h" - -#include <boost/filesystem/operations.hpp> - -#include <algorithm> -#include <fstream> -#include <iterator> - -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<string>(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(); -} Index: src/lyxfunc.C =================================================================== --- src/lyxfunc.C (revision 13495) +++ src/lyxfunc.C (working copy) @@ -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 @@ 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::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 @@ 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 @@ 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: Index: src/frontends/gtk/GView.C =================================================================== --- src/frontends/gtk/GView.C (revision 13495) +++ src/frontends/gtk/GView.C (working copy) @@ -24,12 +24,16 @@ #include "BufferView.h" #include "lyx_cb.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 <boost/bind.hpp> @@ -95,7 +99,17 @@ 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; + // try to grab width/height saved from last session + string val = LyX::ref().session().loadMiscInfo("WindowWidth"); + if (val != "") + width = convert<unsigned int>(val); + val = LyX::ref().session().loadMiscInfo("WindowHeight"); + if (val != "") + height = convert<unsigned int>(val); + set_default_size(width, height); // Make sure the buttons are disabled if needed. updateToolbars(); string const iconName = @@ -117,7 +131,13 @@ bool GView::on_delete_event(GdkEventAny * /*event*/) { - QuitLyX(false); + // save windows size and position + LyX::ref().session().saveMiscInfo("WindowWidth", convert<string>(width())); + LyX::ref().session().saveMiscInfo("WindowHeight", convert<string>(height())); + // trigger LFUN_QUIT instead of quit directly + // since LFUN_QUIT may have more cleanup stuff + // + getLyXFunc().dispatch(FuncRequest(LFUN_QUIT)); return true; } Index: src/frontends/qt2/lyx_gui.C =================================================================== --- src/frontends/qt2/lyx_gui.C (revision 13495) +++ src/frontends/qt2/lyx_gui.C (working copy) @@ -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,28 @@ // initial geometry unsigned int width = 690; unsigned int height = 510; + // try to grab width/height saved from last session + string val = LyX::ref().session().loadMiscInfo("WindowWidth"); + if (val != "") + width = convert<unsigned int>(val); + val = LyX::ref().session().loadMiscInfo("WindowHeight"); + if (val != "") + height = convert<unsigned int>(val); boost::shared_ptr<QtView> view_ptr(new QtView(width, height)); LyX::ref().addLyXView(view_ptr); QtView & view = *view_ptr.get(); + + // moved to saved location (may or may not be a good idea) + // QPoint p = view.pos(); + // val = LyX::ref().session().loadMiscInfo("WindowPosX"); + // if (val != "") + // p.setX(convert<unsigned int>(val)); + // val = LyX::ref().session().loadMiscInfo("WindowPosY"); + // if (val != "") + // p.setY(convert<unsigned int>(val)); + // view.move(p); view.show(); view.init(); Index: src/frontends/qt2/QPrefs.C =================================================================== --- src/frontends/qt2/QPrefs.C (revision 13495) +++ src/frontends/qt2/QPrefs.C (working copy) @@ -35,7 +35,7 @@ #include "ui/QPrefIdentityModule.h" #include "debug.h" -#include "lastfiles.h" +#include "session.h" #include "LColor.h" #include "lyxfont.h" Index: src/frontends/qt2/QtView.C =================================================================== --- src/frontends/qt2/QtView.C (revision 13495) +++ src/frontends/qt2/QtView.C (working copy) @@ -13,12 +13,16 @@ #include "BufferView.h" #include "lyx_cb.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 <boost/bind.hpp> @@ -155,7 +159,17 @@ void QtView::closeEvent(QCloseEvent *) { - QuitLyX(false); + // save windows size and position + LyX::ref().session().saveMiscInfo("WindowWidth", convert<string>(width())); + LyX::ref().session().saveMiscInfo("WindowHeight", convert<string>(height())); + // + // Some people do not like the idea of restoring windows pos + // LyX::ref().session().saveMiscInfo("WindowPosX", convert<string>(pos().x())); + // LyX::ref().session().saveMiscInfo("WindowPosY", convert<string>(pos().y())); + // + // trigger LFUN_QUIT instead of quit directly + // since LFUN_QUIT may have more cleanup stuff + getLyXFunc().dispatch(FuncRequest(LFUN_QUIT)); } Index: src/frontends/qt4/lyx_gui.C =================================================================== --- src/frontends/qt4/lyx_gui.C (revision 13495) +++ src/frontends/qt4/lyx_gui.C (working copy) @@ -218,6 +218,13 @@ // initial geometry unsigned int width = 690; unsigned int height = 510; + // try to grab width/height saved from last session + string val = LyX::ref().session().loadMiscInfo("WindowWidth"); + if (val != "") + width = convert<unsigned int>(val); + val = LyX::ref().session().loadMiscInfo("WindowHeight"); + if (val != "") + height = convert<unsigned int>(val); boost::shared_ptr<QtView> view_ptr(new QtView(width, height)); LyX::ref().addLyXView(view_ptr); Index: src/frontends/qt4/QPrefs.C =================================================================== --- src/frontends/qt4/QPrefs.C (revision 13495) +++ src/frontends/qt4/QPrefs.C (working copy) @@ -18,7 +18,6 @@ #include "qt_helpers.h" #include "debug.h" -#include "lastfiles.h" #include "LColor.h" #include "lyxfont.h" Index: src/frontends/qt4/QtView.C =================================================================== --- src/frontends/qt4/QtView.C (revision 13495) +++ src/frontends/qt4/QtView.C (working copy) @@ -14,8 +14,12 @@ #include "BufferView.h" #include "lyx_cb.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 +27,7 @@ #include "support/filetools.h" +#include "support/convert.h" #include <boost/bind.hpp> #include "QtView.h" @@ -173,7 +178,12 @@ void QtView::closeEvent(QCloseEvent *) { - QuitLyX(false); + // save windows size and position + LyX::ref().session().saveMiscInfo("WindowWidth", convert<string>(width())); + LyX::ref().session().saveMiscInfo("WindowHeight", convert<string>(height())); + // trigger LFUN_QUIT instead of quit directly + // since LFUN_QUIT may have more cleanup stuff + getLyXFunc().dispatch(FuncRequest(LFUN_QUIT)); } Index: src/frontends/qt4/QPrefsDialog.C =================================================================== --- src/frontends/qt4/QPrefsDialog.C (revision 13495) +++ src/frontends/qt4/QPrefsDialog.C (working copy) @@ -18,7 +18,7 @@ #include "qt_helpers.h" #include "debug.h" -#include "lastfiles.h" +#include "session.h" #include "LColor.h" #include "lyxfont.h" Index: src/frontends/xforms/XFormsView.C =================================================================== --- src/frontends/xforms/XFormsView.C (revision 13495) +++ src/frontends/xforms/XFormsView.C (working copy) @@ -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 <boost/bind.hpp> @@ -173,7 +177,13 @@ // Callback for close main form from window manager int XFormsView::atCloseMainFormCB(FL_FORM *, void *) { - QuitLyX(false); + // save windows size + LyX::ref().session().saveMiscInfo("WindowWidth", convert<string>(width())); + LyX::ref().session().saveMiscInfo("WindowHeight", convert<string>(height())); + // trigger LFUN_QUIT instead of quit directly + // since LFUN_QUIT may have more cleanup stuff + // + getLyXFunc().dispatch(FuncRequest(LFUN_QUIT)); return FL_IGNORE; } Index: src/frontends/xforms/lyx_gui.C =================================================================== --- src/frontends/xforms/lyx_gui.C (revision 13495) +++ src/frontends/xforms/lyx_gui.C (working copy) @@ -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,13 @@ int ypos = -1; unsigned int width = 690; unsigned int height = 510; + // try to grab width/height saved from last session + string val = LyX::ref().session().loadMiscInfo("WindowWidth"); + if (val != "") + width = convert<unsigned int>(val); + val = LyX::ref().session().loadMiscInfo("WindowHeight"); + if (val != "") + height = convert<unsigned int>(val); int const geometryBitmask = XParseGeometry(geometry, Index: src/frontends/xforms/FormPreferences.C =================================================================== --- src/frontends/xforms/FormPreferences.C (revision 13495) +++ src/frontends/xforms/FormPreferences.C (working copy) @@ -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" Index: src/Makefile.am =================================================================== --- src/Makefile.am (revision 13495) +++ src/Makefile.am (working copy) @@ -189,8 +189,8 @@ kbsequence.h \ language.C \ language.h \ - lastfiles.C \ - lastfiles.h \ + session.C \ + session.h \ layout.h \ lengthcommon.C \ lengthcommon.h \ Index: src/session.h =================================================================== --- src/session.h (revision 0) +++ src/session.h (revision 0) @@ -0,0 +1,172 @@ +// -*- 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 <support/types.h> +#include <boost/utility.hpp> + +#include <string> +#include <deque> +#include <vector> +#include <map> + +// 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 misc info in the form of key/value pairs + */ +namespace lyx{ + +class Session : boost::noncopyable { + +public: + /// + typedef boost::tuple<lyx::pit_type, lyx::pos_type> FilePos; + /// + typedef std::map<std::string, FilePos> FilePosMap; + /// + typedef std::deque<std::string> LastFiles; + /// + typedef std::vector<std::string> LastOpened; + /// + typedef boost::tuple<std::string, unsigned int, lyx::pos_type> Bookmark; + /// + typedef std::vector<Bookmark> BookmarkList; + /// + typedef std::map<std::string, std::string> 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<std::string> 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 a saved bookmark. If idx is not valid, return an + empty bookmark. + @idx 1-based index to the bookmark list. + */ + Bookmark const loadBookmark(unsigned int idx) const; + + /** clear the bookmark list */ + void clearBookmarks() { bookmarks.clear(); } + + /** set miscellaneous info + @param key key of the value to store + @param value value, a string without newline ('\n') + */ + void saveMiscInfo(std::string const & key, std::string const & value); + + /** load miscellaneous 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 loadMiscInfo(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 misc info + MiscInfo miscinfo; + + /// 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 Index: src/lastfiles.h =================================================================== --- src/lastfiles.h (revision 13495) +++ src/lastfiles.h (working copy) @@ -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 <boost/utility.hpp> - -#include <deque> -#include <string> - -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<std::string> 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 Index: src/lyxrc.C =================================================================== --- src/lyxrc.C (revision 13495) +++ src/lyxrc.C (working copy) @@ -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,8 @@ { "\\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 }, + { "\\use_lastfilepos", LyXRC::RC_USELASTFILEPOS }, + { "\\load_session", LyXRC::RC_LOADSESSION }, { "\\make_backup", LyXRC::RC_MAKE_BACKUP }, { "\\mark_foreign_language", LyXRC::RC_MARK_FOREIGN_LANGUAGE }, { "\\num_lastfiles", LyXRC::RC_NUMLASTFILES }, @@ -246,6 +247,8 @@ 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; @@ -717,12 +720,18 @@ } break; - case RC_LASTFILES: + case RC_USELASTFILEPOS: if (lexrc.next()) { - lastfiles = ExpandPath(os::internal_path(lexrc.getString())); + use_lastfilepos = lexrc.getBool(); } break; + case RC_LOADSESSION: + if (lexrc.next()) { + load_session = lexrc.getBool(); + } + break; + case RC_NUMLASTFILES: if (lexrc.next()) { num_lastfiles = lexrc.getInteger(); @@ -1741,12 +1750,18 @@ string const path = os::external_path(document_path); os << "\\document_path \"" << path << "\"\n"; } - case RC_LASTFILES: + case RC_USELASTFILEPOS: if (ignore_system_lyxrc || - lastfiles != system_lyxrc.lastfiles) { - string const path = os::external_path(lastfiles); - os << "\\lastfiles \"" << path << "\"\n"; + use_lastfilepos != system_lyxrc.use_lastfilepos) { + os << "\\use_session " << convert<string>(use_lastfilepos) + << '\n'; } + case RC_LOADSESSION: + if (ignore_system_lyxrc || + load_session != system_lyxrc.load_session) { + os << "\\load_session " << convert<string>(load_session) + << "\n"; + } case RC_NUMLASTFILES: if (ignore_system_lyxrc || num_lastfiles != system_lyxrc.num_lastfiles) { @@ -2225,10 +2240,14 @@ 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: str = _("De-select if you don't want LyX to create backup files."); break; Index: src/BufferView.C =================================================================== --- src/BufferView.C (revision 13495) +++ src/BufferView.C (working copy) @@ -188,7 +188,16 @@ return pimpl_->isSavedPosition(i); } +void BufferView::scrollToPosition(Buffer* buffer, lyx::pit_type pit, lyx::pos_type pos) +{ + return pimpl_->scrollToPosition(buffer, pit, pos); +} +void BufferView::saveSavedPositions() +{ + return pimpl_->saveSavedPositions(); +} + void BufferView::switchKeyMap() { pimpl_->switchKeyMap(); Index: src/lyxrc.h =================================================================== --- src/lyxrc.h (revision 13495) +++ src/lyxrc.h (working copy) @@ -75,7 +75,8 @@ 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, @@ -227,10 +228,12 @@ 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 Index: src/MenuBackend.C =================================================================== --- src/MenuBackend.C (revision 13495) +++ src/MenuBackend.C (working copy) @@ -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 @@ 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<string>(ii) + ". " + MakeDisplayPath((*lfit), 30) + '|' + convert<string>(ii); Index: src/BufferView.h =================================================================== --- src/BufferView.h (revision 13495) +++ src/BufferView.h (working copy) @@ -120,6 +120,10 @@ void restorePosition(unsigned int i); /// does the given bookmark have a saved position ? bool isSavedPosition(unsigned int i); + /// scroll to pos pos of paragraph pit of Buffer + void scrollToPosition(Buffer* buffer, lyx::pit_type pit, lyx::pos_type pos); + /// save bookmarks to .lyx/session + void saveSavedPositions(); /// return the current change at the cursor Change const getCurrentChange(); Index: src/lyx_main.C =================================================================== --- src/lyx_main.C (revision 13495) +++ src/lyx_main.C (working copy) @@ -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 @@ {} -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 @@ 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<string> 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 @@ "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 @@ 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)); } Index: src/lyx_main.h =================================================================== --- src/lyx_main.h (revision 13495) +++ src/lyx_main.h (working copy) @@ -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 @@ /// 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<LyXView> const & lyxview); @@ -86,8 +88,8 @@ /// the parsed command line batch command if any std::string batch_command; - /// last files loaded - boost::scoped_ptr<LastFiles> lastfiles_; + /// lyx session, containing lastfiles, lastfilepos, and lastopened + boost::scoped_ptr<lyx::Session> session_; /// typedef std::list<boost::shared_ptr<LyXView> > ViewList; ViewList views_;