static int inimode = 0;
static TCHAR *inipath;
-#define PUPPA _T("eitätäoo")
+
+#define ROOT_TREE _T("WinUAE")
+
+static struct ini_line **inidata;
+static int inilines;
+
+struct ini_line
+{
+ int section_order;
+ TCHAR *section;
+ TCHAR *key;
+ TCHAR *value;
+};
+
+static TCHAR *initrim(TCHAR *s)
+{
+ while (*s != 0 && *s <= 32)
+ s++;
+ TCHAR *s2 = s;
+ while (*s2)
+ s2++;
+ while (s2 > s) {
+ s2--;
+ if (*s2 > 32)
+ break;
+ *s2 = 0;
+ }
+ return s;
+}
+
+static void ini_free(void)
+{
+ for(int c = 0; c < inilines; c++) {
+ struct ini_line *il = inidata[c];
+ xfree(il->section);
+ xfree(il->key);
+ xfree(il->value);
+ xfree(il);
+ inidata[c] = NULL;
+ }
+}
+
+static void ini_sort(void)
+{
+ for(int c1 = 0; c1 < inilines; c1++) {
+ struct ini_line *il1 = inidata[c1];
+ if (il1 == NULL)
+ continue;
+ for (int c2 = c1 + 1; c2 < inilines; c2++) {
+ struct ini_line *il2 = inidata[c2];
+ if (il2 == NULL)
+ continue;
+ int order = 0;
+ int sec = _tcsicmp(il1->section, il2->section);
+ if (sec) {
+ if (!il1->section_order && !il2->section_order)
+ order = sec;
+ else
+ order = il2->section_order - il1->section_order;
+ } else {
+ order = _tcsicmp(il1->key, il2->key);
+ }
+ if (order > 0) {
+ struct ini_line il;
+ memcpy(&il, il1, sizeof(struct ini_line));
+ memcpy(il1, il2, sizeof(struct ini_line));
+ memcpy(il2, &il, sizeof(struct ini_line));
+ }
+ }
+ }
+#if 0
+ for(int c1 = 0; c1 < inilines; c1++) {
+ struct ini_line *il1 = inidata[c1];
+ if (il1)
+ write_log(_T("[%s] %s %s\n"), il1->section, il1->key, il1->value);
+ }
+ write_log(_T("\n"));
+#endif
+}
+
+static void ini_addnewstring(const TCHAR *section, const TCHAR *key, const TCHAR *val)
+{
+ struct ini_line *il = xcalloc(struct ini_line, 1);
+ il->section = my_strdup(section);
+ if (!_tcsicmp(section, ROOT_TREE))
+ il->section_order = 1;
+ il->key = my_strdup(key);
+ il->value = my_strdup(val);
+ int cnt = 0;
+ while (cnt < inilines && inidata[cnt])
+ cnt++;
+ if (cnt == inilines) {
+ inilines += 10;
+ inidata = xrealloc(struct ini_line*, inidata, inilines);
+ int cnt2 = cnt;
+ while (cnt2 < inilines) {
+ inidata[cnt2++] = NULL;
+ }
+ }
+ inidata[cnt] = il;
+}
+
+static const uae_u8 bom[3] = { 0xef, 0xbb, 0xbf };
+
+static void ini_load(const TCHAR *path)
+{
+ bool utf8 = false;
+ TCHAR section[MAX_DPATH];
+ uae_u8 tmp[3];
+
+ ini_free();
+
+ FILE *f = _tfopen(path, _T("rb"));
+ if (!f)
+ return;
+ int v = fread(tmp, 1, sizeof tmp, f);
+ fclose (f);
+ if (v == 3 && tmp[0] == 0xef && tmp[1] == 0xbb && tmp[2] == 0xbf) {
+ f = _tfopen (path, _T("rt, ccs=UTF-8"));
+ } else {
+ f = _tfopen (path, _T("rt"));
+ }
+ section[0] = 0;
+ for (;;) {
+ TCHAR tbuffer[MAX_DPATH];
+ tbuffer[0] = 0;
+ if (!fgetws(tbuffer, MAX_DPATH, f))
+ break;
+ TCHAR *s = initrim(tbuffer);
+ if (_tcslen(s) < 3)
+ continue;
+ if (s[0] == '[' && s[_tcslen(s) - 1] == ']') {
+ s[_tcslen(s) - 1] = 0;
+ _tcscpy(section, s + 1);
+ continue;
+ }
+ if (section[0] == 0)
+ continue;
+ TCHAR *s1 = _tcschr(s, '=');
+ if (s1) {
+ *s1++ = 0;
+ TCHAR *s2 = initrim(tbuffer);
+ TCHAR *s3 = initrim(s1);
+ ini_addnewstring(section, s2, s3);
+ }
+ }
+ fclose(f);
+ ini_sort();
+}
+
+static void ini_save(const TCHAR *path)
+{
+ TCHAR section[MAX_DPATH];
+ TCHAR sep[2] = { '=', 0 };
+ TCHAR lf[2] = { 10, 0 };
+ TCHAR left[2] = { '[', 0 };
+ TCHAR right[2] = { ']', 0 };
+
+ ini_sort();
+ FILE *f = _tfopen(path, _T("wt, ccs=UTF-8"));
+ if (!f)
+ return;
+ section[0] = 0;
+ for (int c = 0; c < inilines; c++) {
+ TCHAR out[MAX_DPATH];
+ struct ini_line *il = inidata[c];
+ if (!il)
+ continue;
+ if (_tcscmp(il->section, section)) {
+ _tcscpy(out, lf);
+ _tcscat(out, left);
+ _tcscat(out, il->section);
+ _tcscat(out, right);
+ _tcscat(out, lf);
+ fputws(out, f);
+ _tcscpy(section, il->section);
+ }
+ _tcscpy(out, il->key);
+ _tcscat(out, sep);
+ _tcscat(out, il->value);
+ _tcscat(out, lf);
+ fputws(out, f);
+ }
+ fclose(f);
+}
+
+static bool ini_getstring(const TCHAR *section, const TCHAR *key, TCHAR *out, int *max)
+{
+ for (int c = 0; c < inilines; c++) {
+ struct ini_line *il = inidata[c];
+ if (il && !_tcscmp(section, il->section) && (key == NULL || !_tcscmp(key, il->key))) {
+ if (out) {
+ _tcsncpy(out, il->value, *max);
+ out[*max - 1] = 0;
+ *max = _tcslen(out);
+ }
+ return true;
+ }
+ }
+ return false;
+}
+
+static bool ini_getsectionstring(const TCHAR *section, int idx, TCHAR *keyout, int *keysize, TCHAR *valout, int *valsize)
+{
+ for (int c = 0; c < inilines; c++) {
+ struct ini_line *il = inidata[c];
+ if (il && !_tcscmp(section, il->section)) {
+ if (idx == 0) {
+ if (keyout) {
+ _tcsncpy(keyout, il->key, *keysize);
+ keyout[*keysize - 1] = 0;
+ *keysize = _tcslen(keyout);
+ }
+ if (valout) {
+ _tcsncpy(valout, il->value, *valsize);
+ valout[*valsize - 1] = 0;
+ *valsize = _tcslen(valout);
+ }
+ return true;
+ }
+ idx--;
+ }
+ }
+ return false;
+}
+
+static bool ini_addstring(const TCHAR *section, const TCHAR *key, const TCHAR *val)
+{
+ for (int c = 0; c < inilines; c++) {
+ struct ini_line *il = inidata[c];
+ if (il && !_tcscmp(section, il->section)) {
+ if (!_tcscmp(key, il->key)) {
+ xfree(il->value);
+ il->value = my_strdup(val);
+ return true;
+ }
+ }
+ }
+ ini_addnewstring(section, key, val);
+ return true;
+}
+
+static void ini_delete(const TCHAR *section, const TCHAR *key)
+{
+ for (int c = 0; c < inilines; c++) {
+ struct ini_line *il = inidata[c];
+ if (il && !_tcscmp(section, il->section) && (key == NULL || !_tcscmp(key, il->key))) {
+ xfree(il->section);
+ xfree(il->key);
+ xfree(il->value);
+ xfree(il);
+ inidata[c] = NULL;
+ }
+ }
+}
+
static HKEY gr (UAEREG *root)
{
static TCHAR *gs (UAEREG *root)
{
if (!root)
- return _T("WinUAE");
+ return ROOT_TREE;
return root->inipath;
}
static TCHAR *gsn (UAEREG *root, const TCHAR *name)
int regsetstr (UAEREG *root, const TCHAR *name, const TCHAR *str)
{
if (inimode) {
- DWORD ret;
- ret = WritePrivateProfileString (gs (root), name, str, inipath);
+ int ret = ini_addstring(gs(root), name, str);
return ret;
} else {
HKEY rk = gr (root);
int regsetint (UAEREG *root, const TCHAR *name, int val)
{
if (inimode) {
- DWORD ret;
+ int ret;
TCHAR tmp[100];
_stprintf (tmp, _T("%d"), val);
- ret = WritePrivateProfileString (gs (root), name, tmp, inipath);
+ ret = ini_addstring(gs(root), name, tmp);
return ret;
} else {
DWORD v = val;
if (inimode) {
int ret = 0;
TCHAR tmp[100];
- GetPrivateProfileString (gs (root), name, PUPPA, tmp, sizeof (tmp) / sizeof (TCHAR), inipath);
- if (_tcscmp (tmp, PUPPA)) {
+ int size = sizeof tmp / sizeof(TCHAR);
+ if (ini_getstring(gs(root), name, tmp, &size)) {
*val = _tstol (tmp);
ret = 1;
}
int regsetlonglong (UAEREG *root, const TCHAR *name, ULONGLONG val)
{
if (inimode) {
- DWORD ret;
+ int ret;
TCHAR tmp[100];
_stprintf (tmp, _T("%I64d"), val);
- ret = WritePrivateProfileString (gs (root), name, tmp, inipath);
+ ret = ini_addstring(gs(root), name, tmp);
return ret;
} else {
ULONGLONG v = val;
if (inimode) {
int ret = 0;
TCHAR tmp[100];
- GetPrivateProfileString (gs (root), name, PUPPA, tmp, sizeof (tmp) / sizeof (TCHAR), inipath);
- if (_tcscmp (tmp, PUPPA)) {
+ int size = sizeof tmp / sizeof(TCHAR);
+ if (ini_getstring(gs(root), name, tmp, &size)) {
*val = _tstoi64 (tmp);
ret = 1;
}
if (inimode) {
int ret = 0;
TCHAR *tmp = xmalloc (TCHAR, (*size) + 1);
- GetPrivateProfileString (gs (root), name, PUPPA, tmp, *size, inipath);
- if (_tcscmp (tmp, PUPPA)) {
+ if (ini_getstring(gs(root), name, tmp, size)) {
_tcscpy (str, tmp);
ret = 1;
}
name[0] = 0;
str[0] = 0;
if (inimode) {
- int ret = 0;
- int tmpsize = 65536;
- TCHAR *tmp = xmalloc (TCHAR, tmpsize);
- if (GetPrivateProfileSection (gs (root), tmp, tmpsize, inipath) > 0) {
- int i;
- TCHAR *p = tmp, *p2;
- for (i = 0; i < idx; i++) {
- if (p[0] == 0)
- break;
- p += _tcslen (p) + 1;
- }
- if (p[0]) {
- p2 = _tcschr (p, '=');
- if (p2) {
- *p2++ = 0;
- _tcscpy_s (name, *nsize, p);
- _tcscpy_s (str, *size, p2);
- ret = 1;
- }
- }
- }
- xfree (tmp);
+ int ret = ini_getsectionstring(gs(root), idx, name, nsize, str, size);
return ret;
} else {
DWORD nsize2 = *nsize;
{
if (inimode) {
uae_u8 *in = (uae_u8*)str;
- DWORD ret;
- int i;
+ int ret;
TCHAR *tmp = xmalloc (TCHAR, size * 2 + 1);
- for (i = 0; i < size; i++)
+ for (int i = 0; i < size; i++)
_stprintf (tmp + i * 2, _T("%02X"), in[i]);
- ret = WritePrivateProfileString (gs (root), name, tmp, inipath);
+ ret = ini_addstring(gs(root), name, tmp);
xfree (tmp);
return ret;
} else {
int regdelete (UAEREG *root, const TCHAR *name)
{
if (inimode) {
- WritePrivateProfileString (gs (root), name, NULL, inipath);
+ ini_delete(gs(root), name);
return 1;
} else {
HKEY rk = gr (root);
int regexists (UAEREG *root, const TCHAR *name)
{
if (inimode) {
- int ret = 1;
- TCHAR *tmp = xmalloc (TCHAR, _tcslen (PUPPA) + 1);
- int size = _tcslen (PUPPA) + 1;
- GetPrivateProfileString (gs (root), name, PUPPA, tmp, size, inipath);
- if (!_tcscmp (tmp, PUPPA))
- ret = 0;
- xfree (tmp);
+ if (!inilines)
+ return 0;
+ int ret = ini_getstring(gs(root), name, NULL, NULL);
return ret;
} else {
HKEY rk = gr (root);
TCHAR *s = gsn (root, name);
if (!s)
return;
- WritePrivateProfileSection (s, _T(""), inipath);
+ ini_delete(s, NULL);
xfree (s);
} else {
HKEY rk = gr (root);
{
if (inimode) {
int ret = 0;
- int tmpsize = 65536;
- TCHAR *p, *tmp;
TCHAR *s = gsn (root, name);
if (!s)
return 0;
- tmp = xmalloc (TCHAR, tmpsize / sizeof (TCHAR));
- tmp[0] = 0;
- GetPrivateProfileSectionNames (tmp, tmpsize, inipath);
- p = tmp;
- while (p[0]) {
- if (!_tcscmp (p, name)) {
- ret = 1;
- break;
- }
- p += _tcslen (p) + 1;
- }
- xfree (tmp);
+ ret = ini_getstring(s, NULL, NULL, 0);
xfree (s);
return ret;
} else {
{
if (!key)
return;
+ if (inimode)
+ ini_save(inipath);
if (key->fkey)
RegCloseKey (key->fkey);
xfree (key->inipath);
inimode = 1;
inipath = my_strdup (fpath);
+ ini_load(inipath);
if (!regexists (NULL, _T("Version")))
goto fail;
return 1;