Win98 and earlier support.

git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/branches/BRANCH_1_3_X@10500 a592a061-630c-0410-9148-cb99ea01b6c8
This commit is contained in:
Angus Leeming 2005-09-30 12:23:44 +00:00
parent 79b308513c
commit ae1bb7eec4
8 changed files with 233 additions and 48 deletions

View File

@ -1,3 +1,8 @@
2005-09-30 Angus Leeming <leeming@lyx.org>
* configure.ac:
* configure.in: check for NewAPIs.h.
2005-09-29 Angus Leeming <leeming@lyx.org>
* lyxinclude213.m4:

View File

@ -239,7 +239,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)
AC_CHECK_HEADERS(sys/time.h sys/types.h sys/select.h strings.h locale.h NewAPIs.h)
# some standard structures
AC_HEADER_STAT

View File

@ -242,7 +242,7 @@ AC_LANG_CPLUSPLUS
# 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)
AC_CHECK_HEADERS(sys/time.h sys/types.h sys/select.h strings.h locale.h NewAPIs.h)
# some standard structures
AC_HEADER_STAT

View File

@ -1,3 +1,14 @@
2005-09-30 Angus Leeming <leeming@lyx.org>
* os_win32.h: new file, providing a public and portable interface
to the SHGetFolderPath function for older flavours of Windows.
* os_win32.C: tighten up code. Define the ShGetFolder class. Make
use of Microsoft's NewAPIs.h if available to provide us with
runtime support for Windows 95.
(internal_path): always pass the path through GetLongPathName.
* package.C: move lots of stuff out and into os_win32.C.
2005-09-29 Angus Leeming <leeming@lyx.org>
* Makefile.am: use the Windows-friendly LYX_ABS_INSTALLED_LOCALEDIR

View File

@ -5,7 +5,7 @@ noinst_LTLIBRARIES = libsupport.la
INCLUDES = -I$(srcdir)/.. $(BOOST_INCLUDES)
EXTRA_DIST = lyxstring.C lyxstring.h \
os_cygwin.C os_unix.C os_win32.C os_os2.C
os_cygwin.C os_unix.C os_win32.C os_win32.h os_os2.C
if USE_LYXSTRING
LYXSTRING = lyxstring.C lyxstring.h

View File

