summaryrefslogblamecommitdiffstats
path: root/windows.c
blob: 1c8cd0a0177b12698769ae1ca87106474ccea164 (plain) (tree)
1
2
3
4
5
6
7
                                           
                 
                        
                   
                                      







                                                        
                                                                       
                                                                  







                                                                               
                                                                                          
                                                                                   
                                                                               


                                                                         




                                                                      




                                                                       

                                                        
                                                                                            
                         







                                                                                          
         
                    


                                                             



                                               



                                                                         























                                                                                          
                                    
                                   
         
                                                
 
                                
 
                             


                                
                          

                                 
                      
 



                                  
 

                                         
                                                
















                                                                                           
                                                      
 
                                                                                      

                                                                                   
                                                                                                
                                
 
                                                                   
                                                          
                           
                                                              
                                                                    




















































                                                                                                 
/* windows.c */
/* implements Windows specific functions */
#include "dive.h"
#include "display-gtk.h"
#include <windows.h>
#include <shlobj.h>
#define DIVELIST_DEFAULT_FONT "Sans 8"

static HKEY hkey;

static int get_from_registry(HKEY hkey, const char *key)
{
	DWORD value;
	DWORD len = 4;
	LONG success;

	success = RegQueryValueEx(hkey, (LPCTSTR)TEXT(key), NULL, NULL,
	                         (LPBYTE) &value, (LPDWORD)&len );
	if (success != ERROR_SUCCESS)
		return FALSE; /* that's what happens the first time we start */
	return value;
}

void subsurface_open_conf(void)
{
	LONG success;

	success = RegCreateKeyEx(HKEY_CURRENT_USER, (LPCTSTR)TEXT("Software\\subsurface"),
	                         0L, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS,
	                         NULL, &hkey, NULL);
	if (success != ERROR_SUCCESS)
		printf("CreateKey Software\\subsurface failed %ld\n", success);
}

void subsurface_set_conf(char *name, pref_type_t type, const void *value)
{
	/* since we are using the pointer 'value' as both an actual
	 * pointer to the string setting and as a way to pass the
	 * numbers 0 and 1 to this function for booleans, one of the
	 * calls to RegSetValueEx needs to pass &value (when we want
	 * to pass the boolean value), the other one passes value (the
	 * address of the string. */
	int wlen;
	wchar_t *wname = NULL, *wstring = NULL;

	wname = (wchar_t *)g_utf8_to_utf16(name, -1, NULL, NULL, NULL);
	if (!wname)
		return;
	switch (type) {
	case PREF_BOOL:
		/* we simply store the value as DWORD */
		RegSetValueExW(hkey, (LPCWSTR)wname, 0, REG_DWORD, (const BYTE *)&value, 4);
		break;
	case PREF_STRING:
		wlen = g_utf8_strlen((char *)value, -1);
		wstring = (wchar_t *)g_utf8_to_utf16((char *)value, -1, NULL, NULL, NULL);
		if (!wstring || !wlen) {
			free(wname);
			return;
		}
		RegSetValueExW(hkey, (LPCWSTR)wname, 0, REG_SZ, (const BYTE *)wstring,
		               wlen * sizeof(wchar_t));
		free(wstring);
	}
	free(wname);
}

const void *subsurface_get_conf(char *name, pref_type_t type)
{
	const int csize = 64;
	int blen = 0;
	LONG ret = ERROR_MORE_DATA;
	wchar_t *wstring = NULL, *wname = NULL;
	char *utf8_string;

	switch (type) {
	case PREF_BOOL:
		return get_from_registry(hkey, name) ? (void *) 1 : NULL;
	case PREF_STRING:
		wname = (wchar_t *)g_utf8_to_utf16(name, -1, NULL, NULL, NULL);
		if (!wname)
			return NULL;
		blen = 0;
		/* lest try to load the string in chunks of 'csize' bytes until it fits */
		while(ret == ERROR_MORE_DATA) {
			blen += csize;
			wstring = (wchar_t *)realloc(wstring, blen * sizeof(wchar_t));
			ret = RegQueryValueExW(hkey, (LPCWSTR)wname, NULL, NULL,
			                     (LPBYTE)wstring, (LPDWORD)&blen);
		}
		/* that's what happens the first time we start - just return NULL */
		if (ret != ERROR_SUCCESS) {
			free(wname);
			free(wstring);
			return NULL;
		}
		/* convert the returned string into utf-8 */
		utf8_string = g_utf16_to_utf8(wstring, -1, NULL, NULL, NULL);
		free(wstring);
		free(wname);
		if (!utf8_string)
			return NULL;
		if (!g_utf8_validate(utf8_string, -1, NULL)) {
			free(utf8_string);
			return NULL;
		}
		return utf8_string;
	}
	return NULL; /* we shouldn't get here */
}

