view src/config.c @ 10:42ac054c0231

*: huge refactoring dirtools now uses wchar (wayyy overdue) the timer doesn't have a stupid design anymore we don't use windows.h at all now ...
author Paper <paper@paper.us.eu.org>
date Sun, 11 Feb 2024 19:43:31 -0500
parents 07f0e2f43204
children e6a594f16403
line wrap: on
line source

/**
 * config.c:
 *
 * Functions to load/save/edit the config.
**/

/**
 * example config:
 *
 * ----- wgsdk config ----
 * display_title=1
 * show_elapsed_time=1
**/
#include "dirtools.h"
#include "config.h"
#include "resource.h"
#include "utils.h"

#include <shlobj.h>
#include <shlwapi.h>

#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX_LINE_LENGTH 256

/* from main */
extern void update_rich_presence_details(void);
extern struct config config;

/* must be free'd by the caller */
LPWSTR cfg_get_path() {
	/* get location of appdata folder */
	LPWSTR appdata_folder;
	SHGetKnownFolderPath(&FOLDERID_RoamingAppData, 0, NULL, &appdata_folder);

	/* compatibility with WACUP, falls back to Winamp */
	WCHAR exe_name[MAX_PATH] = {L'\0'};
	if (GetModuleFileNameW(NULL, (LPWSTR)&exe_name, MAX_PATH)) {
		PathStripPathW(exe_name);
		PathRemoveExtensionW(exe_name);
	} else { // fail
		memset(exe_name, '\0', MAX_PATH * sizeof(WCHAR));
		wcscpy(exe_name, L"Winamp");
	}

	/* concat until we get the final path */
	LPWSTR path = dirtools_concat_paths(appdata_folder, exe_name);
	CoTaskMemFree(appdata_folder);

	LPWSTR final = dirtools_concat_paths(path, L"Plugins\\wgsdk");
	free(path);

	return final;
}

int cfg_load(struct config* restrict config) {
	LPWSTR fold_path = cfg_get_path();
	LPWSTR path = dirtools_concat_paths(fold_path, L"config.txt");
	free(fold_path);

	/* find some real win32 replacement for this */
	FILE* config_fp = _wfopen(path, L"r");
	if (config_fp == NULL) {
		free(path);
		return 1;
	}

	/* parse the config */
	char line[MAX_LINE_LENGTH] = {0};
	while (fgets(line, MAX_LINE_LENGTH, config_fp)) {
		/* strtok is okay here. */
		switch (crc32b((unsigned char*)strtok(line, "="))) {
			case 0x2a666380: // display_title
				config->display_title = !!atoi(strtok(NULL, "="));
				break;
			case 0xbb631f7f: // show_elapsed_time
				config->show_elapsed_time = !!atoi(strtok(NULL, "="));
				break;
			default:
				break;
		}
	}

	free(path);
	return 0;
}

int cfg_save(struct config config) {
	LPWSTR fold_path = cfg_get_path();
	assert(!dirtools_create_directory(fold_path));

	LPWSTR path = dirtools_concat_paths(fold_path, L"config.txt");
	free(fold_path);

	FILE* config_fp = _wfopen(path, L"w");
	if (config_fp == NULL) {
		free(path);
		return 1;
	}

	fprintf(config_fp, "----- wgsdk config ----\n");
	fprintf(config_fp, "display_title=%d\n",     config.display_title);
	fprintf(config_fp, "show_elapsed_time=%d\n", config.show_elapsed_time);
	fclose(config_fp);
	free(path);
	return 0;
}

/* --------------------------------- */

#define conf_item_to_dlg(hwnd, cons, var) \
{ \
	HWND checkboxHwnd = GetDlgItem(hwnd, cons); \
	SendMessage(checkboxHwnd, BM_SETCHECK, (var) ? BST_CHECKED : BST_UNCHECKED, 0); \
}
#define dlg_item_to_conf(hwnd, cons, var) \
{ \
	HWND checkboxHwnd = GetDlgItem(hwnd, cons); \
	(var) = (SendMessage(checkboxHwnd, BM_GETCHECK, 0, 0) == BST_CHECKED); \
}
void cfg_get_controls(HWND hWnd) {
	dlg_item_to_conf(hWnd, TITLE_CHECK,        config.display_title);
	dlg_item_to_conf(hWnd, ELAPSED_TIME_CHECK, config.show_elapsed_time);
}

void cfg_set_controls(HWND hWnd) {
	conf_item_to_dlg(hWnd, TITLE_CHECK,        config.display_title);
	conf_item_to_dlg(hWnd, ELAPSED_TIME_CHECK, config.show_elapsed_time);
}
#undef conf_item_to_dlg
#undef dlg_item_to_conf

void cfg_on_confirm_settings_dialog(HWND hWnd) {
	cfg_get_controls(hWnd);
	cfg_save(config);
	update_rich_presence_details();
}

BOOL CALLBACK cfg_win_proc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) {
	switch (msg) {
		case WM_INITDIALOG:
			/* do nothing if this is a child window (tab page) callback, pass to the parent */
			if (GetWindowLong(hWnd, GWL_STYLE) & WS_CHILD)
				return FALSE;
			cfg_set_controls(hWnd);
			return TRUE;
		case WM_COMMAND:
			switch (LOWORD(wParam)) {
				case IDOK:
					cfg_on_confirm_settings_dialog(hWnd);
					EndDialog(hWnd, 0);
					return TRUE;
				case IDCANCEL:
					EndDialog(hWnd, 0);
					return TRUE;
			}
	}

	return FALSE;
}