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 /* This is getting almost as disturbing as the pattern editor. */
25 
26 #include "headers.h"
27 #include "it.h"
28 #include "page.h"
29 #include "song.h"
30 #include "dmoz.h"
31 #include "video.h"
32 
33 #include <sys/stat.h>
34 
35 /* --------------------------------------------------------------------- */
36 /* just one global variable... */
37 
38 int instrument_list_subpage = PAGE_INSTRUMENT_LIST_GENERAL;
39 
40 /* --------------------------------------------------------------------- */
41 /* ... but tons o' ugly statics */
42 
43 static struct widget widgets_general[18];
44 static struct widget widgets_volume[17];
45 static struct widget widgets_panning[19];
46 static struct widget widgets_pitch[20];
47 
48 /* rastops for envelope */
49 static struct vgamem_overlay env_overlay = {
50 	32, 18, 65, 25,
51 	NULL, 0, 0, 0
52 };
53 
54 /* toggled when pressing "," on the note table's sample field
55  * more of a boolean than a bit mask  -delt.
56  */
57 static int note_sample_mask = 1;
58 
get_page_widgets(void)59 static struct widget *get_page_widgets(void)
60 {
61 	switch (instrument_list_subpage) {
62 	case PAGE_INSTRUMENT_LIST_GENERAL:
63 		return widgets_general;
64 	case PAGE_INSTRUMENT_LIST_VOLUME:
65 		return widgets_volume;
66 	case PAGE_INSTRUMENT_LIST_PANNING:
67 		return widgets_panning;
68 	case PAGE_INSTRUMENT_LIST_PITCH:
69 		return widgets_pitch;
70 	};
71 	return widgets_general;
72 }
73 
74 static const int subpage_switches_group[5] = { 1, 2, 3, 4, -1 };
75 static const int nna_group[5] = { 6, 7, 8, 9, -1 };
76 static const int dct_group[5] = { 10, 11, 12, 13, -1 };
77 static const int dca_group[4] = { 14, 15, 16, -1 };
78 
79 static const char *const pitch_envelope_states[] = { "Off", "On Pitch", "On Filter", NULL };
80 
81 static int top_instrument = 1;
82 static int current_instrument = 1;
83 static int _altswap_lastvis = 99; // for alt-down instrument-swapping
84 static int instrument_cursor_pos = 25;  /* "play" mode */
85 
86 static int note_trans_top_line = 0;
87 static int note_trans_sel_line = 0;
88 
89 static int note_trans_cursor_pos = 0;
90 
91 /* shared by all the numentries on a page
92  * (0 = volume, 1 = panning, 2 = pitch) */
93 static int numentry_cursor_pos[3] = { 0 };
94 
95 static int current_node_vol = 0;
96 static int current_node_pan = 0;
97 static int current_node_pitch = 0;
98 
99 static int envelope_edit_mode = 0;
100 static int envelope_mouse_edit = 0;
101 static int envelope_tick_limit = 0;
102 
103 static void set_subpage(int page);
104 
105 /* playback */
106 static int last_note = 61;              /* C-5 */
107 
108 /* strange saved envelopes */
109 static song_envelope_t saved_env[10];
110 static unsigned int flags[10] = {0};
111 
112 /* --------------------------------------------------------------------------------------------------------- */
113 
save_envelope(int slot,song_envelope_t * e,unsigned int sec)114 static void save_envelope(int slot, song_envelope_t *e, unsigned int sec)
115 {
116 	song_instrument_t *ins;
117 
118 	slot = ((unsigned)slot)%10;
119 
120 	ins = song_get_instrument(current_instrument);
121 	memcpy(&saved_env[slot], e, sizeof(song_envelope_t));
122 
123 	switch (sec) {
124 	case ENV_VOLUME:
125 		flags[slot] = ins->flags & (ENV_VOLUME|ENV_VOLSUSTAIN|ENV_VOLLOOP|ENV_VOLCARRY);
126 		break;
127 	case ENV_PANNING:
128 		flags[slot] =
129 			((ins->flags & ENV_PANNING) ? ENV_VOLUME : 0)
130 		|       ((ins->flags & ENV_PANSUSTAIN) ? ENV_VOLSUSTAIN : 0)
131 		|       ((ins->flags & ENV_PANLOOP) ? ENV_VOLLOOP : 0)
132 		|       ((ins->flags & ENV_PANCARRY) ? ENV_VOLCARRY : 0)
133 		|       (ins->flags & ENV_SETPANNING);
134 		break;
135 	case ENV_PITCH:
136 		flags[slot] =
137 			((ins->flags & ENV_PITCH) ? ENV_VOLUME : 0)
138 		|       ((ins->flags & ENV_PITCHSUSTAIN) ? ENV_VOLSUSTAIN : 0)
139 		|       ((ins->flags & ENV_PITCHLOOP) ? ENV_VOLLOOP : 0)
140 		|       ((ins->flags & ENV_PITCHCARRY) ? ENV_VOLCARRY : 0)
141 		|       (ins->flags & ENV_FILTER);
142 		break;
143 	};
144 }
restore_envelope(int slot,song_envelope_t * e,unsigned int sec)145 static void restore_envelope(int slot, song_envelope_t *e, unsigned int sec)
146 {
147 	song_instrument_t *ins;
148 
149 	song_lock_audio();
150 
151 	slot = ((unsigned)slot)%10;
152 
153 	ins = song_get_instrument(current_instrument);
154 	memcpy(e, &saved_env[slot], sizeof(song_envelope_t));
155 
156 	switch (sec) {
157 	case ENV_VOLUME:
158 		ins->flags &= ~(ENV_VOLUME|ENV_VOLSUSTAIN|ENV_VOLLOOP|ENV_VOLCARRY);
159 		ins->flags |= (flags[slot] & (ENV_VOLUME|ENV_VOLSUSTAIN|ENV_VOLLOOP|ENV_VOLCARRY));
160 		break;
161 
162 	case ENV_PANNING:
163 		ins->flags &= ~(ENV_PANNING|ENV_PANSUSTAIN|ENV_PANLOOP|ENV_PANCARRY|ENV_SETPANNING);
164 		if (flags[slot] & ENV_VOLUME) ins->flags |= ENV_PANNING;
165 		if (flags[slot] & ENV_VOLSUSTAIN) ins->flags |= ENV_PANSUSTAIN;
166 		if (flags[slot] & ENV_VOLLOOP) ins->flags |= ENV_PANLOOP;
167 		if (flags[slot] & ENV_VOLCARRY) ins->flags |= ENV_PANCARRY;
168 		ins->flags |= (flags[slot] & ENV_SETPANNING);
169 		break;
170 
171 	case ENV_PITCH:
172 		ins->flags &= ~(ENV_PITCH|ENV_PITCHSUSTAIN|ENV_PITCHLOOP|ENV_PITCHCARRY|ENV_FILTER);
173 		if (flags[slot] & ENV_VOLUME) ins->flags |= ENV_PITCH;
174 		if (flags[slot] & ENV_VOLSUSTAIN) ins->flags |= ENV_PITCHSUSTAIN;
175 		if (flags[slot] & ENV_VOLLOOP) ins->flags |= ENV_PITCHLOOP;
176 		if (flags[slot] & ENV_VOLCARRY) ins->flags |= ENV_PITCHCARRY;
177 		ins->flags |= (flags[slot] & ENV_FILTER);
178 		break;
179 
180 	};
181 
182 	song_unlock_audio();
183 
184 	status.flags |= SONG_NEEDS_SAVE;
185 }
186 
187 
188 
189 /* --------------------------------------------------------------------------------------------------------- */
190 
191 static void instrument_list_draw_list(void);
192 
193 /* --------------------------------------------------------------------------------------------------------- */
_last_vis_inst(void)194 static int _last_vis_inst(void)
195 {
196 	int i, j, n;
197 
198 	n = 99;
199 	j = 0;
200 	/* 65 is first visible sample on last page */
201 	for (i = 65; i < MAX_INSTRUMENTS; i++) {
202 		if (!csf_instrument_is_empty(current_song->instruments[i])) {
203 			j = i;
204 		}
205 	}
206 	while ((j + 34) > n)
207 		n += 34;
208 	return MIN(n, MAX_INSTRUMENTS - 1);
209 }
210 /* the actual list */
211 
instrument_list_reposition(void)212 static void instrument_list_reposition(void)
213 {
214 	if (current_instrument < top_instrument) {
215 		top_instrument = current_instrument;
216 		if (top_instrument < 1) {
217 			top_instrument = 1;
218 		}
219 	} else if (current_instrument > top_instrument + 34) {
220 		top_instrument = current_instrument - 34;
221 	}
222 }
223 
instrument_get_current(void)224 int instrument_get_current(void)
225 {
226 	return current_instrument;
227 }
228 
instrument_set(int n)229 void instrument_set(int n)
230 {
231 	int new_ins = n;
232 	song_instrument_t *ins;
233 
234 	if (page_is_instrument_list(status.current_page)) {
235 		new_ins = CLAMP(n, 1, _last_vis_inst());
236 	} else {
237 		new_ins = CLAMP(n, 0, _last_vis_inst());
238 	}
239 
240 	if (current_instrument == new_ins)
241 		return;
242 
243 	envelope_edit_mode = 0;
244 	current_instrument = new_ins;
245 	instrument_list_reposition();
246 
247 	ins = song_get_instrument(current_instrument);
248 
249 	current_node_vol = ins->vol_env.nodes ? CLAMP(current_node_vol, 0, ins->vol_env.nodes - 1) : 0;
250 	current_node_pan = ins->pan_env.nodes ? CLAMP(current_node_vol, 0, ins->pan_env.nodes - 1) : 0;
251 	current_node_pitch = ins->pitch_env.nodes ? CLAMP(current_node_vol, 0, ins->pan_env.nodes - 1) : 0;
252 
253 	status.flags |= NEED_UPDATE;
254 }
255 
instrument_synchronize_to_sample(void)256 void instrument_synchronize_to_sample(void)
257 {
258 	song_instrument_t *ins;
259 	int sample = sample_get_current();
260 	int n, pos;
261 
262 	/* 1. if the instrument with the same number as the current sample
263 	 * has the sample in its sample_map, change to that instrument. */
264 	ins = song_get_instrument(sample);
265 	for (pos = 0; pos < 120; pos++) {
266 		if ((int)(ins->sample_map[pos]) == sample) {
267 			instrument_set(sample);
268 			return;
269 		}
270 	}
271 
272 	/* 2. look through the instrument list for the first instrument
273 	 * that uses the selected sample. */
274 	for (n = 1; n < 100; n++) {
275 		if (n == sample)
276 			continue;
277 		ins = song_get_instrument(n);
278 		for (pos = 0; pos < 120; pos++) {
279 			if ((int)(ins->sample_map[pos]) == sample) {
280 				instrument_set(n);
281 				return;
282 			}
283 		}
284 	}
285 
286 	/* 3. if no instruments are using the sample, just change to the
287 	 * same-numbered instrument. */
288 	instrument_set(sample);
289 }
290 
291 /* --------------------------------------------------------------------- */
292 
instrument_list_add_char(int c)293 static int instrument_list_add_char(int c)
294 {
295 	song_instrument_t *ins;
296 
297 	if (c < 32)
298 		return 0;
299 	ins = song_get_instrument(current_instrument);
300 	text_add_char(ins->name, c, &instrument_cursor_pos, 25);
301 	if (instrument_cursor_pos == 25)
302 		instrument_cursor_pos--;
303 
304 	get_page_widgets()->accept_text = (instrument_cursor_pos == 25 ? 0 : 1);
305 	status.flags |= NEED_UPDATE;
306 	status.flags |= SONG_NEEDS_SAVE;
307 	return 1;
308 }
309 
instrument_list_delete_char(void)310 static void instrument_list_delete_char(void)
311 {
312 	song_instrument_t *ins = song_get_instrument(current_instrument);
313 	text_delete_char(ins->name, &instrument_cursor_pos, 25);
314 
315 	get_page_widgets()->accept_text = (instrument_cursor_pos == 25 ? 0 : 1);
316 	status.flags |= NEED_UPDATE;
317 	status.flags |= SONG_NEEDS_SAVE;
318 }
319 
instrument_list_delete_next_char(void)320 static void instrument_list_delete_next_char(void)
321 {
322 	song_instrument_t *ins = song_get_instrument(current_instrument);
323 	text_delete_next_char(ins->name, &instrument_cursor_pos, 25);
324 
325 	get_page_widgets()->accept_text = (instrument_cursor_pos == 25 ? 0 : 1);
326 	status.flags |= NEED_UPDATE;
327 	status.flags |= SONG_NEEDS_SAVE;
328 }
329 
clear_instrument_text(void)330 static void clear_instrument_text(void)
331 {
332 	song_instrument_t *ins = song_get_instrument(current_instrument);
333 
334 	memset(ins->filename, 0, 14);
335 	memset(ins->name, 0, 26);
336 	if (instrument_cursor_pos != 25)
337 		instrument_cursor_pos = 0;
338 
339 	get_page_widgets()->accept_text = (instrument_cursor_pos == 25 ? 0 : 1);
340 	status.flags |= NEED_UPDATE;
341 	status.flags |= SONG_NEEDS_SAVE;
342 }
343 
344 /* --------------------------------------------------------------------- */
345 
do_swap_instrument(int n)346 static void do_swap_instrument(int n)
347 {
348 	if (n >= 1 && n <= _last_vis_inst()) {
349 		song_swap_instruments(current_instrument, n);
350 	}
351 }
352 
do_exchange_instrument(int n)353 static void do_exchange_instrument(int n)
354 {
355 	if (n >= 1 && n <= _last_vis_inst()) {
356 		song_exchange_instruments(current_instrument, n);
357 	}
358 }
359 
do_copy_instrument(int n)360 static void do_copy_instrument(int n)
361 {
362 	if (n >= 1 && n <= _last_vis_inst()) {
363 		song_copy_instrument(current_instrument, n);
364 	}
365 }
366 
do_replace_instrument(int n)367 static void do_replace_instrument(int n)
368 {
369 	if (n >= 1 && n <= _last_vis_inst()) {
370 		song_replace_instrument(current_instrument, n);
371 	}
372 }
373 
374 /* --------------------------------------------------------------------- */
375 
instrument_list_draw_list(void)376 static void instrument_list_draw_list(void)
377 {
378 	int pos, n;
379 	song_instrument_t *ins;
380 	int selected = (ACTIVE_PAGE.selected_widget == 0);
381 	int is_current;
382 	int ss, cl = 0, cr = 0;
383 	int is_playing[MAX_INSTRUMENTS];
384 	char buf[4];
385 
386 	ss = -1;
387 
388 	song_get_playing_instruments(is_playing);
389 
390 	for (pos = 0, n = top_instrument; pos < 35; pos++, n++) {
391 		ins = song_get_instrument(n);
392 		is_current = (n == current_instrument);
393 
394 		if (ins->played)
395 			draw_char(is_playing[n] > 1 ? 183 : 173, 1, 13 + pos, is_playing[n] ? 3 : 1, 2);
396 
397 		draw_text(num99tostr(n, buf), 2, 13 + pos, 0, 2);
398 		if (instrument_cursor_pos < 25) {
399 			/* it's in edit mode */
400 			if (is_current) {
401 				draw_text_len(ins->name, 25, 5, 13 + pos, 6, 14);
402 				if (selected) {
403 					draw_char(ins->name[instrument_cursor_pos],
404 						  5 + instrument_cursor_pos,
405 						  13 + pos, 0, 3);
406 				}
407 			} else {
408 				draw_text_len(ins->name, 25, 5, 13 + pos, 6, 0);
409 			}
410 		} else {
411 			draw_text_len(ins->name, 25, 5, 13 + pos,
412 				      ((is_current && selected) ? 0 : 6),
413 				      (is_current ? (selected ? 3 : 14) : 0));
414 		}
415 		if (ss == n) {
416 			draw_text_len(ins->name + cl, (cr-cl)+1,
417 					5 + cl, 13 + pos,
418 					(is_current ? 3 : 11), 8);
419 		}
420 	}
421 }
422 
instrument_list_handle_key_on_list(struct key_event * k)423 static int instrument_list_handle_key_on_list(struct key_event * k)
424 {
425 	int new_ins = current_instrument;
426 
427 	if (k->state == KEY_PRESS && k->mouse != MOUSE_NONE && k->y >= 13 && k->y <= 47 && k->x >= 5 && k->x <= 30) {
428 		if (k->mouse == MOUSE_CLICK) {
429 			new_ins = (k->y - 13) + top_instrument;
430 			if (instrument_cursor_pos < 25)
431 				instrument_cursor_pos = MIN(k->x - 5, 24);
432 			status.flags |= NEED_UPDATE;
433 		} else if (k->mouse == MOUSE_DBLCLICK) {
434 			/* this doesn't seem to work, but I think it'd be
435 			more useful if double click switched to edit mode */
436 			if (instrument_cursor_pos < 25) {
437 				instrument_cursor_pos = 25;
438 				get_page_widgets()->accept_text = 0;
439 			} else {
440 				set_page(PAGE_LOAD_INSTRUMENT);
441 			}
442 			status.flags |= NEED_UPDATE;
443 			return 1;
444 
445 		} else if (k->mouse == MOUSE_SCROLL_UP) {
446 			top_instrument -= MOUSE_SCROLL_LINES;
447 			if (top_instrument < 1) top_instrument = 1;
448 			status.flags |= NEED_UPDATE;
449 			return 1;
450 		} else if (k->mouse == MOUSE_SCROLL_DOWN) {
451 			top_instrument += MOUSE_SCROLL_LINES;
452 			if (top_instrument > (_last_vis_inst()-34)) top_instrument = _last_vis_inst()-34;
453 			status.flags |= NEED_UPDATE;
454 			return 1;
455 		}
456 	} else {
457 		switch (k->sym) {
458 		case SDLK_UP:
459 			if (k->state == KEY_RELEASE)
460 				return 0;
461 			if (k->mod & KMOD_ALT) {
462 				if (current_instrument > 1) {
463 					new_ins = current_instrument - 1;
464 					song_swap_instruments(current_instrument, new_ins);
465 				}
466 			} else if (!NO_MODIFIER(k->mod)) {
467 				return 0;
468 			} else {
469 				new_ins--;
470 			}
471 			break;
472 		case SDLK_DOWN:
473 			if (k->state == KEY_RELEASE)
474 				return 0;
475 			if (k->mod & KMOD_ALT) {
476 				// restrict position to the "old" value of _last_vis_inst()
477 				// (this is entirely for aesthetic reasons)
478 				if (status.last_keysym != SDLK_DOWN && !k->is_repeat)
479 					_altswap_lastvis = _last_vis_inst();
480 				if (current_instrument < _altswap_lastvis) {
481 					new_ins = current_instrument + 1;
482 					song_swap_instruments(current_instrument, new_ins);
483 				}
484 			} else if (!NO_MODIFIER(k->mod)) {
485 				return 0;
486 			} else {
487 				new_ins++;
488 			}
489 			break;
490 		case SDLK_PAGEUP:
491 			if (k->state == KEY_RELEASE)
492 				return 0;
493 			if (k->mod & KMOD_CTRL)
494 				new_ins = 1;
495 			else
496 				new_ins -= 16;
497 			break;
498 		case SDLK_PAGEDOWN:
499 			if (k->state == KEY_RELEASE)
500 				return 0;
501 			if (k->mod & KMOD_CTRL)
502 				new_ins = _last_vis_inst();
503 			else
504 				new_ins += 16;
505 			break;
506 		case SDLK_HOME:
507 			if (k->state == KEY_RELEASE)
508 				return 0;
509 			if (!NO_MODIFIER(k->mod))
510 				return 0;
511 			if (instrument_cursor_pos < 25) {
512 				instrument_cursor_pos = 0;
513 				get_page_widgets()->accept_text = 1;
514 				status.flags |= NEED_UPDATE;
515 			}
516 			return 1;
517 		case SDLK_END:
518 			if (k->state == KEY_RELEASE)
519 				return 0;
520 			if (!NO_MODIFIER(k->mod))
521 				return 0;
522 			if (instrument_cursor_pos < 24) {
523 				instrument_cursor_pos = 24;
524 				get_page_widgets()->accept_text = 1;
525 				status.flags |= NEED_UPDATE;
526 			}
527 			return 1;
528 		case SDLK_LEFT:
529 			if (k->state == KEY_RELEASE)
530 				return 0;
531 			if (!NO_MODIFIER(k->mod))
532 				return 0;
533 			if (instrument_cursor_pos < 25 && instrument_cursor_pos > 0) {
534 				instrument_cursor_pos--;
535 				get_page_widgets()->accept_text = 1;
536 				status.flags |= NEED_UPDATE;
537 			}
538 			return 1;
539 		case SDLK_RIGHT:
540 			if (k->state == KEY_RELEASE)
541 				return 0;
542 			if (!NO_MODIFIER(k->mod))
543 				return 0;
544 			if (instrument_cursor_pos == 25) {
545 				get_page_widgets()->accept_text = 0;
546 				change_focus_to(1);
547 			} else if (instrument_cursor_pos < 24) {
548 				get_page_widgets()->accept_text = 1;
549 				instrument_cursor_pos++;
550 				status.flags |= NEED_UPDATE;
551 			}
552 			return 1;
553 		case SDLK_RETURN:
554 			if (k->state == KEY_PRESS)
555 				return 0;
556 			if (instrument_cursor_pos < 25) {
557 				instrument_cursor_pos = 25;
558 				get_page_widgets()->accept_text = 0;
559 				status.flags |= NEED_UPDATE;
560 			} else {
561 				get_page_widgets()->accept_text = 1;
562 				set_page(PAGE_LOAD_INSTRUMENT);
563 			}
564 			return 1;
565 		case SDLK_ESCAPE:
566 			if ((k->mod & KMOD_SHIFT) || instrument_cursor_pos < 25) {
567 				if (k->state == KEY_RELEASE)
568 					return 1;
569 				instrument_cursor_pos = 25;
570 				get_page_widgets()->accept_text = 0;
571 				status.flags |= NEED_UPDATE;
572 				return 1;
573 			}
574 			return 0;
575 		case SDLK_BACKSPACE:
576 			if (k->state == KEY_RELEASE)
577 				return 0;
578 			if (instrument_cursor_pos == 25)
579 				return 0;
580 			if ((k->mod & (KMOD_CTRL | KMOD_ALT)) == 0)
581 				instrument_list_delete_char();
582 			else if (k->mod & KMOD_CTRL)
583 				instrument_list_add_char(127);
584 			return 1;
585 		case SDLK_INSERT:
586 			if (k->state == KEY_RELEASE)
587 				return 0;
588 			if (k->mod & KMOD_ALT) {
589 				song_insert_instrument_slot(current_instrument);
590 				status.flags |= NEED_UPDATE;
591 				return 1;
592 			}
593 			return 0;
594 		case SDLK_DELETE:
595 			if (k->state == KEY_RELEASE)
596 				return 0;
597 			if (k->mod & KMOD_ALT) {
598 				song_remove_instrument_slot(current_instrument);
599 				status.flags |= NEED_UPDATE;
600 				return 1;
601 			} else if ((k->mod & KMOD_CTRL) == 0) {
602 				if (instrument_cursor_pos == 25)
603 					return 0;
604 				instrument_list_delete_next_char();
605 				return 1;
606 			}
607 			return 0;
608 		default:
609 			if (k->state == KEY_RELEASE)
610 				return 0;
611 			if (k->mod & KMOD_ALT) {
612 				if (k->sym == SDLK_c) {
613 					clear_instrument_text();
614 					return 1;
615 				}
616 			} else if ((k->mod & KMOD_CTRL) == 0) {
617 				if (!k->unicode) return 0;
618 				if (instrument_cursor_pos < 25) {
619 					return instrument_list_add_char(k->unicode);
620 				} else if (k->sym == SDLK_SPACE) {
621 					instrument_cursor_pos = 0;
622 					get_page_widgets()->accept_text = 0;
623 					status.flags |= NEED_UPDATE;
624 					memused_songchanged();
625 					return 1;
626 				}
627 			}
628 			return 0;
629 		};
630 	}
631 
632 	new_ins = CLAMP(new_ins, 1, _last_vis_inst());
633 	if (new_ins != current_instrument) {
634 		instrument_set(new_ins);
635 		status.flags |= NEED_UPDATE;
636 		memused_songchanged();
637 	}
638 
639 	return 1;
640 }
641 
642 /* --------------------------------------------------------------------- */
643 /* note translation table */
644 
note_trans_reposition(void)645 static void note_trans_reposition(void)
646 {
647 	if (note_trans_sel_line < note_trans_top_line) {
648 		note_trans_top_line = note_trans_sel_line;
649 	} else if (note_trans_sel_line > note_trans_top_line + 31) {
650 		note_trans_top_line = note_trans_sel_line - 31;
651 	}
652 }
653 
note_trans_draw(void)654 static void note_trans_draw(void)
655 {
656 	int pos, n;
657 	int is_selected = (ACTIVE_PAGE.selected_widget == 5);
658 	int bg, sel_bg = (is_selected ? 14 : 0);
659 	song_instrument_t *ins = song_get_instrument(current_instrument);
660 	char buf[4];
661 
662 	for (pos = 0, n = note_trans_top_line; pos < 32; pos++, n++) {
663 		bg = ((n == note_trans_sel_line) ? sel_bg : 0);
664 
665 		/* invalid notes are translated to themselves (and yes, this edits the actual instrument) */
666 		if (ins->note_map[n] < 1 || ins->note_map[n] > 120)
667 			ins->note_map[n] = n + 1;
668 
669 		draw_text(get_note_string(n + 1, buf), 32, 16 + pos, 2, bg);
670 		draw_char(168, 35, 16 + pos, 2, bg);
671 		draw_text(get_note_string(ins->note_map[n], buf), 36, 16 + pos, 2, bg);
672 		if (is_selected && n == note_trans_sel_line) {
673 			if (note_trans_cursor_pos == 0)
674 				draw_char(buf[0], 36, 16 + pos, 0, 3);
675 			else if (note_trans_cursor_pos == 1)
676 				draw_char(buf[2], 38, 16 + pos, 0, 3);
677 		}
678 		draw_char(0, 39, 16 + pos, 2, bg);
679 		if (ins->sample_map[n]) {
680 			num99tostr(ins->sample_map[n], buf);
681 		} else {
682 			buf[0] = buf[1] = 173;
683 			buf[2] = 0;
684 		}
685 		draw_text(buf, 40, 16 + pos, 2, bg);
686 		if (is_selected && n == note_trans_sel_line) {
687 			if (note_trans_cursor_pos == 2)
688 				draw_char(buf[0], 40, 16 + pos, 0, 3);
689 			else if (note_trans_cursor_pos == 3)
690 				draw_char(buf[1], 41, 16 + pos, 0, 3);
691 		}
692 	}
693 
694 	/* draw the little mask thingy at the bottom. Could optimize this....  -delt.
695 	   Sure can! This could share the same track-view functions that the
696 	   pattern editor ought to be using. -Storlek */
697 	if (is_selected && !(status.flags & CLASSIC_MODE)) {
698 		switch (note_trans_cursor_pos) {
699 		case 0:
700 			draw_char(171, 36, 48, 3, 2);
701 			draw_char(171, 37, 48, 3, 2);
702 			draw_char(169, 38, 48, 3, 2);
703 			if (note_sample_mask) {
704 				draw_char(169, 40, 48, 3, 2);
705 				draw_char(169, 41, 48, 3, 2);
706 			}
707 			break;
708 		case 1:
709 			draw_char(169, 38, 48, 3, 2);
710 			if (note_sample_mask) {
711 				draw_char(170, 40, 48, 3, 2);
712 				draw_char(170, 41, 48, 3, 2);
713 			}
714 			break;
715 		case 2:
716 		case 3:
717 			draw_char(note_sample_mask ? 171 : 169, 40, 48, 3, 2);
718 			draw_char(note_sample_mask ? 171 : 169, 41, 48, 3, 2);
719 			break;
720 		};
721 	}
722 }
723 
instrument_note_trans_transpose(song_instrument_t * ins,int dir)724 static void instrument_note_trans_transpose(song_instrument_t *ins, int dir)
725 {
726 	int i;
727 	for (i = 0; i < 120; i++) {
728 		ins->note_map[i] = CLAMP(ins->note_map[i]+dir, 1, 120);
729 	}
730 }
731 
instrument_note_trans_insert(song_instrument_t * ins,int pos)732 static void instrument_note_trans_insert(song_instrument_t *ins, int pos)
733 {
734 	int i;
735 	for (i = 119; i > pos; i--) {
736 		ins->note_map[i] = ins->note_map[i-1];
737 		ins->sample_map[i] = ins->sample_map[i-1];
738 	}
739 	if (pos) {
740 		ins->note_map[pos] = ins->note_map[pos-1]+1;
741 	} else {
742 		ins->note_map[0] = 1;
743 	}
744 }
745 
instrument_note_trans_delete(song_instrument_t * ins,int pos)746 static void instrument_note_trans_delete(song_instrument_t *ins, int pos)
747 {
748 	int i;
749 	for (i = pos; i < 120; i++) {
750 		ins->note_map[i] = ins->note_map[i+1];
751 		ins->sample_map[i] = ins->sample_map[i+1];
752 	}
753 	ins->note_map[119] = ins->note_map[118]+1;
754 }
755 
note_trans_handle_key(struct key_event * k)756 static int note_trans_handle_key(struct key_event * k)
757 {
758 	int prev_line = note_trans_sel_line;
759 	int new_line = prev_line;
760 	int prev_pos = note_trans_cursor_pos;
761 	int new_pos = prev_pos;
762 	song_instrument_t *ins = song_get_instrument(current_instrument);
763 	int c, n;
764 
765 	if (k->mouse == MOUSE_CLICK && k->mouse_button == MOUSE_BUTTON_MIDDLE) {
766 		if (k->state == KEY_RELEASE)
767 			status.flags |= CLIPPY_PASTE_SELECTION;
768 		return 1;
769 	} else if (k->mouse == MOUSE_SCROLL_UP || k->mouse == MOUSE_SCROLL_DOWN) {
770 		if (k->state == KEY_PRESS) {
771 			note_trans_top_line += (k->mouse == MOUSE_SCROLL_UP) ? -3 : 3;
772 			note_trans_top_line = CLAMP(note_trans_top_line, 0, 119 - 31);
773 			status.flags |= NEED_UPDATE;
774 		}
775 		return 1;
776 	} else if (k->mouse != MOUSE_NONE) {
777 		if (k->x >= 32 && k->x <= 41 && k->y >= 16 && k->y <= 47) {
778 			new_line = note_trans_top_line + k->y - 16;
779 			if (new_line == prev_line) {
780 				switch (k->x - 36) {
781 				case 2:
782 					new_pos = 1;
783 					break;
784 				case 4:
785 					new_pos = 2;
786 					break;
787 				case 5:
788 					new_pos = 3;
789 					break;
790 				default:
791 					new_pos = 0;
792 					break;
793 				};
794 			}
795 		}
796 	} else if (k->mod & KMOD_ALT) {
797 		if (k->state == KEY_RELEASE)
798 			return 0;
799 		switch (k->sym) {
800 		case SDLK_UP:
801 			instrument_note_trans_transpose(ins, 1);
802 			break;
803 		case SDLK_DOWN:
804 			instrument_note_trans_transpose(ins, -1);
805 			break;
806 		case SDLK_INSERT:
807 			instrument_note_trans_insert(ins, note_trans_sel_line);
808 			break;
809 		case SDLK_DELETE:
810 			instrument_note_trans_delete(ins, note_trans_sel_line);
811 			break;
812 		case SDLK_n:
813 			n = note_trans_sel_line - 1; // the line to copy *from*
814 			if (n < 0 || ins->note_map[n] == NOTE_LAST)
815 				break;
816 			ins->note_map[note_trans_sel_line] = ins->note_map[n] + 1;
817 			ins->sample_map[note_trans_sel_line] = ins->sample_map[n];
818 			new_line++;
819 			break;
820 		case SDLK_p:
821 			n = note_trans_sel_line + 1; // the line to copy *from*
822 			if (n > (NOTE_LAST - NOTE_FIRST) || ins->note_map[n] == NOTE_FIRST)
823 				break;
824 			ins->note_map[note_trans_sel_line] = ins->note_map[n] - 1;
825 			ins->sample_map[note_trans_sel_line] = ins->sample_map[n];
826 			new_line--;
827 			break;
828 		case SDLK_a:
829 			c = sample_get_current();
830 			for (n = 0; n < (NOTE_LAST - NOTE_FIRST + 1); n++)
831 				ins->sample_map[n] = c;
832 			if (k->mod & KMOD_SHIFT) {
833 				// Copy the name too.
834 				memcpy(ins->name, current_song->samples[c].name, 32);
835 			}
836 			break;
837 		default:
838 			return 0;
839 		}
840 	} else {
841 		switch (k->sym) {
842 		case SDLK_UP:
843 			if (k->state == KEY_RELEASE)
844 				return 0;
845 			if (k->mod & KMOD_CTRL)
846 				sample_set(sample_get_current () - 1);
847 			if (!NO_MODIFIER(k->mod))
848 				return 0;
849 			if (--new_line < 0) {
850 				change_focus_to(1);
851 				return 1;
852 			}
853 			break;
854 		case SDLK_DOWN:
855 			if (k->state == KEY_RELEASE)
856 				return 0;
857 			if (k->mod & KMOD_CTRL)
858 				sample_set(sample_get_current () + 1);
859 			if (!NO_MODIFIER(k->mod))
860 				return 0;
861 			new_line++;
862 			break;
863 		case SDLK_PAGEUP:
864 			if (k->state == KEY_RELEASE)
865 				return 0;
866 			if (k->mod & KMOD_CTRL) {
867 				instrument_set(current_instrument - 1);
868 				return 1;
869 			}
870 			new_line -= 16;
871 			break;
872 		case SDLK_PAGEDOWN:
873 			if (k->state == KEY_RELEASE)
874 				return 0;
875 			if (k->mod & KMOD_CTRL) {
876 				instrument_set(current_instrument + 1);
877 				return 1;
878 			}
879 			new_line += 16;
880 			break;
881 		case SDLK_HOME:
882 			if (k->state == KEY_RELEASE)
883 				return 0;
884 			if (!NO_MODIFIER(k->mod))
885 				return 0;
886 			new_line = 0;
887 			break;
888 		case SDLK_END:
889 			if (k->state == KEY_RELEASE)
890 				return 0;
891 			if (!NO_MODIFIER(k->mod))
892 				return 0;
893 			new_line = 119;
894 			break;
895 		case SDLK_LEFT:
896 			if (k->state == KEY_RELEASE)
897 				return 0;
898 			if (!NO_MODIFIER(k->mod))
899 				return 0;
900 			new_pos--;
901 			break;
902 		case SDLK_RIGHT:
903 			if (k->state == KEY_RELEASE)
904 				return 0;
905 			if (!NO_MODIFIER(k->mod))
906 				return 0;
907 			new_pos++;
908 			break;
909 		case SDLK_RETURN:
910 			if (k->state == KEY_PRESS)
911 				return 0;
912 			if (!NO_MODIFIER(k->mod))
913 				return 0;
914 			sample_set(ins->sample_map[note_trans_sel_line]);
915 			get_page_widgets()->accept_text = (instrument_cursor_pos == 25 ? 0 : 1);
916 			return 1;
917 		case SDLK_LESS:
918 		case SDLK_SEMICOLON:
919 		case SDLK_COLON:
920 			if (k->state == KEY_RELEASE)
921 				return 0;
922 			sample_set(sample_get_current() - 1);
923 			return 1;
924 		case SDLK_GREATER:
925 		case SDLK_QUOTE:
926 		case SDLK_QUOTEDBL:
927 			if (k->state == KEY_RELEASE)
928 				return 0;
929 			sample_set(sample_get_current() + 1);
930 			return 1;
931 
932 		default:
933 			if (k->state == KEY_RELEASE)
934 				return 0;
935 			switch (note_trans_cursor_pos) {
936 			case 0:        /* note */
937 				n = kbd_get_note(k);
938 				if (!NOTE_IS_NOTE(n))
939 					return 0;
940 				ins->note_map[note_trans_sel_line] = n;
941 				if (note_sample_mask || (status.flags & CLASSIC_MODE))
942 					ins->sample_map[note_trans_sel_line] = sample_get_current();
943 				new_line++;
944 				break;
945 			case 1:        /* octave */
946 				c = kbd_char_to_hex(k);
947 				if (c < 0 || c > 9) return 0;
948 				n = ins->note_map[note_trans_sel_line];
949 				n = ((n - 1) % 12) + (12 * c) + 1;
950 				ins->note_map[note_trans_sel_line] = n;
951 				new_line++;
952 				break;
953 
954 				/* Made it possible to enter H to R letters
955 				on 1st digit for expanded sample slots.  -delt. */
956 
957 			case 2:        /* instrument, first digit */
958 			case 3:        /* instrument, second digit */
959 				if (k->sym == SDLK_SPACE) {
960 					ins->sample_map[note_trans_sel_line] =
961 						sample_get_current();
962 					new_line++;
963 					break;
964 				}
965 
966 				if ((k->sym == SDLK_PERIOD && NO_MODIFIER(k->mod)) || k->sym == SDLK_DELETE) {
967 					ins->sample_map[note_trans_sel_line] = 0;
968 					new_line += (k->sym == SDLK_PERIOD) ? 1 : 0;
969 					break;
970 				}
971 				if (k->sym == SDLK_COMMA && NO_MODIFIER(k->mod)) {
972 					note_sample_mask = note_sample_mask ? 0 : 1;
973 					break;
974 				}
975 
976 				n = ins->sample_map[note_trans_sel_line];
977 				if (note_trans_cursor_pos == 2) {
978 					c = kbd_char_to_99(k);
979 					if (c < 0) return 0;
980 					n = (c * 10) + (n % 10);
981 					new_pos++;
982 				} else {
983 					c = kbd_char_to_hex(k);
984 					if (c < 0 || c > 9) return 0;
985 					n = ((n / 10) * 10) + c;
986 					new_pos--;
987 					new_line++;
988 				}
989 				n = MIN(n, MAX_SAMPLES - 1);
990 				ins->sample_map[note_trans_sel_line] = n;
991 				sample_set(n);
992 				break;
993 			}
994 			break;
995 		}
996 	}
997 
998 	new_line = CLAMP(new_line, 0, 119);
999 	note_trans_cursor_pos = CLAMP(new_pos, 0, 3);
1000 	if (new_line != prev_line) {
1001 		note_trans_sel_line = new_line;
1002 		note_trans_reposition();
1003 	}
1004 
1005 	/* this causes unneeded redraws in some cases... oh well :P */
1006 	status.flags |= NEED_UPDATE;
1007 	return 1;
1008 }
1009 
1010 /* --------------------------------------------------------------------------------------------------------- */
1011 /* envelope helper functions */
1012 
_env_draw_axes(int middle)1013 static void _env_draw_axes(int middle)
1014 {
1015 	int n, y = middle ? 31 : 62;
1016 	for (n = 0; n < 64; n += 2)
1017 		vgamem_ovl_drawpixel(&env_overlay, 3, n, 12);
1018 	for (n = 0; n < 256; n += 2)
1019 		vgamem_ovl_drawpixel(&env_overlay, 1 + n, y, 12);
1020 }
1021 
_env_draw_node(int x,int y,int on)1022 static void _env_draw_node(int x, int y, int on)
1023 {
1024 	int c = (status.flags & CLASSIC_MODE) ? 12 : 5;
1025 
1026 	vgamem_ovl_drawpixel(&env_overlay, x - 1, y - 1, c);
1027 	vgamem_ovl_drawpixel(&env_overlay, x - 1, y, c);
1028 	vgamem_ovl_drawpixel(&env_overlay, x - 1, y + 1, c);
1029 
1030 	vgamem_ovl_drawpixel(&env_overlay, x, y - 1, c);
1031 	vgamem_ovl_drawpixel(&env_overlay, x, y, c);
1032 	vgamem_ovl_drawpixel(&env_overlay, x, y + 1, c);
1033 
1034 	vgamem_ovl_drawpixel(&env_overlay, x + 1, y - 1,c);
1035 	vgamem_ovl_drawpixel(&env_overlay, x + 1, y,c);
1036 	vgamem_ovl_drawpixel(&env_overlay, x + 1, y + 1,c);
1037 
1038 	if (on) {
1039 		vgamem_ovl_drawpixel(&env_overlay, x - 3, y - 1,c);
1040 		vgamem_ovl_drawpixel(&env_overlay, x - 3, y,c);
1041 		vgamem_ovl_drawpixel(&env_overlay, x - 3, y + 1,c);
1042 
1043 		vgamem_ovl_drawpixel(&env_overlay, x + 3, y - 1,c);
1044 		vgamem_ovl_drawpixel(&env_overlay, x + 3, y,c);
1045 		vgamem_ovl_drawpixel(&env_overlay, x + 3, y + 1,c);
1046 	}
1047 }
1048 
_env_draw_loop(int xs,int xe,int sustain)1049 static void _env_draw_loop(int xs, int xe, int sustain)
1050 {
1051 	int y = 0;
1052 	int c = (status.flags & CLASSIC_MODE) ? 12 : 3;
1053 
1054 	if (sustain) {
1055 		while (y < 62) {
1056 			/* unrolled once */
1057 			vgamem_ovl_drawpixel(&env_overlay, xs, y, c);
1058 			vgamem_ovl_drawpixel(&env_overlay, xe, y, c); y++;
1059 			vgamem_ovl_drawpixel(&env_overlay, xs, y, 0);
1060 			vgamem_ovl_drawpixel(&env_overlay, xe, y, 0); y++;
1061 			vgamem_ovl_drawpixel(&env_overlay, xs, y, c);
1062 			vgamem_ovl_drawpixel(&env_overlay, xe, y, c); y++;
1063 			vgamem_ovl_drawpixel(&env_overlay, xs, y, 0);
1064 			vgamem_ovl_drawpixel(&env_overlay, xe, y, 0); y++;
1065 		}
1066 	} else {
1067 		while (y < 62) {
1068 			vgamem_ovl_drawpixel(&env_overlay, xs, y, 0);
1069 			vgamem_ovl_drawpixel(&env_overlay, xe, y, 0); y++;
1070 			vgamem_ovl_drawpixel(&env_overlay, xs, y, c);
1071 			vgamem_ovl_drawpixel(&env_overlay, xe, y, c); y++;
1072 			vgamem_ovl_drawpixel(&env_overlay, xs, y, c);
1073 			vgamem_ovl_drawpixel(&env_overlay, xe, y, c); y++;
1074 			vgamem_ovl_drawpixel(&env_overlay, xs, y, 0);
1075 			vgamem_ovl_drawpixel(&env_overlay, xe, y, 0); y++;
1076 		}
1077 	}
1078 }
1079 
_env_draw(const song_envelope_t * env,int middle,int current_node,int env_on,int loop_on,int sustain_on,int env_num)1080 static void _env_draw(const song_envelope_t *env, int middle, int current_node,
1081 			int env_on, int loop_on, int sustain_on, int env_num)
1082 {
1083 	song_voice_t *channel;
1084 	unsigned int *channel_list;
1085 	char buf[16];
1086 	unsigned int envpos[3];
1087 	int x, y, n, m, c;
1088 	int last_x = 0, last_y = 0;
1089 	int max_ticks = 50;
1090 
1091 	while (env->ticks[env->nodes - 1] >= max_ticks)
1092 		max_ticks *= 2;
1093 
1094 	vgamem_ovl_clear(&env_overlay, 0);
1095 
1096 	/* draw the axis lines */
1097 	_env_draw_axes(middle);
1098 
1099 	for (n = 0; n < env->nodes; n++) {
1100 		x = 4 + env->ticks[n] * 256 / max_ticks;
1101 
1102 		/* 65 values are being crammed into 62 pixels => have to lose three pixels somewhere.
1103 		 * This is where IT compromises -- I don't quite get how the lines are drawn, though,
1104 		 * because it changes for each value... (apart from drawing 63 and 64 the same way) */
1105 		y = env->values[n];
1106 		if (y > 63) y--;
1107 		if (y > 42) y--;
1108 		if (y > 21) y--;
1109 		y = 62 - y;
1110 
1111 		_env_draw_node(x, y, n == current_node);
1112 
1113 		if (last_x)
1114 			vgamem_ovl_drawline(&env_overlay,
1115 				last_x, last_y, x, y, 12);
1116 
1117 		last_x = x;
1118 		last_y = y;
1119 	}
1120 
1121 	if (sustain_on)
1122 		_env_draw_loop(4 + env->ticks[env->sustain_start] * 256 / max_ticks,
1123 			       4 + env->ticks[env->sustain_end] * 256 / max_ticks, 1);
1124 	if (loop_on)
1125 		_env_draw_loop(4 + env->ticks[env->loop_start] * 256 / max_ticks,
1126 			       4 + env->ticks[env->loop_end] * 256 / max_ticks, 0);
1127 
1128 	if (env_on) {
1129 		max_ticks = env->ticks[env->nodes-1];
1130 		m = max_ticks ? song_get_mix_state(&channel_list) : 0;
1131 		while (m--) {
1132 			channel = song_get_mix_channel(channel_list[m]);
1133 			if (channel->ptr_instrument != song_get_instrument(current_instrument))
1134 				continue;
1135 
1136 			envpos[0] = channel->vol_env_position;
1137 			envpos[1] = channel->pan_env_position;
1138 			envpos[2] = channel->pitch_env_position;
1139 
1140 			x = 4 + (envpos[env_num] * (last_x-4) / max_ticks);
1141 			if (x > last_x)
1142 				x = last_x;
1143 			c =  (status.flags & CLASSIC_MODE)
1144 				? 12
1145 				: ((channel->flags & (CHN_KEYOFF | CHN_NOTEFADE)) ? 8 : 6);
1146 			for (y = 0; y < 62; y++)
1147 				vgamem_ovl_drawpixel(&env_overlay, x, y, c);
1148 		}
1149 	}
1150 
1151 	draw_fill_chars(65, 18, 76, 25, 0);
1152 	vgamem_ovl_apply(&env_overlay);
1153 
1154 	sprintf(buf, "Node %d/%d", current_node, env->nodes);
1155 	draw_text(buf, 66, 19, 2, 0);
1156 	sprintf(buf, "Tick %d", env->ticks[current_node]);
1157 	draw_text(buf, 66, 21, 2, 0);
1158 	sprintf(buf, "Value %d", (int)(env->values[current_node] - (middle ? 32 : 0)));
1159 	draw_text(buf, 66, 23, 2, 0);
1160 }
1161 
1162 /* return: the new current node */
_env_node_add(song_envelope_t * env,int current_node,int override_tick,int override_value)1163 static int _env_node_add(song_envelope_t *env, int current_node, int override_tick, int override_value)
1164 {
1165 	int newtick, newvalue;
1166 
1167 	status.flags |= SONG_NEEDS_SAVE;
1168 
1169 	if (env->nodes > 24 || current_node == env->nodes - 1)
1170 		return current_node;
1171 
1172 	newtick = (env->ticks[current_node] + env->ticks[current_node + 1]) / 2;
1173 	newvalue = (env->values[current_node] + env->values[current_node + 1]) / 2;
1174 	if (override_tick > -1 && override_value > -1) {
1175 		newtick = override_tick;
1176 		newvalue = override_value;
1177 	} else if (newtick == env->ticks[current_node] || newtick == env->ticks[current_node + 1]) {
1178 		printf("Not enough room!\n");
1179 		return current_node;
1180 	}
1181 
1182 	env->nodes++;
1183 	memmove(env->ticks + current_node + 1, env->ticks + current_node,
1184 		(env->nodes - current_node - 1) * sizeof(env->ticks[0]));
1185 	memmove(env->values + current_node + 1, env->values + current_node,
1186 		(env->nodes - current_node - 1) * sizeof(env->values[0]));
1187 	env->ticks[current_node + 1] = newtick;
1188 	env->values[current_node + 1] = newvalue;
1189 	if (env->loop_end > current_node) env->loop_end++;
1190 	if (env->loop_start > current_node) env->loop_start++;
1191 	if (env->sustain_end > current_node) env->sustain_end++;
1192 	if (env->sustain_start > current_node) env->sustain_start++;
1193 
1194 	return current_node;
1195 }
1196 
1197 /* return: the new current node */
_env_node_remove(song_envelope_t * env,int current_node)1198 static int _env_node_remove(song_envelope_t *env, int current_node)
1199 {
1200 	status.flags |= SONG_NEEDS_SAVE;
1201 
1202 	if (current_node == 0 || env->nodes < 3)
1203 		return current_node;
1204 
1205 	memmove(env->ticks + current_node, env->ticks + current_node + 1,
1206 		(env->nodes - current_node - 1) * sizeof(env->ticks[0]));
1207 	memmove(env->values + current_node, env->values + current_node + 1,
1208 		(env->nodes - current_node - 1) * sizeof(env->values[0]));
1209 	env->nodes--;
1210 
1211 	if (env->loop_start >= env->nodes)
1212 		env->loop_start = env->nodes - 1;
1213 	else if (env->loop_start > current_node)
1214 		env->loop_start--;
1215 	if (env->loop_end >= env->nodes)
1216 		env->loop_end = env->nodes - 1;
1217 	else if (env->loop_end > current_node)
1218 		env->loop_end--;
1219 	if (env->sustain_start >= env->nodes)
1220 		env->sustain_start = env->nodes - 1;
1221 	else if (env->sustain_start > current_node)
1222 		env->sustain_start--;
1223 	if (env->sustain_end >= env->nodes)
1224 		env->sustain_end = env->nodes - 1;
1225 	else if (env->sustain_end > current_node)
1226 		env->sustain_end--;
1227 	if (current_node >= env->nodes)
1228 		current_node = env->nodes - 1;
1229 
1230 	return current_node;
1231 }
1232 
do_pre_loop_cut(void * ign)1233 static void do_pre_loop_cut(void *ign)
1234 {
1235 	song_envelope_t *env = (song_envelope_t *)ign;
1236 	unsigned int bt;
1237 	int i;
1238 	bt = env->ticks[env->loop_start];
1239 	for (i = env->loop_start; i < 32; i++) {
1240 		env->ticks[i - env->loop_start] = env->ticks[i] - bt;
1241 		env->values[i - env->loop_start] = env->values[i];
1242 	}
1243 	env->nodes -= env->loop_start;
1244 	if (env->sustain_start > env->loop_start) {
1245 		env->sustain_start -= env->loop_start;
1246 	} else {
1247 		env->sustain_start = 0;
1248 	}
1249 	if (env->sustain_end > env->loop_start) {
1250 		env->sustain_end -= env->loop_start;
1251 	} else {
1252 		env->sustain_end = 0;
1253 	}
1254 	if (env->loop_end > env->loop_start) {
1255 		env->loop_end -= env->loop_start;
1256 	} else {
1257 		env->loop_end = 0;
1258 	}
1259 	env->loop_start = 0;
1260 	if (env->loop_start > env->loop_end)
1261 		env->loop_end = env->loop_start;
1262 	if (env->sustain_start > env->sustain_end)
1263 		env->sustain_end = env->sustain_start;
1264 	status.flags |= NEED_UPDATE;
1265 }
1266 
do_post_loop_cut(void * ign)1267 static void do_post_loop_cut(void *ign)
1268 {
1269 	song_envelope_t *env = (song_envelope_t *)ign;
1270 	env->nodes = env->loop_end+1;
1271 }
1272 
1273 
env_resize(song_envelope_t * env,int ticks)1274 static void env_resize(song_envelope_t *env, int ticks)
1275 {
1276 	int old = env->ticks[env->nodes - 1];
1277 	int n, t;
1278 
1279 	if (ticks > 9999)
1280 		ticks = 9999;
1281 	for (n = 1; n < env->nodes; n++) {
1282 		t = env->ticks[n] * ticks / old;
1283 		env->ticks[n] = MAX(t, env->ticks[n - 1] + 1);
1284 	}
1285 	status.flags |= NEED_UPDATE;
1286 }
1287 
1288 
1289 static struct widget env_resize_widgets[2];
1290 static int env_resize_cursor;
1291 
do_env_resize(void * data)1292 static void do_env_resize(void *data)
1293 {
1294 	env_resize((song_envelope_t *) data, env_resize_widgets[0].d.numentry.value);
1295 }
1296 
env_resize_draw_const(void)1297 static void env_resize_draw_const(void)
1298 {
1299 	draw_text("Resize Envelope", 34, 24, 3, 2);
1300 	draw_text("New Length", 31, 27, 0, 2);
1301 	draw_box(41, 26, 49, 28, BOX_THICK | BOX_INNER | BOX_INSET);
1302 }
1303 
env_resize_dialog(song_envelope_t * env)1304 static void env_resize_dialog(song_envelope_t *env)
1305 {
1306 	struct dialog *dialog;
1307 
1308 	env_resize_cursor = 0;
1309 	create_numentry(env_resize_widgets + 0, 42, 27, 7, 0, 1, 1, NULL, 0, 9999, &env_resize_cursor);
1310 	env_resize_widgets[0].d.numentry.value = env->ticks[env->nodes - 1];
1311 	create_button(env_resize_widgets + 1, 36, 30, 6, 0, 1, 1, 1, 1, dialog_cancel_NULL, "Cancel", 1);
1312 	dialog = dialog_create_custom(26, 22, 29, 11, env_resize_widgets, 2, 0, env_resize_draw_const, env);
1313 	dialog->action_yes = do_env_resize;
1314 }
1315 
1316 
1317 
1318 static struct widget env_adsr_widgets[4];
1319 static int env_adsr_cursor = 0;
1320 
do_env_adsr(void * data)1321 static void do_env_adsr(void *data)
1322 {
1323 	// FIXME | move env flags into the envelope itself, where they should be in the first place.
1324 	// FIXME | then this nonsense can go away.
1325 	song_instrument_t *ins = (song_instrument_t *) data;
1326 	song_envelope_t *env = &ins->vol_env;
1327 	int a = env_adsr_widgets[0].d.thumbbar.value;
1328 	int d = env_adsr_widgets[1].d.thumbbar.value;
1329 	int s = env_adsr_widgets[2].d.thumbbar.value;
1330 	int r = env_adsr_widgets[3].d.thumbbar.value;
1331 	int v1 = MAX(a, a * a / 16);
1332 	int v2 = MAX(v1 + d * d / 16, v1 + d);
1333 	int v3 = MAX(v2 + r * r / 4, v2 + r);
1334 	int n = 0;
1335 
1336 	if (a) {
1337 		env->ticks[n] = 0;
1338 		env->values[n++] = 0;
1339 	}
1340 	if (d) {
1341 		env->ticks[n] = v1;
1342 		env->values[n++] = 64;
1343 	}
1344 	env->sustain_start = env->sustain_end = n;
1345 	env->ticks[n] = v2;
1346 	env->values[n++] = s / 2;
1347 	env->ticks[n] = v3;
1348 	env->values[n++] = 0;
1349 	env->nodes = n;
1350 	for (n = 0; n < env->nodes - 1; n++)
1351 		if (env->ticks[n] >= env->ticks[n + 1])
1352 			env->ticks[n + 1] = env->ticks[n] + 1;
1353 	ins->flags |= ENV_VOLSUSTAIN | ENV_VOLUME; // arghhhhh
1354 }
1355 
env_adsr_draw_const(void)1356 static void env_adsr_draw_const(void)
1357 {
1358 	draw_text("Envelope Generator", 32, 22, 0, 2);
1359 	draw_text("Attack", 27, 24, 0, 2);
1360 	draw_text("Decay", 28, 25, 0, 2);
1361 	draw_text("Sustain", 26, 26, 0, 2);
1362 	draw_text("Release", 26, 27, 0, 2);
1363 
1364 	draw_box(33, 23, 51, 28, BOX_THICK | BOX_INNER | BOX_INSET);
1365 }
1366 
env_adsr_dialog(UNUSED song_envelope_t * env)1367 static void env_adsr_dialog(UNUSED song_envelope_t *env)
1368 {
1369 	struct dialog *dialog;
1370 	song_instrument_t *ins = song_get_instrument(current_instrument); // ARGHHH
1371 
1372 	env_adsr_cursor = 0;
1373 	create_thumbbar(env_adsr_widgets + 0, 34, 24, 17, 4, 1, 4, NULL, 0, 128);
1374 	create_thumbbar(env_adsr_widgets + 1, 34, 25, 17, 0, 2, 4, NULL, 0, 128);
1375 	create_thumbbar(env_adsr_widgets + 2, 34, 26, 17, 1, 3, 4, NULL, 0, 128);
1376 	create_thumbbar(env_adsr_widgets + 3, 34, 27, 17, 2, 4, 4, NULL, 0, 128);
1377 	create_button(env_adsr_widgets + 4, 36, 30, 6, 3, 0, 4, 4, 0, dialog_cancel_NULL, "Cancel", 1);
1378 
1379 	dialog = dialog_create_custom(25, 21, 31, 12, env_adsr_widgets, 5, 0, env_adsr_draw_const, ins);
1380 	dialog->action_yes = do_env_adsr;
1381 }
1382 
1383 
1384 
1385 
1386 /* the return value here is actually a bitmask:
1387 r & 1 => the key was handled
1388 r & 2 => the envelope changed (i.e., it should be enabled) */
_env_handle_key_viewmode(struct key_event * k,song_envelope_t * env,int * current_node,unsigned int sec)1389 static int _env_handle_key_viewmode(struct key_event *k, song_envelope_t *env, int *current_node, unsigned int sec)
1390 {
1391 	int new_node = *current_node;
1392 	int n;
1393 
1394 	switch (k->sym) {
1395 	case SDLK_UP:
1396 		if (k->state == KEY_RELEASE)
1397 			return 0;
1398 		change_focus_to(1);
1399 		return 1;
1400 	case SDLK_DOWN:
1401 		if (k->state == KEY_RELEASE)
1402 			return 0;
1403 		change_focus_to(6);
1404 		return 1;
1405 	case SDLK_LEFT:
1406 		if (k->state == KEY_RELEASE)
1407 			return 0;
1408 		if (!NO_MODIFIER(k->mod))
1409 			return 0;
1410 		new_node--;
1411 		break;
1412 	case SDLK_RIGHT:
1413 		if (k->state == KEY_RELEASE)
1414 			return 0;
1415 		if (!NO_MODIFIER(k->mod))
1416 			return 0;
1417 		new_node++;
1418 		break;
1419 	case SDLK_INSERT:
1420 		if (k->state == KEY_RELEASE)
1421 			return 0;
1422 		if (!NO_MODIFIER(k->mod))
1423 			return 0;
1424 		*current_node = _env_node_add(env, *current_node, -1, -1);
1425 		status.flags |= NEED_UPDATE;
1426 		return 1 | 2;
1427 	case SDLK_DELETE:
1428 		if (k->state == KEY_RELEASE)
1429 			return 0;
1430 		if (!NO_MODIFIER(k->mod))
1431 			return 0;
1432 		*current_node = _env_node_remove(env, *current_node);
1433 		status.flags |= NEED_UPDATE;
1434 		return 1 | 2;
1435 	case SDLK_SPACE:
1436 		if (k->state == KEY_RELEASE)
1437 			return 0;
1438 		if (!NO_MODIFIER(k->mod))
1439 			return 0;
1440 		song_keyup(KEYJAZZ_NOINST, current_instrument, last_note);
1441 		song_keydown(KEYJAZZ_NOINST, current_instrument, last_note, 64, KEYJAZZ_CHAN_CURRENT);
1442 		return 1;
1443 	case SDLK_RETURN:
1444 		if (k->state == KEY_PRESS)
1445 			return 0;
1446 		if (!NO_MODIFIER(k->mod))
1447 			return 0;
1448 		envelope_edit_mode = 1;
1449 		status.flags |= NEED_UPDATE;
1450 		return 1 | 2;
1451 	case SDLK_l:
1452 		if (k->state == KEY_PRESS)
1453 			return 0;
1454 		if (!(k->mod & KMOD_ALT)) return 0;
1455 		if (env->loop_end < (env->nodes-1))  {
1456 			dialog_create(DIALOG_OK_CANCEL, "Cut envelope?", do_post_loop_cut, NULL, 1, env);
1457 			return 1;
1458 		}
1459 		return 0;
1460 	case SDLK_b:
1461 		if (k->state == KEY_PRESS)
1462 			return 0;
1463 		if (!(k->mod & KMOD_ALT)) return 0;
1464 		if (env->loop_start > 0) {
1465 			dialog_create(DIALOG_OK_CANCEL, "Cut envelope?", do_pre_loop_cut, NULL, 1, env);
1466 			return 1;
1467 		}
1468 		return 0;
1469 
1470 	// F/G for key symmetry with pattern double/halve block
1471 	// E for symmetry with sample resize
1472 	case SDLK_f:
1473 		if (k->state == KEY_PRESS)
1474 			return 0;
1475 		if (!(k->mod & KMOD_ALT)) return 0;
1476 		env_resize(env, env->ticks[env->nodes - 1] * 2);
1477 		return 1;
1478 	case SDLK_g:
1479 		if (k->state == KEY_PRESS)
1480 			return 0;
1481 		if (!(k->mod & KMOD_ALT)) return 0;
1482 		env_resize(env, env->ticks[env->nodes - 1] / 2);
1483 		return 1;
1484 	case SDLK_e:
1485 		if (k->state == KEY_PRESS)
1486 			return 0;
1487 		if (!(k->mod & KMOD_ALT)) return 0;
1488 		env_resize_dialog(env);
1489 		return 1;
1490 
1491 	case SDLK_z:
1492 		if (k->state == KEY_PRESS)
1493 			return 0;
1494 		if (!(k->mod & KMOD_ALT)) return 0;
1495 		env_adsr_dialog(env);
1496 		return 1;
1497 
1498 	default:
1499 		if (k->state == KEY_PRESS)
1500 			return 0;
1501 
1502 		n = numeric_key_event(k, 0);
1503 		if (n > -1) {
1504 			if (k->mod & (KMOD_ALT | KMOD_CTRL)) {
1505 				save_envelope(n, env, sec);
1506 				status_text_flash("Envelope copied into slot %d", n);
1507 			} else if (k->mod & KMOD_SHIFT) {
1508 				restore_envelope(n, env, sec);
1509 				if (!(status.flags & CLASSIC_MODE))
1510 					status_text_flash("Pasted envelope from slot %d", n);
1511 			}
1512 			return 1;
1513 		}
1514 		return 0;
1515 	}
1516 
1517 	new_node = CLAMP(new_node, 0, env->nodes - 1);
1518 	if (*current_node != new_node) {
1519 		*current_node = new_node;
1520 		status.flags |= NEED_UPDATE;
1521 	}
1522 
1523 	return 1;
1524 }
1525 
1526 /* mouse handling routines for envelope */
_env_handle_mouse(struct key_event * k,song_envelope_t * env,int * current_node)1527 static int _env_handle_mouse(struct key_event *k, song_envelope_t *env, int *current_node)
1528 {
1529 	int x, y, i;
1530 	int max_ticks = 50;
1531 
1532 	if (k->mouse != MOUSE_CLICK) return 0;
1533 
1534 	if (k->state == KEY_RELEASE) {
1535 		/* mouse release */
1536 		if (envelope_mouse_edit) {
1537 			if (current_node && *current_node) {
1538 				for (i = 0; i < env->nodes-1; i++) {
1539 					if (*current_node == i) continue;
1540 					if (env->ticks[ *current_node ] == env->ticks[i]
1541 					&& env->values[ *current_node ] == env->values[i]) {
1542 						status_text_flash("Removed node %d", (int)(*current_node));
1543 						status.flags |= SONG_NEEDS_SAVE;
1544 
1545 						*current_node = _env_node_remove(env, *current_node);
1546 						break;
1547 					}
1548 				}
1549 
1550 			}
1551 			status.flags |= NEED_UPDATE;
1552 		}
1553 		memused_songchanged();
1554 		envelope_mouse_edit = 0;
1555 		return 1;
1556 	}
1557 
1558 	while (env->ticks[env->nodes - 1] >= max_ticks)
1559 		max_ticks *= 2;
1560 
1561 	if (envelope_mouse_edit) {
1562 		if (k->fx < 259)
1563 			x = 0;
1564 		else
1565 			x = (k->fx - 259) * max_ticks / 256;
1566 		y = 64 - (k->fy - 144);
1567 		if (y > 63) y++;
1568 		if (y > 42) y++;
1569 		if (y > 21) y++;
1570 		if (y > 64) y = 64;
1571 		if (y < 0) y = 0;
1572 
1573 		if (*current_node && env->ticks[ (*current_node)-1 ] >= x) {
1574 			x = env->ticks[ (*current_node)-1 ]+1;
1575 		}
1576 		if (*current_node < (env->nodes-1)) {
1577 			if (env->ticks[ (*current_node)+1 ] <= x) {
1578 				x = env->ticks[ (*current_node)+1 ]-1;
1579 			}
1580 		}
1581 		if (env->ticks[*current_node] == x && env->ticks[*current_node] == y) {
1582 			return 1;
1583 		}
1584 		if (x < 0) x = 0;
1585 		if (x > envelope_tick_limit) x = envelope_tick_limit;
1586 		if (x > 9999) x = 9999;
1587 		if (*current_node) env->ticks[ *current_node ] = x;
1588 		env->values[ *current_node ] = y;
1589 		status.flags |= SONG_NEEDS_SAVE;
1590 		status.flags |= NEED_UPDATE;
1591 	} else {
1592 		int n;
1593 		int dist, dx, dy;
1594 		int best_dist = 0;
1595 		int best_dist_node;
1596 
1597 		best_dist_node = -1;
1598 
1599 		if (k->x < 32 || k->y < 18 || k->x > 32+45 || k->y > 18+8)
1600 			return 0;
1601 
1602 		for (n = 0; n < env->nodes; n++) {
1603 			x = 259 + env->ticks[n] * 256 / max_ticks;
1604 			y = env->values[n];
1605 			if (y > 63) y--;
1606 			if (y > 42) y--;
1607 			if (y > 21) y--;
1608 			y = 206 - y;
1609 
1610 			dx = abs(x - (int) k->fx);
1611 			dy = abs(y - (int) k->fy);
1612 			dist = i_sqrt((dx*dx)+(dy*dy));
1613 			if (best_dist_node == -1 || dist < best_dist) {
1614 				if (dist <= 5) {
1615 					best_dist = dist;
1616 					best_dist_node = n;
1617 				}
1618 			}
1619 		}
1620 		if (best_dist_node == -1) {
1621 			x = (k->fx - 259) * max_ticks / 256;
1622 			y = 64 - (k->fy - 144);
1623 			if (y > 63) y++;
1624 			if (y > 42) y++;
1625 			if (y > 21) y++;
1626 			if (y > 64) y = 64;
1627 			if (y < 0) y = 0;
1628 			if (x > 0 && x < max_ticks) {
1629 				*current_node = 0;
1630 				for (i = 1; i < env->nodes; i++) {
1631 					/* something too close */
1632 					if (env->ticks[i] <= x) *current_node = i;
1633 					if (abs(env->ticks[i] - x) < 2) return 0;
1634 				}
1635 				best_dist_node = (_env_node_add(env, *current_node, x, y))+1;
1636 				status_text_flash("Created node %d", best_dist_node);
1637 			}
1638 			if (best_dist_node == -1) return 0;
1639 		}
1640 
1641 		envelope_tick_limit = env->ticks[env->nodes - 1] * 2;
1642 		envelope_mouse_edit = 1;
1643 		*current_node = best_dist_node;
1644 		status.flags |= SONG_NEEDS_SAVE;
1645 		status.flags |= NEED_UPDATE;
1646 		return 1;
1647 	}
1648 	return 0;
1649 }
1650 
1651 
1652 
1653 /* - this function is only ever called when the envelope is in edit mode
1654    - envelope_edit_mode is only ever assigned a true value once, in _env_handle_key_viewmode.
1655    - when _env_handle_key_viewmode enables envelope_edit_mode, it indicates in its return value
1656      that the envelope should be enabled.
1657    - therefore, the envelope will always be enabled when this function is called, so there is
1658      no reason to indicate a change in the envelope here. */
_env_handle_key_editmode(struct key_event * k,song_envelope_t * env,int * current_node)1659 static int _env_handle_key_editmode(struct key_event *k, song_envelope_t *env, int *current_node)
1660 {
1661 	int new_node = *current_node, new_tick = env->ticks[*current_node],
1662 		new_value = env->values[*current_node];
1663 
1664 	/* TODO: when does adding/removing a node alter loop points? */
1665 
1666 	switch (k->sym) {
1667 	case SDLK_UP:
1668 		if (k->state == KEY_RELEASE)
1669 			return 0;
1670 		if (k->mod & KMOD_ALT)
1671 			new_value += 16;
1672 		else
1673 			new_value++;
1674 		break;
1675 	case SDLK_DOWN:
1676 		if (k->state == KEY_RELEASE)
1677 			return 0;
1678 		if (k->mod & KMOD_ALT)
1679 			new_value -= 16;
1680 		else
1681 			new_value--;
1682 		break;
1683 	case SDLK_PAGEUP:
1684 		if (k->state == KEY_RELEASE)
1685 			return 0;
1686 		if (!NO_MODIFIER(k->mod))
1687 			return 0;
1688 		new_value += 16;
1689 		break;
1690 	case SDLK_PAGEDOWN:
1691 		if (k->state == KEY_RELEASE)
1692 			return 0;
1693 		if (!NO_MODIFIER(k->mod))
1694 			return 0;
1695 		new_value -= 16;
1696 		break;
1697 	case SDLK_LEFT:
1698 		if (k->state == KEY_RELEASE)
1699 			return 1;
1700 		if (k->mod & KMOD_CTRL)
1701 			new_node--;
1702 		else if (k->mod & KMOD_ALT)
1703 			new_tick -= 16;
1704 		else
1705 			new_tick--;
1706 		break;
1707 	case SDLK_RIGHT:
1708 		if (k->state == KEY_RELEASE)
1709 			return 1;
1710 		if (k->mod & KMOD_CTRL)
1711 			new_node++;
1712 		else if (k->mod & KMOD_ALT)
1713 			new_tick += 16;
1714 		else
1715 			new_tick++;
1716 		break;
1717 	case SDLK_TAB:
1718 		if (k->state == KEY_RELEASE)
1719 			return 0;
1720 		if (k->mod & KMOD_SHIFT)
1721 			new_tick -= 16;
1722 		else
1723 			new_tick += 16;
1724 		break;
1725 	case SDLK_HOME:
1726 		if (k->state == KEY_RELEASE)
1727 			return 0;
1728 		if (!NO_MODIFIER(k->mod))
1729 			return 0;
1730 		new_tick = 0;
1731 		break;
1732 	case SDLK_END:
1733 		if (k->state == KEY_RELEASE)
1734 			return 0;
1735 		if (!NO_MODIFIER(k->mod))
1736 			return 0;
1737 		new_tick = 10000;
1738 		break;
1739 	case SDLK_INSERT:
1740 		if (k->state == KEY_RELEASE)
1741 			return 0;
1742 		if (!NO_MODIFIER(k->mod))
1743 			return 0;
1744 		*current_node = _env_node_add(env, *current_node, -1, -1);
1745 		status.flags |= NEED_UPDATE;
1746 		return 1;
1747 	case SDLK_DELETE:
1748 		if (k->state == KEY_RELEASE)
1749 			return 0;
1750 		if (!NO_MODIFIER(k->mod))
1751 			return 0;
1752 		*current_node = _env_node_remove(env, *current_node);
1753 		status.flags |= NEED_UPDATE;
1754 		return 1;
1755 	case SDLK_SPACE:
1756 		if (k->state == KEY_RELEASE)
1757 			return 0;
1758 		if (!NO_MODIFIER(k->mod))
1759 			return 0;
1760 		song_keyup(KEYJAZZ_NOINST, current_instrument, last_note);
1761 		song_keydown(KEYJAZZ_NOINST, current_instrument, last_note, 64, KEYJAZZ_CHAN_CURRENT);
1762 		return 1;
1763 	case SDLK_RETURN:
1764 		if (k->state == KEY_PRESS)
1765 			return 0;
1766 		if (!NO_MODIFIER(k->mod))
1767 			return 0;
1768 		envelope_edit_mode = 0;
1769 		memused_songchanged();
1770 		status.flags |= NEED_UPDATE;
1771 		break;
1772 	default:
1773 		return 0;
1774 	}
1775 
1776 	new_node = CLAMP(new_node, 0, env->nodes - 1);
1777 	if (new_node != *current_node) {
1778 		status.flags |= NEED_UPDATE;
1779 		*current_node = new_node;
1780 		return 1;
1781 	}
1782 
1783 	new_tick = (new_node == 0) ? 0 : CLAMP(new_tick,
1784 					env->ticks[new_node - 1] + 1,
1785 				       ((new_node == env->nodes - 1)
1786 					? 10000 : env->ticks[new_node + 1]) - 1);
1787 	if (new_tick != env->ticks[new_node]) {
1788 		env->ticks[*current_node] = new_tick;
1789 		status.flags |= SONG_NEEDS_SAVE;
1790 		status.flags |= NEED_UPDATE;
1791 		return 1;
1792 	}
1793 	new_value = CLAMP(new_value, 0, 64);
1794 
1795 	if (new_value != (int)env->values[new_node]) {
1796 		env->values[*current_node] = (unsigned int)new_value;
1797 		status.flags |= SONG_NEEDS_SAVE;
1798 		status.flags |= NEED_UPDATE;
1799 		return 1;
1800 	}
1801 
1802 	return 1;
1803 }
1804 
1805 /* --------------------------------------------------------------------------------------------------------- */
1806 /* envelope stuff (draw()'s and handle_key()'s) */
1807 
_draw_env_label(const char * env_name,int is_selected)1808 static void _draw_env_label(const char *env_name, int is_selected)
1809 {
1810 	int pos = 33;
1811 
1812 	pos += draw_text(env_name, pos, 16, is_selected ? 3 : 0, 2);
1813 	pos += draw_text(" Envelope", pos, 16, is_selected ? 3 : 0, 2);
1814 	if (envelope_edit_mode || envelope_mouse_edit)
1815 		draw_text(" (Edit)", pos, 16, is_selected ? 3 : 0, 2);
1816 }
1817 
volume_envelope_draw(void)1818 static void volume_envelope_draw(void)
1819 {
1820 	int is_selected = (ACTIVE_PAGE.selected_widget == 5);
1821 	song_instrument_t *ins = song_get_instrument(current_instrument);
1822 
1823 	_draw_env_label("Volume", is_selected);
1824 	_env_draw(&ins->vol_env, 0, current_node_vol,
1825 		ins->flags & ENV_VOLUME,
1826 		  ins->flags & ENV_VOLLOOP, ins->flags & ENV_VOLSUSTAIN, 0);
1827 }
1828 
panning_envelope_draw(void)1829 static void panning_envelope_draw(void)
1830 {
1831 	int is_selected = (ACTIVE_PAGE.selected_widget == 5);
1832 	song_instrument_t *ins = song_get_instrument(current_instrument);
1833 
1834 	_draw_env_label("Panning", is_selected);
1835 	_env_draw(&ins->pan_env, 1, current_node_pan,
1836 		ins->flags & ENV_PANNING,
1837 		  ins->flags & ENV_PANLOOP, ins->flags & ENV_PANSUSTAIN, 1);
1838 }
1839 
pitch_envelope_draw(void)1840 static void pitch_envelope_draw(void)
1841 {
1842 	int is_selected = (ACTIVE_PAGE.selected_widget == 5);
1843 	song_instrument_t *ins = song_get_instrument(current_instrument);
1844 
1845 	_draw_env_label("Frequency", is_selected);
1846 	_env_draw(&ins->pitch_env, (ins->flags & ENV_FILTER) ? 0 : 1, current_node_pitch,
1847 		ins->flags & (ENV_PITCH|ENV_FILTER),
1848 		  ins->flags & ENV_PITCHLOOP, ins->flags & ENV_PITCHSUSTAIN, 2);
1849 }
1850 
volume_envelope_handle_key(struct key_event * k)1851 static int volume_envelope_handle_key(struct key_event * k)
1852 {
1853 	song_instrument_t *ins = song_get_instrument(current_instrument);
1854 	int r;
1855 
1856 	if (_env_handle_mouse(k, &ins->vol_env, &current_node_vol)) {
1857 		ins->flags |= ENV_VOLUME;
1858 		return 1;
1859 	}
1860 	if (envelope_edit_mode)
1861 		r = _env_handle_key_editmode(k, &ins->vol_env, &current_node_vol);
1862 	else
1863 		r = _env_handle_key_viewmode(k, &ins->vol_env, &current_node_vol, ENV_VOLUME);
1864 	if (r & 2) {
1865 		r ^= 2;
1866 		ins->flags |= ENV_VOLUME;
1867 	}
1868 	return r;
1869 }
1870 
panning_envelope_handle_key(struct key_event * k)1871 static int panning_envelope_handle_key(struct key_event * k)
1872 {
1873 	song_instrument_t *ins = song_get_instrument(current_instrument);
1874 	int r;
1875 
1876 	if (_env_handle_mouse(k, &ins->pan_env, &current_node_pan)) {
1877 		ins->flags |= ENV_PANNING;
1878 		return 1;
1879 	}
1880 
1881 	if (envelope_edit_mode)
1882 		r = _env_handle_key_editmode(k, &ins->pan_env, &current_node_pan);
1883 	else
1884 		r = _env_handle_key_viewmode(k, &ins->pan_env, &current_node_pan, ENV_PANNING);
1885 	if (r & 2) {
1886 		r ^= 2;
1887 		ins->flags |= ENV_PANNING;
1888 	}
1889 	return r;
1890 }
1891 
pitch_envelope_handle_key(struct key_event * k)1892 static int pitch_envelope_handle_key(struct key_event * k)
1893 {
1894 	song_instrument_t *ins = song_get_instrument(current_instrument);
1895 	int r;
1896 
1897 	if (_env_handle_mouse(k, &ins->pitch_env, &current_node_pitch)) {
1898 		ins->flags |= ENV_PITCH;
1899 		return 1;
1900 	}
1901 	if (envelope_edit_mode)
1902 		r = _env_handle_key_editmode(k, &ins->pitch_env, &current_node_pitch);
1903 	else
1904 		r = _env_handle_key_viewmode(k, &ins->pitch_env, &current_node_pitch, ENV_PITCH);
1905 	if (r & 2) {
1906 		r ^= 2;
1907 		ins->flags |= ENV_PITCH;
1908 	}
1909 	return r;
1910 }
1911 
1912 /* --------------------------------------------------------------------------------------------------------- */
1913 /* pitch-pan center */
1914 
pitch_pan_center_handle_key(struct key_event * k)1915 static int pitch_pan_center_handle_key(struct key_event *k)
1916 {
1917 	song_instrument_t *ins = song_get_instrument(current_instrument);
1918 	int ppc = ins->pitch_pan_center;
1919 
1920 	if (k->state == KEY_RELEASE)
1921 		return 0;
1922 	switch (k->sym) {
1923 	case SDLK_LEFT:
1924 		if (!NO_MODIFIER(k->mod))
1925 			return 0;
1926 		ppc--;
1927 		break;
1928 	case SDLK_RIGHT:
1929 		if (!NO_MODIFIER(k->mod))
1930 			return 0;
1931 		ppc++;
1932 		break;
1933 	default:
1934 		if ((k->mod & (KMOD_CTRL | KMOD_ALT)) == 0) {
1935 			ppc = kbd_get_note(k);
1936 			if (ppc < 1 || ppc > 120)
1937 				return 0;
1938 			ppc--;
1939 			break;
1940 		}
1941 		return 0;
1942 	}
1943 	if ((unsigned int)ppc != ins->pitch_pan_center
1944 	&& ppc >= 0 && ppc < 120) {
1945 		ins->pitch_pan_center = (unsigned int)ppc;
1946 		status.flags |= NEED_UPDATE;
1947 	}
1948 	return 1;
1949 }
1950 
pitch_pan_center_draw(void)1951 static void pitch_pan_center_draw(void)
1952 {
1953 	char buf[4];
1954 	int selected = (ACTIVE_PAGE.selected_widget == 16);
1955 	song_instrument_t *ins = song_get_instrument(current_instrument);
1956 
1957 	draw_text(get_note_string(ins->pitch_pan_center + 1, buf), 54, 45, selected ? 3 : 2, 0);
1958 }
1959 
1960 /* --------------------------------------------------------------------------------------------------------- */
1961 /* default key handler (for instrument changing on pgup/pgdn) */
1962 
do_ins_save(void * p)1963 static void do_ins_save(void *p)
1964 {
1965 	char *ptr = (char *)p;
1966 	if (song_save_instrument(current_instrument, ptr))
1967 		status_text_flash("Instrument saved (instrument %d)", current_instrument);
1968 	else
1969 		status_text_flash("Error: Instrument %d NOT saved! (No Filename?)", current_instrument);
1970 	free(ptr);
1971 }
1972 
instrument_save(void)1973 static void instrument_save(void)
1974 {
1975 	song_instrument_t *ins = song_get_instrument(current_instrument);
1976 	char *ptr = (char *) dmoz_path_concat(cfg_dir_instruments, ins->filename);
1977 	struct stat buf;
1978 
1979 	if (stat(ptr, &buf) == 0) {
1980 		if (S_ISDIR(buf.st_mode)) {
1981 			status_text_flash("%s is a directory", ins->filename);
1982 			return;
1983 		} else if (S_ISREG(buf.st_mode)) {
1984 			dialog_create(DIALOG_OK_CANCEL,
1985 				"Overwrite file?", do_ins_save,
1986 				free, 1, ptr);
1987 			return;
1988 		} else {
1989 			status_text_flash("%s is not a regular file", ins->filename);
1990 			return;
1991 		}
1992 	}
1993 	if (song_save_instrument(current_instrument, ptr))
1994 		status_text_flash("Instrument saved (instrument %d)", current_instrument);
1995 	else
1996 		status_text_flash("Error: Instrument %d NOT saved! (No Filename?)", current_instrument);
1997 	free(ptr);
1998 }
1999 
do_delete_inst(UNUSED void * ign)2000 static void do_delete_inst(UNUSED void *ign)
2001 {
2002 	song_delete_instrument(current_instrument, 0);
2003 }
2004 
do_delete_inst_preserve(UNUSED void * ign)2005 static void do_delete_inst_preserve(UNUSED void *ign)
2006 {
2007 	song_delete_instrument(current_instrument, 1);
2008 }
2009 
instrument_list_handle_alt_key(struct key_event * k)2010 static void instrument_list_handle_alt_key(struct key_event *k)
2011 {
2012 	/* song_instrument_t *ins = song_get_instrument(current_instrument); */
2013 
2014 	if (k->state == KEY_RELEASE)
2015 		return;
2016 	switch (k->sym) {
2017 	case SDLK_n:
2018 		song_toggle_multichannel_mode();
2019 		return;
2020 	case SDLK_o:
2021 		instrument_save();
2022 		return;
2023 	case SDLK_r:
2024 		smpprompt_create("Replace instrument with:", "Instrument", do_replace_instrument);
2025 		return;
2026 	case SDLK_s:
2027 		// extra space to align the text like IT
2028 		smpprompt_create("Swap instrument with: ", "Instrument", do_swap_instrument);
2029 		return;
2030 	case SDLK_x:
2031 		smpprompt_create("Exchange instrument with:", "Instrument", do_exchange_instrument);
2032 		return;
2033 	case SDLK_p:
2034 		smpprompt_create("Copy instrument:", "Instrument", do_copy_instrument);
2035 		return;
2036 	case SDLK_w:
2037 		song_wipe_instrument(current_instrument);
2038 		break;
2039 	case SDLK_d:
2040         if (k->mod & KMOD_SHIFT) {
2041             dialog_create(DIALOG_OK_CANCEL,
2042                 "Delete Instrument? (preserve shared samples)",
2043                 do_delete_inst_preserve, NULL, 1, NULL);
2044         } else {
2045             dialog_create(DIALOG_OK_CANCEL,
2046                 "Delete Instrument?",
2047                 do_delete_inst, NULL, 1, NULL);
2048         }
2049 		return;
2050 	default:
2051 		return;
2052 	}
2053 
2054 	status.flags |= NEED_UPDATE;
2055 }
2056 
instrument_list_pre_handle_key(struct key_event * k)2057 static int instrument_list_pre_handle_key(struct key_event * k)
2058 {
2059 	// Only handle plain F4 key when no dialog is active.
2060 	if (status.dialog_type != DIALOG_NONE || k->sym != SDLK_F4 || (k->mod & (KMOD_CTRL | KMOD_ALT)))
2061 		return 0;
2062 	if (k->state == KEY_RELEASE)
2063 		return 1;
2064 
2065 	if (song_is_instrument_mode()) {
2066 		int csamp = sample_get_current();
2067 		sample_synchronize_to_instrument();
2068 		if (csamp != sample_get_current())
2069 			return 0;
2070 	}
2071 
2072 	if (k->mod & KMOD_SHIFT) {
2073 		switch (status.current_page) {
2074 			default:
2075 			case PAGE_INSTRUMENT_LIST_VOLUME:  set_subpage(PAGE_INSTRUMENT_LIST_GENERAL); break;
2076 			case PAGE_INSTRUMENT_LIST_PANNING: set_subpage(PAGE_INSTRUMENT_LIST_VOLUME);  break;
2077 			case PAGE_INSTRUMENT_LIST_PITCH:   set_subpage(PAGE_INSTRUMENT_LIST_PANNING); break;
2078 			case PAGE_INSTRUMENT_LIST_GENERAL: set_subpage(PAGE_INSTRUMENT_LIST_PITCH);   break;
2079 		}
2080 	} else {
2081 		switch (status.current_page) {
2082 			default:
2083 			case PAGE_INSTRUMENT_LIST_PITCH:   set_subpage(PAGE_INSTRUMENT_LIST_GENERAL); break;
2084 			case PAGE_INSTRUMENT_LIST_GENERAL: set_subpage(PAGE_INSTRUMENT_LIST_VOLUME);  break;
2085 			case PAGE_INSTRUMENT_LIST_VOLUME:  set_subpage(PAGE_INSTRUMENT_LIST_PANNING); break;
2086 			case PAGE_INSTRUMENT_LIST_PANNING: set_subpage(PAGE_INSTRUMENT_LIST_PITCH);   break;
2087 		}
2088 	}
2089 	return 1;
2090 }
instrument_list_handle_key(struct key_event * k)2091 static void instrument_list_handle_key(struct key_event * k)
2092 {
2093 	switch (k->sym) {
2094 	case SDLK_COMMA:
2095 		if (NO_MODIFIER(k->mod)) {
2096 			if (!(status.flags & CLASSIC_MODE)
2097 			&& ACTIVE_PAGE.selected_widget == 5) return;
2098 		}
2099 	case SDLK_LESS:
2100 		if (k->state == KEY_RELEASE)
2101 			return;
2102 		song_change_current_play_channel(-1, 0);
2103 		return;
2104 	case SDLK_PERIOD:
2105 		if (NO_MODIFIER(k->mod)) {
2106 			if (!(status.flags & CLASSIC_MODE)
2107 			&& ACTIVE_PAGE.selected_widget == 5) return;
2108 		}
2109 	case SDLK_GREATER:
2110 		if (k->state == KEY_RELEASE)
2111 			return;
2112 		song_change_current_play_channel(1, 0);
2113 		return;
2114 
2115 	case SDLK_PAGEUP:
2116 		if (k->state == KEY_RELEASE)
2117 			return;
2118 		instrument_set(current_instrument - 1);
2119 		break;
2120 	case SDLK_PAGEDOWN:
2121 		if (k->state == KEY_RELEASE)
2122 			return;
2123 		instrument_set(current_instrument + 1);
2124 		break;
2125 	case SDLK_ESCAPE:
2126 		if ((k->mod & KMOD_SHIFT) || instrument_cursor_pos < 25) {
2127 			if (k->state == KEY_RELEASE)
2128 				return;
2129 			instrument_cursor_pos = 25;
2130 			get_page_widgets()->accept_text = 0;
2131 			change_focus_to(0);
2132 			status.flags |= NEED_UPDATE;
2133 			return;
2134 		}
2135 		return;
2136 	default:
2137 		if (k->mod & (KMOD_ALT)) {
2138 			instrument_list_handle_alt_key(k);
2139 		} else {
2140 			int n, v;
2141 
2142 			if (k->midi_note > -1) {
2143 				n = k->midi_note;
2144 				if (k->midi_volume > -1) {
2145 					v = k->midi_volume / 2;
2146 				} else {
2147 					v = 64;
2148 				}
2149 			} else {
2150 				v = 64;
2151 				n = kbd_get_note(k);
2152 				if (n <= 0 || n > 120)
2153 					return;
2154 			}
2155 
2156 			if (k->state == KEY_RELEASE) {
2157 				song_keyup(0, current_instrument, n);
2158 				status.last_keysym = 0;
2159 			} else if (!k->is_repeat) {
2160 				song_keydown(KEYJAZZ_NOINST, current_instrument, n, v, KEYJAZZ_CHAN_CURRENT);
2161 			}
2162 			last_note = n;
2163 		}
2164 		return;
2165 	}
2166 }
2167 
2168 /* --------------------------------------------------------------------- */
2169 
set_subpage(int page)2170 static void set_subpage(int page)
2171 {
2172 	int widget = ACTIVE_PAGE.selected_widget;
2173 	int b = 1;
2174 	switch (page) {
2175 	case PAGE_INSTRUMENT_LIST_GENERAL: b = 1; break;
2176 	case PAGE_INSTRUMENT_LIST_VOLUME:  b = 2; break;
2177 	case PAGE_INSTRUMENT_LIST_PANNING: b = 3; break;
2178 	case PAGE_INSTRUMENT_LIST_PITCH:   b = 4; break;
2179 	default: return;
2180 	};
2181 	togglebutton_set(pages[page].widgets, b, 0);
2182 	set_page(page);
2183 	if (widget >= ACTIVE_PAGE.total_widgets)
2184 		widget = ACTIVE_PAGE.total_widgets - 1;
2185 	ACTIVE_PAGE.selected_widget = widget;
2186 	instrument_list_subpage = page;
2187 	status.flags |= NEED_UPDATE;
2188 }
2189 
change_subpage(void)2190 static void change_subpage(void)
2191 {
2192 	int widget = ACTIVE_PAGE.selected_widget;
2193 	int p[] = {
2194 		PAGE_INSTRUMENT_LIST_GENERAL,
2195 		PAGE_INSTRUMENT_LIST_VOLUME,
2196 		PAGE_INSTRUMENT_LIST_PANNING,
2197 		PAGE_INSTRUMENT_LIST_PITCH,
2198 	};
2199 	set_subpage(p[CLAMP(widget - 1, 0, 3)]);
2200 }
2201 
2202 /* --------------------------------------------------------------------- */
2203 /* predraw hooks... */
2204 
instrument_list_general_predraw_hook(void)2205 static void instrument_list_general_predraw_hook(void)
2206 {
2207 	song_instrument_t *ins = song_get_instrument(current_instrument);
2208 
2209 	togglebutton_set(widgets_general, 6 + (ins->nna % 4), 0);
2210 	togglebutton_set(widgets_general, 10 + (ins->dct % 4), 0);
2211 	togglebutton_set(widgets_general, 14 + (ins->dca % 3), 0);
2212 
2213 	widgets_general[17].d.textentry.text = ins->filename;
2214 }
2215 
instrument_list_volume_predraw_hook(void)2216 static void instrument_list_volume_predraw_hook(void)
2217 {
2218 	song_instrument_t *ins = song_get_instrument(current_instrument);
2219 
2220 	widgets_volume[6].d.toggle.state = !!(ins->flags & ENV_VOLUME);
2221 	widgets_volume[7].d.toggle.state = !!(ins->flags & ENV_VOLCARRY);
2222 	widgets_volume[8].d.toggle.state = !!(ins->flags & ENV_VOLLOOP);
2223 	widgets_volume[11].d.toggle.state = !!(ins->flags & ENV_VOLSUSTAIN);
2224 
2225 	/* FIXME: this is the wrong place for this.
2226 	... and it's probably not even right -- how does Impulse Tracker handle loop constraints?
2227 	See below for panning/pitch envelopes; same deal there. */
2228 	if (ins->vol_env.loop_start > ins->vol_env.loop_end)
2229 		ins->vol_env.loop_end = ins->vol_env.loop_start;
2230 	if (ins->vol_env.sustain_start > ins->vol_env.sustain_end)
2231 		ins->vol_env.sustain_end = ins->vol_env.sustain_start;
2232 
2233 	widgets_volume[9].d.numentry.max = ins->vol_env.nodes - 1;
2234 	widgets_volume[10].d.numentry.max = ins->vol_env.nodes - 1;
2235 	widgets_volume[12].d.numentry.max = ins->vol_env.nodes - 1;
2236 	widgets_volume[13].d.numentry.max = ins->vol_env.nodes - 1;
2237 
2238 	widgets_volume[9].d.numentry.value = ins->vol_env.loop_start;
2239 	widgets_volume[10].d.numentry.value = ins->vol_env.loop_end;
2240 	widgets_volume[12].d.numentry.value = ins->vol_env.sustain_start;
2241 	widgets_volume[13].d.numentry.value = ins->vol_env.sustain_end;
2242 
2243 	/* current_song hack: shifting values all over the place here, ugh */
2244 	widgets_volume[14].d.thumbbar.value = ins->global_volume;
2245 	widgets_volume[15].d.thumbbar.value = ins->fadeout >> 5;
2246 	widgets_volume[16].d.thumbbar.value = ins->vol_swing;
2247 }
2248 
instrument_list_panning_predraw_hook(void)2249 static void instrument_list_panning_predraw_hook(void)
2250 {
2251 	song_instrument_t *ins = song_get_instrument(current_instrument);
2252 
2253 	widgets_panning[6].d.toggle.state = !!(ins->flags & ENV_PANNING);
2254 	widgets_panning[7].d.toggle.state = !!(ins->flags & ENV_PANCARRY);
2255 	widgets_panning[8].d.toggle.state = !!(ins->flags & ENV_PANLOOP);
2256 	widgets_panning[11].d.toggle.state = !!(ins->flags & ENV_PANSUSTAIN);
2257 
2258 	if (ins->pan_env.loop_start > ins->pan_env.loop_end)
2259 		ins->pan_env.loop_end = ins->pan_env.loop_start;
2260 	if (ins->pan_env.sustain_start > ins->pan_env.sustain_end)
2261 		ins->pan_env.sustain_end = ins->pan_env.sustain_start;
2262 
2263 	widgets_panning[9].d.numentry.max = ins->pan_env.nodes - 1;
2264 	widgets_panning[10].d.numentry.max = ins->pan_env.nodes - 1;
2265 	widgets_panning[12].d.numentry.max = ins->pan_env.nodes - 1;
2266 	widgets_panning[13].d.numentry.max = ins->pan_env.nodes - 1;
2267 
2268 	widgets_panning[9].d.numentry.value = ins->pan_env.loop_start;
2269 	widgets_panning[10].d.numentry.value = ins->pan_env.loop_end;
2270 	widgets_panning[12].d.numentry.value = ins->pan_env.sustain_start;
2271 	widgets_panning[13].d.numentry.value = ins->pan_env.sustain_end;
2272 
2273 	widgets_panning[14].d.toggle.state = !!(ins->flags & ENV_SETPANNING);
2274 	widgets_panning[15].d.thumbbar.value = ins->panning >> 2;
2275 	/* (widgets_panning[16] is the pitch-pan center) */
2276 	widgets_panning[17].d.thumbbar.value = ins->pitch_pan_separation;
2277 	widgets_panning[18].d.thumbbar.value = ins->pan_swing;
2278 }
2279 
instrument_list_pitch_predraw_hook(void)2280 static void instrument_list_pitch_predraw_hook(void)
2281 {
2282 	song_instrument_t *ins = song_get_instrument(current_instrument);
2283 
2284 	widgets_pitch[6].d.menutoggle.state = ((ins->flags & ENV_PITCH)
2285 					     ? ((ins->flags & ENV_FILTER)
2286 						? 2 : 1) : 0);
2287 	widgets_pitch[7].d.toggle.state = !!(ins->flags & ENV_PITCHCARRY);
2288 	widgets_pitch[8].d.toggle.state = !!(ins->flags & ENV_PITCHLOOP);
2289 	widgets_pitch[11].d.toggle.state = !!(ins->flags & ENV_PITCHSUSTAIN);
2290 
2291 	if (ins->pitch_env.loop_start > ins->pitch_env.loop_end)
2292 		ins->pitch_env.loop_end = ins->pitch_env.loop_start;
2293 	if (ins->pitch_env.sustain_start > ins->pitch_env.sustain_end)
2294 		ins->pitch_env.sustain_end = ins->pitch_env.sustain_start;
2295 
2296 	widgets_pitch[9].d.numentry.max = ins->pitch_env.nodes - 1;
2297 	widgets_pitch[10].d.numentry.max = ins->pitch_env.nodes - 1;
2298 	widgets_pitch[12].d.numentry.max = ins->pitch_env.nodes - 1;
2299 	widgets_pitch[13].d.numentry.max = ins->pitch_env.nodes - 1;
2300 
2301 	widgets_pitch[9].d.numentry.value = ins->pitch_env.loop_start;
2302 	widgets_pitch[10].d.numentry.value = ins->pitch_env.loop_end;
2303 	widgets_pitch[12].d.numentry.value = ins->pitch_env.sustain_start;
2304 	widgets_pitch[13].d.numentry.value = ins->pitch_env.sustain_end;
2305 
2306 	if (ins->ifc & 0x80)
2307 		widgets_pitch[14].d.thumbbar.value = ins->ifc & 0x7f;
2308 	else
2309 		widgets_pitch[14].d.thumbbar.value = -1;
2310 	if (ins->ifr & 0x80)
2311 		widgets_pitch[15].d.thumbbar.value = ins->ifr & 0x7f;
2312 	else
2313 		widgets_pitch[15].d.thumbbar.value = -1;
2314 
2315 	/* printf("ins%02d: ch%04d pgm%04d bank%06d drum%04d\n", current_instrument,
2316 		ins->midi_channel, ins->midi_program, ins->midi_bank, ins->midi_drum_key); */
2317 	widgets_pitch[16].d.bitset.value           = ins->midi_channel_mask;
2318 	widgets_pitch[17].d.thumbbar.value = (signed char) ins->midi_program;
2319 	widgets_pitch[18].d.thumbbar.value = (signed char) (ins->midi_bank & 0xff);
2320 	widgets_pitch[19].d.thumbbar.value = (signed char) (ins->midi_bank >> 8);
2321 	/* what is midi_drum_key for? */
2322 }
2323 
2324 /* --------------------------------------------------------------------- */
2325 /* update values in song */
2326 
instrument_list_general_update_values(void)2327 static void instrument_list_general_update_values(void)
2328 {
2329 	song_instrument_t *ins = song_get_instrument(current_instrument);
2330 
2331 	status.flags |= SONG_NEEDS_SAVE;
2332 	for (ins->nna = 4; ins->nna--;)
2333 		if (widgets_general[ins->nna + 6].d.togglebutton.state)
2334 			break;
2335 	for (ins->dct = 4; ins->dct--;)
2336 		if (widgets_general[ins->dct + 10].d.togglebutton.state)
2337 			break;
2338 	for (ins->dca = 3; ins->dca--;)
2339 		if (widgets_general[ins->dca + 14].d.togglebutton.state)
2340 			break;
2341 }
2342 
update_filename(void)2343 static void update_filename(void)
2344 {
2345 	status.flags |= SONG_NEEDS_SAVE;
2346 }
2347 
2348 #define CHECK_SET(a,b,c) if (a != b) { a = b; c; }
2349 
instrument_list_volume_update_values(void)2350 static void instrument_list_volume_update_values(void)
2351 {
2352 	song_instrument_t *ins = song_get_instrument(current_instrument);
2353 
2354 	status.flags |= SONG_NEEDS_SAVE;
2355 	ins->flags &= ~(ENV_VOLUME | ENV_VOLCARRY | ENV_VOLLOOP | ENV_VOLSUSTAIN);
2356 	if (widgets_volume[6].d.toggle.state)
2357 		ins->flags |= ENV_VOLUME;
2358 	if (widgets_volume[7].d.toggle.state)
2359 		ins->flags |= ENV_VOLCARRY;
2360 	if (widgets_volume[8].d.toggle.state)
2361 		ins->flags |= ENV_VOLLOOP;
2362 	if (widgets_volume[11].d.toggle.state)
2363 		ins->flags |= ENV_VOLSUSTAIN;
2364 
2365 	CHECK_SET(ins->vol_env.loop_start, widgets_volume[9].d.numentry.value,
2366 		  ins->flags |= ENV_VOLLOOP);
2367 	CHECK_SET(ins->vol_env.loop_end, widgets_volume[10].d.numentry.value,
2368 		  ins->flags |= ENV_VOLLOOP);
2369 	CHECK_SET(ins->vol_env.sustain_start, widgets_volume[12].d.numentry.value,
2370 		  ins->flags |= ENV_VOLSUSTAIN);
2371 	CHECK_SET(ins->vol_env.sustain_end, widgets_volume[13].d.numentry.value,
2372 		  ins->flags |= ENV_VOLSUSTAIN);
2373 
2374 	/* more ugly shifts */
2375 	ins->global_volume = widgets_volume[14].d.thumbbar.value;
2376 	ins->fadeout = widgets_volume[15].d.thumbbar.value << 5;
2377 	ins->vol_swing = widgets_volume[16].d.thumbbar.value;
2378 
2379 	song_update_playing_instrument(current_instrument);
2380 }
2381 
instrument_list_panning_update_values(void)2382 static void instrument_list_panning_update_values(void)
2383 {
2384 	song_instrument_t *ins = song_get_instrument(current_instrument);
2385 	int n;
2386 
2387 	status.flags |= SONG_NEEDS_SAVE;
2388 	ins->flags &= ~(ENV_PANNING | ENV_PANCARRY | ENV_PANLOOP | ENV_PANSUSTAIN | ENV_SETPANNING);
2389 	if (widgets_panning[6].d.toggle.state)
2390 		ins->flags |= ENV_PANNING;
2391 	if (widgets_panning[7].d.toggle.state)
2392 		ins->flags |= ENV_PANCARRY;
2393 	if (widgets_panning[8].d.toggle.state)
2394 		ins->flags |= ENV_PANLOOP;
2395 	if (widgets_panning[11].d.toggle.state)
2396 		ins->flags |= ENV_PANSUSTAIN;
2397 	if (widgets_panning[14].d.toggle.state)
2398 		ins->flags |= ENV_SETPANNING;
2399 
2400 	CHECK_SET(ins->pan_env.loop_start, widgets_panning[9].d.numentry.value,
2401 		  ins->flags |= ENV_PANLOOP);
2402 	CHECK_SET(ins->pan_env.loop_end, widgets_panning[10].d.numentry.value,
2403 		  ins->flags |= ENV_PANLOOP);
2404 	CHECK_SET(ins->pan_env.sustain_start, widgets_panning[12].d.numentry.value,
2405 		  ins->flags |= ENV_PANSUSTAIN);
2406 	CHECK_SET(ins->pan_env.sustain_end, widgets_panning[13].d.numentry.value,
2407 		  ins->flags |= ENV_PANSUSTAIN);
2408 
2409 	n = widgets_panning[15].d.thumbbar.value << 2;
2410 	if (ins->panning != (unsigned int)n) {
2411 		ins->panning = (unsigned int)n;
2412 		ins->flags |= ENV_SETPANNING;
2413 	}
2414 	/* (widgets_panning[16] is the pitch-pan center) */
2415 	ins->pitch_pan_separation = widgets_panning[17].d.thumbbar.value;
2416 	ins->pan_swing = widgets_panning[18].d.thumbbar.value;
2417 
2418 	song_update_playing_instrument(current_instrument);
2419 }
2420 
instrument_list_pitch_update_values(void)2421 static void instrument_list_pitch_update_values(void)
2422 {
2423 	song_instrument_t *ins = song_get_instrument(current_instrument);
2424 
2425 	status.flags |= SONG_NEEDS_SAVE;
2426 	ins->flags &= ~(ENV_PITCH | ENV_PITCHCARRY | ENV_PITCHLOOP | ENV_PITCHSUSTAIN | ENV_FILTER);
2427 
2428 	switch (widgets_pitch[6].d.menutoggle.state) {
2429 	case 2: ins->flags |= ENV_FILTER;
2430 	case 1: ins->flags |= ENV_PITCH;
2431 	}
2432 
2433 	if (widgets_pitch[6].d.menutoggle.state)
2434 		ins->flags |= ENV_PITCH;
2435 	if (widgets_pitch[7].d.toggle.state)
2436 		ins->flags |= ENV_PITCHCARRY;
2437 	if (widgets_pitch[8].d.toggle.state)
2438 		ins->flags |= ENV_PITCHLOOP;
2439 	if (widgets_pitch[11].d.toggle.state)
2440 		ins->flags |= ENV_PITCHSUSTAIN;
2441 
2442 	CHECK_SET(ins->pitch_env.loop_start, widgets_pitch[9].d.numentry.value,
2443 		  ins->flags |= ENV_PITCHLOOP);
2444 	CHECK_SET(ins->pitch_env.loop_end, widgets_pitch[10].d.numentry.value,
2445 		  ins->flags |= ENV_PITCHLOOP);
2446 	CHECK_SET(ins->pitch_env.sustain_start, widgets_pitch[12].d.numentry.value,
2447 		  ins->flags |= ENV_PITCHSUSTAIN);
2448 	CHECK_SET(ins->pitch_env.sustain_end, widgets_pitch[13].d.numentry.value,
2449 		  ins->flags |= ENV_PITCHSUSTAIN);
2450 	if (widgets_pitch[14].d.thumbbar.value > -1) {
2451 		ins->ifc = widgets_pitch[14].d.thumbbar.value | 0x80;
2452 	} else {
2453 		ins->ifc = 0x7f;
2454 	}
2455 	if (widgets_pitch[15].d.thumbbar.value > -1) {
2456 		ins->ifr = widgets_pitch[15].d.thumbbar.value | 0x80;
2457 	} else {
2458 		ins->ifr = 0x7f;
2459 	}
2460 	ins->midi_channel_mask = widgets_pitch[16].d.bitset.value;
2461 	ins->midi_program = widgets_pitch[17].d.thumbbar.value;
2462 	ins->midi_bank = ((widgets_pitch[19].d.thumbbar.value << 8)
2463 			  | (widgets_pitch[18].d.thumbbar.value & 0xff));
2464 
2465 	song_update_playing_instrument(current_instrument);
2466 }
2467 
2468 /* --------------------------------------------------------------------- */
2469 /* draw_const functions */
2470 
instrument_list_draw_const(void)2471 static void instrument_list_draw_const(void)
2472 {
2473 	draw_box(4, 12, 30, 48, BOX_THICK | BOX_INNER | BOX_INSET);
2474 }
2475 
instrument_list_general_draw_const(void)2476 static void instrument_list_general_draw_const(void)
2477 {
2478 	int n;
2479 
2480 	instrument_list_draw_const();
2481 
2482 	draw_box(31, 15, 42, 48, BOX_THICK | BOX_INNER | BOX_INSET);
2483 
2484 	/* Kind of a hack, and not really useful, but... :) */
2485 	if (status.flags & CLASSIC_MODE) {
2486 		draw_box(55, 46, 73, 48, BOX_THICK | BOX_INNER | BOX_INSET);
2487 		draw_text("    ", 69, 47, 1, 0);
2488 	} else {
2489 		draw_box(55, 46, 69, 48, BOX_THICK | BOX_INNER | BOX_INSET);
2490 	}
2491 
2492 	draw_text("New Note Action", 54, 17, 0, 2);
2493 	draw_text("Duplicate Check Type & Action", 47, 32, 0, 2);
2494 	draw_text("Filename", 47, 47, 0, 2);
2495 
2496 	for (n = 0; n < 35; n++) {
2497 		draw_char(134, 44 + n, 15, 0, 2);
2498 		draw_char(134, 44 + n, 30, 0, 2);
2499 		draw_char(154, 44 + n, 45, 0, 2);
2500 	}
2501 }
2502 
instrument_list_volume_draw_const(void)2503 static void instrument_list_volume_draw_const(void)
2504 {
2505 	instrument_list_draw_const();
2506 
2507 	draw_fill_chars(57, 28, 62, 29, 0);
2508 	draw_fill_chars(57, 32, 62, 34, 0);
2509 	draw_fill_chars(57, 37, 62, 39, 0);
2510 
2511 	draw_box(31, 17, 77, 26, BOX_THICK | BOX_INNER | BOX_INSET);
2512 	draw_box(53, 27, 63, 30, BOX_THICK | BOX_INNER | BOX_INSET);
2513 	draw_box(53, 31, 63, 35, BOX_THICK | BOX_INNER | BOX_INSET);
2514 	draw_box(53, 36, 63, 40, BOX_THICK | BOX_INNER | BOX_INSET);
2515 	draw_box(53, 41, 71, 44, BOX_THICK | BOX_INNER | BOX_INSET);
2516 	draw_box(53, 45, 71, 47, BOX_THICK | BOX_INNER | BOX_INSET);
2517 
2518 	draw_text("Volume Envelope", 38, 28, 0, 2);
2519 	draw_text("Carry", 48, 29, 0, 2);
2520 	draw_text("Envelope Loop", 40, 32, 0, 2);
2521 	draw_text("Loop Begin", 43, 33, 0, 2);
2522 	draw_text("Loop End", 45, 34, 0, 2);
2523 	draw_text("Sustain Loop", 41, 37, 0, 2);
2524 	draw_text("SusLoop Begin", 40, 38, 0, 2);
2525 	draw_text("SusLoop End", 42, 39, 0, 2);
2526 	draw_text("Global Volume", 40, 42, 0, 2);
2527 	draw_text("Fadeout", 46, 43, 0, 2);
2528 	draw_text("Volume Swing %", 39, 46, 0, 2);
2529 }
2530 
instrument_list_panning_draw_const(void)2531 static void instrument_list_panning_draw_const(void)
2532 {
2533 	instrument_list_draw_const();
2534 
2535 	draw_fill_chars(57, 28, 62, 29, 0);
2536 	draw_fill_chars(57, 32, 62, 34, 0);
2537 	draw_fill_chars(57, 37, 62, 39, 0);
2538 	draw_fill_chars(57, 42, 62, 45, 0);
2539 
2540 	draw_box(31, 17, 77, 26, BOX_THICK | BOX_INNER | BOX_INSET);
2541 	draw_box(53, 27, 63, 30, BOX_THICK | BOX_INNER | BOX_INSET);
2542 	draw_box(53, 31, 63, 35, BOX_THICK | BOX_INNER | BOX_INSET);
2543 	draw_box(53, 36, 63, 40, BOX_THICK | BOX_INNER | BOX_INSET);
2544 	draw_box(53, 41, 63, 48, BOX_THICK | BOX_INNER | BOX_INSET);
2545 
2546 	draw_text("Panning Envelope", 37, 28, 0, 2);
2547 	draw_text("Carry", 48, 29, 0, 2);
2548 	draw_text("Envelope Loop", 40, 32, 0, 2);
2549 	draw_text("Loop Begin", 43, 33, 0, 2);
2550 	draw_text("Loop End", 45, 34, 0, 2);
2551 	draw_text("Sustain Loop", 41, 37, 0, 2);
2552 	draw_text("SusLoop Begin", 40, 38, 0, 2);
2553 	draw_text("SusLoop End", 42, 39, 0, 2);
2554 	draw_text("Default Pan", 42, 42, 0, 2);
2555 	draw_text("Pan Value", 44, 43, 0, 2);
2556 	draw_text("Pitch-Pan Center", 37, 45, 0, 2);
2557 	draw_text("Pitch-Pan Separation", 33, 46, 0, 2);
2558 	if (status.flags & CLASSIC_MODE) {
2559 		/* Hmm. The 's' in swing isn't capitalised. ;) */
2560 		draw_text("Pan swing", 44, 47, 0, 2);
2561 	} else {
2562 		draw_text("Pan Swing", 44, 47, 0, 2);
2563 	}
2564 
2565 	draw_text("\x9a\x9a\x9a\x9a\x9a\x9a\x9a\x9a\x9a", 54, 44, 2, 0);
2566 }
2567 
instrument_list_pitch_draw_const(void)2568 static void instrument_list_pitch_draw_const(void)
2569 {
2570 	instrument_list_draw_const();
2571 
2572 	draw_fill_chars(57, 28, 62, 29, 0);
2573 	draw_fill_chars(57, 32, 62, 34, 0);
2574 	draw_fill_chars(57, 37, 62, 39, 0);
2575 
2576 	draw_box(31, 17, 77, 26, BOX_THICK | BOX_INNER | BOX_INSET);
2577 	draw_box(53, 27, 63, 30, BOX_THICK | BOX_INNER | BOX_INSET);
2578 	draw_box(53, 31, 63, 35, BOX_THICK | BOX_INNER | BOX_INSET);
2579 	draw_box(53, 36, 63, 40, BOX_THICK | BOX_INNER | BOX_INSET);
2580 	draw_box(53, 41, 71, 48, BOX_THICK | BOX_INNER | BOX_INSET);
2581 
2582 	draw_text("Frequency Envelope", 35, 28, 0, 2);
2583 	draw_text("Carry", 48, 29, 0, 2);
2584 	draw_text("Envelope Loop", 40, 32, 0, 2);
2585 	draw_text("Loop Begin", 43, 33, 0, 2);
2586 	draw_text("Loop End", 45, 34, 0, 2);
2587 	draw_text("Sustain Loop", 41, 37, 0, 2);
2588 	draw_text("SusLoop Begin", 40, 38, 0, 2);
2589 	draw_text("SusLoop End", 42, 39, 0, 2);
2590 	draw_text("Default Cutoff", 36, 42, 0, 2);
2591 	draw_text("Default Resonance", 36, 43, 0, 2);
2592 	draw_text("MIDI Channels", 36, 44, 0, 2);
2593 	draw_text("MIDI Program", 36, 45, 0, 2);
2594 	draw_text("MIDI Bank Low", 36, 46, 0, 2);
2595 	draw_text("MIDI Bank High", 36, 47, 0, 2);
2596 }
2597 
2598 /* --------------------------------------------------------------------- */
2599 /* load_page functions */
2600 
_load_page_common(struct page * page,struct widget * page_widgets)2601 static void _load_page_common(struct page *page, struct widget *page_widgets)
2602 {
2603 	int i;
2604 
2605 	memset(saved_env, 0, sizeof(saved_env));
2606 	for (i = 0; i < 10; i++) {
2607 		saved_env[i].nodes = 2;
2608 		saved_env[i].ticks[0] = 0;
2609 		saved_env[i].ticks[1] = 100;
2610 		saved_env[i].values[0] = 32;
2611 		saved_env[i].values[1] = 32;
2612 	}
2613 	vgamem_ovl_alloc(&env_overlay);
2614 
2615 	page->title = "Instrument List (F4)";
2616 	page->pre_handle_key = instrument_list_pre_handle_key;
2617 	page->handle_key = instrument_list_handle_key;
2618 	page->widgets = page_widgets;
2619 	page->help_index = HELP_INSTRUMENT_LIST;
2620 	page->set_page = instrument_list_reposition;
2621 
2622 	/* the first five widgets are the same for all four pages. */
2623 
2624 	/* 0 = instrument list */
2625 	create_other(page_widgets + 0, 1, instrument_list_handle_key_on_list, instrument_list_draw_list);
2626 	page_widgets[0].accept_text = (instrument_cursor_pos == 25 ? 0 : 1);
2627 	page_widgets[0].x = 5;
2628 	page_widgets[0].y = 13;
2629 	page_widgets[0].width = 24;
2630 	page_widgets[0].height = 34;
2631 
2632 	/* 1-4 = subpage switches */
2633 	create_togglebutton(page_widgets + 1, 32, 13, 7, 1, 5, 0, 2, 2, change_subpage, "General",
2634 			    1, subpage_switches_group);
2635 	create_togglebutton(page_widgets + 2, 44, 13, 7, 2, 5, 1, 3, 3, change_subpage, "Volume",
2636 			    1, subpage_switches_group);
2637 	create_togglebutton(page_widgets + 3, 56, 13, 7, 3, 5, 2, 4, 4, change_subpage, "Panning",
2638 			    1, subpage_switches_group);
2639 	create_togglebutton(page_widgets + 4, 68, 13, 7, 4, 5, 3, 0, 0, change_subpage, "Pitch",
2640 			    2, subpage_switches_group);
2641 }
2642 
instrument_list_general_load_page(struct page * page)2643 void instrument_list_general_load_page(struct page *page)
2644 {
2645 	_load_page_common(page, widgets_general);
2646 
2647 	page->draw_const = instrument_list_general_draw_const;
2648 	page->predraw_hook = instrument_list_general_predraw_hook;
2649 	page->total_widgets = 18;
2650 
2651 	/* special case stuff */
2652 	widgets_general[1].d.togglebutton.state = 1;
2653 	widgets_general[2].next.down = widgets_general[3].next.down = widgets_general[4].next.down = 6;
2654 
2655 	/* 5 = note trans table */
2656 	create_other(widgets_general + 5, 6, note_trans_handle_key, note_trans_draw);
2657 	widgets_general[5].x = 32;
2658 	widgets_general[5].y = 16;
2659 	widgets_general[5].width = 9;
2660 	widgets_general[5].height = 31;
2661 
2662 	/* 6-9 = nna toggles */
2663 	create_togglebutton(widgets_general + 6, 46, 19, 29, 2, 7, 5, 0, 0,
2664 			    instrument_list_general_update_values,
2665 			    "Note Cut", 2, nna_group);
2666 	create_togglebutton(widgets_general + 7, 46, 22, 29, 6, 8, 5, 0, 0,
2667 			    instrument_list_general_update_values,
2668 			    "Continue", 2, nna_group);
2669 	create_togglebutton(widgets_general + 8, 46, 25, 29, 7, 9, 5, 0, 0,
2670 			    instrument_list_general_update_values,
2671 			    "Note Off", 2, nna_group);
2672 	create_togglebutton(widgets_general + 9, 46, 28, 29, 8, 10, 5, 0, 0,
2673 			    instrument_list_general_update_values,
2674 			    "Note Fade", 2, nna_group);
2675 
2676 	/* 10-13 = dct toggles */
2677 	create_togglebutton(widgets_general + 10, 46, 34, 12, 9, 11, 5, 14,
2678 			    14, instrument_list_general_update_values,
2679 			    "Disabled", 2, dct_group);
2680 	create_togglebutton(widgets_general + 11, 46, 37, 12, 10, 12, 5, 15,
2681 			    15, instrument_list_general_update_values,
2682 			    "Note", 2, dct_group);
2683 	create_togglebutton(widgets_general + 12, 46, 40, 12, 11, 13, 5, 16,
2684 			    16, instrument_list_general_update_values,
2685 			    "Sample", 2, dct_group);
2686 	create_togglebutton(widgets_general + 13, 46, 43, 12, 12, 17, 5, 13,
2687 			    13, instrument_list_general_update_values,
2688 			    "Instrument", 2, dct_group);
2689 	/* 14-16 = dca toggles */
2690 	create_togglebutton(widgets_general + 14, 62, 34, 13, 9, 15, 10, 0,
2691 			    0, instrument_list_general_update_values,
2692 			    "Note Cut", 2, dca_group);
2693 	create_togglebutton(widgets_general + 15, 62, 37, 13, 14, 16, 11, 0,
2694 			    0, instrument_list_general_update_values,
2695 			    "Note Off", 2, dca_group);
2696 	create_togglebutton(widgets_general + 16, 62, 40, 13, 15, 17, 12, 0,
2697 			    0, instrument_list_general_update_values,
2698 			    "Note Fade", 2, dca_group);
2699 	/* 17 = filename */
2700 	/* impulse tracker has a 17-char-wide box for the filename for
2701 	 * some reason, though it still limits the actual text to 12
2702 	 * characters. go figure... */
2703 	create_textentry(widgets_general + 17, 56, 47, 13, 13, 17, 0, update_filename,
2704 			 NULL, 12);
2705 }
2706 
_fixup_mouse_instpage_volume(struct key_event * k)2707 static int _fixup_mouse_instpage_volume(struct key_event *k)
2708 {
2709 	song_instrument_t *ins = song_get_instrument(current_instrument);
2710 	if (envelope_mouse_edit && ins) {
2711 		if (_env_handle_mouse(k, &ins->vol_env, &current_node_vol)) {
2712 			ins->flags |= ENV_VOLUME;
2713 			return 1;
2714 		}
2715 	}
2716 	if ((k->sym == SDLK_l || k->sym == SDLK_b) && (k->mod & KMOD_ALT)) {
2717 		return _env_handle_key_viewmode(k, &ins->vol_env, &current_node_vol, ENV_VOLUME);
2718 	}
2719 	return instrument_list_pre_handle_key(k);
2720 }
2721 
instrument_list_volume_load_page(struct page * page)2722 void instrument_list_volume_load_page(struct page *page)
2723 {
2724 	_load_page_common(page, widgets_volume);
2725 
2726 	page->pre_handle_key = _fixup_mouse_instpage_volume;
2727 	page->draw_const = instrument_list_volume_draw_const;
2728 	page->predraw_hook = instrument_list_volume_predraw_hook;
2729 	page->total_widgets = 17;
2730 
2731 	/* 5 = volume envelope */
2732 	create_other(widgets_volume + 5, 0, volume_envelope_handle_key, volume_envelope_draw);
2733 	widgets_volume[5].x = 32;
2734 	widgets_volume[5].y = 18;
2735 	widgets_volume[5].width = 45;
2736 	widgets_volume[5].height = 8;
2737 
2738 	/* 6-7 = envelope switches */
2739 	create_toggle(widgets_volume + 6, 54, 28, 5, 7, 0, 0, 0,
2740 		      instrument_list_volume_update_values);
2741 	create_toggle(widgets_volume + 7, 54, 29, 6, 8, 0, 0, 0,
2742 		      instrument_list_volume_update_values);
2743 
2744 	/* 8-10 envelope loop settings */
2745 	create_toggle(widgets_volume + 8, 54, 32, 7, 9, 0, 0, 0,
2746 		      instrument_list_volume_update_values);
2747 	create_numentry(widgets_volume + 9, 54, 33, 3, 8, 10, 0,
2748 			instrument_list_volume_update_values, 0, 1,
2749 			numentry_cursor_pos + 0);
2750 	create_numentry(widgets_volume + 10, 54, 34, 3, 9, 11, 0,
2751 			instrument_list_volume_update_values, 0, 1,
2752 			numentry_cursor_pos + 0);
2753 
2754 	/* 11-13 = susloop settings */
2755 	create_toggle(widgets_volume + 11, 54, 37, 10, 12, 0, 0, 0,
2756 		      instrument_list_volume_update_values);
2757 	create_numentry(widgets_volume + 12, 54, 38, 3, 11, 13, 0,
2758 			instrument_list_volume_update_values, 0, 1,
2759 			numentry_cursor_pos + 0);
2760 	create_numentry(widgets_volume + 13, 54, 39, 3, 12, 14, 0,
2761 			instrument_list_volume_update_values, 0, 1,
2762 			numentry_cursor_pos + 0);
2763 
2764 	/* 14-16 = volume thumbbars */
2765 	create_thumbbar(widgets_volume + 14, 54, 42, 17, 13, 15, 0,
2766 			instrument_list_volume_update_values, 0, 128);
2767 	create_thumbbar(widgets_volume + 15, 54, 43, 17, 14, 16, 0,
2768 			instrument_list_volume_update_values, 0, 256);
2769 	create_thumbbar(widgets_volume + 16, 54, 46, 17, 15, 16, 0,
2770 			instrument_list_volume_update_values, 0, 100);
2771 }
2772 
_fixup_mouse_instpage_panning(struct key_event * k)2773 static int _fixup_mouse_instpage_panning(struct key_event *k)
2774 {
2775 	song_instrument_t *ins = song_get_instrument(current_instrument);
2776 	if (envelope_mouse_edit && ins) {
2777 		if (_env_handle_mouse(k, &ins->pan_env, &current_node_pan)) {
2778 			ins->flags |= ENV_PANNING;
2779 			return 1;
2780 		}
2781 	}
2782 	if ((k->sym == SDLK_l || k->sym == SDLK_b) && (k->mod & KMOD_ALT)) {
2783 		return _env_handle_key_viewmode(k, &ins->pan_env, &current_node_pan, ENV_PANNING);
2784 	}
2785 	return instrument_list_pre_handle_key(k);
2786 }
instrument_list_panning_load_page(struct page * page)2787 void instrument_list_panning_load_page(struct page *page)
2788 {
2789 	_load_page_common(page, widgets_panning);
2790 
2791 	page->pre_handle_key = _fixup_mouse_instpage_panning;
2792 	page->draw_const = instrument_list_panning_draw_const;
2793 	page->predraw_hook = instrument_list_panning_predraw_hook;
2794 	page->total_widgets = 19;
2795 
2796 	/* 5 = panning envelope */
2797 	create_other(widgets_panning + 5, 0, panning_envelope_handle_key, panning_envelope_draw);
2798 	widgets_panning[5].x = 32;
2799 	widgets_panning[5].y = 18;
2800 	widgets_panning[5].width = 45;
2801 	widgets_panning[5].height = 8;
2802 
2803 	/* 6-7 = envelope switches */
2804 	create_toggle(widgets_panning + 6, 54, 28, 5, 7, 0, 0, 0,
2805 		      instrument_list_panning_update_values);
2806 	create_toggle(widgets_panning + 7, 54, 29, 6, 8, 0, 0, 0,
2807 		      instrument_list_panning_update_values);
2808 
2809 	/* 8-10 envelope loop settings */
2810 	create_toggle(widgets_panning + 8, 54, 32, 7, 9, 0, 0, 0,
2811 		      instrument_list_panning_update_values);
2812 	create_numentry(widgets_panning + 9, 54, 33, 3, 8, 10, 0,
2813 			instrument_list_panning_update_values, 0, 1,
2814 			numentry_cursor_pos + 1);
2815 	create_numentry(widgets_panning + 10, 54, 34, 3, 9, 11, 0,
2816 			instrument_list_panning_update_values, 0, 1,
2817 			numentry_cursor_pos + 1);
2818 
2819 	/* 11-13 = susloop settings */
2820 	create_toggle(widgets_panning + 11, 54, 37, 10, 12, 0, 0, 0,
2821 		      instrument_list_panning_update_values);
2822 	create_numentry(widgets_panning + 12, 54, 38, 3, 11, 13, 0,
2823 			instrument_list_panning_update_values, 0, 1,
2824 			numentry_cursor_pos + 1);
2825 	create_numentry(widgets_panning + 13, 54, 39, 3, 12, 14, 0,
2826 			instrument_list_panning_update_values, 0, 1,
2827 			numentry_cursor_pos + 1);
2828 
2829 	/* 14-15 = default panning */
2830 	create_toggle(widgets_panning + 14, 54, 42, 13, 15, 0, 0, 0,
2831 		      instrument_list_panning_update_values);
2832 	create_thumbbar(widgets_panning + 15, 54, 43, 9, 14, 16, 0,
2833 			instrument_list_panning_update_values, 0, 64);
2834 
2835 	/* 16 = pitch-pan center */
2836 	create_other(widgets_panning + 16, 0, pitch_pan_center_handle_key, pitch_pan_center_draw);
2837 	widgets_panning[16].next.up = 15;
2838 	widgets_panning[16].next.down = 17;
2839 
2840 	/* 17-18 = other panning stuff */
2841 	create_thumbbar(widgets_panning + 17, 54, 46, 9, 16, 18, 0,
2842 			instrument_list_panning_update_values, -32, 32);
2843 	create_thumbbar(widgets_panning + 18, 54, 47, 9, 17, 18, 0,
2844 			instrument_list_panning_update_values, 0, 64);
2845 }
2846 
_fixup_mouse_instpage_pitch(struct key_event * k)2847 static int _fixup_mouse_instpage_pitch(struct key_event *k)
2848 {
2849 	song_instrument_t *ins = song_get_instrument(current_instrument);
2850 	if (envelope_mouse_edit && ins) {
2851 		if (_env_handle_mouse(k, &ins->pitch_env, &current_node_pitch)) {
2852 			ins->flags |= ENV_PITCH;
2853 			return 1;
2854 		}
2855 	}
2856 	if ((k->sym == SDLK_l || k->sym == SDLK_b) && (k->mod & KMOD_ALT)) {
2857 		return _env_handle_key_viewmode(k, &ins->pitch_env, &current_node_pitch, ENV_PITCH);
2858 	}
2859 	return instrument_list_pre_handle_key(k);
2860 }
instrument_list_pitch_load_page(struct page * page)2861 void instrument_list_pitch_load_page(struct page *page)
2862 {
2863 	static int midi_channel_selection_cursor_position = 0;
2864 
2865 	_load_page_common(page, widgets_pitch);
2866 
2867 	page->pre_handle_key = _fixup_mouse_instpage_pitch;
2868 	page->draw_const = instrument_list_pitch_draw_const;
2869 	page->predraw_hook = instrument_list_pitch_predraw_hook;
2870 	page->total_widgets = 20;
2871 
2872 	/* 5 = pitch envelope */
2873 	create_other(widgets_pitch + 5, 0, pitch_envelope_handle_key, pitch_envelope_draw);
2874 	widgets_pitch[5].x = 32;
2875 	widgets_pitch[5].y = 18;
2876 	widgets_pitch[5].width = 45;
2877 	widgets_pitch[5].height = 8;
2878 
2879 	/* 6-7 = envelope switches */
2880 	create_menutoggle(widgets_pitch + 6, 54, 28, 5, 7, 0, 0, 0,
2881 		      instrument_list_pitch_update_values, pitch_envelope_states);
2882 	create_toggle(widgets_pitch + 7, 54, 29, 6, 8, 0, 0, 0,
2883 		      instrument_list_pitch_update_values);
2884 
2885 	/* 8-10 envelope loop settings */
2886 	create_toggle(widgets_pitch + 8, 54, 32, 7, 9, 0, 0, 0,
2887 		      instrument_list_pitch_update_values);
2888 	create_numentry(widgets_pitch + 9, 54, 33, 3, 8, 10, 0,
2889 			instrument_list_pitch_update_values, 0, 1,
2890 			numentry_cursor_pos + 2);
2891 	create_numentry(widgets_pitch + 10, 54, 34, 3, 9, 11, 0,
2892 			instrument_list_pitch_update_values, 0, 1,
2893 			numentry_cursor_pos + 2);
2894 
2895 	/* 11-13 = susloop settings */
2896 	create_toggle(widgets_pitch + 11, 54, 37, 10, 12, 0, 0, 0,
2897 		      instrument_list_pitch_update_values);
2898 	create_numentry(widgets_pitch + 12, 54, 38, 3, 11, 13, 0,
2899 			instrument_list_pitch_update_values, 0, 1,
2900 			numentry_cursor_pos + 2);
2901 	create_numentry(widgets_pitch + 13, 54, 39, 3, 12, 14, 0,
2902 			instrument_list_pitch_update_values, 0, 1,
2903 			numentry_cursor_pos + 2);
2904 
2905 	/* 14-15 = filter cutoff/resonance */
2906 	create_thumbbar(widgets_pitch + 14, 54, 42, 17, 13, 15, 0,
2907 			instrument_list_pitch_update_values, -1, 127);
2908 	create_thumbbar(widgets_pitch + 15, 54, 43, 17, 14, 16, 0,
2909 			instrument_list_pitch_update_values, -1, 127);
2910 	widgets_pitch[14].d.thumbbar.text_at_min = "Off";
2911 	widgets_pitch[15].d.thumbbar.text_at_min = "Off";
2912 
2913 	/* 16-19 = midi crap */
2914 	create_bitset(widgets_pitch + 16, 54, 44, 17, 15, 17, 0,
2915 			instrument_list_pitch_update_values,
2916 			17,
2917 			" 1 2 3 4 5 6 7 8 9P\0""111213141516M\0",
2918 			".\0.\0.\0.\0.\0.\0.\0.\0.\0p\0.\0.\0.\0.\0.\0.\0m\0",
2919 			&midi_channel_selection_cursor_position
2920 			);
2921 	widgets_pitch[16].d.bitset.activation_keys =
2922 		"123456789pabcdefm";
2923 
2924 	create_thumbbar(widgets_pitch + 17, 54, 45, 17, 16, 18, 0,
2925 			instrument_list_pitch_update_values, -1, 127);
2926 	create_thumbbar(widgets_pitch + 18, 54, 46, 17, 17, 19, 0,
2927 			instrument_list_pitch_update_values, -1, 127);
2928 	create_thumbbar(widgets_pitch + 19, 54, 47, 17, 18, 19, 0,
2929 			instrument_list_pitch_update_values, -1, 127);
2930 	widgets_pitch[17].d.thumbbar.text_at_min = "Off";
2931 	widgets_pitch[18].d.thumbbar.text_at_min = "Off";
2932 	widgets_pitch[19].d.thumbbar.text_at_min = "Off";
2933 }
2934 
2935