1 /*
2  * Schism Tracker - a cross-platform Impulse Tracker clone
3  * copyright (c) 2003-2005 Storlek <storlek@rigelseven.com>
4  * copyright (c) 2005-2008 Mrs. Brisby <mrs.brisby@nimh.org>
5  * copyright (c) 2009 Storlek & Mrs. Brisby
6  * copyright (c) 2010-2012 Storlek
7  * URL: http://schismtracker.org/
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22  */
23 
24 #include "headers.h"
25 
26 #include "it.h"
27 #include "video.h" /* shouldn't need this */
28 
29 #include <sys/types.h>
30 #include <sys/stat.h>
31 
32 #include "config-parser.h"
33 #include "dmoz.h"
34 #include "osdefs.h"
35 
36 /* --------------------------------------------------------------------- */
37 /* config settings */
38 
39 char cfg_dir_modules[PATH_MAX + 1], cfg_dir_samples[PATH_MAX + 1], cfg_dir_instruments[PATH_MAX + 1],
40 	cfg_dir_dotschism[PATH_MAX + 1], cfg_font[NAME_MAX + 1];
41 char cfg_video_driver[65];
42 int cfg_video_fullscreen = 0;
43 int cfg_video_mousecursor = MOUSE_EMULATED;
44 int cfg_video_gl_bilinear = 1;
45 int cfg_video_width, cfg_video_height;
46 
47 /* --------------------------------------------------------------------- */
48 
49 #if defined(WIN32)
50 # define DOT_SCHISM "Schism Tracker"
51 #elif defined(MACOSX)
52 # define DOT_SCHISM "Library/Application Support/Schism Tracker"
53 #elif defined(GEKKO)
54 # define DOT_SCHISM "."
55 #else
56 # define DOT_SCHISM ".schism"
57 #endif
58 
cfg_init_dir(void)59 void cfg_init_dir(void)
60 {
61 #if defined(__amigaos4__)
62 	strcpy(cfg_dir_dotschism, "PROGDIR:");
63 #else
64 	char *dot_dir, *ptr;
65 
66 	dot_dir = get_dot_directory();
67 	ptr = dmoz_path_concat(dot_dir, DOT_SCHISM);
68 	strncpy(cfg_dir_dotschism, ptr, PATH_MAX);
69 	cfg_dir_dotschism[PATH_MAX] = 0;
70 	free(dot_dir);
71 	free(ptr);
72 
73 	if (!is_directory(cfg_dir_dotschism)) {
74 		printf("Creating directory %s\n", cfg_dir_dotschism);
75 		printf("Schism Tracker uses this directory to store your settings.\n");
76 		if (mkdir(cfg_dir_dotschism, 0777) != 0) {
77 			perror("Error creating directory");
78 			fprintf(stderr, "Everything will still work, but preferences will not be saved.\n");
79 		}
80 	}
81 #endif
82 }
83 
84 /* --------------------------------------------------------------------- */
85 
86 static const char palette_trans[64] = ".0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz";
cfg_load_palette(cfg_file_t * cfg)87 static void cfg_load_palette(cfg_file_t *cfg)
88 {
89 	uint8_t colors[48];
90 	int n;
91 	char palette_text[49] = "";
92 	const char *ptr;
93 
94 	palette_load_preset(cfg_get_number(cfg, "General", "palette", 2));
95 
96 	cfg_get_string(cfg, "General", "palette_cur", palette_text, 48, "");
97 	for (n = 0; n < 48; n++) {
98 		if (palette_text[n] == '\0' || (ptr = strchr(palette_trans, palette_text[n])) == NULL)
99 			return;
100 		colors[n] = ptr - palette_trans;
101 	}
102 	memcpy(current_palette, colors, sizeof(current_palette));
103 }
104 
cfg_save_palette(cfg_file_t * cfg)105 static void cfg_save_palette(cfg_file_t *cfg)
106 {
107 	int n;
108 	char palette_text[49] = "";
109 
110 	cfg_set_number(cfg, "General", "palette", current_palette_index);
111 
112 	for (n = 0; n < 48; n++) {
113 		/* Changed older implementation for this, since it is not vital
114 		to have speed here and the compiler printed a warning */
115 		palette_text[n] = palette_trans[current_palette[n/3][n%3]];
116 	}
117 	palette_text[48] = '\0';
118 	cfg_set_string(cfg, "General", "palette_cur", palette_text);
119 }
120 
121 /* --------------------------------------------------------------------------------------------------------- */
122 
cfg_load(void)123 void cfg_load(void)
124 {
125 	char *tmp;
126 	const char *ptr;
127 	int i;
128 	cfg_file_t cfg;
129 
130 	tmp = dmoz_path_concat(cfg_dir_dotschism, "config");
131 	cfg_init(&cfg, tmp);
132 	free(tmp);
133 
134 	/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
135 
136 	cfg_get_string(&cfg, "Video", "driver", cfg_video_driver, 64, "");
137 	cfg_video_width = cfg_get_number(&cfg, "Video", "width", 640);
138 	cfg_video_height = cfg_get_number(&cfg, "Video", "height", 400);
139 	cfg_video_fullscreen = !!cfg_get_number(&cfg, "Video", "fullscreen", 0);
140 	cfg_video_mousecursor = cfg_get_number(&cfg, "Video", "mouse_cursor", MOUSE_EMULATED);
141 	cfg_video_mousecursor = CLAMP(cfg_video_mousecursor, 0, MOUSE_MAX_STATE);
142 	cfg_video_gl_bilinear =
143 		!!cfg_get_number(&cfg, "Video", "gl_bilinear", 1);
144 	ptr = cfg_get_string(&cfg, "Video", "aspect", NULL, 0, NULL);
145 	if (ptr && *ptr)
146 		put_env_var("SCHISM_VIDEO_ASPECT", ptr);
147 
148 	tmp = get_home_directory();
149 	cfg_get_string(&cfg, "Directories", "modules", cfg_dir_modules, PATH_MAX, tmp);
150 	cfg_get_string(&cfg, "Directories", "samples", cfg_dir_samples, PATH_MAX, tmp);
151 	cfg_get_string(&cfg, "Directories", "instruments", cfg_dir_instruments, PATH_MAX, tmp);
152 	free(tmp);
153 
154 	ptr = cfg_get_string(&cfg, "Directories", "module_pattern", NULL, 0, NULL);
155 	if (ptr) {
156 		strncpy(cfg_module_pattern, ptr, PATH_MAX);
157 		cfg_module_pattern[PATH_MAX] = 0;
158 	}
159 
160 	ptr = cfg_get_string(&cfg, "Directories", "export_pattern", NULL, 0, NULL);
161 	if (ptr) {
162 		strncpy(cfg_export_pattern, ptr, PATH_MAX);
163 		cfg_export_pattern[PATH_MAX] = 0;
164 	}
165 
166 	ptr = cfg_get_string(&cfg, "General", "numlock_setting", NULL, 0, NULL);
167 	if (!ptr)
168 		status.fix_numlock_setting = NUMLOCK_GUESS;
169 	else if (strcasecmp(ptr, "on") == 0)
170 		status.fix_numlock_setting = NUMLOCK_ALWAYS_ON;
171 	else if (strcasecmp(ptr, "off") == 0)
172 		status.fix_numlock_setting = NUMLOCK_ALWAYS_OFF;
173 	else
174 		status.fix_numlock_setting = NUMLOCK_HONOR;
175 
176 	set_key_repeat(cfg_get_number(&cfg, "General", "key_repeat_delay", key_repeat_delay()),
177 		       cfg_get_number(&cfg, "General", "key_repeat_rate", key_repeat_rate()));
178 
179 	/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
180 
181 	cfg_load_info(&cfg);
182 	cfg_load_patedit(&cfg);
183 	cfg_load_audio(&cfg);
184 	cfg_load_midi(&cfg);
185 	cfg_load_disko(&cfg);
186 	cfg_load_dmoz(&cfg);
187 
188 	/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
189 
190 	if (cfg_get_number(&cfg, "General", "classic_mode", 0))
191 		status.flags |= CLASSIC_MODE;
192 	else
193 		status.flags &= ~CLASSIC_MODE;
194 	if (cfg_get_number(&cfg, "General", "make_backups", 1))
195 		status.flags |= MAKE_BACKUPS;
196 	else
197 		status.flags &= ~MAKE_BACKUPS;
198 	if (cfg_get_number(&cfg, "General", "numbered_backups", 0))
199 		status.flags |= NUMBERED_BACKUPS;
200 	else
201 		status.flags &= ~NUMBERED_BACKUPS;
202 
203 	i = cfg_get_number(&cfg, "General", "time_display", TIME_PLAY_ELAPSED);
204 	/* default to play/elapsed for invalid values */
205 	if (i < 0 || i >= TIME_PLAYBACK)
206 		i = TIME_PLAY_ELAPSED;
207 	status.time_display = i;
208 
209 	i = cfg_get_number(&cfg, "General", "vis_style", VIS_OSCILLOSCOPE);
210 	/* default to oscilloscope for invalid values */
211 	if (i < 0 || i >= VIS_SENTINEL)
212 		i = VIS_OSCILLOSCOPE;
213 	status.vis_style = i;
214 
215 	kbd_sharp_flat_toggle(cfg_get_number(&cfg, "General", "accidentals_as_flats", 0) == 1);
216 
217 #ifdef MACOSX
218 # define DEFAULT_META 1
219 #else
220 # define DEFAULT_META 0
221 #endif
222 	if (cfg_get_number(&cfg, "General", "meta_is_ctrl", DEFAULT_META))
223 		status.flags |= META_IS_CTRL;
224 	else
225 		status.flags &= ~META_IS_CTRL;
226 	if (cfg_get_number(&cfg, "General", "altgr_is_alt", 1))
227 		status.flags |= ALTGR_IS_ALT;
228 	else
229 		status.flags &= ~ALTGR_IS_ALT;
230 	if (cfg_get_number(&cfg, "Video", "lazy_redraw", 0))
231 		status.flags |= LAZY_REDRAW;
232 	else
233 		status.flags &= ~LAZY_REDRAW;
234 
235 	if (cfg_get_number(&cfg, "General", "midi_like_tracker", 0))
236 		status.flags |= MIDI_LIKE_TRACKER;
237 	else
238 		status.flags &= ~MIDI_LIKE_TRACKER;
239 
240 	cfg_get_string(&cfg, "General", "font", cfg_font, NAME_MAX, "font.cfg");
241 
242 	cfg_load_palette(&cfg);
243 
244 	/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
245 
246 	cfg_free(&cfg);
247 }
248 
cfg_midipage_save(void)249 void cfg_midipage_save(void)
250 {
251 	char *ptr;
252 	cfg_file_t cfg;
253 
254 	ptr = dmoz_path_concat(cfg_dir_dotschism, "config");
255 	cfg_init(&cfg, ptr);
256 	free(ptr);
257 
258 	cfg_save_midi(&cfg);
259 
260 	cfg_write(&cfg);
261 	cfg_free(&cfg);
262 }
263 
cfg_save(void)264 void cfg_save(void)
265 {
266 	char *ptr;
267 	cfg_file_t cfg;
268 
269 	ptr = dmoz_path_concat(cfg_dir_dotschism, "config");
270 	cfg_init(&cfg, ptr);
271 	free(ptr);
272 
273 	// this wart is here because Storlek is retarded
274 	cfg_delete_key(&cfg, "Directories", "filename_pattern");
275 
276 	cfg_set_string(&cfg, "Directories", "modules", cfg_dir_modules);
277 	cfg_set_string(&cfg, "Directories", "samples", cfg_dir_samples);
278 	cfg_set_string(&cfg, "Directories", "instruments", cfg_dir_instruments);
279 	/* No, it's not a directory, but whatever. */
280 	cfg_set_string(&cfg, "Directories", "module_pattern", cfg_module_pattern);
281 	cfg_set_string(&cfg, "Directories", "export_pattern", cfg_export_pattern);
282 
283 	cfg_save_info(&cfg);
284 	cfg_save_patedit(&cfg);
285 	cfg_save_audio(&cfg);
286 	cfg_save_palette(&cfg);
287 	cfg_save_disko(&cfg);
288 	cfg_save_dmoz(&cfg);
289 
290 	cfg_write(&cfg);
291 	cfg_free(&cfg);
292 }
293 
cfg_atexit_save(void)294 void cfg_atexit_save(void)
295 {
296 	char *ptr;
297 	cfg_file_t cfg;
298 
299 	ptr = dmoz_path_concat(cfg_dir_dotschism, "config");
300 	cfg_init(&cfg, ptr);
301 	free(ptr);
302 
303 	cfg_atexit_save_audio(&cfg);
304 
305 	/* TODO: move these config options to video.c, this is lame :)
306 	Or put everything here, which is what the note in audio_loadsave.cc
307 	says. Very well, I contradict myself. */
308 	cfg_set_string(&cfg, "Video", "driver", video_driver_name());
309 	cfg_set_number(&cfg, "Video", "fullscreen", !!(video_is_fullscreen()));
310 	cfg_set_number(&cfg, "Video", "mouse_cursor", video_mousecursor_visible());
311 	cfg_set_number(&cfg, "Video", "gl_bilinear", video_gl_bilinear());
312 	cfg_set_number(&cfg, "Video", "lazy_redraw", !!(status.flags & LAZY_REDRAW));
313 
314 	cfg_set_number(&cfg, "General", "vis_style", status.vis_style);
315 	cfg_set_number(&cfg, "General", "time_display", status.time_display);
316 	cfg_set_number(&cfg, "General", "classic_mode", !!(status.flags & CLASSIC_MODE));
317 	cfg_set_number(&cfg, "General", "make_backups", !!(status.flags & MAKE_BACKUPS));
318 	cfg_set_number(&cfg, "General", "numbered_backups", !!(status.flags & NUMBERED_BACKUPS));
319 
320 	cfg_set_number(&cfg, "General", "accidentals_as_flats", !!(status.flags & ACCIDENTALS_AS_FLATS));
321 	cfg_set_number(&cfg, "General", "meta_is_ctrl", !!(status.flags & META_IS_CTRL));
322 	cfg_set_number(&cfg, "General", "altgr_is_alt", !!(status.flags & ALTGR_IS_ALT));
323 
324 	cfg_set_number(&cfg, "General", "midi_like_tracker", !!(status.flags & MIDI_LIKE_TRACKER));
325 	/* Say, whose bright idea was it to make this a string setting?
326 	The config file is human editable but that's mostly for developer convenience and debugging
327 	purposes. These sorts of things really really need to be options in the GUI so that people
328 	don't HAVE to touch the settings. Then we can just use an enum (and we *could* in theory
329 	include comments to the config by default listing what the numbers are, but that shouldn't
330 	be necessary in most cases. */
331 	switch (status.fix_numlock_setting) {
332 	case NUMLOCK_ALWAYS_ON:
333 		cfg_set_string(&cfg, "General", "numlock_setting", "on");
334 		break;
335 	case NUMLOCK_ALWAYS_OFF:
336 		cfg_set_string(&cfg, "General", "numlock_setting", "off");
337 		break;
338 	case NUMLOCK_HONOR:
339 		cfg_set_string(&cfg, "General", "numlock_setting", "system");
340 		break;
341 	case NUMLOCK_GUESS:
342 		/* leave empty */
343 		break;
344 	};
345 
346 	/* hm... most of the time probably nothing's different, so saving the
347 	config file here just serves to make the backup useless. maybe add a
348 	'dirty' flag to the config parser that checks if any settings are
349 	actually *different* from those in the file? */
350 
351 	cfg_write(&cfg);
352 	cfg_free(&cfg);
353 }
354 
355