| 7 | 1 /** | 
|  | 2  * config.c: | 
|  | 3  * | 
|  | 4  * Functions to load/save/edit the config. | 
|  | 5 **/ | 
|  | 6 | 
|  | 7 /** | 
|  | 8  * example config: | 
|  | 9  * | 
|  | 10  * ----- wgsdk config ---- | 
|  | 11  * display_title=1 | 
|  | 12  * show_elapsed_time=1 | 
|  | 13 **/ | 
| 10 | 14 #include "dirtools.h" | 
|  | 15 #include "config.h" | 
|  | 16 #include "resource.h" | 
|  | 17 #include "utils.h" | 
|  | 18 | 
|  | 19 #include <shlobj.h> | 
|  | 20 #include <shlwapi.h> | 
|  | 21 | 
| 0 | 22 #include <assert.h> | 
|  | 23 #include <stdio.h> | 
|  | 24 #include <stdlib.h> | 
|  | 25 #include <string.h> | 
| 10 | 26 | 
|  | 27 #define MAX_LINE_LENGTH 256 | 
| 0 | 28 | 
| 7 | 29 /* from main */ | 
|  | 30 extern void update_rich_presence_details(void); | 
|  | 31 extern struct config config; | 
| 0 | 32 | 
| 10 | 33 /* must be free'd by the caller */ | 
|  | 34 LPWSTR cfg_get_path() { | 
|  | 35 	/* get location of appdata folder */ | 
|  | 36 	LPWSTR appdata_folder; | 
|  | 37 	SHGetKnownFolderPath(&FOLDERID_RoamingAppData, 0, NULL, &appdata_folder); | 
|  | 38 | 
|  | 39 	/* compatibility with WACUP, falls back to Winamp */ | 
|  | 40 	WCHAR exe_name[MAX_PATH] = {L'\0'}; | 
|  | 41 	if (GetModuleFileNameW(NULL, (LPWSTR)&exe_name, MAX_PATH)) { | 
|  | 42 		PathStripPathW(exe_name); | 
|  | 43 		PathRemoveExtensionW(exe_name); | 
|  | 44 	} else { // fail | 
|  | 45 		memset(exe_name, '\0', MAX_PATH * sizeof(WCHAR)); | 
|  | 46 		wcscpy(exe_name, L"Winamp"); | 
|  | 47 	} | 
|  | 48 | 
|  | 49 	/* concat until we get the final path */ | 
|  | 50 	LPWSTR path = dirtools_concat_paths(appdata_folder, exe_name); | 
|  | 51 	CoTaskMemFree(appdata_folder); | 
|  | 52 | 
|  | 53 	LPWSTR final = dirtools_concat_paths(path, L"Plugins\\wgsdk"); | 
|  | 54 	free(path); | 
|  | 55 | 
|  | 56 	return final; | 
|  | 57 } | 
|  | 58 | 
| 9 | 59 int cfg_load(struct config* restrict config) { | 
| 10 | 60 	LPWSTR fold_path = cfg_get_path(); | 
|  | 61 	LPWSTR path = dirtools_concat_paths(fold_path, L"config.txt"); | 
|  | 62 	free(fold_path); | 
|  | 63 | 
|  | 64 	/* find some real win32 replacement for this */ | 
|  | 65 	FILE* config_fp = _wfopen(path, L"r"); | 
| 0 | 66 	if (config_fp == NULL) { | 
|  | 67 		free(path); | 
|  | 68 		return 1; | 
|  | 69 	} | 
| 10 | 70 | 
| 7 | 71 	/* parse the config */ | 
| 10 | 72 	char line[MAX_LINE_LENGTH] = {0}; | 
| 0 | 73 	while (fgets(line, MAX_LINE_LENGTH, config_fp)) { | 
| 10 | 74 		/* strtok is okay here. */ | 
| 0 | 75 		switch (crc32b((unsigned char*)strtok(line, "="))) { | 
|  | 76 			case 0x2a666380: // display_title | 
| 1 | 77 				config->display_title = !!atoi(strtok(NULL, "=")); | 
| 0 | 78 				break; | 
|  | 79 			case 0xbb631f7f: // show_elapsed_time | 
| 1 | 80 				config->show_elapsed_time = !!atoi(strtok(NULL, "=")); | 
| 0 | 81 				break; | 
|  | 82 			default: | 
|  | 83 				break; | 
|  | 84 		} | 
|  | 85 	} | 
| 10 | 86 | 
| 0 | 87 	free(path); | 
|  | 88 	return 0; | 
|  | 89 } | 
|  | 90 | 
| 4 | 91 int cfg_save(struct config config) { | 
| 10 | 92 	LPWSTR fold_path = cfg_get_path(); | 
|  | 93 	assert(!dirtools_create_directory(fold_path)); | 
|  | 94 | 
|  | 95 	LPWSTR path = dirtools_concat_paths(fold_path, L"config.txt"); | 
|  | 96 	free(fold_path); | 
| 7 | 97 | 
| 10 | 98 	FILE* config_fp = _wfopen(path, L"w"); | 
|  | 99 	if (config_fp == NULL) { | 
|  | 100 		free(path); | 
| 0 | 101 		return 1; | 
| 10 | 102 	} | 
|  | 103 | 
| 1 | 104 	fprintf(config_fp, "----- wgsdk config ----\n"); | 
| 7 | 105 	fprintf(config_fp, "display_title=%d\n",     config.display_title); | 
| 0 | 106 	fprintf(config_fp, "show_elapsed_time=%d\n", config.show_elapsed_time); | 
|  | 107 	fclose(config_fp); | 
| 10 | 108 	free(path); | 
| 0 | 109 	return 0; | 
|  | 110 } | 
| 1 | 111 | 
|  | 112 /* --------------------------------- */ | 
|  | 113 | 
| 10 | 114 #define conf_item_to_dlg(hwnd, cons, var) \ | 
|  | 115 { \ | 
|  | 116 	HWND checkboxHwnd = GetDlgItem(hwnd, cons); \ | 
|  | 117 	SendMessage(checkboxHwnd, BM_SETCHECK, (var) ? BST_CHECKED : BST_UNCHECKED, 0); \ | 
|  | 118 } | 
|  | 119 #define dlg_item_to_conf(hwnd, cons, var) \ | 
|  | 120 { \ | 
|  | 121 	HWND checkboxHwnd = GetDlgItem(hwnd, cons); \ | 
|  | 122 	(var) = (SendMessage(checkboxHwnd, BM_GETCHECK, 0, 0) == BST_CHECKED); \ | 
|  | 123 } | 
| 7 | 124 void cfg_get_controls(HWND hWnd) { | 
| 10 | 125 	dlg_item_to_conf(hWnd, TITLE_CHECK,        config.display_title); | 
|  | 126 	dlg_item_to_conf(hWnd, ELAPSED_TIME_CHECK, config.show_elapsed_time); | 
| 1 | 127 } | 
|  | 128 | 
|  | 129 void cfg_set_controls(HWND hWnd) { | 
| 10 | 130 	conf_item_to_dlg(hWnd, TITLE_CHECK,        config.display_title); | 
|  | 131 	conf_item_to_dlg(hWnd, ELAPSED_TIME_CHECK, config.show_elapsed_time); | 
| 7 | 132 } | 
|  | 133 #undef conf_item_to_dlg | 
|  | 134 #undef dlg_item_to_conf | 
|  | 135 | 
|  | 136 void cfg_on_confirm_settings_dialog(HWND hWnd) { | 
|  | 137 	cfg_get_controls(hWnd); | 
|  | 138 	cfg_save(config); | 
|  | 139 	update_rich_presence_details(); | 
| 1 | 140 } | 
|  | 141 | 
|  | 142 BOOL CALLBACK cfg_win_proc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { | 
|  | 143 	switch (msg) { | 
| 7 | 144 		case WM_INITDIALOG: | 
|  | 145 			/* do nothing if this is a child window (tab page) callback, pass to the parent */ | 
| 1 | 146 			if (GetWindowLong(hWnd, GWL_STYLE) & WS_CHILD) | 
|  | 147 				return FALSE; | 
|  | 148 			cfg_set_controls(hWnd); | 
|  | 149 			return TRUE; | 
|  | 150 		case WM_COMMAND: | 
|  | 151 			switch (LOWORD(wParam)) { | 
| 7 | 152 				case IDOK: | 
| 1 | 153 					cfg_on_confirm_settings_dialog(hWnd); | 
|  | 154 					EndDialog(hWnd, 0); | 
|  | 155 					return TRUE; | 
| 7 | 156 				case IDCANCEL: | 
| 1 | 157 					EndDialog(hWnd, 0); | 
|  | 158 					return TRUE; | 
|  | 159 			} | 
|  | 160 	} | 
|  | 161 | 
| 7 | 162 	return FALSE; | 
| 1 | 163 } |