Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RFC: switch Windows to UTF-8 locale entirely #15899

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ Requirements

* Linux (64-bit)
* FreeBSD (64-bit)
* Windows (64-bit), 8.1 w/ [UCRT](https://support.microsoft.com/en-us/topic/update-for-universal-c-runtime-in-windows-c0514201-7fe6-95a3-b0a5-287930f3560c) and later
* Windows (64-bit), 10 1903 and later
* macOS 13.5 and later

*Big-endian platforms are not supported.*
Expand All @@ -73,7 +73,7 @@ So we recommend, if you have a choice of platform, to use darktable on Linux.*

(workable minimum / **recommended minimum**):
* RAM: 4 GB / **8 GB**
* CPU: Intel Pentium 4 (Core 2 for Windows) / **Intel Core i5 4×2.4 GHz**
* CPU: Intel Pentium 4 (Celeron 3000 for Windows) / **Intel Core i5 4×2.4 GHz**
* GPU: none / **Nvidia with 1024 CUDA cores, 4 GB, OpenCL 1.2 compatible**
* free disk space: 250 MB / **1 GB**

Expand Down
7 changes: 3 additions & 4 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -207,14 +207,13 @@ if(WIN32)
# add it to have proper time.h functions available
ADD_DEFINITIONS(-D_POSIX_THREAD_SAFE_FUNCTIONS)

# avoid calling legacy ANSI win api functions
add_definitions("-DUNICODE -D_UNICODE")

# add icon, version, ... resources for Windows executable
configure_file("${CMAKE_SOURCE_DIR}/data/pixmaps/dt_logo_128x128.ico" "${CMAKE_BINARY_DIR}/data/pixmaps/dt_logo_128x128.ico" COPYONLY)
SET(CMAKE_RC_COMPILE_OBJECT "<CMAKE_RC_COMPILER> -O coff <DEFINES> -i <SOURCE> -o <OBJECT>")
set(RESOURCE_OBJECT "${CMAKE_CURRENT_BINARY_DIR}/win/darktable.rc")
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/win/darktable.rc.in" "${CMAKE_CURRENT_BINARY_DIR}/win/darktable.rc")
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/win/cli.rc" "${CMAKE_CURRENT_BINARY_DIR}/win/cli.rc" COPYONLY)
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/win/utf8.manifest" "${CMAKE_CURRENT_BINARY_DIR}/win/utf8.manifest" COPYONLY)
endif(WIN32)

set(SOURCES ${SOURCE_FILES} ${HEADER_FILES})
Expand Down Expand Up @@ -679,7 +678,7 @@ if(NOT CUSTOM_CFLAGS)
endif(NOT CUSTOM_CFLAGS)

if(WIN32)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--enable-runtime-pseudo-reloc -municode")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--enable-runtime-pseudo-reloc")
set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -Wl,--enable-runtime-pseudo-reloc")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--enable-runtime-pseudo-reloc")

