diff --git a/src/BufferView.cpp b/src/BufferView.cpp index 5754d6ed29..e4a845ff17 100644 --- a/src/BufferView.cpp +++ b/src/BufferView.cpp @@ -901,12 +901,12 @@ Update::flags BufferView::dispatch(FuncRequest const & cmd) case LFUN_FILE_INSERT_PLAINTEXT_PARA: // FIXME UNICODE - insertPlaintextFile(to_utf8(cmd.argument()), true); + insertPlaintextFile(FileName(to_utf8(cmd.argument())), true); break; case LFUN_FILE_INSERT_PLAINTEXT: // FIXME UNICODE - insertPlaintextFile(to_utf8(cmd.argument()), false); + insertPlaintextFile(FileName(to_utf8(cmd.argument())), false); break; case LFUN_FONT_STATE: @@ -1995,11 +1995,9 @@ void BufferView::setGuiDelegate(frontend::GuiBufferViewDelegate * gui) // FIXME: Move this out of BufferView again -docstring BufferView::contentsOfPlaintextFile(string const & f, +docstring BufferView::contentsOfPlaintextFile(FileName const & fname, bool asParagraph) { - FileName fname(f); - if (fname.empty()) { FileDialog dlg(_("Select file to insert"), ( asParagraph @@ -2016,7 +2014,7 @@ docstring BufferView::contentsOfPlaintextFile(string const & f, if (result.second.empty()) return docstring(); - fname = makeAbsPath(to_utf8(result.second)); + return contentsOfPlaintextFile(FileName(to_utf8(result.second)), false); } if (!fname.isReadableFile()) { @@ -2029,36 +2027,16 @@ docstring BufferView::contentsOfPlaintextFile(string const & f, return docstring(); } - ifstream ifs(fname.toFilesystemEncoding().c_str()); - if (!ifs) { - docstring const error = from_ascii(strerror(errno)); + if (!fname.isReadableFile()) { docstring const file = makeDisplayPath(fname.absFilename(), 50); docstring const text = - bformat(_("Could not open the specified document\n" - "%1$s\ndue to the error: %2$s"), file, error); + bformat(_("%1$s\n is not readable."), file); Alert::error(_("Could not open file"), text); return docstring(); } - ifs.unsetf(std::ios::skipws); - istream_iterator ii(ifs); - istream_iterator end; -#if !defined(USE_INCLUDED_STRING) && !defined(STD_STRING_IS_GOOD) - // We use this until the compilers get better... - std::vector tmp; - copy(ii, end, back_inserter(tmp)); - string const tmpstr(tmp.begin(), tmp.end()); -#else - // This is what we want to use and what we will use once the - // compilers get good enough. - //string tmpstr(ii, end); // yet a reason for using std::string - // alternate approach to get the file into a string: - string tmpstr; - copy(ii, end, back_inserter(tmpstr)); -#endif - // FIXME UNICODE: We don't know the encoding of the file - docstring file_content = from_utf8(tmpstr); + docstring file_content = fname.fileContents("UTF-8"); if (file_content.empty()) { Alert::error(_("Reading not UTF-8 encoded file"), _("The file is not UTF-8 encoded.\n" @@ -2066,14 +2044,14 @@ docstring BufferView::contentsOfPlaintextFile(string const & f, "If this does not give the correct result\n" "then please change the encoding of the file\n" "to UTF-8 with a program other than LyX.\n")); - file_content = from_local8bit(tmpstr); + file_content = fname.fileContents("local8bit"); } return normalize_c(file_content); } -void BufferView::insertPlaintextFile(string const & f, bool asParagraph) +void BufferView::insertPlaintextFile(FileName const & f, bool asParagraph) { docstring const tmpstr = contentsOfPlaintextFile(f, asParagraph); diff --git a/src/BufferView.h b/src/BufferView.h index 92fd310727..847d67ab29 100644 --- a/src/BufferView.h +++ b/src/BufferView.h @@ -241,9 +241,10 @@ public: void setGuiDelegate(frontend::GuiBufferViewDelegate *); /// - docstring contentsOfPlaintextFile(std::string const & f, bool asParagraph); + docstring contentsOfPlaintextFile(support::FileName const & f, + bool asParagraph); // Insert plain text file (if filename is empty, prompt for one) - void insertPlaintextFile(std::string const & fileName, bool asParagraph); + void insertPlaintextFile(support::FileName const & f, bool asParagraph); private: /// noncopyable diff --git a/src/LyXFunc.cpp b/src/LyXFunc.cpp index 7e9fe5a3da..62db7bd67a 100644 --- a/src/LyXFunc.cpp +++ b/src/LyXFunc.cpp @@ -194,7 +194,7 @@ bool import(LyXView * lv, FileName const & filename, string filename2 = (loader_format == format) ? filename.absFilename() : changeExtension(filename.absFilename(), formats.extension(loader_format)); - lv->view()->insertPlaintextFile(filename2, as_paragraphs); + lv->view()->insertPlaintextFile(FileName(filename2), as_paragraphs); theLyXFunc().setLyXView(lv); lyx::dispatch(FuncRequest(LFUN_MARK_OFF)); } diff --git a/src/frontends/qt4/GuiShowFile.cpp b/src/frontends/qt4/GuiShowFile.cpp index ed0b6b2b27..76f273345d 100644 --- a/src/frontends/qt4/GuiShowFile.cpp +++ b/src/frontends/qt4/GuiShowFile.cpp @@ -51,9 +51,9 @@ void GuiShowFile::updateContents() { setWindowTitle(toqstr(onlyFilename(filename_.absFilename()))); - std::string contents = filename_.fileContents(); + docstring contents = filename_.fileContents("UTF-8"); if (contents.empty()) - contents = "Error -> Cannot load file!"; + contents = _("Error -> Cannot load file!"); textTB->setPlainText(toqstr(contents)); } diff --git a/src/frontends/qt4/GuiTexinfo.cpp b/src/frontends/qt4/GuiTexinfo.cpp index f434c6721f..23b0b39b5f 100644 --- a/src/frontends/qt4/GuiTexinfo.cpp +++ b/src/frontends/qt4/GuiTexinfo.cpp @@ -68,7 +68,8 @@ static string texFileFromList(string const & file, string const & type) lyxerr << "File `'" << lstfile << "' not found." << endl; return string(); } - string const allClasses = abslstfile.fileContents(); + // FIXME UNICODE + string const allClasses = to_utf8(abslstfile.fileContents("UTF-8")); int entries = 0; string classfile = token(allClasses, '\n', entries); int count = 0; diff --git a/src/frontends/qt4/qt_helpers.cpp b/src/frontends/qt4/qt_helpers.cpp index 1bb5d6eda0..02a344ef9e 100644 --- a/src/frontends/qt4/qt_helpers.cpp +++ b/src/frontends/qt4/qt_helpers.cpp @@ -348,14 +348,16 @@ void getTexFileList(string const & filename, std::vector & list) if (file.empty()) return; - list = getVectorFromString(file.fileContents(), "\n"); + // FIXME Unicode. + std::vector doclist = + getVectorFromString(file.fileContents("UTF-8"), from_ascii("\n")); // Normalise paths like /foo//bar ==> /foo/bar boost::RegEx regex("/{2,}"); - std::vector::iterator it = list.begin(); - std::vector::iterator end = list.end(); + std::vector::iterator it = doclist.begin(); + std::vector::iterator end = doclist.end(); for (; it != end; ++it) - *it = regex.Merge((*it), "/"); + list.push_back(regex.Merge(to_utf8(*it), "/")); // remove empty items and duplicates list.erase(std::remove(list.begin(), list.end(), ""), list.end()); diff --git a/src/insets/ExternalSupport.cpp b/src/insets/ExternalSupport.cpp index 4da96e81bc..108df0e555 100644 --- a/src/insets/ExternalSupport.cpp +++ b/src/insets/ExternalSupport.cpp @@ -187,7 +187,8 @@ string const doSubstitution(InsetExternalParams const & params, FileName const absfile( support::makeAbsPath(file, masterBuffer->temppath())); if (absfile.isReadableFile()) - contents = absfile.fileContents(); + // FIXME UNICODE + contents = to_utf8(absfile.fileContents("UTF-8")); size_t const pos = result.find("$$Contents(\""); size_t const end = result.find("\")", pos); diff --git a/src/insets/InsetGraphics.cpp b/src/insets/InsetGraphics.cpp index a5d6c61a42..be567ce62e 100644 --- a/src/insets/InsetGraphics.cpp +++ b/src/insets/InsetGraphics.cpp @@ -495,6 +495,7 @@ enum GraphicsCopyStatus { std::pair const copyFileIfNeeded(FileName const & file_in, FileName const & file_out) { + LYXERR(Debug::FILES, "Comparing " << file_in << " and " << file_out); unsigned long const checksum_in = file_in.checksum(); unsigned long const checksum_out = file_out.checksum(); diff --git a/src/insets/InsetInclude.cpp b/src/insets/InsetInclude.cpp index 957bd8a033..4099175314 100644 --- a/src/insets/InsetInclude.cpp +++ b/src/insets/InsetInclude.cpp @@ -563,10 +563,8 @@ int InsetInclude::plaintext(Buffer const & buffer, odocstream & os, { if (isVerbatim(params()) || isListings(params())) { os << '[' << getScreenLabel(buffer) << '\n'; - // FIXME: We don't know the encoding of the file - docstring const str = - from_utf8(includedFilename(buffer, params()).fileContents()); - os << str; + // FIXME: We don't know the encoding of the file, default to UTF-8. + os << includedFilename(buffer, params()).fileContents("UTF-8"); os << "\n]"; return PLAINTEXT_NEWLINE + 1; // one char on a separate line } else { diff --git a/src/insets/InsetTabular.cpp b/src/insets/InsetTabular.cpp index 53fac2ceac..5c6affae0b 100644 --- a/src/insets/InsetTabular.cpp +++ b/src/insets/InsetTabular.cpp @@ -48,6 +48,7 @@ #include "support/convert.h" #include "support/docstream.h" +#include "support/FileName.h" #include "support/lstrings.h" #include "frontends/alert.h" @@ -83,6 +84,7 @@ using boost::dynamic_pointer_cast; namespace lyx { using support::prefixIs; +using support::FileName; using support::ltrim; using support::rtrim; using support::suffixIs; @@ -3408,7 +3410,8 @@ void InsetTabular::doDispatch(Cursor & cur, FuncRequest & cmd) case LFUN_FILE_INSERT_PLAINTEXT_PARA: case LFUN_FILE_INSERT_PLAINTEXT: { // FIXME UNICODE - docstring const tmpstr = cur.bv().contentsOfPlaintextFile(to_utf8(cmd.argument()), false); + docstring const tmpstr = cur.bv().contentsOfPlaintextFile( + FileName(to_utf8(cmd.argument())), false); if (!tmpstr.empty() && !insertPlaintextString(cur.bv(), tmpstr, false)) cur.undispatched(); break; diff --git a/src/support/FileName.cpp b/src/support/FileName.cpp index e45c805661..cc476eecc8 100644 --- a/src/support/FileName.cpp +++ b/src/support/FileName.cpp @@ -338,20 +338,40 @@ docstring FileName::displayName(int threshold) const } -string FileName::fileContents() const +docstring FileName::fileContents(string const & encoding) const { - if (exists()) { - string const encodedname = toFilesystemEncoding(); - ifstream ifs(encodedname.c_str()); - ostringstream ofs; - if (ifs && ofs) { - ofs << ifs.rdbuf(); - ifs.close(); - return ofs.str(); - } + if (!isReadableFile()) { + LYXERR0("File '" << *this + << "' is not redable!"); + return docstring(); } - lyxerr << "LyX was not able to read file '" << *this << '\'' << std::endl; - return string(); + + QFile file(d->fi.absoluteFilePath()); + if (!file.open(QIODevice::ReadOnly)) { + LYXERR0("File '" << *this + << "' could not be opened in read only mode!"); + return docstring(); + } + QByteArray contents = file.readAll(); + file.close(); + + if (contents.isEmpty()) { + LYXERR(Debug::FILES, "File '" << *this + << "' is either empty or some error happened while reading it."); + return docstring(); + } + + QString s; + if (encoding.empty() || encoding == "UTF-8") + s = QString::fromUtf8(contents.data()); + else if (encoding == "ascii") + s = QString::fromAscii(contents.data()); + else if (encoding == "local8bit") + s = QString::fromLocal8Bit(contents.data()); + else if (encoding == "latin1") + s = QString::fromLatin1(contents.data()); + + return qstring_to_ucs4(s); } diff --git a/src/support/FileName.h b/src/support/FileName.h index 519ba896ac..be47e158f7 100644 --- a/src/support/FileName.h +++ b/src/support/FileName.h @@ -98,14 +98,12 @@ public: /// Creates directory. Returns true on success bool createDirectory(int permissions) const; - /// Get the contents of a file as a huge std::string - std::string fileContents() const; - /** - * Get a FileName from \p name in the encoding used by the file system. - * Only use this for filenames you got directly from the file system, - * e.g. from reading a directory. - * \p name must have an absolute path. - */ + /// Get the contents of a file as a huge docstring. + /// \param encoding defines the encoding of the file contents. + /// Only four encodings are supported: + /// "UTF-8", "ascii", "latin1" and "local8bit" which uses the + /// current system locale. + docstring fileContents(std::string const & encoding) const; /// Change extension. /**