summaryrefslogtreecommitdiffstats
path: root/windows.c
diff options
context:
space:
mode:
authorGravatar Tomaz Canabrava <tomaz.canabrava@intel.com>2015-09-02 20:52:34 -0300
committerGravatar Dirk Hohndel <dirk@hohndel.org>2015-10-30 10:36:48 -0700
commit4c0156e3d51b389db8eccc3fa3da4b8f248f9b13 (patch)
tree966868d29150fdba13a5a56fb4305bc432ec7a72 /windows.c
parenta0798214231c652ac6142228f5ddfc4b65c921f8 (diff)
downloadsubsurface-4c0156e3d51b389db8eccc3fa3da4b8f248f9b13.tar.gz
Move all core-functionality to subsurface-core
And adapt a new CMakeLists.txt file for it. On the way I've also found out that we where double-compilling a few files. I've also set the subsurface-core as a include_path but that was just to reduce the noise on this commit, since I plan to remove it from the include path to make it obligatory to specify something like include "subsurface-core/dive.h" for the header files. Since the app is growing quite a bit we ended up having a few different files with almost same name that did similar things, I want to kill that (for instance Dive.h, dive.h, PrintDive.h and such). Signed-off-by: Tomaz Canabrava <tomaz.canabrava@intel.com> Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Diffstat (limited to 'windows.c')
-rw-r--r--windows.c448
1 files changed, 0 insertions, 448 deletions
diff --git a/windows.c b/windows.c
deleted file mode 100644
index a2386fd83..000000000
--- a/windows.c
+++ /dev/null
@@ -1,448 +0,0 @@
-/* windows.c */
-/* implements Windows specific functions */
-#include <io.h>
-#include "dive.h"
-#include "display.h"
-#undef _WIN32_WINNT
-#define _WIN32_WINNT 0x500
-#include <windows.h>
-#include <shlobj.h>
-#include <stdio.h>
-#include <fcntl.h>
-#include <assert.h>
-#include <dirent.h>
-#include <zip.h>
-#include <lmcons.h>
-
-const char non_standard_system_divelist_default_font[] = "Calibri";
-const char current_system_divelist_default_font[] = "Segoe UI";
-const char *system_divelist_default_font = non_standard_system_divelist_default_font;
-double system_divelist_default_font_size = -1;
-
-void subsurface_user_info(struct user_info *user)
-{ /* Encourage use of at least libgit2-0.20 */ }
-
-extern bool isWin7Or8();
-
-void subsurface_OS_pref_setup(void)
-{
- if (isWin7Or8())
- system_divelist_default_font = current_system_divelist_default_font;
-}
-
-bool subsurface_ignore_font(const char *font)
-{
- // if this is running on a recent enough version of Windows and the font
- // passed in is the pre 4.3 default font, ignore it
- if (isWin7Or8() && strcmp(font, non_standard_system_divelist_default_font) == 0)
- return true;
- return false;
-}
-
-/* this function returns the Win32 Roaming path for the current user as UTF-8.
- * it never returns NULL but fallsback to .\ instead!
- * the append argument will append a wchar_t string to the end of the path.
- */
-static const char *system_default_path_append(const wchar_t *append)
-{
- wchar_t wpath[MAX_PATH] = { 0 };
- const char *fname = "system_default_path_append()";
-
- /* obtain the user path via SHGetFolderPathW.
- * this API is deprecated but still supported on modern Win32.
- * fallback to .\ if it fails.
- */
- if (!SUCCEEDED(SHGetFolderPathW(NULL, CSIDL_APPDATA, NULL, 0, wpath))) {
- fprintf(stderr, "%s: cannot obtain path!\n", fname);
- wpath[0] = L'.';
- wpath[1] = L'\0';
- }
-
- wcscat(wpath, L"\\Subsurface");
- if (append) {
- wcscat(wpath, L"\\");
- wcscat(wpath, append);
- }
-
- /* attempt to convert the UTF-16 string to UTF-8.
- * resize the buffer and fallback to .\Subsurface if it fails.
- */
- const int wsz = wcslen(wpath);
- const int sz = WideCharToMultiByte(CP_UTF8, 0, wpath, wsz, NULL, 0, NULL, NULL);
- char *path = (char *)malloc(sz + 1);
- if (!sz)
- goto fallback;
- if (WideCharToMultiByte(CP_UTF8, 0, wpath, wsz, path, sz, NULL, NULL)) {
- path[sz] = '\0';
- return path;
- }
-
-fallback:
- fprintf(stderr, "%s: cannot obtain path as UTF-8!\n", fname);
- const char *local = ".\\Subsurface";
- const int len = strlen(local) + 1;
- path = (char *)realloc(path, len);
- memset(path, 0, len);
- strcat(path, local);
- return path;
-}
-
-/* by passing NULL to system_default_path_append() we obtain the pure path.
- * '\' not included at the end.
- */
-const char *system_default_directory(void)
-{
- static const char *path = NULL;
- if (!path)
- path = system_default_path_append(NULL);
- return path;
-}
-
-/* obtain the Roaming path and append "\\<USERNAME>.xml" to it.
- */
-const char *system_default_filename(void)
-{
- static wchar_t filename[UNLEN + 5] = { 0 };
- if (!*filename) {
- wchar_t username[UNLEN + 1] = { 0 };
- DWORD username_len = UNLEN + 1;
- GetUserNameW(username, &username_len);
- wcscat(filename, username);
- wcscat(filename, L".xml");
- }
- static const char *path = NULL;
- if (!path)
- path = system_default_path_append(filename);
- return path;
-}
-
-int enumerate_devices(device_callback_t callback, void *userdata, int dc_type)
-{
- int index = -1;
- DWORD i;
- if (dc_type != DC_TYPE_UEMIS) {
- // Open the registry key.
- HKEY hKey;
- LONG rc = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "HARDWARE\\DEVICEMAP\\SERIALCOMM", 0, KEY_QUERY_VALUE, &hKey);
- if (rc != ERROR_SUCCESS) {
- return -1;
- }
-
- // Get the number of values.
- DWORD count = 0;
- rc = RegQueryInfoKey(hKey, NULL, NULL, NULL, NULL, NULL, NULL, &count, NULL, NULL, NULL, NULL);
- if (rc != ERROR_SUCCESS) {
- RegCloseKey(hKey);
- return -1;
- }
- for (i = 0; i < count; ++i) {
- // Get the value name, data and type.
- char name[512], data[512];
- DWORD name_len = sizeof(name);
- DWORD data_len = sizeof(data);
- DWORD type = 0;
- rc = RegEnumValue(hKey, i, name, &name_len, NULL, &type, (LPBYTE)data, &data_len);
- if (rc != ERROR_SUCCESS) {
- RegCloseKey(hKey);
- return -1;
- }
-
- // Ignore non-string values.
- if (type != REG_SZ)
- continue;
-
- // Prevent a possible buffer overflow.
- if (data_len >= sizeof(data)) {
- RegCloseKey(hKey);
- return -1;
- }
-
- // Null terminate the string.
- data[data_len] = 0;
-
- callback(data, userdata);
- index++;
- if (is_default_dive_computer_device(name))
- index = i;
- }
-
- RegCloseKey(hKey);
- }
- if (dc_type != DC_TYPE_SERIAL) {
- int i;
- int count_drives = 0;
- const int bufdef = 512;
- const char *dlabels[] = {"UEMISSDA", NULL};
- char bufname[bufdef], bufval[bufdef], *p;
- DWORD bufname_len;
-
- /* add drive letters that match labels */
- memset(bufname, 0, bufdef);
- bufname_len = bufdef;
- if (GetLogicalDriveStringsA(bufname_len, bufname)) {
- p = bufname;
-
- while (*p) {
- memset(bufval, 0, bufdef);
- if (GetVolumeInformationA(p, bufval, bufdef, NULL, NULL, NULL, NULL, 0)) {
- for (i = 0; dlabels[i] != NULL; i++)
- if (!strcmp(bufval, dlabels[i])) {
- char data[512];
- snprintf(data, sizeof(data), "%s (%s)", p, dlabels[i]);
- callback(data, userdata);
- if (is_default_dive_computer_device(p))
- index = count_drives;
- count_drives++;
- }
- }
- p = &p[strlen(p) + 1];
- }
- if (count_drives == 1) /* we found exactly one Uemis "drive" */
- index = 0; /* make it the selected "device" */
- }
- }
- return index;
-}
-
-/* this function converts a utf-8 string to win32's utf-16 2 byte string.
- * the caller function should manage the allocated memory.
- */
-static wchar_t *utf8_to_utf16_fl(const char *utf8, char *file, int line)
-{
- assert(utf8 != NULL);
- assert(file != NULL);
- assert(line);
- /* estimate buffer size */
- const int sz = strlen(utf8) + 1;
- wchar_t *utf16 = (wchar_t *)malloc(sizeof(wchar_t) * sz);
- if (!utf16) {
- fprintf(stderr, "%s:%d: %s %d.", file, line, "cannot allocate buffer of size", sz);
- return NULL;
- }
- if (MultiByteToWideChar(CP_UTF8, 0, utf8, -1, utf16, sz))
- return utf16;
- fprintf(stderr, "%s:%d: %s", file, line, "cannot convert string.");
- free((void *)utf16);
- return NULL;
-}
-
-#define utf8_to_utf16(s) utf8_to_utf16_fl(s, __FILE__, __LINE__)
-
-/* bellow we provide a set of wrappers for some I/O functions to use wchar_t.
- * on win32 this solves the issue that we need paths to be utf-16 encoded.
- */
-int subsurface_rename(const char *path, const char *newpath)
-{
- int ret = -1;
- if (!path || !newpath)
- return ret;
-
- wchar_t *wpath = utf8_to_utf16(path);
- wchar_t *wnewpath = utf8_to_utf16(newpath);
-
- if (wpath && wnewpath)
- ret = _wrename(wpath, wnewpath);
- free((void *)wpath);
- free((void *)wnewpath);
- return ret;
-}
-
-// if the QDir based rename fails, we try this one
-int subsurface_dir_rename(const char *path, const char *newpath)
-{
- // check if the folder exists
- BOOL exists = FALSE;
- DWORD attrib = GetFileAttributes(path);
- if (attrib != INVALID_FILE_ATTRIBUTES && attrib & FILE_ATTRIBUTE_DIRECTORY)
- exists = TRUE;
- if (!exists && verbose) {
- fprintf(stderr, "folder not found or path is not a folder: %s\n", path);
- return EXIT_FAILURE;
- }
-
- // list of error codes:
- // https://msdn.microsoft.com/en-us/library/windows/desktop/ms681381(v=vs.85).aspx
- DWORD errorCode;
-
- // if this fails something has already obatained (more) exclusive access to the folder
- HANDLE h = CreateFile(path, GENERIC_WRITE, FILE_SHARE_WRITE |
- FILE_SHARE_DELETE, 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
- if (h == INVALID_HANDLE_VALUE) {
- errorCode = GetLastError();
- if (verbose)
- fprintf(stderr, "cannot obtain exclusive write access for folder: %u\n", (unsigned int)errorCode );
- return EXIT_FAILURE;
- } else {
- if (verbose)
- fprintf(stderr, "exclusive write access obtained...closing handle!");
- CloseHandle(h);
-
- // attempt to rename
- BOOL result = MoveFile(path, newpath);
- if (!result) {
- errorCode = GetLastError();
- if (verbose)
- fprintf(stderr, "rename failed: %u\n", (unsigned int)errorCode);
- return EXIT_FAILURE;
- }
- if (verbose > 1)
- fprintf(stderr, "folder rename success: %s ---> %s\n", path, newpath);
- }
- return EXIT_SUCCESS;
-}
-
-int subsurface_open(const char *path, int oflags, mode_t mode)
-{
- int ret = -1;
- if (!path)
- return ret;
- wchar_t *wpath = utf8_to_utf16(path);
- if (wpath)
- ret = _wopen(wpath, oflags, mode);
- free((void *)wpath);
- return ret;
-}
-
-FILE *subsurface_fopen(const char *path, const char *mode)
-{
- FILE *ret = NULL;
- if (!path)
- return ret;
- wchar_t *wpath = utf8_to_utf16(path);
- if (wpath) {
- const int len = strlen(mode);
- wchar_t wmode[len + 1];
- for (int i = 0; i < len; i++)
- wmode[i] = (wchar_t)mode[i];
- wmode[len] = 0;
- ret = _wfopen(wpath, wmode);
- }
- free((void *)wpath);
- return ret;
-}
-
-/* here we return a void pointer instead of _WDIR or DIR pointer */
-void *subsurface_opendir(const char *path)
-{
- _WDIR *ret = NULL;
- if (!path)
- return ret;
- wchar_t *wpath = utf8_to_utf16(path);
- if (wpath)
- ret = _wopendir(wpath);
- free((void *)wpath);
- return (void *)ret;
-}
-
-int subsurface_access(const char *path, int mode)
-{
- int ret = -1;
- if (!path)
- return ret;
- wchar_t *wpath = utf8_to_utf16(path);
- if (wpath)
- ret = _waccess(wpath, mode);
- free((void *)wpath);
- return ret;
-}
-
-#ifndef O_BINARY
-#define O_BINARY 0
-#endif
-
-struct zip *subsurface_zip_open_readonly(const char *path, int flags, int *errorp)
-{
-#if defined(LIBZIP_VERSION_MAJOR)
- /* libzip 0.10 has zip_fdopen, let's use it since zip_open doesn't have a
- * wchar_t version */
- int fd = subsurface_open(path, O_RDONLY | O_BINARY, 0);
- struct zip *ret = zip_fdopen(fd, flags, errorp);
- if (!ret)
- close(fd);
- return ret;
-#else
- return zip_open(path, flags, errorp);
-#endif
-}
-
-int subsurface_zip_close(struct zip *zip)
-{
- return zip_close(zip);
-}
-
-/* win32 console */
-static struct {
- bool allocated;
- UINT cp;
- FILE *out, *err;
-} console_desc;
-
-void subsurface_console_init(bool dedicated)
-{
- (void)console_desc;
- /* if this is a console app already, do nothing */
-#ifndef WIN32_CONSOLE_APP
- /* just in case of multiple calls */
- memset((void *)&console_desc, 0, sizeof(console_desc));
- /* the AttachConsole(..) call can be used to determine if the parent process
- * is a terminal. if it succeeds, there is no need for a dedicated console
- * window and we don't need to call the AllocConsole() function. on the other
- * hand if the user has set the 'dedicated' flag to 'true' and if AttachConsole()
- * has failed, we create a dedicated console window.
- */
- console_desc.allocated = AttachConsole(ATTACH_PARENT_PROCESS);
- if (console_desc.allocated)
- dedicated = false;
- if (!console_desc.allocated && dedicated)
- console_desc.allocated = AllocConsole();
- if (!console_desc.allocated)
- return;
-
- console_desc.cp = GetConsoleCP();
- SetConsoleOutputCP(CP_UTF8); /* make the ouput utf8 */
-
- /* set some console modes; we don't need to reset these back.
- * ENABLE_EXTENDED_FLAGS = 0x0080, ENABLE_QUICK_EDIT_MODE = 0x0040 */
- HANDLE h_in = GetStdHandle(STD_INPUT_HANDLE);
- if (h_in) {
- SetConsoleMode(h_in, 0x0080 | 0x0040);
- CloseHandle(h_in);
- }
-
- /* dedicated only; disable the 'x' button as it will close the main process as well */
- HWND h_cw = GetConsoleWindow();
- if (h_cw && dedicated) {
- SetWindowTextA(h_cw, "Subsurface Console");
- HMENU h_menu = GetSystemMenu(h_cw, 0);
- if (h_menu) {
- EnableMenuItem(h_menu, SC_CLOSE, MF_BYCOMMAND | MF_DISABLED);
- DrawMenuBar(h_cw);
- }
- SetConsoleCtrlHandler(NULL, TRUE); /* disable the CTRL handler */
- }
-
- /* redirect; on win32, CON is a reserved pipe target, like NUL */
- console_desc.out = freopen("CON", "w", stdout);
- console_desc.err = freopen("CON", "w", stderr);
- if (!dedicated)
- puts(""); /* add an empty line */
-#endif
-}
-
-void subsurface_console_exit(void)
-{
-#ifndef WIN32_CONSOLE_APP
- if (!console_desc.allocated)
- return;
-
- /* close handles */
- if (console_desc.out)
- fclose(console_desc.out);
- if (console_desc.err)
- fclose(console_desc.err);
-
- /* reset code page and free */
- SetConsoleOutputCP(console_desc.cp);
- FreeConsole();
-#endif
-}