Expand Down
4 changes: 4 additions & 0 deletions src/chart/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
if(WIN32)
set(CLI_RESOURCE_OBJECT "${CMAKE_CURRENT_BINARY_DIR}/../win/cli.rc")
endif(WIN32)
add_executable(darktable-chart
main.c
${CLI_RESOURCE_OBJECT}
colorchart.c
deltaE.c
pfm.c
Expand Down
5 changes: 0 additions & 5 deletions src/chart/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,6 @@
#include "osx/osx.h"
#endif

#ifdef _WIN32
#include "win/main_wrapper.h"
#endif

const double thrs = 200.0;

static const point_t bb_ref[] = {{.x=.0, .y=.0}, {.x=1., .y=0.}, {.x=1., .y=1.}, {.x=0., .y=1.}};
Expand Down Expand Up @@ -1949,4 +1945,3 @@ int main(int argc, char *argv[])
// vim: shiftwidth=2 expandtab tabstop=2 cindent
// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
// clang-format on

6 changes: 5 additions & 1 deletion src/cli/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
include_directories(${DARKTABLE_BINDIR})
add_executable(darktable-cli main.c)

if(WIN32)
set(CLI_RESOURCE_OBJECT "${CMAKE_CURRENT_BINARY_DIR}/../win/cli.rc")
endif(WIN32)
add_executable(darktable-cli main.c ${CLI_RESOURCE_OBJECT})

set_target_properties(darktable-cli PROPERTIES LINKER_LANGUAGE C)
target_link_libraries(darktable-cli lib_darktable whereami)
Expand Down
4 changes: 0 additions & 4 deletions src/cli/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,6 @@
#include "osx/osx.h"
#endif

#ifdef _WIN32
#include "win/main_wrapper.h"
#endif

#define DT_MAX_STYLE_NAME_LENGTH 128

// Make sure it's OK to limit output extension length
Expand Down
6 changes: 5 additions & 1 deletion src/cltest/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
include_directories(${DARKTABLE_BINDIR})
add_executable(darktable-cltest main.c)

if(WIN32)
set(CLI_RESOURCE_OBJECT "${CMAKE_CURRENT_BINARY_DIR}/../win/cli.rc")
endif(WIN32)
add_executable(darktable-cltest main.c ${CLI_RESOURCE_OBJECT})

set_target_properties(darktable-cltest PROPERTIES LINKER_LANGUAGE C)
target_link_libraries(darktable-cltest lib_darktable)
Expand Down
2 changes: 0 additions & 2 deletions src/cltest/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@

#ifdef _WIN32
#include <conio.h>
#include "win/main_wrapper.h"
#endif

int main(int argc, char *arg[])
Expand Down Expand Up @@ -65,4 +64,3 @@ int main(int argc, char *arg[])
// vim: shiftwidth=2 expandtab tabstop=2 cindent
// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
// clang-format on

10 changes: 4 additions & 6 deletions src/common/colorspaces.c
Original file line number Diff line number Diff line change
Expand Up @@ -2009,21 +2009,19 @@ void dt_colorspaces_set_display_profile
if(hdc != NULL)
{
DWORD len = 0;
GetICMProfile(hdc, &len, NULL);
wchar_t *wpath = g_new(wchar_t, len);
GetICMProfileA(hdc, &len, NULL);
char *path = g_new(char, len);

if(GetICMProfileW(hdc, &len, wpath))
if(GetICMProfileA(hdc, &len, path))
{
gchar *path = g_utf16_to_utf8(wpath, -1, NULL, NULL, NULL);
if(path)
{
gsize size;
g_file_get_contents(path, (gchar **)&buffer, &size, NULL);
buffer_size = size;
g_free(path);
}
}
g_free(wpath);
g_free(path);
ReleaseDC(NULL, hdc);
}
profile_source = g_strdup("windows color profile api");
Expand Down
10 changes: 4 additions & 6 deletions src/common/database.c
Original file line number Diff line number Diff line change
Expand Up @@ -3669,13 +3669,11 @@ static gboolean pid_is_alive(int pid)
HANDLE h = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid);
if(h)
{
wchar_t wfilename[MAX_PATH];
long unsigned int n_filename = sizeof(wfilename);
int ret = QueryFullProcessImageNameW(h, 0, wfilename, &n_filename);
char *filename = g_utf16_to_utf8(wfilename, -1, NULL, NULL, NULL);
if(ret && n_filename > 0 && filename && g_str_has_suffix(filename, "darktable.exe"))
char filename[MAX_PATH];
long unsigned int n_filename = sizeof(filename);
int ret = QueryFullProcessImageNameA(h, 0, filename, &n_filename);
if(ret && n_filename > 0 && g_str_has_suffix(filename, "darktable.exe"))
pid_is_alive = TRUE;
g_free(filename);
CloseHandle(h);
}
#else
Expand Down
30 changes: 12 additions & 18 deletions src/common/exif.cc
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,6 @@

#include "control/control.h"

#if defined(_WIN32) && defined(EXV_UNICODE_PATH)
#define WIDEN(s) pugi::as_wide(s)
#else
#define WIDEN(s) (s)
#endif

#include <pugixml.hpp>

