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 header has all the page definitions, the kinds of interactive
25  * widgets on each page, etc. Since this information isn't useful outside
26  * page*.c, it's not in the main header. */
27 
28 #ifndef PAGE_H
29 #define PAGE_H
30 
31 /* How much to scroll. */
32 #define MOUSE_SCROLL_LINES       3
33 
34 struct key_event {
35 	SDLKey sym, orig_sym;
36 	SDLMod mod;
37 	uint16_t unicode;
38 	int scancode;
39 
40 	enum { KEY_PRESS=0, KEY_RELEASE } state;
41 	enum { MOUSE_NONE=0, MOUSE_CLICK, MOUSE_SCROLL_UP, MOUSE_SCROLL_DOWN, MOUSE_DBLCLICK } mouse;
42 	enum { MOUSE_BUTTON_LEFT=0, MOUSE_BUTTON_MIDDLE, MOUSE_BUTTON_RIGHT } mouse_button;
43 	int midi_note;
44 	int midi_channel;
45 	int midi_volume; /* -1 for not a midi key otherwise 0...128 */
46 	int midi_bend;  /* normally 0; -8192 to +8192  */
47 	unsigned int sx, sy; /* start x and y position (character) */
48 	unsigned int x, hx, fx; /* x position of mouse (character, halfcharacter, fine) */
49 	unsigned int y, fy; /* y position of mouse (character, fine) */
50 
51 	unsigned int rx, ry; /* x/y resolution */
52 
53 	int is_repeat;
54 	int on_target;
55 	int is_synthetic; /* 1 came from paste */
56 };
57 
58 /* --------------------------------------------------------------------- */
59 /* help text */
60 
61 /* NOTE: this enum should be in the same order as helptexts in Makefile.am */
62 enum {
63 	HELP_GLOBAL, /* needs to be first! */
64 	HELP_COPYRIGHT,
65 	HELP_INFO_PAGE,
66 	HELP_INSTRUMENT_LIST,
67 	HELP_MESSAGE_EDITOR,
68 	HELP_MIDI_OUTPUT,
69 	HELP_ORDERLIST_PANNING,
70 	HELP_ORDERLIST_VOLUME,
71 	HELP_PATTERN_EDITOR,
72 	HELP_ADLIB_SAMPLE,
73 	HELP_SAMPLE_LIST,
74 
75 	HELP_NUM_ITEMS /* needs to be last! */
76 };
77 
78 extern const char *help_text[HELP_NUM_ITEMS];
79 
80 /* --------------------------------------------------------------------- */
81 /* there's a value in this enum for each kind of widget... */
82 
83 enum widget_type {
84 	WIDGET_TOGGLE, WIDGET_MENUTOGGLE,
85 	WIDGET_BUTTON, WIDGET_TOGGLEBUTTON,
86 	WIDGET_TEXTENTRY,
87 	WIDGET_NUMENTRY, WIDGET_THUMBBAR, WIDGET_BITSET, WIDGET_PANBAR,
88 	/* this last one is for anything that doesn't fit some standard
89 	type, like the sample list, envelope editor, etc.; a widget of
90 	this type is just a placeholder so page.c knows there's
91 	something going on. */
92 	WIDGET_OTHER      /* sample list, envelopes, etc. */
93 };
94 
95 /* --------------------------------------------------------------------- */
96 /* every widget in the enum has a corresponding struct here. the notes
97  * before each widget indicate what keypresses are trapped in page.c for
98  * it, and what happens.
99  * note that all widget types (except WIDGET_OTHER) trap the enter key for the
100  * activate callback. */
101 
102 /* space -> state changed; cb triggered */
103 struct widget_toggle {
104 	int state;      /* 0 = off, 1 = on */
105 };
106 
107 /* space -> state changed; cb triggered */
108 struct widget_menutoggle {
109 	int state;      /* 0, 1, ..., num_choices - 1, num_choices */
110 	const char *const *choices;
111 	int num_choices;
112 	const char *activation_keys;
113 };
114 
115 /* enter -> cb triggered */
116 struct widget_button {
117 	const char *text;
118 	int padding;
119 };
120 
121 /* enter -> state changed; cb triggered */
122 struct widget_togglebutton {
123 	const char *text;
124 	int padding;
125 	int state;      /* 0 = off, 1 = on */
126 	const int *group;
127 };
128 
129 /* backspace -> truncated; changed cb triggered
130  * ctrl-bs -> cleared; changed cb triggered
131  * <any ascii char> -> appended; changed cb triggered
132  * (the callback isn't triggered unless something really changed)
133  * left/right -> cursor_pos changed; no cb triggered
134  *
135  * - if (max_length > (width - 1)) the text scrolls
136  * - cursor_pos is set to the end of the text when the widget is focused */
137 struct widget_textentry {
138 	char *text;
139 	int max_length;
140 	int firstchar;  /* first visible character (generally 0) */
141 	int cursor_pos; /* 0 = first character */
142 };
143 
144 /* <0-9> -> digit @ cursor_pos changed; cursor_pos increased; cb triggered
145  * left/right -> cursor_pos changed; cb NOT triggered.
146  * +/- -> value increased/decreased; cb triggered
147  * cursor_pos for this widget is a pointer so that multiple numbers that
148  * are all lined up can share the same position. */
149 struct widget_numentry {
150 	int min;
151 	int max;
152 	int value;
153 	int *cursor_pos;
154 	int (*handle_unknown_key)(struct key_event *k);
155 	int reverse;
156 };
157 
158 /* left/right -> value changed; cb triggered
159  * ctrl-left/right -> value changed 4x; cb triggered
160  * shift-left/right -> value changed 2x; cb triggered
161  * home/end -> value set to min/max; cb triggered
162  * <0-9> -> prompt for new number; value changed; cb triggered */
163 struct widget_thumbbar {
164 	/* pretty much the same as the numentry, just without the cursor
165 	 * position field... (NOTE - don't rearrange the order of the
166 	 * fields in either of these; some code depends on them being
167 	 * the same) */
168 	int min;
169 	int max;
170 	int value;
171 	/* this is currently only used with the midi thumbbars on the ins. list + pitch page. if
172 	 * this is non-NULL, and value == {min,max}, the text is drawn instead of the thumbbar. */
173 	const char *text_at_min, *text_at_max;
174 };
175 
176 struct widget_bitset {
177 	/* A widget for controlling individual bits */
178 	int nbits;
179 	int value;
180 	int *cursor_pos;
181 	const char* bits_on;
182 	const char* bits_off;
183 	const char* activation_keys;
184 };
185 
186 
187 /* special case of the thumbbar; range goes from 0 to 64. if mute is
188  * set, the bar is replaced with the word "muted"; if surround is set,
189  * it's replaced with the word "surround". some keys: L/M/R set the
190  * value to 0/32/64 respectively, S switches the surround flag, and
191  * space toggles the mute flag (and selects the next.down control!)
192  * min/max are just for thumbbar compatibility, and are always set to
193  * 0 and 64 respectively.
194  * note that, due to some weirdness with IT, these draw the channel text
195  * as well as the actual bar. */
196 struct widget_panbar {
197 	int min;
198 	int max;
199 	int value;
200 	int channel;
201 	unsigned int muted:1;
202 	unsigned int surround:1;
203 };
204 
205 struct widget_other {
206 	/* bah. can't do much of anything with this.
207 	 *
208 	 * if an 'other' type widget gets the focus, it soaks up all the
209 	 * keyboard events that the main handler doesn't catch. thus
210 	 * it is responsible for changing the focus to something else
211 	 * (and, of course, if it doesn't ever do that, the cursor is
212 	 * pretty much stuck)
213 	 * this MUST be set to a valid function.
214 	 * return value is 1 if the key was handled, 0 if not. */
215 	int (*handle_key) (struct key_event * k);
216 
217 	/* also the widget drawing function can't possibly know how to
218 	 * draw a custom widget, so it calls this instead.
219 	 * this MUST be set to a valid function. */
220 	void (*redraw) (void);
221 };
222 
223 /* --------------------------------------------------------------------- */
224 /* and all the widget structs go in the union in this struct... */
225 
226 union _widget_data_union {
227 	struct widget_toggle toggle;
228 	struct widget_menutoggle menutoggle;
229 	struct widget_button button;
230 	struct widget_togglebutton togglebutton;
231 	struct widget_textentry textentry;
232 	struct widget_numentry numentry;
233 	struct widget_thumbbar thumbbar;
234 	struct widget_panbar panbar;
235 	struct widget_other other;
236 	struct widget_bitset bitset;
237 };
238 struct widget {
239 	enum widget_type type;
240 
241 	union _widget_data_union        d;
242 
243 	/* for redrawing */
244 	int x, y, width, height, depressed;
245 	int clip_start, clip_end;
246 
247 	/* these next 5 fields specify what widget gets selected next */
248 	struct {
249 		int up, down, left, right, tab;
250 	} next;
251 
252 	/* called whenever the value is changed... duh ;) */
253 	void (*changed) (void);
254 
255 	/* called when the enter key is pressed */
256 	void (*activate) (void);
257 
258 	/* called by the clipboard manager; really, only "other" widgets
259 	should "override" this... */
260 	int (*clipboard_paste)(int cb, const void *cptr);
261 
262 	/* true if the widget accepts "text"- used for digraphs and unicode
263 	and alt+kp entry... */
264 	int accept_text;
265 };
266 
267 /* this structure keeps all the information needed to draw a page, and a
268  * list of all the different widgets on the page. it's the job of the page
269  * to change the necessary information when something changes; that's
270  * done in the page's draw and update functions.
271  *
272  * everything in this struct MUST be set for each page.
273  * functions that aren't implemented should be set to NULL. */
274 struct page {
275 	/* the title of the page, eg "Sample List (F3)" */
276 	const char *title;
277 
278 	/* font editor takes over full screen */
279 	void (*draw_full)(void);
280 	/* draw the labels, etc. that don't change */
281 	void (*draw_const) (void);
282 	/* called after the song is changed. this is to copy the new
283 	 * values from the song to the widgets on the page. */
284 	void (*song_changed_cb) (void);
285 	/* called before widgets are drawn, mostly to fix the values
286 	 * (for example, on the sample page this sets everything to
287 	 * whatever values the current sample has) - this is a lousy
288 	 * hack. sorry. :P */
289 	void (*predraw_hook) (void);
290 	/* draw the parts of the page that change when the song is playing
291 	 * (this is called *very* frequently) */
292 	void (*playback_update) (void);
293 	/* this gets first shot at keys (to do unnatural overrides) */
294 	int (*pre_handle_key) (struct key_event * k);
295 	/* this catches any keys that the main handler doesn't deal with */
296 	void (*handle_key) (struct key_event * k);
297 	/* called when the page is set. this is for reloading the
298 	 * directory in the file browsers. */
299 	void (*set_page) (void);
300 
301 	/* called when the song-mode changes */
302 	void (*song_mode_changed_cb) (void);
303 
304 	/* called by the clipboard manager */
305 	int (*clipboard_paste)(int cb, const void *cptr);
306 
307 	struct widget *widgets;
308 	int selected_widget;
309 	int total_widgets;
310 
311 	/* 0 if no page-specific help */
312 	int help_index;
313 };
314 
315 /* --------------------------------------------------------------------- */
316 
317 extern struct page pages[];
318 
319 /* these are updated to point to the relevant data in the selected page
320  * (or the dialog, if one is active) */
321 extern struct widget *widgets;
322 extern int *selected_widget;
323 extern int *total_widgets;
324 
325 /* to make it easier to deal with either the page's widgets or the
326  * current dialog's:
327  *
328  * ACTIVE_WIDGET deals with whatever widget is *really* active.
329  * ACTIVE_PAGE_WIDGET references the *page's* idea of what's active.
330  *     (these are different if there's a dialog) */
331 #define ACTIVE_PAGE        (pages[status.current_page])
332 #define ACTIVE_WIDGET      (widgets[*selected_widget])
333 #define ACTIVE_PAGE_WIDGET (ACTIVE_PAGE.widgets[ACTIVE_PAGE.selected_widget])
334 
335 extern int instrument_list_subpage;
336 #define PAGE_INSTRUMENT_LIST instrument_list_subpage
337 
338 /* --------------------------------------------------------------------- */
339 
340 enum page_numbers {
341 	PAGE_BLANK,
342 	PAGE_HELP,
343 	PAGE_ABOUT,
344 	PAGE_LOG,
345 
346 	PAGE_PATTERN_EDITOR,
347 	PAGE_SAMPLE_LIST,
348 	// PAGE_INSTRUMENT_LIST doesn't exist
349 	PAGE_INFO,
350 
351 	PAGE_CONFIG,
352 	PAGE_PREFERENCES,
353 
354 	PAGE_MIDI,
355 	PAGE_MIDI_OUTPUT,
356 
357 	PAGE_LOAD_MODULE,
358 	PAGE_SAVE_MODULE,
359 	PAGE_EXPORT_MODULE,
360 
361 	PAGE_ORDERLIST_PANNING,
362 	PAGE_ORDERLIST_VOLUMES,
363 
364 	PAGE_SONG_VARIABLES,
365 	PAGE_MESSAGE,
366 
367 	/* don't use these directly with set_page */
368 	PAGE_INSTRUMENT_LIST_GENERAL,
369 	PAGE_INSTRUMENT_LIST_VOLUME,
370 	PAGE_INSTRUMENT_LIST_PANNING,
371 	PAGE_INSTRUMENT_LIST_PITCH,
372 
373 	PAGE_LOAD_SAMPLE,
374 	PAGE_LIBRARY_SAMPLE,
375 	PAGE_LOAD_INSTRUMENT,
376 	PAGE_LIBRARY_INSTRUMENT,
377 
378 	PAGE_PALETTE_EDITOR,
379 	PAGE_FONT_EDIT,
380 
381 	PAGE_WATERFALL,
382 
383 	PAGE_MAX
384 };
385 
386 /* --------------------------------------------------------------------- */
387 void show_about(void);
388 
389 void blank_load_page(struct page *page);
390 void help_load_page(struct page *page);
391 void pattern_editor_load_page(struct page *page);
392 void sample_list_load_page(struct page *page);
393 void instrument_list_general_load_page(struct page *page);
394 void instrument_list_volume_load_page(struct page *page);
395 void instrument_list_panning_load_page(struct page *page);
396 void instrument_list_pitch_load_page(struct page *page);
397 void info_load_page(struct page *page);
398 void midi_load_page(struct page *page);
399 void midiout_load_page(struct page *page);
400 void fontedit_load_page(struct page *page);
401 void preferences_load_page(struct page *page);
402 void load_module_load_page(struct page *page);
403 void save_module_load_page(struct page *page, int do_export);
404 void orderpan_load_page(struct page *page);
405 void ordervol_load_page(struct page *page);
406 void song_vars_load_page(struct page *page);
407 void message_load_page(struct page *page);
408 void palette_load_page(struct page *page);
409 void log_load_page(struct page *page);
410 void load_sample_load_page(struct page *page);
411 void load_instrument_load_page(struct page *page);
412 void about_load_page(struct page *page);
413 void library_sample_load_page(struct page *page);
414 void library_instrument_load_page(struct page *page);
415 void config_load_page(struct page *page);
416 void waterfall_load_page(struct page *page);
417 
418 /* --------------------------------------------------------------------- */
419 
420 void create_toggle(struct widget *w, int x, int y, int next_up,
421 		   int next_down, int next_left, int next_right,
422 		   int next_tab, void (*changed) (void));
423 void create_menutoggle(struct widget *w, int x, int y, int next_up,
424 		       int next_down, int next_left, int next_right,
425 		       int next_tab, void (*changed) (void),
426 		       const char *const *choices);
427 void create_button(struct widget *w, int x, int y, int width, int next_up,
428 		   int next_down, int next_left, int next_right,
429 		   int next_tab, void (*changed) (void), const char *text,
430 		   int padding);
431 void create_togglebutton(struct widget *w, int x, int y, int width,
432 			 int next_up, int next_down, int next_left,
433 			 int next_right, int next_tab,
434 			 void (*changed) (void), const char *text,
435 			 int padding, const int *group);
436 void create_textentry(struct widget *w, int x, int y, int width, int next_up,
437 		      int next_down, int next_tab, void (*changed) (void),
438 		      char *text, int max_length);
439 void create_numentry(struct widget *w, int x, int y, int width, int next_up,
440 		     int next_down, int next_tab, void (*changed) (void),
441 		     int min, int max, int *cursor_pos);
442 void create_thumbbar(struct widget *w, int x, int y, int width, int next_up,
443 		     int next_down, int next_tab, void (*changed) (void),
444 		     int min, int max);
445 void create_bitset(struct widget *w, int x, int y, int width, int next_up,
446 		   int next_down, int next_tab, void (*changed) (void),
447 		   int nbits, const char* bits_on, const char* bits_off,
448 		   int *cursor_pos);
449 void create_panbar(struct widget *w, int x, int y, int next_up,
450 		   int next_down, int next_tab, void (*changed) (void),
451 		   int channel);
452 void create_other(struct widget *w, int next_tab,
453 		  int (*w_handle_key) (struct key_event * k),
454 		  void (*w_redraw) (void));
455 
456 /* --------------------------------------------------------------------- */
457 
458 /* widget.c */
459 int textentry_add_char(struct widget *widget, uint16_t unicode);
460 void numentry_change_value(struct widget *widget, int new_value);
461 int numentry_handle_digit(struct widget *widget, struct key_event *k);
462 int menutoggle_handle_key(struct widget *widget, struct key_event *k);
463 int bitset_handle_key(struct widget *widget, struct key_event *k);
464 
465 int change_focus_to_xy(int x, int y);
466 void change_focus_to(int new_widget_index);
467 /* p_widgets should point to the group of widgets (not the actual widget that is
468  * being set!) and widget should be the index of the widget within the group. */
469 void togglebutton_set(struct widget *p_widgets, int widget, int do_callback);
470 void draw_widget(struct widget *w, int selected);
471 
472 /* widget-keyhandler.c
473  * [note: this always uses the current widget] */
474 int widget_handle_key(struct key_event * k);
475 
476 /* draw-misc.c */
477 void draw_thumb_bar(int x, int y, int width, int min, int max, int val,
478 		    int selected);
479 /* vu meter values should range from 0 to 64. the color is generally 5
480  * unless the channel is disabled (in which case it's 1). impulse tracker
481  * doesn't do peak color; st3 style, use color 4 (unless it's disabled,
482  * in which case it should probably be 2, or maybe 3).
483  * the width should be a multiple of three. */
484 void draw_vu_meter(int x, int y, int val, int width, int color, int peak_color);
485 
486 /* page.c */
487 int page_is_instrument_list(int page);
488 void update_current_instrument(void);
489 
490 void new_song_dialog(void);
491 void save_song_or_save_as(void);
492 
493 // support for the song length dialog
494 void show_length_dialog(const char *label, unsigned int length);
495 
496 /* page_patedit.c */
497 void update_current_row(void);
498 void update_current_pattern(void);
499 void pattern_editor_display_options(void);
500 void pattern_editor_length_edit(void);
501 int pattern_max_channels(int patno, int opt_bits[64]);
502 
503 /* page_orderpan.c */
504 void update_current_order(void);
505 
506 /* menu.c */
507 void menu_show(void);
508 void menu_hide(void);
509 void menu_draw(void);
510 int menu_handle_key(struct key_event * k);
511 
512 /* status.c */
513 void status_text_redraw(void);
514 
515 /* charset.c (this is slightly out of place...) */
516 int char_digraph(int k1, int k2);
517 int char_unicode_to_cp437(unsigned int c);
518 
519 // page_message.c
520 void message_reset_selection(void);
521 
522 /* --------------------------------------------------------------------- */
523 /* dialog crap */
524 
525 struct dialog {
526 	int type;
527 	int x, y, w, h;
528 
529 	/* next two are for "simple" dialogs (type != DIALOG_CUSTOM) */
530 	char *text;     /* malloc'ed */
531 	int text_x;
532 
533 	struct widget *widgets;     /* malloc'ed */
534 	int selected_widget;
535 	int total_widgets;
536 
537 	void *data; /* extra data pointer */
538 
539 	/* maybe these should get the data pointer as well? */
540 	void (*draw_const) (void);
541 	int (*handle_key) (struct key_event * k);
542 
543 	/* there's no action_ok, as yes and ok are fundamentally the same */
544 	void (*action_yes) (void *data);
545 	void (*action_no) (void *data); /* only useful for y/n dialogs? */
546 	/* currently, this is only settable for custom dialogs.
547 	 * it's only used in a couple of places (mostly on the pattern editor) */
548 	void (*action_cancel) (void *data);
549 };
550 
551 /* dialog handlers
552  * these are set by default for normal dialogs, and can be used with the custom dialogs.
553  * they call the {yes, no, cancel} callback, destroy the dialog, and schedule a screen
554  * update. (note: connect these to the BUTTONS, not the action_* callbacks!) */
555 void dialog_yes(void *data);
556 void dialog_no(void *data);
557 void dialog_cancel(void *data);
558 /* these are the same as dialog_yes(NULL) etc., and are used in button callbacks */
559 void dialog_yes_NULL(void);
560 void dialog_no_NULL(void);
561 void dialog_cancel_NULL(void);
562 
563 int dialog_handle_key(struct key_event * k);
564 void dialog_draw(void);
565 
566 struct dialog *dialog_create(int type, const char *text, void (*action_yes) (void *data),
567 		   void (*action_no) (void *data), int default_widget, void *data);
568 
569 void dialog_destroy(void);
570 void dialog_destroy_all(void);
571 
572 /* this builds and displays a dialog with an unspecified widget structure.
573  * the caller can set other properties of the dialog (i.e. the yes/no/cancel callbacks) after
574  * the dialog has been displayed. */
575 struct dialog *dialog_create_custom(int x, int y, int w, int h, struct widget *dialog_widgets,
576 				    int dialog_total_widgets, int dialog_selected_widget,
577 				    void (*draw_const) (void), void *data);
578 
579 /* --------------------------------------------------------------------- */
580 /* Other UI prompt stuff. */
581 
582 /* Ask for a value, like the thumbbars. */
583 void numprompt_create(const char *prompt, void (*finish)(int n), char initvalue);
584 
585 /* Ask for a sample / instrument number, like the "swap sample" dialog. */
586 void smpprompt_create(const char *title, const char *prompt, void (*finish)(int n));
587 
588 #endif /* ! PAGE_H */
589