Skip to content

Commit

Permalink
Make libthai relocatable on native Windows
Browse files Browse the repository at this point in the history
* src/thbrk/brk-common.c:
  - Deduce location of DLL or statically-linked EXE and construct
    path dynamically where thbrk.tri can be loaded.
  • Loading branch information
fanc999-1 committed Dec 13, 2021
1 parent 36131a4 commit 391b612
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 5 deletions.
7 changes: 7 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,13 @@

* configure.ac:
- Remove duplicate AC_CONFIG_MACRO_DIR
2020-02-14 Chun-wei Fan <fanc999@yahoo.com.tw>
Make libthai relocatable on native Windows

* src/thbrk/brk-common.c:
- Deduce location of DLL or statically-linked EXE and construct
path dynamically where thbrk.tri can be loaded.

2020-02-14 Chun-wei Fan <fanc999@yahoo.com.tw>

Don't use __attribute__((destructor)) on MSVC builds
Expand Down
82 changes: 77 additions & 5 deletions src/thbrk/brk-common.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ extern void _libthai_on_unload ();
#endif /* MSVC_BUILD_LIBTHAI_TESTS */
#endif /* !__GNUC__ && !__clang__ */

/* This way, we can use the current directory where the .exe is if no DLL is built, such as in tests */
static HMODULE libthai_dll = NULL;

BOOL WINAPI DllMain(HINSTANCE hinstDLL,
DWORD fdwReason,
LPVOID lpvReserved);
Expand All @@ -59,19 +62,77 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL,
DWORD fdwReason,
LPVOID lpvReserved)
{

#if !defined (__GNUC__) && !defined (__clang__)
/* fallback for lack of GCC's __attribute__((destructor)) */
switch (fdwReason)
{
case DLL_PROCESS_ATTACH:
libthai_dll = hinstDLL;
break;

#if !defined (__GNUC__) && !defined (__clang__)
/* fallback for lack of GCC's __attribute__((destructor)) */
case DLL_PROCESS_DETACH:
_libthai_on_unload ();
break;
}
#endif
}

return TRUE;
}

/*
* modelled around GLib's g_win32_get_package_installation_directory_of_module()
* without Cygwin support
*/
#ifndef __CYGWIN__
char *
libthai_get_installdir (HMODULE hmodule)
{
char *retval;
char *filename;
char *p;
wchar_t wc_fn[MAX_PATH];
size_t length;
size_t converted = 0;

/* NOTE: it relies that GetModuleFileNameW returns only canonical paths */
if (!GetModuleFileNameW (hmodule, wc_fn, MAX_PATH))
return NULL;

length = wcslen(wc_fn);
filename = (char *)malloc (sizeof(char) * (length * 2 + 1));
wcstombs_s(&converted, filename, length * 2, wc_fn, _TRUNCATE);

if ((p = strrchr (filename, '\\')) != NULL)
*p = '\0';

retval = (char *)malloc (sizeof(char) * (length * 2 + 1));
memcpy (retval, filename, strlen(filename));

do
{
p = strrchr (retval, '\\');
if (p == NULL)
break;

*p = '\0';

if (_stricmp (p + 1, "bin") == 0 ||
_stricmp (p + 1, "lib") == 0)
break;
}
while (p != NULL);

if (p == NULL)
{
free (retval);
retval = filename;
}
else
free (filename);

return retval;
}
#endif /* !__CYGWIN__ */
#endif /* _WIN32 */

#define DICT_NAME "thbrk"
Expand Down Expand Up @@ -99,9 +160,20 @@ brk_load_default_dict ()
free (path);
}

/* Then, fall back to default DICT_DIR macro */
/* Then, fall back to default DICT_DIR macro or relative $(datadir)\share\libthai for native Windows DLL */
if (!dict_trie) {
#if defined (_WIN32) && !defined (__CYGWIN__)
char *basedir = libthai_get_installdir (libthai_dll);
const char *sharedir = "share\\libthai\\" DICT_NAME ".tri";
size_t total_len = strlen (basedir) + strlen (sharedir) + 1; /* '+ 1' for the '\\' that we are using below */
char *filepath = (char *) malloc (sizeof (char) * (total_len + 1));
sprintf (filepath, "%s\\%s", basedir, sharedir);
dict_trie = trie_new_from_file (filepath);
free (filepath);
free (basedir);
#else
dict_trie = trie_new_from_file (DICT_DIR "/" DICT_NAME ".tri");
#endif
}

return dict_trie;
Expand Down

0 comments on commit 391b612

Please sign in to comment.