-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathConfigManager.cs
More file actions
103 lines (90 loc) · 3.38 KB
/
ConfigManager.cs
File metadata and controls
103 lines (90 loc) · 3.38 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
namespace CapsNumTray;
/// <summary>
/// Simple INI file reader/writer compatible with AHK's IniRead/IniWrite format.
/// </summary>
internal sealed class ConfigManager
{
private static readonly System.Text.Encoding Utf8NoBom = new System.Text.UTF8Encoding(false);
private readonly string _iniPath;
public bool ShowCaps { get; set; } = true;
public bool ShowNum { get; set; } = true;
public bool ShowScroll { get; set; } // false by default (opt-in)
public bool ShowOSD { get; set; } = true;
public bool BeepOnToggle { get; set; }
public int PollInterval { get; set; } // seconds, 0 = disabled (default), max 300 (5 min)
public ConfigManager(string iniPath)
{
_iniPath = iniPath;
Load();
}
public void Load()
{
if (!File.Exists(_iniPath))
return;
try
{
string[] lines = File.ReadAllLines(_iniPath, Utf8NoBom);
string currentSection = "";
foreach (string rawLine in lines)
{
string line = rawLine.Trim();
if (line.Length == 0 || line[0] == ';')
continue;
if (line[0] == '[' && line[^1] == ']')
{
currentSection = line[1..^1];
continue;
}
int eq = line.IndexOf('=');
if (eq < 0) continue;
string key = line[..eq].Trim();
string val = line[(eq + 1)..].Trim();
switch (currentSection)
{
case "Visibility":
if (key == "ShowCaps") ShowCaps = val == "1";
else if (key == "ShowNum") ShowNum = val == "1";
else if (key == "ShowScroll") ShowScroll = val == "1";
break;
case "General":
if (key == "ShowOSD") ShowOSD = val == "1";
else if (key == "BeepOnToggle") BeepOnToggle = val == "1";
else if (key == "PollInterval" && int.TryParse(val, out int pi))
PollInterval = Math.Clamp(pi, 0, 300);
break;
}
}
}
catch
{
// Graceful default on locked/corrupt file
}
}
public void Save()
{
string content =
"[Visibility]\r\n" +
$"ShowCaps={B(ShowCaps)}\r\n" +
$"ShowNum={B(ShowNum)}\r\n" +
$"ShowScroll={B(ShowScroll)}\r\n" +
"\r\n[General]\r\n" +
$"ShowOSD={B(ShowOSD)}\r\n" +
$"BeepOnToggle={B(BeepOnToggle)}\r\n" +
$"PollInterval={PollInterval}\r\n";
// Atomic save: write to temp then rename. Protects against power loss or
// process kill leaving a half-written INI that reverts all settings.
// Unique suffix avoids collision if two Save() calls ever overlap.
string tmpPath = $"{_iniPath}.{Guid.NewGuid():N}.tmp";
try
{
File.WriteAllText(tmpPath, content, Utf8NoBom);
File.Move(tmpPath, _iniPath, overwrite: true);
}
catch
{
// Silently fail if file is locked; best-effort cleanup of temp.
try { File.Delete(tmpPath); } catch { }
}
}
private static string B(bool v) => v ? "1" : "0";
}