mirror of
https://git.lyx.org/repos/lyx.git
synced 2024-12-12 16:50:39 +00:00
Fix bug #5238: LyX 1.6 fails with non-ascii chars in path (on Windows)
git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/branches/BRANCH_1_6_X@33577 a592a061-630c-0410-9148-cb99ea01b6c8
This commit is contained in:
parent
3394f063f5
commit
f024c86911
@ -222,7 +222,7 @@ AC_LANG_POP(C)
|
||||
# some standard header files
|
||||
AC_HEADER_DIRENT
|
||||
AC_HEADER_MAJOR
|
||||
AC_CHECK_HEADERS(sys/time.h sys/types.h sys/select.h strings.h locale.h io.h process.h NewAPIs.h utime.h sys/utime.h)
|
||||
AC_CHECK_HEADERS(sys/time.h sys/types.h sys/select.h strings.h locale.h io.h process.h utime.h sys/utime.h)
|
||||
|
||||
# some standard structures
|
||||
AC_HEADER_STAT
|
||||
@ -360,10 +360,6 @@ char * strerror(int n);
|
||||
# define BOOST_POSIX_PATH 1
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_NEWAPIS_H)
|
||||
# define WANT_GETFILEATTRIBUTESEX_WRAPPER 1
|
||||
#endif
|
||||
|
||||
/*
|
||||
* the FreeBSD libc uses UCS4, but libstdc++ has no proper wchar_t
|
||||
* support compiled in:
|
||||
|
@ -364,6 +364,12 @@ if(MSVC)
|
||||
"${CMAKE_CXX_FLAGS_MINSIZEREL} ${MSVC_W_ERROR} ${MSVC_W_DISABLE}")
|
||||
|
||||
endif()
|
||||
set(CMAKE_CXX_FLAGS_DEBUG
|
||||
"${CMAKE_CXX_FLAGS_DEBUG} /Zc:wchar_t-")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE
|
||||
"${CMAKE_CXX_FLAGS_RELEASE} /Zc:wchar_t-")
|
||||
set(CMAKE_CXX_FLAGS_MINSIZEREL
|
||||
"${CMAKE_CXX_FLAGS_MINSIZEREL} /Zc:wchar_t-")
|
||||
|
||||
message(STATUS "----- Warning level : ${CMAKE_CXX_WARNING_LEVEL} ${WARNING_LEVEL_MESSAGE}")
|
||||
message(STATUS "----- Warnings as errors : ${MSVC_W_ERROR}")
|
||||
|
@ -149,10 +149,6 @@
|
||||
# define BOOST_POSIX_PATH 1
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_NEWAPIS_H
|
||||
# define WANT_GETFILEATTRIBUTESEX_WRAPPER 1
|
||||
#endif
|
||||
|
||||
/*
|
||||
* the FreeBSD libc uses UCS4, but libstdc++ has no proper wchar_t
|
||||
* support compiled in:
|
||||
|
@ -146,10 +146,6 @@
|
||||
# define BOOST_POSIX_PATH 1
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_NEWAPIS_H
|
||||
# define WANT_GETFILEATTRIBUTESEX_WRAPPER 1
|
||||
#endif
|
||||
|
||||
/*
|
||||
* the FreeBSD libc uses UCS4, but libstdc++ has no proper wchar_t
|
||||
* support compiled in:
|
||||
|
@ -411,6 +411,7 @@ if platform_name == 'win32':
|
||||
# hard-coded options are required and will always be there
|
||||
# default options can be replaced by enviromental variables or command line options
|
||||
CCFLAGS_required = []
|
||||
CXXFLAGS_required = []
|
||||
LINKFLAGS_required = []
|
||||
CCFLAGS_default = []
|
||||
|
||||
@ -420,6 +421,7 @@ if use_vc:
|
||||
# in the current code page (number)
|
||||
# C4996: foo was decleared deprecated
|
||||
CCFLAGS_required.append('/EHsc')
|
||||
CXXFLAGS_required.append('/Zc:wchar_t-')
|
||||
if mode == 'debug':
|
||||
CCFLAGS_default.extend(['/wd4819', '/wd4996', '/nologo', '/MDd'])
|
||||
else:
|
||||
@ -514,7 +516,7 @@ setEnvVariable(env, 'CPP')
|
||||
setEnvVariable(env, 'CXX')
|
||||
setEnvVariable(env, 'CXXCPP')
|
||||
setEnvVariable(env, 'CCFLAGS', CCFLAGS_required, CCFLAGS_default)
|
||||
setEnvVariable(env, 'CXXFLAGS')
|
||||
setEnvVariable(env, 'CXXFLAGS', CXXFLAGS_required)
|
||||
setEnvVariable(env, 'CPPFLAGS')
|
||||
setEnvVariable(env, 'LINKFLAGS', LINKFLAGS_required)
|
||||
|
||||
@ -740,7 +742,6 @@ utils.createConfigFile(conf,
|
||||
('ostream', 'HAVE_OSTREAM', 'cxx'),
|
||||
('locale', 'HAVE_LOCALE', 'cxx'),
|
||||
('sstream', 'HAVE_SSTREAM', 'cxx'),
|
||||
#('newapis.h', 'HAVE_NEWAPIS_H', 'c'),
|
||||
],
|
||||
custom_tests = [
|
||||
(env.has_key('assertions') and env['assertions'] and mode == 'debug',
|
||||
@ -775,10 +776,6 @@ utils.createConfigFile(conf,
|
||||
|
||||
#define BOOST_ALL_NO_LIB 1
|
||||
|
||||
#if defined(HAVE_NEWAPIS_H)
|
||||
# define WANT_GETFILEATTRIBUTESEX_WRAPPER 1
|
||||
#endif
|
||||
|
||||
/*
|
||||
* the FreeBSD libc uses UCS4, but libstdc++ has no proper wchar_t
|
||||
* support compiled in:
|
||||
|
@ -440,6 +440,7 @@ int main() {
|
||||
def checkSizeOfWChar(conf):
|
||||
''' check the size of wchar '''
|
||||
check_sizeof_wchar = '''
|
||||
#include <wchar.h>
|
||||
int i[ ( sizeof(wchar_t)==%d ? 1 : -1 ) ];
|
||||
int main()
|
||||
{
|
||||
|
@ -817,7 +817,7 @@ Buffer::ReadStatus Buffer::readFile(Lexer & lex, FileName const & filename,
|
||||
<< ' ' << quoteName(lyx2lyx.toFilesystemEncoding())
|
||||
<< " -t " << convert<string>(LYX_FORMAT)
|
||||
<< " -o " << quoteName(tmpfile.toFilesystemEncoding())
|
||||
<< ' ' << quoteName(filename.toFilesystemEncoding());
|
||||
<< ' ' << quoteName(filename.toSafeFilesystemEncoding());
|
||||
string const command_str = command.str();
|
||||
|
||||
LYXERR(Debug::INFO, "Running '" << command_str << '\'');
|
||||
@ -856,8 +856,6 @@ bool Buffer::save() const
|
||||
// We don't need autosaves in the immediate future. (Asger)
|
||||
resetAutosaveTimers();
|
||||
|
||||
string const encodedFilename = d->filename.toFilesystemEncoding();
|
||||
|
||||
FileName backupName;
|
||||
bool madeBackup = false;
|
||||
|
||||
@ -915,11 +913,13 @@ bool Buffer::writeFile(FileName const & fname) const
|
||||
makeDisplayPath(fname.absFilename()));
|
||||
message(str);
|
||||
|
||||
string const encoded_fname = fname.toSafeFilesystemEncoding(os::CREATE);
|
||||
|
||||
if (params().compressed) {
|
||||
gz::ogzstream ofs(fname.toFilesystemEncoding().c_str(), ios::out|ios::trunc);
|
||||
gz::ogzstream ofs(encoded_fname.c_str(), ios::out|ios::trunc);
|
||||
retval = ofs && write(ofs);
|
||||
} else {
|
||||
ofstream ofs(fname.toFilesystemEncoding().c_str(), ios::out|ios::trunc);
|
||||
ofstream ofs(encoded_fname.c_str(), ios::out|ios::trunc);
|
||||
retval = ofs && write(ofs);
|
||||
}
|
||||
|
||||
|
@ -264,7 +264,7 @@ bool Lexer::Pimpl::setFile(FileName const & filename)
|
||||
LYXERR(Debug::LYXLEX, "Error in Lexer::setFile: "
|
||||
"file or stream already set.");
|
||||
}
|
||||
fb_.open(filename.toFilesystemEncoding().c_str(), ios::in);
|
||||
fb_.open(filename.toSafeFilesystemEncoding().c_str(), ios::in);
|
||||
is.rdbuf(&fb_);
|
||||
name = filename.absFilename();
|
||||
lineno = 0;
|
||||
|
10
src/LyX.cpp
10
src/LyX.cpp
@ -257,7 +257,7 @@ int LyX::exec(int & argc, char * argv[])
|
||||
easyParse(argc, argv);
|
||||
|
||||
try {
|
||||
init_package(to_utf8(from_local8bit(argv[0])),
|
||||
init_package(os::utf8_argv(0),
|
||||
cl_system_support, cl_user_support,
|
||||
top_build_dir_is_one_level_up);
|
||||
} catch (ExceptionMessage const & message) {
|
||||
@ -414,7 +414,7 @@ int LyX::init(int & argc, char * argv[])
|
||||
if (argv[argi][0] == '-') {
|
||||
lyxerr << to_utf8(
|
||||
bformat(_("Wrong command line option `%1$s'. Exiting."),
|
||||
from_utf8(argv[argi]))) << endl;
|
||||
from_utf8(os::utf8_argv(argi)))) << endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
@ -428,7 +428,7 @@ int LyX::init(int & argc, char * argv[])
|
||||
|
||||
// Remaining arguments are assumed to be files to load.
|
||||
for (int argi = argc - 1; argi >= 1; --argi)
|
||||
pimpl_->files_to_load_.push_back(to_utf8(from_local8bit(argv[argi])));
|
||||
pimpl_->files_to_load_.push_back(os::utf8_argv(argi));
|
||||
|
||||
if (first_start) {
|
||||
pimpl_->files_to_load_.push_back(
|
||||
@ -1096,9 +1096,9 @@ void LyX::easyParse(int & argc, char * argv[])
|
||||
continue;
|
||||
|
||||
string const arg =
|
||||
(i + 1 < argc) ? to_utf8(from_local8bit(argv[i + 1])) : string();
|
||||
(i + 1 < argc) ? os::utf8_argv(i + 1) : string();
|
||||
string const arg2 =
|
||||
(i + 2 < argc) ? to_utf8(from_local8bit(argv[i + 2])) : string();
|
||||
(i + 2 < argc) ? os::utf8_argv(i + 2) : string();
|
||||
|
||||
string batch;
|
||||
int const remove = 1 + it->second(arg, arg2, batch);
|
||||
|
@ -208,8 +208,8 @@ static string const move_file(string const & from_file, string const & to_file)
|
||||
return string();
|
||||
|
||||
ostringstream command;
|
||||
command << "fromfile = utf8ToDefaultEncoding(" << from_file << ")\n"
|
||||
<< "tofile = utf8ToDefaultEncoding(" << to_file << ")\n\n"
|
||||
command << "fromfile = toUnicode(" << from_file << ")\n"
|
||||
<< "tofile = toUnicode(" << to_file << ")\n\n"
|
||||
<< "try:\n"
|
||||
<< " os.rename(fromfile, tofile)\n"
|
||||
<< "except:\n"
|
||||
@ -264,20 +264,17 @@ static void build_script(FileName const & from_file,
|
||||
|
||||
script << "#!/usr/bin/env python\n"
|
||||
"# -*- coding: utf-8 -*-\n"
|
||||
"import os, shutil, sys, locale\n\n"
|
||||
"import os, shutil, sys\n\n"
|
||||
"def unlinkNoThrow(file):\n"
|
||||
" ''' remove a file, do not throw if an error occurs '''\n"
|
||||
" try:\n"
|
||||
" os.unlink(file)\n"
|
||||
" except:\n"
|
||||
" pass\n\n"
|
||||
"def utf8ToDefaultEncoding(file):\n"
|
||||
" ''' if possible, convert to the default encoding '''\n"
|
||||
"def toUnicode(file):\n"
|
||||
" ''' if possible, convert to python unicode format '''\n"
|
||||
" try:\n"
|
||||
" language, output_encoding = locale.getdefaultlocale()\n"
|
||||
" if output_encoding == None:\n"
|
||||
" output_encoding = 'latin1'\n"
|
||||
" return unicode(file, 'utf8').encode(output_encoding)\n"
|
||||
" return unicode(file, 'utf8')\n"
|
||||
" except:\n"
|
||||
" return file\n\n";
|
||||
|
||||
@ -301,10 +298,10 @@ static void build_script(FileName const & from_file,
|
||||
// in python, but the converters might be shell scripts and have more
|
||||
// troubles with it.
|
||||
string outfile = addExtension(to_base.absFilename(), getExtension(from_file.absFilename()));
|
||||
script << "infile = utf8ToDefaultEncoding("
|
||||
script << "infile = toUnicode("
|
||||
<< quoteName(from_file.absFilename(), quote_python)
|
||||
<< ")\n"
|
||||
"outfile = utf8ToDefaultEncoding("
|
||||
"outfile = toUnicode("
|
||||
<< quoteName(outfile, quote_python) << ")\n"
|
||||
"shutil.copy(infile, outfile)\n";
|
||||
|
||||
@ -313,7 +310,7 @@ static void build_script(FileName const & from_file,
|
||||
// This has the added benefit that all other files that may be
|
||||
// generated by the converter are deleted when LyX closes and do not
|
||||
// clutter the real working directory.
|
||||
script << "os.chdir(utf8ToDefaultEncoding("
|
||||
script << "os.chdir(toUnicode("
|
||||
<< quoteName(onlyPath(outfile)) << "))\n";
|
||||
|
||||
if (edgepath.empty()) {
|
||||
@ -321,7 +318,7 @@ static void build_script(FileName const & from_file,
|
||||
// converter path from from_format to to_format, so we use
|
||||
// the default converter.
|
||||
script << "infile = outfile\n"
|
||||
<< "outfile = utf8ToDefaultEncoding("
|
||||
<< "outfile = toUnicode("
|
||||
<< quoteName(to_file, quote_python) << ")\n";
|
||||
|
||||
ostringstream os;
|
||||
@ -362,11 +359,11 @@ static void build_script(FileName const & from_file,
|
||||
outfile = addExtension(to_base.absFilename(), conv.To->extension());
|
||||
|
||||
// Store these names in the python script
|
||||
script << "infile = utf8ToDefaultEncoding("
|
||||
script << "infile = toUnicode("
|
||||
<< quoteName(infile, quote_python) << ")\n"
|
||||
"infile_base = utf8ToDefaultEncoding("
|
||||
"infile_base = toUnicode("
|
||||
<< quoteName(infile_base, quote_python) << ")\n"
|
||||
"outfile = utf8ToDefaultEncoding("
|
||||
"outfile = toUnicode("
|
||||
<< quoteName(outfile, quote_python) << ")\n";
|
||||
|
||||
// See comment about extra " quotes above (although that
|
||||
|
@ -80,6 +80,7 @@ extern "C" int mkstemp(char *);
|
||||
#endif // SUM_WITH_MMAP
|
||||
|
||||
using namespace std;
|
||||
using namespace lyx::support;
|
||||
|
||||
// OK, this is ugly, but it is the only workaround I found to compile
|
||||
// with gcc (any version) on a system which uses a non-GNU toolchain.
|
||||
@ -204,7 +205,7 @@ string FileName::absFilename() const
|
||||
|
||||
string FileName::realPath() const
|
||||
{
|
||||
return os::real_path(toFilesystemEncoding());
|
||||
return os::real_path(absFilename());
|
||||
}
|
||||
|
||||
|
||||
@ -284,13 +285,22 @@ bool FileName::changePermission(unsigned long int mode) const
|
||||
|
||||
string FileName::toFilesystemEncoding() const
|
||||
{
|
||||
// FIXME: This doesn't work on Windows for non ascii file names with Qt < 4.4.
|
||||
// Provided that Windows package uses Qt4.4, this isn't a problem.
|
||||
// This doesn't work on Windows for non ascii file names.
|
||||
QByteArray const encoded = QFile::encodeName(d->fi.absoluteFilePath());
|
||||
return string(encoded.begin(), encoded.end());
|
||||
}
|
||||
|
||||
|
||||
string FileName::toSafeFilesystemEncoding(os::file_access how) const
|
||||
{
|
||||
// This will work on Windows for non ascii file names.
|
||||
QString const safe_path =
|
||||
toqstr(os::safe_internal_path(absFilename(), how));
|
||||
QByteArray const encoded = QFile::encodeName(safe_path);
|
||||
return string(encoded.begin(), encoded.end());
|
||||
}
|
||||
|
||||
|
||||
FileName FileName::fromFilesystemEncoding(string const & name)
|
||||
{
|
||||
QByteArray const encoded(name.c_str(), name.length());
|
||||
@ -536,7 +546,7 @@ unsigned long FileName::checksum() const
|
||||
|
||||
#else // QT_VERSION
|
||||
|
||||
string const encoded = toFilesystemEncoding();
|
||||
string const encoded = toSafeFilesystemEncoding();
|
||||
char const * file = encoded.c_str();
|
||||
|
||||
#ifdef SUM_WITH_MMAP
|
||||
|
@ -12,6 +12,7 @@
|
||||
#ifndef FILENAME_H
|
||||
#define FILENAME_H
|
||||
|
||||
#include "support/os.h"
|
||||
#include "support/strfwd.h"
|
||||
|
||||
#include <ctime>
|
||||
@ -72,10 +73,25 @@ public:
|
||||
|
||||
/**
|
||||
* Get the file name in the encoding used by the file system.
|
||||
* Only use this for accessing the file, e.g. with an fstream.
|
||||
* Only use this for passing file names to external commands.
|
||||
* Warning: On Windows this is not unicode safe and should not
|
||||
* be used for accessing files with an fstream, for example.
|
||||
*/
|
||||
std::string toFilesystemEncoding() const;
|
||||
|
||||
/**
|
||||
* Get the file name in a unicode safe encoding used by the file system.
|
||||
* Only use this for accessing the file with standard I/O functions
|
||||
* non explicitly unicode aware, e.g. with an fstream. This can also
|
||||
* be used for passing file names to external commands, but only if
|
||||
* you are sure that the stem of the name will not be used for
|
||||
* producing derivative files. For example, don't use this for passing
|
||||
* file names to LaTeX, as the stem of the .dvi file will not correspond
|
||||
* to the stem of the .tex file anymore.
|
||||
* Use os::CREATE if the file is to be accessed for writing.
|
||||
*/
|
||||
std::string toSafeFilesystemEncoding(os::file_access how = os::EXISTING) const;
|
||||
|
||||
/// returns true if the file exists
|
||||
bool exists() const;
|
||||
/// refreshes the file info
|
||||
|
@ -32,9 +32,17 @@ enum path_case {
|
||||
CASE_ADJUSTED
|
||||
};
|
||||
|
||||
enum file_access {
|
||||
EXISTING,
|
||||
CREATE
|
||||
};
|
||||
|
||||
/// Do some work just once.
|
||||
void init(int argc, char * argv[]);
|
||||
|
||||
/// Returns the i-th program argument in utf8 encoding.
|
||||
std::string utf8_argv(int i);
|
||||
|
||||
/// Returns the name of the NULL device (/dev/null, null).
|
||||
std::string const & nulldev();
|
||||
|
||||
@ -64,6 +72,15 @@ std::string external_path(std::string const & p);
|
||||
/// \p p and the return value are encoded in utf8.
|
||||
std::string internal_path(std::string const & p);
|
||||
|
||||
/// Converts a host OS style path to a unicode safe unix style.
|
||||
/// On Windows, this is achieved by using the short form of the path,
|
||||
/// which can be safely passed to standard I/O functions expecting narrow
|
||||
/// char paths even when the path contains non-ascii chars.
|
||||
/// As the short form is only available for existing files, if the file is
|
||||
/// to be accessed for writing, \param how should be set to CREATE.
|
||||
/// \p p and the return value are encoded in utf8.
|
||||
std::string safe_internal_path(std::string const & p, file_access how = EXISTING);
|
||||
|
||||
/// Converts a unix style path list to host OS style.
|
||||
/// \p p and the return value are encoded in utf8.
|
||||
std::string external_path_list(std::string const & p);
|
||||
@ -120,8 +137,7 @@ bool canAutoOpenFile(std::string const & ext, auto_open_mode const mode = VIEW);
|
||||
bool autoOpenFile(std::string const & filename, auto_open_mode const mode = VIEW);
|
||||
|
||||
/** Resolves a path such that it does not contain '.', '..', or symbolic links.
|
||||
* \warning the path must already be in the filesystem encoding.
|
||||
* \returns the resolved path in utf8 encoding.
|
||||
* \p path and the return value are encoded in utf8.
|
||||
*/
|
||||
std::string real_path(std::string const & path);
|
||||
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include "support/os.h"
|
||||
|
||||
#include "support/FileName.h"
|
||||
#include "support/lassert.h"
|
||||
#include "support/lstrings.h"
|
||||
#include "support/debug.h"
|
||||
|
||||
@ -44,6 +45,9 @@ namespace os {
|
||||
|
||||
namespace {
|
||||
|
||||
int argc_ = 0;
|
||||
char ** argv_ = 0;
|
||||
|
||||
bool windows_style_tex_paths_ = false;
|
||||
|
||||
// In both is_posix_path() and is_windows_path() it is assumed that
|
||||
@ -201,8 +205,11 @@ BOOL terminate_handler(DWORD event)
|
||||
|
||||
} // namespace anon
|
||||
|
||||
void init(int, char *[])
|
||||
void init(int argc, char * argv[])
|
||||
{
|
||||
argc_ = argc;
|
||||
argv_ = argv;
|
||||
|
||||
// Make sure that the TEMP variable is set
|
||||
// and sync the Windows environment.
|
||||
setenv("TEMP", "/tmp", false);
|
||||
@ -213,6 +220,13 @@ void init(int, char *[])
|
||||
}
|
||||
|
||||
|
||||
string utf8_argv(int i)
|
||||
{
|
||||
LASSERT(i < argc_, /**/);
|
||||
return to_utf8(from_local8bit(argv_[i]));
|
||||
}
|
||||
|
||||
|
||||
string current_root()
|
||||
{
|
||||
return string("/");
|
||||
@ -289,6 +303,12 @@ string internal_path(string const & p)
|
||||
}
|
||||
|
||||
|
||||
string safe_internal_path(string const & p, file_access)
|
||||
{
|
||||
return convert_path(p, PathStyle(posix));
|
||||
}
|
||||
|
||||
|
||||
string external_path_list(string const & p)
|
||||
{
|
||||
return convert_path_list(p, PathStyle(posix));
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "support/docstring.h"
|
||||
#include "support/FileName.h"
|
||||
#include "support/lstrings.h"
|
||||
#include "support/lassert.h"
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
@ -30,8 +31,25 @@ namespace lyx {
|
||||
namespace support {
|
||||
namespace os {
|
||||
|
||||
void init(int, char *[])
|
||||
{}
|
||||
namespace {
|
||||
|
||||
int argc_ = 0;
|
||||
char ** argv_ = 0;
|
||||
|
||||
} // namespace anon
|
||||
|
||||
void init(int argc, char * argv[])
|
||||
{
|
||||
argc_ = argc;
|
||||
argv_ = argv;
|
||||
}
|
||||
|
||||
|
||||
string utf8_argv(int i)
|
||||
{
|
||||
LASSERT(i < argc_, /**/);
|
||||
return to_utf8(from_local8bit(argv_[i]));
|
||||
}
|
||||
|
||||
|
||||
string current_root()
|
||||
@ -130,6 +148,12 @@ string internal_path(string const & p)
|
||||
}
|
||||
|
||||
|
||||
string safe_internal_path(string const & p, file_access)
|
||||
{
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
string external_path_list(string const & p)
|
||||
{
|
||||
return p;
|
||||
|
@ -6,6 +6,7 @@
|
||||
* \author Ruurd A. Reitsma
|
||||
* \author Claus Hentschel
|
||||
* \author Angus Leeming
|
||||
* \author Enrico Forestieri
|
||||
*
|
||||
* Full author contact details are available in file CREDITS.
|
||||
*
|
||||
@ -23,30 +24,14 @@
|
||||
#include "support/filetools.h"
|
||||
#include "support/lstrings.h"
|
||||
#include "support/ExceptionMessage.h"
|
||||
#include "support/qstring_helpers.h"
|
||||
|
||||
#include "support/lassert.h"
|
||||
|
||||
#include <cstdlib>
|
||||
#include <vector>
|
||||
|
||||
/* The GetLongPathName macro may be defined on the compiling machine,
|
||||
* but we must use a bit of trickery if the resulting executable is
|
||||
* to run on a Win95 machine.
|
||||
* Fortunately, Microsoft provide the trickery. All we need is the
|
||||
* NewAPIs.h header file, available for download from Microsoft as
|
||||
* part of the Platform SDK.
|
||||
*/
|
||||
#if defined (HAVE_NEWAPIS_H)
|
||||
// This should be defined already to keep Boost.Filesystem happy.
|
||||
# if !defined (WANT_GETFILEATTRIBUTESEX_WRAPPER)
|
||||
# error Expected WANT_GETFILEATTRIBUTESEX_WRAPPER to be defined!
|
||||
# endif
|
||||
# define WANT_GETLONGPATHNAME_WRAPPER 1
|
||||
# define COMPILE_NEWAPIS_STUBS
|
||||
# include <NewAPIs.h>
|
||||
# undef COMPILE_NEWAPIS_STUBS
|
||||
# undef WANT_GETLONGPATHNAME_WRAPPER
|
||||
#endif
|
||||
#include <QString>
|
||||
|
||||
#include <io.h>
|
||||
#include <direct.h> // _getdrive
|
||||
@ -68,6 +53,11 @@
|
||||
#define ASSOCF_INIT_IGNOREUNKNOWN 0
|
||||
#endif
|
||||
|
||||
extern "C" {
|
||||
extern void __wgetmainargs(int * argc, wchar_t *** argv, wchar_t *** envp,
|
||||
int expand_wildcards, int * new_mode);
|
||||
}
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace lyx {
|
||||
@ -79,6 +69,9 @@ namespace os {
|
||||
|
||||
namespace {
|
||||
|
||||
int argc_ = 0;
|
||||
wchar_t ** argv_ = 0;
|
||||
|
||||
bool windows_style_tex_paths_ = true;
|
||||
|
||||
string cygdrive = "/cygdrive";
|
||||
@ -96,7 +89,7 @@ BOOL terminate_handler(DWORD event)
|
||||
|
||||
} // namespace anon
|
||||
|
||||
void init(int /* argc */, char * argv[])
|
||||
void init(int argc, char * argv[])
|
||||
{
|
||||
/* Note from Angus, 17 Jan 2005:
|
||||
*
|
||||
@ -154,6 +147,13 @@ void init(int /* argc */, char * argv[])
|
||||
* lyx is invoked as a parameter of hidecmd.exe.
|
||||
*/
|
||||
|
||||
|
||||
// Get the wide program arguments array
|
||||
wchar_t ** envp = 0;
|
||||
int newmode = 0;
|
||||
__wgetmainargs(&argc_, &argv_, &envp, -1, &newmode);
|
||||
LASSERT(argc == argc_, /**/);
|
||||
|
||||
// If Cygwin is detected, query the cygdrive prefix.
|
||||
// The cygdrive prefix is needed for translating windows style paths
|
||||
// to posix style paths in LaTeX files when the Cygwin teTeX is used.
|
||||
@ -202,6 +202,13 @@ void init(int /* argc */, char * argv[])
|
||||
}
|
||||
|
||||
|
||||
string utf8_argv(int i)
|
||||
{
|
||||
LASSERT(i < argc_, /**/);
|
||||
return fromqstr(QString::fromWCharArray(argv_[i]));
|
||||
}
|
||||
|
||||
|
||||
string current_root()
|
||||
{
|
||||
// _getdrive returns the current drive (1=A, 2=B, and so on).
|
||||
@ -278,29 +285,60 @@ string external_path(string const & p)
|
||||
}
|
||||
|
||||
|
||||
static string const get_long_path(string const & short_path)
|
||||
static QString const get_long_path(QString const & short_path)
|
||||
{
|
||||
// GetLongPathName needs the path in file system encoding.
|
||||
// We can use to_local8bit, since file system encoding and the
|
||||
// local 8 bit encoding are identical on windows.
|
||||
vector<char> long_path(MAX_PATH);
|
||||
DWORD result = GetLongPathName(to_local8bit(from_utf8(short_path)).c_str(),
|
||||
// GetLongPathNameW needs the path in utf16 encoding.
|
||||
vector<wchar_t> long_path(MAX_PATH);
|
||||
DWORD result = GetLongPathNameW((wchar_t *) short_path.utf16(),
|
||||
&long_path[0], long_path.size());
|
||||
|
||||
if (result > long_path.size()) {
|
||||
long_path.resize(result);
|
||||
result = GetLongPathName(short_path.c_str(),
|
||||
result = GetLongPathNameW((wchar_t *) short_path.utf16(),
|
||||
&long_path[0], long_path.size());
|
||||
LASSERT(result <= long_path.size(), /**/);
|
||||
}
|
||||
|
||||
return (result == 0) ? short_path : to_utf8(from_filesystem8bit(&long_path[0]));
|
||||
return (result == 0) ? short_path : QString::fromWCharArray(&long_path[0]);
|
||||
}
|
||||
|
||||
|
||||
static QString const get_short_path(QString const & long_path, file_access how)
|
||||
{
|
||||
// CreateFileW and GetShortPathNameW need the path in utf16 encoding.
|
||||
if (how == CREATE) {
|
||||
HANDLE h = CreateFileW((wchar_t *) long_path.utf16(),
|
||||
GENERIC_WRITE, 0, NULL, CREATE_NEW,
|
||||
FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if (h == INVALID_HANDLE_VALUE
|
||||
&& GetLastError() != ERROR_FILE_EXISTS)
|
||||
return long_path;
|
||||
CloseHandle(h);
|
||||
}
|
||||
vector<wchar_t> short_path(MAX_PATH);
|
||||
DWORD result = GetShortPathNameW((wchar_t *) long_path.utf16(),
|
||||
&short_path[0], short_path.size());
|
||||
|
||||
if (result > short_path.size()) {
|
||||
short_path.resize(result);
|
||||
result = GetShortPathNameW((wchar_t *) long_path.utf16(),
|
||||
&short_path[0], short_path.size());
|
||||
LASSERT(result <= short_path.size(), /**/);
|
||||
}
|
||||
|
||||
return (result == 0) ? long_path : QString::fromWCharArray(&short_path[0]);
|
||||
}
|
||||
|
||||
|
||||
string internal_path(string const & p)
|
||||
{
|
||||
return subst(get_long_path(p), "\\", "/");
|
||||
return subst(fromqstr(get_long_path(toqstr(p))), "\\", "/");
|
||||
}
|
||||
|
||||
|
||||
string safe_internal_path(string const & p, file_access how)
|
||||
{
|
||||
return subst(fromqstr(get_short_path(toqstr(p), how)), "\\", "/");
|
||||
}
|
||||
|
||||
|
||||
@ -462,12 +500,13 @@ bool autoOpenFile(string const & filename, auto_open_mode const mode)
|
||||
string real_path(string const & path)
|
||||
{
|
||||
// See http://msdn.microsoft.com/en-us/library/aa366789(VS.85).aspx
|
||||
HANDLE hpath = CreateFile(subst(path, '/', '\\').c_str(), GENERIC_READ,
|
||||
QString const qpath = get_long_path(toqstr(path));
|
||||
HANDLE hpath = CreateFileW((wchar_t *) qpath.utf16(), GENERIC_READ,
|
||||
FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
|
||||
|
||||
if (hpath == INVALID_HANDLE_VALUE) {
|
||||
// The file cannot be accessed.
|
||||
return FileName::fromFilesystemEncoding(path).absFilename();
|
||||
return path;
|
||||
}
|
||||
|
||||
// Get the file size.
|
||||
@ -477,7 +516,7 @@ string real_path(string const & path)
|
||||
if (size_lo == 0 && size_hi == 0) {
|
||||
// A zero-length file cannot be mapped.
|
||||
CloseHandle(hpath);
|
||||
return FileName::fromFilesystemEncoding(path).absFilename();
|
||||
return path;
|
||||
}
|
||||
|
||||
// Create a file mapping object.
|
||||
@ -485,7 +524,7 @@ string real_path(string const & path)
|
||||
|
||||
if (!hmap) {
|
||||
CloseHandle(hpath);
|
||||
return FileName::fromFilesystemEncoding(path).absFilename();
|
||||
return path;
|
||||
}
|
||||
|
||||
// Create a file mapping to get the file name.
|
||||
@ -494,7 +533,7 @@ string real_path(string const & path)
|
||||
if (!pmem) {
|
||||
CloseHandle(hmap);
|
||||
CloseHandle(hpath);
|
||||
return FileName::fromFilesystemEncoding(path).absFilename();
|
||||
return path;
|
||||
}
|
||||
|
||||
TCHAR realpath[MAX_PATH + 1];
|
||||
@ -503,7 +542,7 @@ string real_path(string const & path)
|
||||
UnmapViewOfFile(pmem);
|
||||
CloseHandle(hmap);
|
||||
CloseHandle(hpath);
|
||||
return FileName::fromFilesystemEncoding(path).absFilename();
|
||||
return path;
|
||||
}
|
||||
|
||||
// Translate device name to UNC prefix or drive letters.
|
||||
|
@ -137,6 +137,9 @@ What's new
|
||||
- Fix positioning of error dialog in child documents with parent macros
|
||||
(bug 6502).
|
||||
|
||||
- On Windows, allow loading and saving files whose path and/or name contains
|
||||
characters not encodable in the current code page (bug 5238).
|
||||
|
||||
|
||||
* USER INTERFACE
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user