diff options
author | Tomaz Canabrava <tomaz.canabrava@intel.com> | 2015-09-02 20:52:34 -0300 |
---|---|---|
committer | Dirk Hohndel <dirk@hohndel.org> | 2015-10-30 10:36:48 -0700 |
commit | 4c0156e3d51b389db8eccc3fa3da4b8f248f9b13 (patch) | |
tree | 966868d29150fdba13a5a56fb4305bc432ec7a72 /windows.c | |
parent | a0798214231c652ac6142228f5ddfc4b65c921f8 (diff) | |
download | subsurface-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.c | 448 |
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 -} |