tagging release
[dasher.git] / Src / Win32 / Common / WinOptions.cpp
blob3404ffcdfdac36dc9824d3a2048a1f96dd4f2e29
1 // WinOptions.cpp
2 //
3 /////////////////////////////////////////////////////////////////////////////
4 //
5 // Copyright (c) 2002 Iain Murray, Inference Group, Cavendish, Cambridge.
6 //
7 /////////////////////////////////////////////////////////////////////////////
9 #include "WinCommon.h"
11 #include "WinOptions.h"
13 using namespace WinUTF8;
15 // Track memory leaks on Windows to the line that new'd the memory
16 #ifdef _WIN32
17 #ifdef _DEBUG
18 #define DEBUG_NEW new( _NORMAL_BLOCK, THIS_FILE, __LINE__ )
19 #define new DEBUG_NEW
20 #undef THIS_FILE
21 static char THIS_FILE[] = __FILE__;
22 #endif
23 #endif
25 /* TODO: Consider using Template functions to make this neater. */
27 CWinOptions::CWinOptions(const std::string &Group, const std::string &Product, Dasher::CEventHandler *pEventHandler):CSettingsStore(pEventHandler) {
28 // Windows requires strings as Tstring
29 Tstring TGroup, TProduct;
30 UTF8string_to_wstring(Group, TGroup);
31 UTF8string_to_wstring(Product, TProduct);
33 // Get hold of HKEY_CURRENT_USER\Software
34 HKEY SoftwareKey;
35 if(GetOrCreate(HKEY_CURRENT_USER, TEXT("Software"), KEY_WRITE, &SoftwareKey) != 0) {
36 // Can't open or create key - do something...
37 // Probably flag registry as failed and just return default options
38 exit(1); // give up for now.
41 // Then HKEY_CURRENT_USER\Software\<Group>
42 HKEY GroupKey;
43 if(GetOrCreate(SoftwareKey, TGroup.c_str(), KEY_WRITE, &GroupKey) != 0) {
44 exit(1);
46 RegCloseKey(SoftwareKey);
48 // Then HKEY_CURRENT_USER\Software\<Group>\<Product>
49 if(GetOrCreate(GroupKey, TProduct.c_str(), KEY_ALL_ACCESS, &ProductKey) != 0) {
50 exit(1);
52 RegCloseKey(GroupKey);
54 LoadPersistent();
57 CWinOptions::~CWinOptions() {
58 RegCloseKey(ProductKey);
61 /* Private functions -- Used to load and save to the Windows Registry
62 --------------------------------------------------------------------------*/
64 bool CWinOptions::LoadSetting(const std::string &Key, bool *Value) {
65 Tstring TKey;
66 UTF8string_to_wstring(Key, TKey);
67 BYTE *Data = 0;
69 if(!GetlpByte(TKey, &Data)) {
70 delete[]Data;
71 return false;
74 if((DWORD) * Data == 0)
75 *Value = false;
76 else
77 *Value = true;
79 delete[]Data;
80 return true;
83 /////////////////////////////////////////////////////////////////////////////
85 bool CWinOptions::LoadSetting(const std::string &Key, long *Value) {
86 Tstring TKey;
87 UTF8string_to_wstring(Key, TKey);
88 BYTE *Data = 0;
90 if(!GetlpByte(TKey, &Data)) {
91 delete[]Data;
92 return false;
95 // Evil casting to make sure I can retrieve signed longs, even
96 // though windows registry only stores +ve values.
97 *Value = *((long *)Data);
98 delete[]Data;
99 return true;
102 /////////////////////////////////////////////////////////////////////////////
104 bool CWinOptions::LoadSettingT(const std::string &Key, Tstring *TValue) {
105 Tstring TKey;
106 UTF8string_to_wstring(Key, TKey);
107 BYTE *Data = 0;
109 if(!GetlpByte(TKey, &Data)) {
110 delete[]Data;
111 return false;
114 *TValue = (TCHAR *) Data;
115 delete[]Data;
117 return true;
120 /////////////////////////////////////////////////////////////////////////////
122 bool CWinOptions::LoadSetting(const std::string &Key, std::string *Value) {
124 Tstring str;
125 if(LoadSettingT(Key, &str)) {
126 wstring_to_UTF8string(str, *Value);
127 return true;
130 return false;
134 /////////////////////////////////////////////////////////////////////////////
136 static TCHAR FormatWindowPlacement[] = TEXT("%u,%u,%d,%d,%d,%d,%d,%d,%d,%d");
138 /////////////////////////////////////////////////////////////////////////////
139 #ifndef DASHER_WINCE
141 void CWinOptions::SaveSetting(const std::string &Key, const LPWINDOWPLACEMENT pwp) {
142 DASHER_ASSERT(pwp != NULL);
144 TCHAR t[200];
145 _stprintf(t, FormatWindowPlacement, pwp->flags, pwp->showCmd, pwp->ptMinPosition.x, pwp->ptMinPosition.y, pwp->ptMaxPosition.x, pwp->ptMaxPosition.y, pwp->rcNormalPosition.left, pwp->rcNormalPosition.top, pwp->rcNormalPosition.right, pwp->rcNormalPosition.bottom);
147 Tstring ts(t);
148 SaveSettingT(Key, ts);
152 /////////////////////////////////////////////////////////////////////////////
154 bool CWinOptions::LoadSetting(const std::string &Key, LPWINDOWPLACEMENT pwp) {
155 DASHER_ASSERT(pwp != NULL);
157 Tstring str;
159 if(!LoadSettingT(Key, &str))
160 return false;
162 WINDOWPLACEMENT wp;
163 int nRead = _stscanf(str.c_str(), FormatWindowPlacement,
164 &wp.flags, &wp.showCmd,
165 &wp.ptMinPosition.x, &wp.ptMinPosition.y,
166 &wp.ptMaxPosition.x, &wp.ptMaxPosition.y,
167 &wp.rcNormalPosition.left, &wp.rcNormalPosition.top,
168 &wp.rcNormalPosition.right, &wp.rcNormalPosition.bottom);
170 if(nRead != 10)
171 return false;
172 wp.length = sizeof(wp);
174 *pwp = wp;
175 return true;
179 #endif
180 /////////////////////////////////////////////////////////////////////////////
182 void CWinOptions::SaveSetting(const std::string &Key, bool Value) {
183 if(Value)
184 SaveSetting(Key, 1l);
185 else
186 SaveSetting(Key, 0l);
189 /////////////////////////////////////////////////////////////////////////////
191 void CWinOptions::SaveSetting(const std::string &Key, long Value) {
192 Tstring TKey;
193 UTF8string_to_wstring(Key, TKey);
194 // Evil casting. Registry stores DWORD's (unsigned longs)
195 // I'm forcing in signed longs and if I force them out again in the same
196 // way I should get a sensible result.
197 DWORD *RegValue = (DWORD *) & Value;
198 DWORD MemAllow = sizeof(DWORD);
199 LONG ErrVal = RegSetValueEx(ProductKey, TKey.c_str(), 0,
200 REG_DWORD, (const unsigned char *)RegValue, MemAllow);
203 /////////////////////////////////////////////////////////////////////////////
205 void CWinOptions::SaveSettingT(const std::string &Key, const Tstring &TValue) {
206 Tstring TKey;
207 UTF8string_to_wstring(Key, TKey);
209 DWORD MemAllow = (TValue.size() + 1) * sizeof(TCHAR);
211 //const unsigned char* StrInput = (const unsigned char*) Value.c_str();
212 //LONG ErrVal = RegSetValueEx(ProductKey, TKey.c_str(), 0,
213 // REG_SZ, StrInput, MemAllow);
215 LONG ErrVal = RegSetValueEx(ProductKey, TKey.c_str(), 0,
216 REG_SZ, (CONST BYTE *) TValue.c_str(), MemAllow);
220 /////////////////////////////////////////////////////////////////////////////
222 void CWinOptions::SaveSetting(const std::string &Key, const std::string &Value) {
224 // DJW20031107 - i think Values should also be converted to Tstring
225 Tstring TValue;
226 UTF8string_to_wstring(Value, TValue);
228 SaveSettingT(Key, TValue);
231 // Used for getting a handle on the Dasher key in the constructor.
232 int CWinOptions::GetOrCreate(HKEY hKey, LPCTSTR lpSubKey, REGSAM samDesired, HKEY *lpNewKey) {
233 if(!(RegOpenKeyEx(hKey, lpSubKey, 0, samDesired, lpNewKey) == ERROR_SUCCESS)) {
235 if(!(RegCreateKeyEx(hKey, lpSubKey, 0, NULL, REG_OPTION_NON_VOLATILE, samDesired, NULL, lpNewKey, NULL) == ERROR_SUCCESS)) {
237 return (1);
240 return 0;
243 bool CWinOptions::GetlpByte(const Tstring &Key, BYTE **Data) const {
244 *Data = new BYTE[1];
245 unsigned long datasize = sizeof(BYTE[1]);
246 DWORD Type;
248 LONG ErrVal = RegQueryValueEx(ProductKey, Key.c_str(), 0, &Type, *Data, &datasize);
249 while(ErrVal == ERROR_MORE_DATA) {
250 delete[] * Data;
251 *Data = new BYTE[datasize];
252 ErrVal = RegQueryValueEx(ProductKey, Key.c_str(), 0, &Type, *Data, &datasize);
255 // Perhaps I should spend lots of time working out why the registry doesn't work.
256 // when this fails. Would probably just confuse users though. Users with a broken
257 // registry can live with defaults :)
258 if((ErrVal == ERROR_SUCCESS) && (*Data != 0))
259 return true;
260 else
261 return false;