void subsurface_flush_conf(void)
{
	/* this is a no-op */
}

void subsurface_close_conf(void)
{
	RegCloseKey(hkey);
}

const char *subsurface_USB_name()
{
	return "COM3";
}

const char *subsurface_icon_name()
{
	return "subsurface.ico";
}

const char *subsurface_default_filename()
{
	if (default_filename) {
		return strdup(default_filename);
	} else {
		char datapath[MAX_PATH];
		const char *user;
		char *buffer;
		int len;

		user = g_get_user_name();
		if (! SUCCEEDED(SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, 0, datapath))) {
			datapath[0] = '.';
			datapath[1] = '\0';
		}
		len = strlen(datapath) + strlen(user) + 17;
		buffer = malloc(len);
		snprintf(buffer, len, "%s\\Subsurface\\%s.xml", datapath, user);
		return buffer;
	}
}

const char *subsurface_gettext_domainpath(char *argv0)
{
	/* first hackishly make sure that the LANGUAGE information is correctly set up
	 * in the environment */
	char buffer[80];
	snprintf(buffer, sizeof(buffer), "LANGUAGE=%s.UTF-8", g_win32_getlocale());
	putenv(buffer);
	/* always use translation directory relative to install location, regardless of argv0 */
	return "./share/locale";
}

void subsurface_ui_setup(GtkSettings *settings, GtkWidget *menubar,
		GtkWidget *vbox, GtkUIManager *ui_manager)
{
	if (!divelist_font)
		divelist_font = strdup(DIVELIST_DEFAULT_FONT);
	gtk_box_pack_start(GTK_BOX(vbox), menubar, FALSE, FALSE, 0);
}

/* barely documented API */
extern int __wgetmainargs(int *, wchar_t ***, wchar_t ***, int, int *);

/* expand-convert the UTF-16 argument list to a list of UTF-8 strings */
void subsurface_command_line_init(gint *argc, gchar ***argv)
{
	wchar_t **wargv, **wenviron;
	gchar **argv_new;
	gchar *s;
	/* for si we assume that a struct address will equal the address
	 * of its first and only int member */
	gint i, n, ret, si;

	/* memory leak tools may reports a potential issue here at a call
	 * to strcpy_s in msvcrt, wich should be a false positive. but even if there
	 * is some kind of a leak, it should be unique and have the same
	 * lifespan as the process heap. */
	ret = __wgetmainargs(&n, &wargv, &wenviron, TRUE, &si);
	if (ret < 0) {
		g_warning("Cannot convert command line");
		return;
	}
	argv_new = g_malloc(sizeof(gchar *) * (n + 1));

	for (i = 0; i < n; ++i) {
		s = g_utf16_to_utf8((gunichar2 *)wargv[i], -1, NULL, NULL, NULL);
		if (!s) {
			g_warning("Cannot convert command line argument (%d) to UTF-8", (i + 1));
			s = "\0";
		}	else if (!g_utf8_validate(s, -1, NULL)) {
			g_warning("Cannot validate command line argument '%s' (%d)", s, (i + 1));
			g_free(s);
			s = "\0";
		}
		argv_new[i] = s;
	}
	argv_new[n] = NULL;

	/* update the argument list and count */
	if (argv && argc) {
		*argv = argv_new;
		*argc = n;
	}
}

/* once done, free the argument list */
void subsurface_command_line_exit(gint *argc, gchar ***argv)
{
	int i;
	for (i = 0; i < *argc; i++)
		g_free((*argv)[i]);
	g_free(*argv);
}