using namespace std;
Expand Down Expand Up @@ -1064,7 +1058,7 @@ void dt_exif_img_check_additional_tags(dt_image_t *img,
{
try
{
std::unique_ptr<Exiv2::Image> image(Exiv2::ImageFactory::open(WIDEN(filename)));
std::unique_ptr<Exiv2::Image> image(Exiv2::ImageFactory::open(filename));
assert(image.get() != 0);
read_metadata_threadsafe(image);
Exiv2::ExifData &exifData = image->exifData();
Expand Down Expand Up @@ -2184,7 +2178,7 @@ gboolean dt_exif_get_thumbnail(const char *path,
{
try
{
std::unique_ptr<Exiv2::Image> image(Exiv2::ImageFactory::open(WIDEN(path)));
std::unique_ptr<Exiv2::Image> image(Exiv2::ImageFactory::open(path));
assert(image.get() != 0);
read_metadata_threadsafe(image);

Expand Down Expand Up @@ -2250,7 +2244,7 @@ gboolean dt_exif_read(dt_image_t *img,

try
{
std::unique_ptr<Exiv2::Image> image(Exiv2::ImageFactory::open(WIDEN(path)));
std::unique_ptr<Exiv2::Image> image(Exiv2::ImageFactory::open(path));
assert(image.get() != 0);
read_metadata_threadsafe(image);
bool res = true;
Expand Down Expand Up @@ -2318,7 +2312,7 @@ int dt_exif_write_blob(uint8_t *blob,
{
try
{
std::unique_ptr<Exiv2::Image> image(Exiv2::ImageFactory::open(WIDEN(path)));
std::unique_ptr<Exiv2::Image> image(Exiv2::ImageFactory::open(path));
assert(image.get() != 0);
read_metadata_threadsafe(image);
Exiv2::ExifData &imgExifData = image->exifData();
Expand Down Expand Up @@ -2401,7 +2395,7 @@ int dt_exif_read_blob(uint8_t **buf,
*buf = NULL;
try
{
std::unique_ptr<Exiv2::Image> image(Exiv2::ImageFactory::open(WIDEN(path)));
std::unique_ptr<Exiv2::Image> image(Exiv2::ImageFactory::open(path));
assert(image.get() != 0);
read_metadata_threadsafe(image);
Exiv2::ExifData &exifData = image->exifData();
Expand Down Expand Up @@ -3704,7 +3698,7 @@ gboolean dt_exif_xmp_read(dt_image_t *img,
try
{
// Read XMP sidecar
std::unique_ptr<Exiv2::Image> image(Exiv2::ImageFactory::open(WIDEN(filename)));
std::unique_ptr<Exiv2::Image> image(Exiv2::ImageFactory::open(filename));
assert(image.get() != 0);
read_metadata_threadsafe(image);
Exiv2::XmpData &xmpData = image->xmpData();
Expand Down Expand Up @@ -5018,7 +5012,7 @@ char *dt_exif_xmp_read_string(const dt_imgid_t imgid)
{
std::string xmpPacket;

Exiv2::DataBuf buf = Exiv2::readFile(WIDEN(input_filename));
Exiv2::DataBuf buf = Exiv2::readFile(input_filename);
#if EXIV2_TEST_VERSION(0,28,0)
xmpPacket.assign(buf.c_str(), buf.size());
#else
Expand All @@ -5039,7 +5033,7 @@ char *dt_exif_xmp_read_string(const dt_imgid_t imgid)
Exiv2::XmpData sidecarXmpData;
std::string xmpPacket;

Exiv2::DataBuf buf = Exiv2::readFile(WIDEN(input_filename));
Exiv2::DataBuf buf = Exiv2::readFile(input_filename);
#if EXIV2_TEST_VERSION(0,28,0)
xmpPacket.assign(buf.c_str(), buf.size());
#else
Expand Down Expand Up @@ -5368,7 +5362,7 @@ gboolean dt_exif_xmp_attach_export(const dt_imgid_t imgid,
gboolean from_cache = TRUE;
dt_image_full_path(imgid, input_filename, sizeof(input_filename), &from_cache);

std::unique_ptr<Exiv2::Image> img(Exiv2::ImageFactory::open(WIDEN(filename)));
std::unique_ptr<Exiv2::Image> img(Exiv2::ImageFactory::open(filename));

// Unfortunately it seems we have to read the metadata, to not
// erase the exif (which we just wrote). Will make export slightly
Expand All @@ -5379,7 +5373,7 @@ gboolean dt_exif_xmp_attach_export(const dt_imgid_t imgid,
{
// Initialize XMP and IPTC data with the one from the original file.
std::unique_ptr<Exiv2::Image> input_image
(Exiv2::ImageFactory::open(WIDEN(input_filename)));
(Exiv2::ImageFactory::open(input_filename));
if(input_image.get() != 0)
{
read_metadata_threadsafe(input_image);
Expand All @@ -5406,7 +5400,7 @@ gboolean dt_exif_xmp_attach_export(const dt_imgid_t imgid,
Exiv2::XmpData sidecarXmpData;
std::string xmpPacket;

Exiv2::DataBuf buf = Exiv2::readFile(WIDEN(input_filename));
Exiv2::DataBuf buf = Exiv2::readFile(input_filename);
#if EXIV2_TEST_VERSION(0,28,0)
xmpPacket.assign(buf.c_str(), buf.size());
#else
Expand Down Expand Up @@ -5663,7 +5657,7 @@ gboolean dt_exif_xmp_write(const dt_imgid_t imgid,
dt_control_log(_("cannot read XMP file '%s': '%s'"), filename, strerror(errno));
}

Exiv2::DataBuf buf = Exiv2::readFile(WIDEN(filename));
Exiv2::DataBuf buf = Exiv2::readFile(filename);
#if EXIV2_TEST_VERSION(0,28,0)
xmpPacket.assign(buf.c_str(), buf.size());
#else
Expand Down
5 changes: 1 addition & 4 deletions src/common/file_location.c
Original file line number Diff line number Diff line change
Expand Up @@ -216,9 +216,7 @@ void dt_check_opendir(const char* context, const char* directory)
}

#if _WIN32
wchar_t *wdirectory = g_utf8_to_utf16 (directory, -1, NULL, NULL, NULL);
DWORD attribs = GetFileAttributesW(wdirectory);
g_free(wdirectory);
DWORD attribs = GetFileAttributesA(directory);
if(attribs != INVALID_FILE_ATTRIBUTES &&
(attribs & FILE_ATTRIBUTE_DIRECTORY))
{
Expand Down Expand Up @@ -304,4 +302,3 @@ void dt_loc_get_sharedir(char *sharedir, size_t bufsize)
// vim: shiftwidth=2 expandtab tabstop=2 cindent
// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
// clang-format on

15 changes: 5 additions & 10 deletions src/common/l10n.c
Original file line number Diff line number Diff line change
Expand Up @@ -341,17 +341,12 @@ dt_l10n_t *dt_l10n_init(const gchar *filename, const gboolean init_list)
// the config file
if(!ui_lang || !*ui_lang)
{
const wchar_t *wcLocaleName = NULL;
wcLocaleName = dtwin_get_locale();
if(wcLocaleName != NULL)
const char *langLocale = NULL;
langLocale = dtwin_get_locale();
if(langLocale != NULL)
{
gchar *langLocale;
langLocale = g_utf16_to_utf8(wcLocaleName, -1, NULL, NULL, NULL);
if(langLocale != NULL)
{
g_free(ui_lang);
ui_lang = g_strdup(langLocale);
}
g_free(ui_lang);
ui_lang = g_strdup(langLocale);
}
}
#endif // defined (_WIN32)
Expand Down
5 changes: 1 addition & 4 deletions src/common/system_signal_handling.c
Original file line number Diff line number Diff line change
Expand Up @@ -164,10 +164,8 @@ static LONG WINAPI dt_toplevel_exception_handler(PEXCEPTION_POINTERS pExceptionI
"after you click on the OK button.\nIf you report this issue, "
"please share this backtrace with the developers.\n",
name_used);
wchar_t *wexception_message = g_utf8_to_utf16(exception_message, -1, NULL, NULL, NULL);
MessageBoxW(0, wexception_message, L"Error!", MB_OK);
MessageBoxA(0, exception_message, "Error!", MB_OK);
g_free(exception_message);
g_free(wexception_message);
}

g_free(name_used);
Expand Down Expand Up @@ -259,4 +257,3 @@ void dt_set_signal_handlers()
// vim: shiftwidth=2 expandtab tabstop=2 cindent
// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
// clang-format on

28 changes: 7 additions & 21 deletions src/common/utility.c
Original file line number Diff line number Diff line change
Expand Up @@ -306,14 +306,7 @@ gboolean dt_util_test_image_file(const char *filename)
#ifdef _WIN32
struct _stati64 stats;

// the code this replaced used utf8 paths with no problem
// utf8 paths will not work in this context for no reason
// that I can figure out, but converting utf8 to utf16 works
// fine.

wchar_t *wfilename = g_utf8_to_utf16(filename, -1, NULL, NULL, NULL);
const int result = _wstati64(wfilename, &stats);
g_free(wfilename);
const int result = _stati64(filename, &stats);
if(result) return FALSE; // there was an error
#else
struct stat stats;
Expand All @@ -331,9 +324,7 @@ gboolean dt_util_test_writable_dir(const char *path)
#ifdef _WIN32
struct _stati64 stats;

wchar_t *wpath = g_utf8_to_utf16(path, -1, NULL, NULL, NULL);
const int result = _wstati64(wpath, &stats);
g_free(wpath);
const int result = _stati64(path, &stats);

if(result)
{ // error while testing path:
Expand Down Expand Up @@ -716,25 +707,20 @@ gchar *dt_util_normalize_path(const gchar *_input)
// this handles filenames in the formats <drive letter>:\path\to\file or \\host-name\share-name\file
// some other formats like \Device\... are not supported

// the Windows api expects wide chars and not utf8 :(
wchar_t *wfilename = g_utf8_to_utf16(filename, -1, NULL, NULL, NULL);
g_free(filename);
if(!wfilename)
if(!filename)
return NULL;

wchar_t LongPath[MAX_PATH] = {0};
const DWORD size = GetLongPathNameW(wfilename, LongPath, MAX_PATH);
g_free(wfilename);
char LongPath[MAX_PATH] = {0};
const DWORD size = GetLongPathNameA(filename, LongPath, MAX_PATH);
g_free(filename);
if(size == 0 || size > MAX_PATH)
return NULL;

// back to utf8!
filename = g_utf16_to_utf8(LongPath, -1, NULL, NULL, NULL);
filename = LongPath;
if(!filename)
return NULL;

GFile *gfile = g_file_new_for_path(filename);
g_free(filename);
if(!gfile)
return NULL;
filename = g_file_get_path(gfile);
Expand Down