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