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