@ -3,15 +3,58 @@
// Various OS specific functions
#include <config.h>
/* The GetLongPathNameA function declaration in
* <winbase.h> under MinGW or Cygwin is protected
* by the WINVER macro which is defined in <windef.h>
*
* SHGFP_TYPE_CURRENT is defined in <shlobj.h> for __W32API_VERSION >= 3.2
* where it is protected by _WIN32_IE.
* It is missing in earlier versions of the MinGW w32api headers.
*/
#if defined(__MINGW32__) || defined(__CYGWIN__) || defined(__CYGWIN32__)
# include <w32api.h>
# define WINVER 0x0500
# define _WIN32_IE 0x0500
#endif
#include "os.h"
#include "support/os_win32.h"
#include "support/filetools.h"
#include "support/LAssert.h"
#include "support/lstrings.h"
#include "debug.h"
#include <cstdlib>
#include <vector>
#include <windows.h>
/* 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)
# define WANT_GETLONGPATHNAME_WRAPPER 1
# define COMPILE_NEWAPIS_STUBS
# include <NewAPIs.h>
# undef COMPILE_NEWAPIS_STUBS
# undef WANT_GETLONGPATHNAME_WRAPPER
#endif
#include <io.h>
#include <direct.h> // _getdrive
#include <shlobj.h> // SHGetFolderPath
// Needed by older versions of MinGW.
#if defined (__W32API_MAJOR_VERSION) && \
defined (__W32API_MINOR_VERSION) && \
(__W32API_MAJOR_VERSION < 3 || \
__W32API_MAJOR_VERSION == 3 && __W32API_MINOR_VERSION < 2)
# define SHGFP_TYPE_CURRENT 0
#endif
string const os::nulldev_ = "nul";
os::shell_type os::shell_ = os::CMD_EXE;
@ -136,9 +179,30 @@ string os::external_path(string const & p)
}
namespace {
string const get_long_path(string const & short_path)
{
std::vector<char> long_path(PATH_MAX);
DWORD result = GetLongPathName(short_path.c_str(),
&long_path[0], long_path.size());
if (result > long_path.size()) {
long_path.resize(result);
result = GetLongPathName(short_path.c_str(),
&long_path[0], long_path.size());
lyx::Assert(result <= long_path.size());
}
return (result == 0) ? short_path : &long_path[0];
}
} // namespace anon
string os::internal_path(string const & p)
{
return subst(p, "\\", "/");
return subst(get_long_path(p), "\\", "/");
}
@ -183,3 +247,68 @@ char os::path_separator()
void os::cygwin_path_fix(bool)
{}
namespace {
void bail_out()
{
#ifndef CXX_GLOBAL_CSTD
using std::exit;
#endif
exit(1);
}
} // namespace anon
GetFolderPath::GetFolderPath()
: folder_module_(0),
folder_path_func_(0)
{
folder_module_ = LoadLibrary("shfolder.dll");
if (!folder_module_) {
lyxerr << "Unable to load shfolder.dll\nPlease install."
<< std::endl;
bail_out();
}
folder_path_func_ = reinterpret_cast<function_pointer>(::GetProcAddress(folder_module_, "SHGetFolderPathA"));
if (folder_path_func_ == 0) {
lyxerr << "Unable to find SHGetFolderPathA in shfolder.dll\n"
"Don't know how to proceed. Sorry."
<< std::endl;
bail_out();
}
}
GetFolderPath::~GetFolderPath()
{
if (folder_module_)
FreeLibrary(folder_module_);
}
// Given a folder ID, returns the folder name (in unix-style format).
// Eg CSIDL_PERSONAL -> "C:/Documents and Settings/USERNAME/My Documents"
string const GetFolderPath::operator()(folder_id _id) const
{
char folder_path[PATH_MAX];
int id = 0;
switch (_id) {
case PERSONAL:
id = CSIDL_PERSONAL;
break;
case APPDATA:
id = CSIDL_APPDATA;
break;
default:
lyx::Assert(false);
}
HRESULT const result = (folder_path_func_)(0, id, 0,
SHGFP_TYPE_CURRENT,
folder_path);
return (result == 0) ? os::internal_path(folder_path) : string();
}

76
src/support/os_win32.h Normal file
View File

@ -0,0 +1,76 @@
// -*- C++ -*-
/**
* \file os_win32.h
* This file is part of LyX, the document processor.
* Licence details can be found in the file COPYING.
*
* \author Angus Leeming
*
* Full author contact details are available in file CREDITS.
*
* These classes should be used only on Windows machines.
*/
#ifndef OS_WIN32_H
#define OS_WIN32_H
#include "LString.h"
#if !defined(_WIN32)
# error os_win32.h should be compiled only under Windows.
#endif
/* The GetLongPathNameA function declaration in
* winbase.h under MinGW or Cygwin is protected
* by the WINVER macro which is defined in windef.h
*
* We need to #include this file to make available the
* DWORD, HMODULE et al. typedefs, so check WINVER now.
*
* Note: __CYGWIN__ can be defined here if building in _WIN32 mode.
*/
#if defined(__MINGW32__) || defined(__CYGWIN__) || defined(__CYGWIN32__)
# if !defined(WINVER) || WINVER < 0x0500
# error WINVER must be >= 0x0500
# endif
#endif
#include <windef.h>
/** Win98 and earlier don't have SHGetFolderPath in shell32.dll.
* Microsoft recommend that we load shfolder.dll at run time and
* access the function through that.
*
* shfolder.dll is loaded dynamically in the constructor. If loading
* fails or if the .dll is found not to contain SHGetFolderPathA then
* the program exits immediately. Otherwise, the .dll is unloaded in
* the destructor
*
* The class makes SHGetFolderPath available through its function operator.
* It will work on all versions of Windows >= Win95.
*/
class GetFolderPath {
public:
enum folder_id {
/// CSIDL_PERSONAL
PERSONAL,
/// CSIDL_APPDATA
APPDATA
};
GetFolderPath();
~GetFolderPath();
/** Wrapper for SHGetFolderPathA, returning
* the path asscociated with @c id.
*/
string const operator()(folder_id id) const;
private:
typedef HRESULT (__stdcall * function_pointer)(HWND, int, HANDLE, DWORD, LPCSTR);
HMODULE folder_module_;
function_pointer folder_path_func_;
};
#endif // OS_WIN32_H

