1 
2 /*
3  * The Real SoundTracker - Preferences handling
4  *
5  * Copyright (C) 1998-2019 Michael Krause
6  * Copyright (C) 2000 Fabian Giesen
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21  */
22 
23 #include <config.h>
24 
25 #if !defined(_WIN32)
26 
27 #include <sys/stat.h>
28 
29 #include <glib/gi18n.h>
30 
31 #include "gui-subs.h"
32 #include "preferences.h"
33 
34 static GKeyFile* kf = NULL;
35 static gchar* config;
36 
37 gchar*
prefs_get_prefsdir(void)38 prefs_get_prefsdir(void)
39 {
40     static gchar xdir[PATH_MAX]; /* Assume that $HOME is sane */
41     const gchar* homedir = g_getenv("HOME");
42 
43     if (!homedir)
44         homedir = g_get_home_dir();
45     sprintf(xdir, "%s/.soundtracker", homedir);
46     return (xdir);
47 }
48 
49 static void
prefs_check_prefs_dir(void)50 prefs_check_prefs_dir(void)
51 {
52     struct stat st;
53     static GtkWidget* dialog = NULL;
54     gchar* dir = prefs_get_prefsdir();
55 
56     if (stat(dir, &st) < 0) {
57         mkdir(dir, S_IRUSR | S_IWUSR | S_IXUSR);
58         strcat(dir, "/tmp");
59         mkdir(dir, S_IRUSR | S_IWUSR | S_IXUSR);
60         gui_info_dialog(&dialog, _("A directory called \".soundtracker\" has been created in your\nhome directory to store configuration files.\n"), FALSE);
61     }
62 }
63 
64 gchar*
prefs_get_filename(const gchar * name)65 prefs_get_filename(const gchar* name)
66 {
67     gchar* buf;
68 
69     prefs_check_prefs_dir();
70     buf = g_strdup_printf("%s/%s", prefs_get_prefsdir(), name);
71     return buf;
72 }
73 
prefs_init(void)74 void prefs_init(void)
75 {
76     GError* error;
77 
78     config = prefs_get_filename("config");
79     kf = g_key_file_new();
80 
81     /* Don't panic, this loop will be executed no more than 2 times */
82     while (1) {
83         error = NULL;
84         g_key_file_load_from_file(kf, config, G_KEY_FILE_NONE, &error);
85         if (error) {
86             if (error->code == G_FILE_ERROR_NOENT) {
87                 gchar* buf = prefs_get_filename("settings"); /* maybe ST-gtk1 configs exist */
88 
89                 if (g_file_test(buf, G_FILE_TEST_EXISTS)) {
90                     if (gui_ok_cancel_modal(NULL, _("Would you like to import settings from old version of Soundtracker?"))) {
91                         GError* err = NULL;
92 
93                         if (!g_spawn_command_line_sync("soundtracker_convert_config -f", NULL, NULL, NULL, &err)) {
94                             gchar* buff = g_strdup_printf(_("An error is occured during converting config:\n%s"), error->message);
95                             static GtkWidget* dialog = NULL;
96 
97                             gui_error_dialog(&dialog, buff, TRUE);
98                             g_free(buff);
99                             g_error_free(err);
100                         } else {
101                             g_free(buf);
102                             g_error_free(error);
103                             continue; /* Try to load config after the conversion */
104                         }
105                     }
106                 }
107                 g_free(buf);
108             } else {
109                 gchar* buf = g_strdup_printf(_("An error is occured during reading or parsing config:\n%s"), error->message);
110                 static GtkWidget* dialog = NULL;
111 
112                 gui_error_dialog(&dialog, buf, TRUE);
113                 g_free(buf);
114             }
115             g_error_free(error);
116         }
117         /* The second attempt is not required */
118         break;
119     }
120 }
121 
prefs_save(void)122 void prefs_save(void)
123 {
124     gchar* contents;
125     gsize length;
126     GError* error = NULL;
127 
128     g_assert(kf != NULL);
129 
130     contents = g_key_file_to_data(kf, &length, NULL);
131     g_file_set_contents(config, contents, length, &error);
132     if (error) {
133         gchar* buf = g_strdup_printf(_("An error is occured during saving config:\n%s"), error->message);
134         static GtkWidget* dialog = NULL;
135 
136         gui_error_dialog(&dialog, buf, TRUE);
137         g_free(buf);
138         g_error_free(error);
139     }
140 
141     g_free(contents);
142 }
143 
prefs_close(void)144 void prefs_close(void)
145 {
146     g_assert(kf != NULL);
147 
148     g_key_file_free(kf);
149     kf = NULL;
150     g_free(config);
151 }
152 
153 gboolean
prefs_remove_key(const gchar * section,const gchar * key)154 prefs_remove_key(const gchar* section, const gchar* key)
155 {
156     g_assert(kf != NULL);
157 
158     return g_key_file_remove_key(kf, section, key, NULL);
159 }
160 
161 gchar**
prefs_get_str_array(const gchar * section,const gchar * key,gsize * length)162 prefs_get_str_array(const gchar* section,
163     const gchar* key,
164     gsize* length)
165 {
166     gchar** ret;
167     GError* error = NULL;
168 
169     g_assert(kf != NULL);
170 
171     ret = g_key_file_get_string_list(kf, section, key, length, &error);
172     if (error) {
173         ret = NULL;
174         g_error_free(error);
175     }
176 
177     return ret;
178 }
179 
prefs_get_int_array(const gchar * section,const gchar * key,gsize * length)180 gint* prefs_get_int_array(const gchar* section,
181     const gchar* key,
182     gsize* length)
183 {
184     gint* ret;
185     GError* error = NULL;
186 
187     g_assert(kf != NULL);
188 
189     ret = g_key_file_get_integer_list(kf, section, key, length, &error);
190     if (error) {
191         ret = NULL;
192         g_error_free(error);
193     }
194 
195     return ret;
196 }
197 
198 gboolean*
prefs_get_bool_array(const gchar * section,const gchar * key,gsize * length)199 prefs_get_bool_array(const gchar* section,
200     const gchar* key,
201     gsize* length)
202 {
203     gboolean* ret;
204     GError* error = NULL;
205 
206     g_assert(kf != NULL);
207 
208     ret = g_key_file_get_boolean_list(kf, section, key, length, &error);
209     if (error) {
210         g_error_free(error);
211         error = NULL;
212         /* Try to read values as integer list; maybe the config is from elder version */
213         ret = (gboolean*)g_key_file_get_integer_list(kf, section, key, length, &error);
214         if (error) {
215             ret = NULL;
216             g_error_free(error);
217         }
218     }
219 
220     return ret;
221 }
222 
prefs_get_int(const gchar * section,const gchar * key,const gint dflt)223 gint prefs_get_int(const gchar* section,
224     const gchar* key,
225     const gint dflt)
226 {
227     gint retval;
228 
229     GError* error = NULL;
230 
231     g_assert(kf != NULL);
232 
233     retval = g_key_file_get_integer(kf, section, key, &error);
234     if (error) {
235         retval = dflt;
236         g_error_free(error);
237     }
238 
239     return retval;
240 }
241 
prefs_get_double(const gchar * section,const gchar * key,const gdouble dflt)242 gdouble prefs_get_double(const gchar* section,
243     const gchar* key,
244     const gdouble dflt)
245 {
246     gdouble retval;
247 
248     GError* error = NULL;
249 
250     g_assert(kf != NULL);
251 
252     retval = g_key_file_get_double(kf, section, key, &error);
253     if (error) {
254         retval = dflt;
255         g_error_free(error);
256     }
257 
258     return retval;
259 }
260 
261 gboolean
prefs_get_bool(const gchar * section,const gchar * key,const gboolean dflt)262 prefs_get_bool(const gchar* section,
263     const gchar* key,
264     const gboolean dflt)
265 {
266     gboolean retval;
267 
268     GError* error = NULL;
269 
270     g_assert(kf != NULL);
271 
272     retval = g_key_file_get_boolean(kf, section, key, &error);
273     if (error) {
274         g_error_free(error);
275         error = NULL;
276         /* Try to read values as integer; maybe the config is from elder version */
277         retval = g_key_file_get_integer(kf, section, key, &error);
278         if (error) {
279             retval = dflt;
280             g_error_free(error);
281         }
282     }
283 
284     return retval;
285 }
286 
287 GdkColor
prefs_get_color(const gchar * section,const gchar * key,const GdkColor dflt)288 prefs_get_color(const gchar* section,
289     const gchar* key,
290     const GdkColor dflt)
291 {
292     gint* retval;
293     GdkColor ret;
294     gsize size;
295 
296     GError* error = NULL;
297 
298     g_assert(kf != NULL);
299 
300     retval = g_key_file_get_integer_list(kf, section, key, &size, &error);
301     if (error || size < 3) {
302         ret.red = dflt.red;
303         ret.green = dflt.green;
304         ret.blue = dflt.blue;
305         g_error_free(error);
306     } else {
307         ret.red = retval[0];
308         ret.green = retval[1];
309         ret.blue = retval[2];
310         g_free(retval);
311     }
312 
313     ret.pixel = 0;
314     return ret;
315 }
316 
317 gchar*
prefs_get_string(const gchar * section,const gchar * key,const gchar * dflt)318 prefs_get_string(const gchar* section,
319     const gchar* key,
320     const gchar* dflt)
321 {
322     gchar* retval;
323 
324     GError* error = NULL;
325 
326     g_assert(kf != NULL);
327 
328     retval = g_key_file_get_string(kf, section, key, &error);
329     if (error) {
330         if (dflt)
331             retval = g_strdup(dflt);
332         else
333             retval = NULL;
334 
335         g_error_free(error);
336     }
337 
338     return retval;
339 }
340 
prefs_get_pairs(const gchar * section,gchar *** keys,gchar *** values)341 gsize prefs_get_pairs(const gchar* section,
342     gchar*** keys,
343     gchar*** values)
344 {
345     gsize lgth;
346     guint i;
347     GError* error = NULL;
348     gchar **ks, **vs;
349 
350     g_assert(kf != NULL);
351 
352     ks = g_key_file_get_keys(kf, section, &lgth, &error);
353     if (error) {
354         g_error_free(error);
355         return 0;
356     }
357 
358     vs = g_new0(gchar*, lgth + 1); /* +1 for terminating NULL */
359 
360     for (i = 0; i < lgth; i++) {
361         vs[i] = g_key_file_get_string(kf, section, ks[i], &error);
362         if (error) {
363             g_strfreev(ks);
364             g_strfreev(vs);
365             g_error_free(error);
366             return 0;
367         }
368     }
369 
370     *keys = ks;
371     *values = vs;
372     return lgth;
373 }
374 
prefs_put_int(const gchar * section,const gchar * key,const gint value)375 void prefs_put_int(const gchar* section,
376     const gchar* key,
377     const gint value)
378 {
379     g_assert(kf != NULL);
380 
381     g_key_file_set_integer(kf, section, key, value);
382 }
383 
prefs_put_double(const gchar * section,const gchar * key,const gdouble value)384 void prefs_put_double(const gchar* section,
385     const gchar* key,
386     const gdouble value)
387 {
388     g_assert(kf != NULL);
389 
390     g_key_file_set_double(kf, section, key, value);
391 }
392 
prefs_put_bool(const gchar * section,const gchar * key,const gboolean value)393 void prefs_put_bool(const gchar* section,
394     const gchar* key,
395     const gboolean value)
396 {
397     g_assert(kf != NULL);
398 
399     g_key_file_set_boolean(kf, section, key, value);
400 }
401 
prefs_put_color(const gchar * section,const gchar * key,const GdkColor value)402 void prefs_put_color(const gchar* section,
403     const gchar* key,
404     const GdkColor value)
405 {
406     gint val[3];
407 
408     g_assert(kf != NULL);
409 
410     val[0] = value.red;
411     val[1] = value.green;
412     val[2] = value.blue;
413 
414     g_key_file_set_integer_list(kf, section, key, val, 3);
415 }
416 
prefs_put_string(const gchar * section,const gchar * key,const gchar * value)417 void prefs_put_string(const gchar* section,
418     const gchar* key,
419     const gchar* value)
420 {
421     g_assert(kf != NULL);
422 
423     g_key_file_set_string(kf, section, key, value);
424 }
425 /*
426 void
427 prefs_put_str_array (const gchar *section,
428                      const gchar *key,
429                      const gchar * const *value,
430                      gsize length)
431 {
432 	g_assert(kf != NULL);
433 
434 	g_key_file_set_string_list(kf, section, key, value, length);
435 }
436 */
prefs_put_int_array(const gchar * section,const gchar * key,gint * value,gsize length)437 void prefs_put_int_array(const gchar* section,
438     const gchar* key,
439     gint* value,
440     gsize length)
441 {
442     g_assert(kf != NULL);
443 
444     g_key_file_set_integer_list(kf, section, key, value, length);
445 }
446 
prefs_put_bool_array(const gchar * section,const gchar * key,gboolean * value,gsize length)447 void prefs_put_bool_array(const gchar* section,
448     const gchar* key,
449     gboolean* value,
450     gsize length)
451 {
452     g_assert(kf != NULL);
453 
454     g_key_file_set_boolean_list(kf, section, key, value, length);
455 }
456 
457 #else /* defined(_WIN32) */
458 
459 /*
460 
461   Attention!
462 
463   These don't work in their current form; what needs to be done is:
464 
465   a, change void* into prefs_node*
466   b, add prefs_get_file_pointer() - if this is used by the caller
467      after opening, use a real file instead of the registry.
468 
469  */
470 
471 #include <glib/gi18n.h>
472 #include <stdio.h>
473 #include <stdlib.h>
474 #include <string.h>
475 
476 #include <sys/stat.h>
477 #include <sys/types.h>
478 
479 #define WIN32_LEAN_AND_MEAN
480 #include <windows.h>
481 
482 #include "errors.h"
483 #include "gui-subs.h"
484 #include "preferences.h"
485 #include "scope-group.h"
486 #include "track-editor.h"
487 
prefs_open_read(const char * name)488 void* prefs_open_read(const char* name)
489 {
490     char buf[256];
491     HKEY hk;
492 
493     sprintf(buf, "Software/Soundtracker/Soundtracker/%s", name);
494 
495     while (strchr(buf, '/'))
496         *strchr(buf, '/') = '\\';
497 
498     if (!RegOpenKeyEx(HKEY_LOCAL_MACHINE, buf, 0, KEY_ALL_ACCESS, &hk))
499         hk = 0;
500 
501     return (void*)hk;
502 }
503 
prefs_open_write(const char * name)504 void* prefs_open_write(const char* name)
505 {
506     char buf[256];
507     HKEY hk;
508     DWORD bla;
509 
510     sprintf(buf, "Software/Soundtracker/Soundtracker/%s", name);
511 
512     while (strchr(buf, '/'))
513         *strchr(buf, '/') = '\\';
514 
515     if (!RegCreateKeyEx(HKEY_LOCAL_MACHINE, buf, 0, 0, 0, KEY_ALL_ACCESS, 0, &hk, &bla))
516         hk = 0;
517 
518     return (void*)hk;
519 }
520 
prefs_close(void * node)521 void prefs_close(void* node)
522 {
523     HKEY hk;
524 
525     hk = (HKEY)node;
526 
527     RegFlushKey(hk);
528     RegCloseKey(hk);
529 }
530 
531 static int
prefs_query_reg(HKEY hk,const char * key,char ** buf,DWORD * size,DWORD * type)532 prefs_query_reg(HKEY hk,
533     const char* key,
534     char** buf,
535     DWORD* size,
536     DWORD* type)
537 {
538     if (RegQueryValueEx(hk, key, 0, type, 0, size) == ERROR_SUCCESS) {
539         *buf = (char*)malloc(*size + 1);
540 
541         if (RegQueryValueEx(hk, key, 0, type, *buf, size) == ERROR_SUCCESS)
542             return 1;
543         else {
544             free(*buf);
545             return 0;
546         }
547     } else
548         return 0;
549 }
550 
551 static void
prefs_set_reg(HKEY hk,const char * key,char * buf,DWORD size,DWORD type)552 prefs_set_reg(HKEY hk,
553     const char* key,
554     char* buf,
555     DWORD size,
556     DWORD type)
557 {
558     RegSetValueEx(hk, key, 0, type, buf, size);
559 }
560 
561 gboolean
prefs_get_int(void * f,const char * key,int * dest)562 prefs_get_int(void* f,
563     const char* key,
564     int* dest)
565 {
566     char* buf;
567     DWORD sz, type;
568     HKEY hk;
569 
570     hk = (HKEY)f;
571 
572     if (prefs_query_reg(hk, key, &buf, &sz, &type)) {
573         if (type == REG_DWORD) {
574             *dest = *((DWORD*)buf);
575             free(buf);
576             return 1;
577         }
578     }
579 
580     return 0;
581 }
582 
583 gboolean
prefs_get_string(void * f,const char * key,char * dest)584 prefs_get_string(void* f,
585     const char* key,
586     char* dest)
587 {
588     char* buf;
589     DWORD sz, type;
590     HKEY hk;
591 
592     hk = (HKEY)f;
593 
594     if (prefs_query_reg(hk, key, &buf, &sz, &type)) {
595         if (type == REG_SZ) {
596             buf[127] = 0;
597             strcpy(dest, buf);
598             free(buf);
599             return 1;
600         }
601     }
602 
603     return 0;
604 }
605 
prefs_put_int(void * f,const char * key,int value)606 void prefs_put_int(void* f,
607     const char* key,
608     int value)
609 {
610     prefs_set_reg((HKEY)f, key, &value, 4, REG_DWORD);
611 }
612 
prefs_put_string(void * f,const char * key,const char * value)613 void prefs_put_string(void* f,
614     const char* key,
615     const char* value)
616 {
617     prefs_set_reg((HKEY)f, key, value, strlen(value + 1), REG_SZ);
618 }
619 
620 #endif /* defined(_WIN32) */
621