X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Fbufferlist.C;h=448a01af271a29df14080adb4aea393389d46044;hb=2f08c8882155b1158548f1c34b100f58a7b63f01;hp=a38e4bdb8c9a4422b60ed57af7564a283c404021;hpb=27de1486ca34aaad446adb798d71a77d6f6304da;p=lyx.git diff --git a/src/bufferlist.C b/src/bufferlist.C index a38e4bdb8c..448a01af27 100644 --- a/src/bufferlist.C +++ b/src/bufferlist.C @@ -1,15 +1,15 @@ /* This file is part of - * ====================================================== + * ====================================================== * * LyX, The Document Word Processor * - * Copyright (C) 1995 Matthias Ettrich - * Copyright (C) 1995-1998 The LyX Team. + * Copyright 1995 Matthias Ettrich + * Copyright 1995-2000 The LyX Team. * - * This file is Copyleft (C) 1996-1998 + * This file is Copyright 1996-2000 * Lars Gullik Bjønnes * - *====================================================== + * ====================================================== */ #ifdef __GNUG__ @@ -17,161 +17,106 @@ #endif #include -#include -#include + +#include + #include "bufferlist.h" #include "lyx_main.h" #include "minibuffer.h" -#include "FileInfo.h" -#include "filetools.h" +#include "support/FileInfo.h" +#include "support/filetools.h" #include "lyx_gui_misc.h" #include "lastfiles.h" -#include "error.h" +#include "debug.h" #include "lyxrc.h" -#include "lyxscreen.h" #include "lyxtext.h" #include "lyx_cb.h" +#include "bufferview_funcs.h" #include "gettext.h" +#include "LyXView.h" +#include "vc-backend.h" +#include "TextCache.h" -// $Id: bufferlist.C,v 1.1 1999/09/27 18:44:37 larsbj Exp $ - -#if !defined(lint) && !defined(WITH_WARNINGS) -static char vcid[] = "$Id: bufferlist.C,v 1.1 1999/09/27 18:44:37 larsbj Exp $"; -#endif /* lint */ +extern BufferView * current_view; // called too many times in this file... -extern BufferView *current_view; -extern MiniBuffer *minibuffer; -extern void SmallUpdate(signed char); -extern void BeforeChange(); -extern int RunLinuxDoc(int, LString const &); +using std::vector; +using std::find; +using std::endl; // // Class BufferStorage // -BufferStorage::BufferStorage() -{ - // Initialize the buffer array - for (int i=NUMBER_OF_BUFFERS-1; i >=0; i--) { - buffer[i] = 0; - } -} - - -bool BufferStorage::isEmpty() -{ - for (int i=NUMBER_OF_BUFFERS-1; i >=0; i--) { - if (buffer[i]) return false; - } - return true; -} - - -void BufferStorage::release(Buffer* buf) -{ - int i=0; - for (i=0; iparams.useClassDefaults(); - lyxerr.debug(LString("Assigning to buffer ") + i, Error::ANY); - return buffer[i]; -} - - -// -// Class BufferStrorage_Iter -// - -Buffer* BufferStorage_Iter::operator() () +void BufferStorage::release(Buffer * buf) { - int i=0; - for (i=index; i < BufferStorage::NUMBER_OF_BUFFERS; i++) { - if (cs->buffer[i]) { - index = i+1; - return cs->buffer[i]; - } + Container::iterator it = find(container.begin(), container.end(), buf); + if (it != container.end()) { + // Make sure that we don't store a LyXText in + // the textcache that points to the buffer + // we just deleted. + Buffer * tmp = (*it); + container.erase(it); + textcache.removeAllWithBuffer(tmp); + delete tmp; } - return 0; } -Buffer* BufferStorage_Iter::operator[] (int a) +Buffer * BufferStorage::newBuffer(string const & s, bool ronly) { - // a is >=1 - if (a<=0) return 0; - - int i=0; - while (a--) { - while(!cs->buffer[i++]); - } - if (i-1 < BufferStorage::NUMBER_OF_BUFFERS) - return cs->buffer[i-1]; - return 0; + Buffer * tmpbuf = new Buffer(s, ronly); + tmpbuf->params.useClassDefaults(); + lyxerr.debug() << "Assigning to buffer " + << container.size() << endl; + container.push_back(tmpbuf); + return tmpbuf; } // // Class BufferList // + BufferList::BufferList() -{ - _state = BufferList::OK; -} + : state_(BufferList::OK) +{} -BufferList::~BufferList() +bool BufferList::empty() const { - // I am sure something should be done here too. + return bstore.empty(); } -bool BufferList::isEmpty() -{ - return bstore.isEmpty(); -} - -extern void MenuWrite(Buffer*); +extern void MenuWrite(Buffer *); bool BufferList::QwriteAll() { bool askMoreConfirmation = false; - LString unsaved; - BufferStorage_Iter biter(bstore); - Buffer *b=0; - while ((b=biter())) { - if (!b->isLyxClean()) { + string unsaved; + for(BufferStorage::iterator it = bstore.begin(); + it != bstore.end(); ++it) { + if (!(*it)->isLyxClean()) { switch(AskConfirmation(_("Changes in document:"), - MakeDisplayPath(b->filename,50), + MakeDisplayPath((*it)->fileName(), + 50), _("Save document?"))) { case 1: // Yes - MenuWrite(b); + MenuWrite((*it)); break; case 2: // No askMoreConfirmation = true; - unsaved += MakeDisplayPath(b->filename,50); + unsaved += MakeDisplayPath((*it)->fileName(), + 50); unsaved += "\n"; - break; + break; case 3: // Cancel return false; } } } if (askMoreConfirmation && - lyxrc->exit_confirmation && + lyxrc.exit_confirmation && !AskQuestion(_("Some documents were not saved:"), unsaved, _("Exit anyway?"))) { return false; @@ -181,156 +126,54 @@ bool BufferList::QwriteAll() } -// Should probably be moved to somewhere else: BufferView? LyXView? -bool BufferList::write(Buffer *buf, bool makeBackup) -{ - minibuffer->Set(_("Saving document"), - MakeDisplayPath(buf->filename),"..."); - - // We don't need autosaves in the immediate future. (Asger) - buf->resetAutosaveTimers(); - - // make a backup - if (makeBackup) { - LString s = buf->filename + '~'; - // Rename is the wrong way of making a backup, - // this is the correct way. - /* truss cp fil fil2: - lstat("LyXVC3.lyx", 0xEFFFF898) Err#2 ENOENT - stat("LyXVC.lyx", 0xEFFFF688) = 0 - open("LyXVC.lyx", O_RDONLY) = 3 - open("LyXVC3.lyx", O_WRONLY|O_CREAT|O_TRUNC, 0600) = 4 - fstat(4, 0xEFFFF508) = 0 - fstat(3, 0xEFFFF508) = 0 - read(3, " # T h i s f i l e w".., 8192) = 5579 - write(4, " # T h i s f i l e w".., 5579) = 5579 - read(3, 0xEFFFD4A0, 8192) = 0 - close(4) = 0 - close(3) = 0 - chmod("LyXVC3.lyx", 0100644) = 0 - lseek(0, 0, SEEK_CUR) = 46440 - _exit(0) - */ - - // Should proabaly have some more error checking here. - // Should be cleaned up in 0.13, at least a bit. - // Doing it this way, also makes the inodes stay the same. - // This is still not a very good solution, in particular we - // might loose the owner of the backup. - FileInfo finfo(buf->filename); - if (finfo.exist()) { - mode_t fmode = finfo.getMode(); - - struct utimbuf *times = - (struct utimbuf*)new char[sizeof(struct utimbuf)]; - times->actime = finfo.getAccessTime(); - times->modtime = finfo.getModificationTime(); - long blksize = finfo.getBlockSize(); - lyxerr.debug(LString("BlockSize: ") + int(blksize)); - FilePtr fin(buf->filename,FilePtr::read); - FilePtr fout(s,FilePtr::truncate); - if (fin() && fout()) { - char * cbuf = new char[blksize+1]; - size_t c_read = 0; - size_t c_write = 0; - do { - c_read = fread(cbuf, 1, blksize, fin); - if (c_read != 0) - c_write = - fwrite(cbuf, 1, c_read, fout); - } while (c_read); - fin.close(); - fout.close(); - chmod(s.c_str(), fmode); - - if (utime(s.c_str(), times)) { - lyxerr.print("utime error."); - } - delete [] cbuf; - } else { - lyxerr.print("LyX was not able to make backupcopy. Beware."); - } - delete[] times; - } - } - - if (buf->writeFile(buf->filename,false)) { - buf->markLyxClean(); - - minibuffer->Set(_("Document saved as"), - MakeDisplayPath(buf->filename)); - - // now delete the autosavefile - LString a = OnlyPath(buf->filename); - a += '#'; - a += OnlyFilename(buf->filename); - a += '#'; - FileInfo fileinfo(a); - if (fileinfo.exist()) { - if (remove(a.c_str()) != 0) { - WriteFSAlert(_("Could not delete " - "auto-save file!"), a); - } - } - } else { - // Saving failed, so backup is not backup - if (makeBackup) { - LString s = buf->filename + '~'; - rename(s.c_str(), buf->filename.c_str()); - } - minibuffer->Set(_("Save failed!")); - return false; - } - - return true; -} - - void BufferList::closeAll() { - _state = BufferList::CLOSING; + state_ = BufferList::CLOSING; + // Since we are closing we can just as well delete all + // in the textcache this will also speed the closing/quiting up a bit. + textcache.clear(); - BufferStorage_Iter biter(bstore); - Buffer *b=0; - while ((b=biter())) { - close(b); + while (!bstore.empty()) { + close(bstore.front()); } - _state = BufferList::OK; + state_ = BufferList::OK; } void BufferList::resize() { - BufferStorage_Iter biter(bstore); - Buffer *b=0; - while ((b=biter())) { - b->resize(); + for(BufferStorage::iterator it = bstore.begin(); + it != bstore.end(); ++it) { + (*it)->resize(); } } -bool BufferList::close(Buffer *buf) +bool BufferList::close(Buffer * buf) { - buf->InsetUnlock(); + // CHECK + // Trace back why we need to use buf->getUser here. + // Perhaps slight rewrite is in order? (Lgb) + if (buf->getUser()) buf->getUser()->insetUnlock(); if (buf->paragraph && !buf->isLyxClean() && !quitting) { - ProhibitInput(); + if (buf->getUser()) ProhibitInput(buf->getUser()); switch(AskConfirmation(_("Changes in document:"), - MakeDisplayPath(buf->filename,50), - _("Save document?"))){ + MakeDisplayPath(buf->fileName(), 50), + _("Save document?"))){ case 1: // Yes - if (write(buf)) { - lastfiles->newFile(buf->filename); + if (buf->save()) { + lastfiles->newFile(buf->fileName()); } else { - AllowInput(); + if (buf->getUser()) AllowInput(buf->getUser()); return false; } break; case 3: // Cancel - AllowInput(); + if (buf->getUser()) AllowInput(buf->getUser()); return false; } - AllowInput(); + if (buf->getUser()) AllowInput(buf->getUser()); } bstore.release(buf); @@ -338,64 +181,39 @@ bool BufferList::close(Buffer *buf) } -void BufferList::makePup(int pup) - /* This should be changed to return a char const *const - in the same way as for lastfiles.[hC] - */ +vector BufferList::getFileNames() const { - int ant=0; - BufferStorage_Iter biter(bstore); - Buffer *b=0; - while ((b=biter())) { - LString relbuf = MakeDisplayPath(b->filename,30); - fl_addtopup(pup, relbuf.c_str()); - ant++; + vector nvec; + for(BufferStorage::const_iterator cit = bstore.begin(); + cit != bstore.end(); ++cit) { + nvec.push_back((*cit)->fileName()); } - if (ant == 0) fl_addtopup(pup,_("No Documents Open!%t")); + return nvec; } -Buffer* BufferList::first() +Buffer * BufferList::first() { - BufferStorage_Iter biter(bstore); - return biter(); + if (bstore.empty()) return 0; + return bstore.front(); } -Buffer* BufferList::getBuffer(int choice) +Buffer * BufferList::getBuffer(int choice) { - BufferStorage_Iter biter(bstore); - Buffer *b=0; - b = biter[choice]; - - // Be careful, this could be 0. - return b; + if (choice >= bstore.size()) return 0; + return bstore[choice]; } -void BufferList::updateInset(Inset *inset, bool mark_dirty) -{ - BufferStorage_Iter biter(bstore); - Buffer *b=0; - while ((b=biter())) { - if (b->text && b->text->UpdateInset(inset)) { - if (mark_dirty) - b->markDirty(); - break; - } - } -} - - -int BufferList::unlockInset(UpdatableInset *inset) +int BufferList::unlockInset(UpdatableInset * inset) { if (!inset) return 1; - - BufferStorage_Iter biter(bstore); - Buffer *b=0; - while ((b=biter())) { - if (b->the_locking_inset == inset) { - b->InsetUnlock(); + for(BufferStorage::iterator it = bstore.begin(); + it != bstore.end(); ++it) { + if ((*it)->getUser() + && (*it)->getUser()->the_locking_inset == inset) { + (*it)->getUser()->insetUnlock(); return 0; } } @@ -403,17 +221,17 @@ int BufferList::unlockInset(UpdatableInset *inset) } -void BufferList::updateIncludedTeXfiles(LString const & mastertmpdir) +void BufferList::updateIncludedTeXfiles(string const & mastertmpdir) { - BufferStorage_Iter biter(bstore); - Buffer *b=0; - while ((b=biter())) { - if (!b->isDepClean(mastertmpdir)) { - LString writefile = mastertmpdir; + for(BufferStorage::iterator it = bstore.begin(); + it != bstore.end(); ++it) { + if (!(*it)->isDepClean(mastertmpdir)) { + string writefile = mastertmpdir; writefile += '/'; - writefile += ChangeExtension(b->getFileName(), ".tex", true); - b->makeLaTeXFile(writefile,mastertmpdir,false,true); - b->markDepClean(mastertmpdir); + writefile += (*it)->getLatexName(); + (*it)->makeLaTeXFile(writefile, mastertmpdir, + false, true); + (*it)->markDepClean(mastertmpdir); } } } @@ -421,45 +239,50 @@ void BufferList::updateIncludedTeXfiles(LString const & mastertmpdir) void BufferList::emergencyWriteAll() { - BufferStorage_Iter biter(bstore); - Buffer *b=0; - while ((b=biter())) { - if (!b->isLyxClean()) { - bool madeit=false; + for (BufferStorage::iterator it = bstore.begin(); + it != bstore.end(); ++it) { + if (!(*it)->isLyxClean()) { + bool madeit = false; - lyxerr.print(_("lyx: Attempting to save" - " document ") - + b->filename - + _(" as...")); + lyxerr <<_("lyx: Attempting to save" + " document ") + << (*it)->fileName() + << _(" as...") << endl; - for (int i=0; i<3 && !madeit; i++) { - LString s; + for (int i = 0; i < 3 && !madeit; ++i) { + string s; // We try to save three places: // 1) Same place as document. // 2) In HOME directory. // 3) In "/tmp" directory. - if (i==0) { - s = b->filename; - } else if (i==1) { - s = AddName(getEnvPath("HOME"), - b->filename); - } else { // MakeAbsPath to prepend the current drive letter on OS/2 + if (i == 0) { + s = (*it)->fileName(); + } else if (i == 1) { + s = AddName(GetEnvPath("HOME"), + (*it)->fileName()); + } else { + // MakeAbsPath to prepend the current + // drive letter on OS/2 s = AddName(MakeAbsPath("/tmp/"), - b->filename); + (*it)->fileName()); } s += ".emergency"; - lyxerr.print(LString(" ") + (i+1) + ") " + s); + lyxerr << " " << i + 1 << ") " << s << endl; - if (b->writeFile(s,true)) { - b->markLyxClean(); - lyxerr.print(_(" Save seems successful. Phew.")); + if ((*it)->writeFile(s, true)) { + (*it)->markLyxClean(); + lyxerr << _(" Save seems successful. " + "Phew.") << endl; madeit = true; } else if (i != 2) { - lyxerr.print(_(" Save failed! Trying...")); + lyxerr << _(" Save failed! Trying...") + << endl; } else { - lyxerr.print(_(" Save failed! Bummer. Document is lost.")); + lyxerr << _(" Save failed! Bummer. " + "Document is lost.") + << endl; } } } @@ -467,13 +290,13 @@ void BufferList::emergencyWriteAll() } -Buffer* BufferList::readFile(LString const & s, bool ronly) +Buffer * BufferList::readFile(string const & s, bool ronly) { - Buffer *b = bstore.newBuffer(s, lyxrc, ronly); + Buffer * b = bstore.newBuffer(s, ronly); - LString ts = s; - LString e = OnlyPath(s); - LString a = e; + string ts = s; + string e = OnlyPath(s); + string a = e; // File information about normal file FileInfo fileInfo2(s); @@ -487,7 +310,7 @@ Buffer* BufferList::readFile(LString const & s, bool ronly) if (fileInfoE.getModificationTime() > fileInfo2.getModificationTime()) { if (AskQuestion(_("An emergency save of this document exists!"), - MakeDisplayPath(s,50), + MakeDisplayPath(s, 50), _("Try to load that instead?"))) { ts = e; // the file is not saved if we load the @@ -496,7 +319,7 @@ Buffer* BufferList::readFile(LString const & s, bool ronly) use_emergency = true; } else { // Here, we should delete the emergency save - unlink(e.c_str()); + ::unlink(e.c_str()); } } } @@ -511,7 +334,7 @@ Buffer* BufferList::readFile(LString const & s, bool ronly) if (fileInfoA.getModificationTime() > fileInfo2.getModificationTime()) { if (AskQuestion(_("Autosave file is newer."), - MakeDisplayPath(s,50), + MakeDisplayPath(s, 50), _("Load that one instead?"))) { ts = a; // the file is not saved if we load the @@ -519,13 +342,13 @@ Buffer* BufferList::readFile(LString const & s, bool ronly) b->markDirty(); } else { // Here, we should delete the autosave - unlink(a.c_str()); + ::unlink(a.c_str()); } } } } // not sure if this is the correct place to begin LyXLex - LyXLex lex(NULL, 0); + LyXLex lex(0, 0); lex.setFile(ts); if (b->readFile(lex)) return b; @@ -536,42 +359,48 @@ Buffer* BufferList::readFile(LString const & s, bool ronly) } -bool BufferList::exists(LString const & s) +bool BufferList::exists(string const & s) const { - BufferStorage_Iter biter(bstore); - Buffer *b=0; - while ((b=biter())) { - if (b->filename == s) + for (BufferStorage::const_iterator cit = bstore.begin(); + cit != bstore.end(); ++cit) { + if ((*cit)->fileName() == s) return true; } return false; } -Buffer* BufferList::getBuffer(LString const &s) +bool BufferList::isLoaded(Buffer const * b) const { - BufferStorage_Iter biter(bstore); - Buffer *b=0; - while ((b=biter())) { - if (b->filename ==s) - return b; + BufferStorage::const_iterator cit = + find(bstore.begin(), bstore.end(), b); + return cit != bstore.end(); +} + + +Buffer * BufferList::getBuffer(string const & s) +{ + for(BufferStorage::iterator it = bstore.begin(); + it != bstore.end(); ++it) { + if ((*it)->fileName() == s) + return (*it); } return 0; } -Buffer* BufferList::newFile(LString const & name, LString tname) +Buffer * BufferList::newFile(string const & name, string tname) { - /* get a free buffer */ - Buffer *b = bstore.newBuffer(name, lyxrc); + // get a free buffer + Buffer * b = bstore.newBuffer(name); // use defaults.lyx as a default template if it exists. if (tname.empty()) { tname = LibFileSearch("templates", "defaults.lyx"); } - if (!tname.empty() && IsLyXFilename(tname)){ + if (!tname.empty() && IsLyXFilename(tname)) { bool templateok = false; - LyXLex lex(NULL,0); + LyXLex lex(0, 0); lex.setFile(tname); if (lex.IsOK()) { if (b->readFile(lex)) { @@ -579,14 +408,14 @@ Buffer* BufferList::newFile(LString const & name, LString tname) } } if (!templateok) { - WriteAlert(_("Error!"),_("Unable to open template"), + WriteAlert(_("Error!"), _("Unable to open template"), MakeDisplayPath(tname)); // no template, start with empty buffer - b->paragraph = new LyXParagraph(); + b->paragraph = new LyXParagraph; } } else { // start with empty buffer - b->paragraph = new LyXParagraph(); + b->paragraph = new LyXParagraph; } b->markDirty(); @@ -596,35 +425,15 @@ Buffer* BufferList::newFile(LString const & name, LString tname) } -Buffer* BufferList::loadLyXFile(LString const & filename, bool tolastfiles) +Buffer * BufferList::loadLyXFile(string const & filename, bool tolastfiles) { // make sure our path is absolute - LString s = MakeAbsPath(filename); - - // Is this done too early? - // Is it LinuxDoc? - if (IsSGMLFilename(s)) { - FileInfo fi(s); - if (fi.exist() && fi.readable()) { - if (!RunLinuxDoc(-1, s)) { - s = ChangeExtension (s, ".lyx", false); - } else { // sgml2lyx failed - WriteAlert(_("Error!"), - _("Could not convert file"),s); - return 0; - } - } else { - // just change the extension and it will be - // handled like a regular lyx file that does - // not exist. - s = ChangeExtension(s, ".lyx", false); - } - } - + string s = MakeAbsPath(filename); + // file already open? if (exists(s)) { if (AskQuestion(_("Document is already open:"), - MakeDisplayPath(s,50), + MakeDisplayPath(s, 50), _("Do you want to reload that document?"))) { // Reload is accomplished by closing and then loading if (!close(getBuffer(s))) { @@ -637,16 +446,19 @@ Buffer* BufferList::loadLyXFile(LString const & filename, bool tolastfiles) return getBuffer(s); } } - Buffer *b=0; + Buffer * b = 0; bool ro = false; switch (IsFileWriteable(s)) { case 0: - minibuffer->Set(_("File `")+MakeDisplayPath(s,50)+ - _("' is read-only.")); +#if 0 + current_view->owner()->getMiniBuffer()-> + Set(_("File `") + MakeDisplayPath(s, 50) + + _("' is read-only.")); +#endif ro = true; // Fall through case 1: - b=readFile(s, ro); + b = readFile(s, ro); if (b) { b->lyxvc.file_found_hook(s); } @@ -656,20 +468,26 @@ Buffer* BufferList::loadLyXFile(LString const & filename, bool tolastfiles) if (LyXVC::file_not_found_hook(s)) { // Ask if the file should be checked out for // viewing/editing, if so: load it. - lyxerr.print("Do you want to checkout?"); + if (AskQuestion(_("Do you want to retrieve file under version control?"))) { + // How can we know _how_ to do the checkout? + // With the current VC support it has to be, + // a RCS file since CVS do not have special ,v files. + RCS::retrive(s); + return loadLyXFile(filename, tolastfiles); + } } if (AskQuestion(_("Cannot open specified file:"), - MakeDisplayPath(s,50), + MakeDisplayPath(s, 50), _("Create new document with this name?"))) - { - // Find a free buffer - b = newFile(s,LString()); - } + { + // Find a free buffer + b = newFile(s, string()); + } break; } if (b && tolastfiles) - lastfiles->newFile(b->getFileName()); + lastfiles->newFile(b->fileName()); return b; }