View File

@ -22,6 +22,10 @@
#include "support/lstrings.h"
#include "support/os.h"
#if defined (USE_WINDOWS_PACKAGING)
# include "support/os_win32.h"
#endif
#include <boost/tuple/tuple.hpp>
#include <list>
@ -35,32 +39,7 @@
#if defined (USE_WINDOWS_PACKAGING)
/*
* MinGW's version of winver.h contains this comment:
*
* If you need Win32 API features newer the Win95 and WinNT then you must
* define WINVER before including windows.h or any other method of including
* the windef.h header.
*
* GetLongPathNameA requires WINVER == 0x0500.
*
* It doesn't matter if the Windows version is older than this because the
* function will compile but will fail at run time. See
* http://msdn.microsoft.com/library/en-us/mslu/winprog/microsoft_layer_for_unicode_apis_with_limited_support.asp
*/
# if defined(__MINGW32__)
# define WINVER 0x0500
# endif
# include <windows.h>
# include <shlobj.h> // SHGetFolderPath
// Needed for MinGW:
# ifndef SHGFP_TYPE_CURRENT
# define SHGFP_TYPE_CURRENT 0
# endif
#elif defined (USE_MACOSX_PACKAGING)
# include <CoreServices/CoreServices.h> // FSFindFolder, FSRefMakePath
#endif
@ -187,20 +166,6 @@ string const relative_locale_dir();
string const relative_system_support_dir();
#if defined (USE_WINDOWS_PACKAGING)
// Given a folder ID, returns the folder name (in unix-style format).
// Eg CSIDL_PERSONAL -> "C:/Documents and Settings/USERNAME/My Documents"
string const win32_folder_path(int folder_id)
{
char folder_path[PATH_MAX + 1];
if (SUCCEEDED(SHGetFolderPath(0, folder_id, 0,
SHGFP_TYPE_CURRENT, folder_path)))
return os::internal_path(folder_path);
return string();
}
#endif
std::pair<string, string> const get_build_dirs(string const & abs_binary)
{
string const check_text = "Checking whether LyX is run in place...";
@ -259,7 +224,8 @@ string const get_document_dir(string const & home_dir)
{
#if defined (USE_WINDOWS_PACKAGING)
(void)home_dir; // Silence warning about unused variable.
return win32_folder_path(CSIDL_PERSONAL);
GetFolderPath win32_folder_path;
return win32_folder_path(GetFolderPath::PERSONAL);
#else // Posix-like.
return home_dir;
#endif
@ -317,7 +283,6 @@ string const get_temp_dir()
// Typical example: C:/TEMP/.
char path[PATH_MAX + 1];
GetTempPath(PATH_MAX, path);
GetLongPathName(path, path, PATH_MAX + 1);
return os::internal_path(path);
#else // Posix-like.
return "/tmp";
@ -325,8 +290,6 @@ string const get_temp_dir()
}
// If we use a 'lazy' lyxerr in the hope of setting the locale before
// printing any messages, then we should ensure that it is flushed first.
void bail_out()
{
#ifndef CXX_GLOBAL_CSTD
@ -590,7 +553,8 @@ string const get_default_user_support_dir(string const & home_dir)
(void)home_dir; // Silence warning about unused variable.
string const user_dir = (string(PACKAGE) == "lyx") ? "LyX" : PACKAGE;
return AddPath(win32_folder_path(CSIDL_APPDATA), user_dir);
GetFolderPath win32_folder_path;
return AddPath(win32_folder_path(GetFolderPath::APPDATA), user_dir);
#elif defined (USE_MACOSX_PACKAGING)
(void)home_dir; // Silence warning about unused variable.