/** set current row **/
    void set_current_row( dom::element& table, dom::element& row, UINT keyboardStates, bool dblClick = false )
    {
      if(is_multiple(table))
      {
		     if (keyboardStates & SHIFT_KEY_PRESSED)
         {
			      checkall(table, false);
				    check_range(table,row.index(),TRUE); // from current to new
         } 
         else 
         {			
				   if (keyboardStates & CONTROL_KEY_PRESSED)
				     set_checked_row (table,row, true); // toggle
           else
             checkall(table, false);
           set_anchor(table,row.index ());
         }
      }

      // get previously selected row:
      dom::element prev = get_current_row( table );
      if( prev.is_valid() )
      {
        if( prev != row ) 
          prev.set_state(0,STATE_CURRENT, false); // drop state flags
      }
      row.set_state(STATE_CURRENT); // set state flags
      row.scroll_to_view();
      ::UpdateWindow(row.get_element_hwnd(false));
      table.post_event( dblClick? TABLE_ROW_DBL_CLICK:TABLE_ROW_CLICK, row.index(), row); 
    }
Beispiel #2
0
 /** set current row **/
 void set_current_row( dom::element& table, dom::element& row, UINT keyboardStates, bool dblClick = false )
 {
   // get previously selected row:
   dom::element prev = get_current_row( table );
   if( prev.is_valid() )
   {
     if( prev != row ) 
       prev.set_state(0,STATE_CURRENT, false); // drop state flags
   }
   row.set_state(STATE_CURRENT); // set state flags
   row.scroll_to_view();
   table.post_event( dblClick? TABLE_ROW_DBL_CLICK:TABLE_ROW_CLICK, row.index(), row); 
 }
  virtual void on_column_click( dom::element& table, dom::element& header_cell )
  {
    super::on_column_click( table, header_cell );

    dom::element current = table.find_first("th:checked");
    if( current == header_cell )
      return; // already here, nothing to do.

    if( current.is_valid() )
      current.set_state(0, STATE_CHECKED);
    header_cell.set_state(STATE_CHECKED);

	dom::element ctr = get_current_row( table );
    sort_rows( table, header_cell.index() );
	if( ctr.is_valid() )
		ctr.scroll_to_view();

  }
    /** set current row **/
    void set_current_row( dom::element& table, dom::element& row, UINT keyboardStates, bool dblClick = false, bool smooth = false )
    {
      // get previously selected row:
      dom::element prev = get_current_row( table );

      uint new_row_checked = STATE_CHECKED;
      uint old_row_checked = STATE_CHECKED;

      if(is_multiple(table))
      {
         if (keyboardStates & SHIFT_KEY_PRESSED)
         {
            checkall(table, false);
            check_range(table,row.index(),TRUE); // from current to new
         } 
         else 
         {      
           if (keyboardStates & CONTROL_KEY_PRESSED)
           {
             set_checked_row (table,row, true); // toggle
             new_row_checked = 0;
           }
           else
             checkall(table, false);
           set_anchor(table,row.index ());
         }
         old_row_checked = 0;
      }
      
      if( prev.is_valid() )
      {
        if( prev != row ) 
          prev.set_state(0,STATE_CURRENT | old_row_checked); // drop state flags
      }
      row.set_state(STATE_CURRENT | new_row_checked); // set state flags
      row.scroll_to_view(false,smooth);
      //::UpdateWindow(row.get_element_hwnd(false));
      table.post_event( dblClick? TABLE_ROW_DBL_CLICK:TABLE_ROW_CLICK, row.index(), row); 
      table.post_event(WY_GRID_VERTICAL_SCROLL, 0);
    }
    virtual BOOL on_key(HELEMENT he, HELEMENT target, UINT event_type, UINT code, UINT keyboardStates ) 
    { 
      if( event_type == KEY_DOWN )
      {
        dom::element table = he;
        switch( code )
        {
          case VK_DOWN: 
            {
               dom::element c = get_current_row( table );
               int idx = c.is_valid()? (c.index() + 1):fixed_rows(table);
               while( idx < (int)table.children_count() )
               {
                   dom::element row = table.child(idx);
                   if( wcseq(row.get_style_attribute("display"),L"none" ))
                   {
                     ++idx;
                     continue;
                   }
                   set_current_row(table, row, keyboardStates); 
                   break;
               }
            }
            return TRUE;
          case VK_UP:             
            {
               dom::element c = get_current_row( table );
               int idx = c.is_valid()? (c.index() - 1):(table.children_count() - 1);
               while( idx >= fixed_rows(table) )
               {
                   dom::element row = table.child(idx);
                   if( wcseq(row.get_style_attribute("display"),L"none" ))
                   {
                     --idx;
                     continue;
                   }
                   set_current_row(table, row, keyboardStates); 
                   break;
               }
            }
            return TRUE;
          case VK_PRIOR:
            {
               RECT trc = table.get_location(ROOT_RELATIVE | SCROLLABLE_AREA);
               int y = trc.top - (trc.bottom - trc.top);
               int first = fixed_rows(table);
               dom::element r;
               for( int i = table.children_count() - 1; i >= first; --i )
               {
                   dom::element nr = table.child(i);
                   if( wcseq(nr.get_style_attribute("display"),L"none" ))
                     continue;
                   dom::element pr = r;
                   r = nr;
                   if( r.get_location(ROOT_RELATIVE | BORDER_BOX).top < y )
                   {
                      // row found
                      if(pr.is_valid()) r = pr; // to last fully visible
                      break;
                   }
               }
               set_current_row(table, r, keyboardStates); 
            }
            return TRUE;

          case VK_NEXT:
            {
               RECT trc = table.get_location(ROOT_RELATIVE | SCROLLABLE_AREA);
               int y = trc.bottom + (trc.bottom - trc.top);
               int last = table.children_count() - 1;
               dom::element r; 
               for( int i = fixed_rows(table); i <= last; ++i )
               {
                   dom::element nr = table.child(i);
                   if( wcseq(nr.get_style_attribute("display"),L"none" ))
                     continue;
                   dom::element pr = r;
                   r = nr;
                   if( r.get_location(ROOT_RELATIVE | BORDER_BOX).bottom > y )
                   {
                      // row found
                      if(pr.is_valid()) r = pr; // to last fully visible
                      break;
                   }
               }
               set_current_row(table, r, keyboardStates); 
            }
            return TRUE;

          case VK_HOME:
            {
               int idx = fixed_rows(table);
               while( (int)idx < (int)table.children_count() )
               {
                   dom::element row = table.child(idx);
                   if( wcseq(row.get_style_attribute("display"),L"none" ))
                   {
                     ++idx;
                     continue;
                   }
                   set_current_row(table, row, keyboardStates); 
                   break;
               }
            }
            return TRUE;

          case VK_END:
            {
               int idx = table.children_count() - 1;
               while( idx >= fixed_rows(table) )
               {
                   dom::element row = table.child(idx);
                   if( wcseq(row.get_style_attribute("display"),L"none" ))
                   {
                     --idx;
                     continue;
                   }
                   set_current_row(table, row, keyboardStates); 
                   break;
               }
            }
            return TRUE;
          case 'A':
            if( is_multiple(table) && (keyboardStates & CONTROL_KEY_PRESSED) != 0 )
            {
              checkall(table, true);
              return TRUE;
            }
            return FALSE;
        }
      }
      return FALSE; 
    }
Beispiel #6
0
/* return 1 -> the time changed; need to redraw */
static int check_time(void)
{
	static int last_o = -1, last_r = -1, last_timep = -1;

	time_t timep = 0;
	int h, m, s;
	enum tracker_time_display td = status.time_display;
	int is_playing = song_get_mode() & (MODE_PLAYING | MODE_PATTERN_LOOP);

	int row, order;

	switch (td) {
	case TIME_PLAY_ELAPSED:
		td = (is_playing ? TIME_PLAYBACK : TIME_ELAPSED);
		break;
	case TIME_PLAY_CLOCK:
		td = (is_playing ? TIME_PLAYBACK : TIME_CLOCK);
		break;
	case TIME_PLAY_OFF:
		td = (is_playing ? TIME_PLAYBACK : TIME_OFF);
		break;
	default:
		break;
	}

	switch (td) {
	case TIME_OFF:
		h = m = s = 0;
		break;
	case TIME_PLAYBACK:
		h = (m = (s = song_get_current_time()) / 60) / 60;
		break;
	case TIME_ELAPSED:
		h = (m = (s = SDL_GetTicks() / 1000) / 60) / 60;
		break;
	case TIME_ABSOLUTE:
		/* absolute time shows the time of the current cursor
		position in the pattern editor :) */
		if (status.current_page == PAGE_PATTERN_EDITOR) {
			row = get_current_row();
			order = song_next_order_for_pattern(get_current_pattern());
		} else {
			order = get_current_order();
			row = 0;
		}
		if (order < 0) {
			s = m = h = 0;
		} else {
			if (last_o == order && last_r == row) {
				timep = last_timep;
			} else {
				last_timep = timep = song_get_length_to(order, row);
				last_o = order;
				last_r = row;
			}
			s = timep % 60;
			m = (timep / 60) % 60;
			h = (timep / 3600);
		}
		break;
	default:
		/* this will never happen */
	case TIME_CLOCK:
		/* Impulse Tracker doesn't have this, but I always wanted it, so here 'tis. */
		h = status.tmnow.tm_hour;
		m = status.tmnow.tm_min;
		s = status.tmnow.tm_sec;
		break;
	}

	if (h == current_time.h && m == current_time.m && s == current_time.s) {
		return 0;
	}

	current_time.h = h;
	current_time.m = m;
	current_time.s = s;
	return 1;
}
Beispiel #7
0
/* returns 1 if the key was handled */
static int handle_key_global(struct key_event * k)
{
	int i, ins_mode;

	if (_mp_active == 2 && (k->mouse == MOUSE_CLICK && k->state == KEY_RELEASE)) {
		status.flags |= NEED_UPDATE;
		dialog_destroy_all();
		_mp_active = 0;
		// eat it...
		return 1;
	}
	if ((!_mp_active) && k->state == KEY_PRESS && k->mouse == MOUSE_CLICK) {
		if (k->x >= 63 && k->x <= 77 && k->y >= 6 && k->y <= 7) {
			status.vis_style++;
			status.vis_style %= VIS_SENTINEL;
			status.flags |= NEED_UPDATE;
			return 1;
		} else if (k->y == 5 && k->x == 50) {
			minipop_slide(kbd_get_current_octave(), "Octave", 0, 8,
				kbd_set_current_octave, NULL, 50, 5);
			return 1;
		} else if (k->y == 4 && k->x >= 50 && k->x <= 52) {
			minipop_slide(song_get_current_speed(), "Speed", 1, 255,
				song_set_current_speed, song_set_initial_speed, 51, 4);
			return 1;
		} else if (k->y == 4 && k->x >= 54 && k->x <= 56) {
			minipop_slide(song_get_current_tempo(), "Tempo", 32, 255,
				song_set_current_tempo, song_set_initial_tempo, 55, 4);
			return 1;
		} else if (k->y == 3 && k->x >= 50 && k-> x <= 77) {
			if (page_is_instrument_list(status.current_page)
			    || status.current_page == PAGE_SAMPLE_LIST
			    || (!(status.flags & CLASSIC_MODE)
				&& (status.current_page == PAGE_ORDERLIST_PANNING
				    || status.current_page == PAGE_ORDERLIST_VOLUMES)))
				ins_mode = 0;
			else
				ins_mode = song_is_instrument_mode();
			if (ins_mode) {
				minipop_slide(instrument_get_current(), "!",
					status.current_page == PAGE_INSTRUMENT_LIST ? 1 : 0,
					99 /* FIXME */, instrument_set, NULL, 58, 3);
			} else {
				minipop_slide(sample_get_current(), "@",
					status.current_page == PAGE_SAMPLE_LIST ? 1 : 0,
					99 /* FIXME */, sample_set, NULL, 58, 3);
			}

		} else if (k->y == 7 && k->x >= 11 && k->x <= 17) {
			minipop_slide(get_current_row(), "Row",
				0, song_get_rows_in_pattern(get_current_pattern()),
				set_current_row, NULL, 14, 7);
			return 1;
		} else if (k->y == 6 && k->x >= 11 && k->x <= 17) {
			minipop_slide(get_current_pattern(), "Pattern",
				0, csf_get_num_patterns(current_song),
				set_current_pattern, NULL, 14, 6);
			return 1;
		} else if (k->y == 5 && k->x >= 11 && k->x <= 17) {
			minipop_slide(song_get_current_order(), "Order",
				0, csf_get_num_orders(current_song),
				set_current_order, NULL, 14, 5);
			return 1;
		}
	} else if ((!_mp_active) && k->mouse == MOUSE_DBLCLICK) {
		if (k->y == 4 && k->x >= 11 && k->x <= 28) {
			set_page(PAGE_SAVE_MODULE);
			return 1;
		} else if (k->y == 3 && k->x >= 11 && k->x <= 35) {
			set_page(PAGE_SONG_VARIABLES);
			return 1;
		}
	}

	/* shortcut */
	if (k->mouse != MOUSE_NONE) {
		return 0;
	}

	/* first, check the truly global keys (the ones that still work if
	 * a dialog's open) */
	switch (k->sym) {
	case SDLK_RETURN:
		if ((k->mod & KMOD_CTRL) && k->mod & KMOD_ALT) {
			if (k->state == KEY_PRESS)
				return 1;
			toggle_display_fullscreen();
			return 1;
		}
		break;
	case SDLK_m:
		if (k->mod & KMOD_CTRL) {
			if (k->state == KEY_RELEASE)
				return 1;
			video_mousecursor(MOUSE_CYCLE_STATE);
			return 1;
		}
		break;

	case SDLK_d:
		if (k->mod & KMOD_CTRL) {
			if (k->state == KEY_RELEASE)
				return 1; /* argh */
			i = SDL_WM_GrabInput(SDL_GRAB_QUERY);
			if (i == SDL_GRAB_QUERY)
				i = currently_grabbed;
			currently_grabbed = i = (i != SDL_GRAB_ON ? SDL_GRAB_ON : SDL_GRAB_OFF);
			SDL_WM_GrabInput(i);
			status_text_flash(i
				? "Mouse and keyboard grabbed, press Ctrl+D to release"
				: "Mouse and keyboard released");
			return 1;
		}
		break;

	case SDLK_i:
		/* reset audio stuff? */
		if (k->mod & KMOD_CTRL) {
			if (k->state == KEY_RELEASE)
				return 1;
			audio_reinit();
			return 1;
		}
		break;
	case SDLK_e:
		/* This should reset everything display-related. */
		if (k->mod & KMOD_CTRL) {
			if (k->state == KEY_RELEASE)
				return 1;
			font_init();
			status.flags |= NEED_UPDATE;
			return 1;
		}
		break;
	case SDLK_HOME:
		if (!(k->mod & KMOD_ALT)) break;
		if (status.flags & DISKWRITER_ACTIVE) break;
		if (k->state == KEY_RELEASE)
			return 0;
		kbd_set_current_octave(kbd_get_current_octave() - 1);
		return 1;
	case SDLK_END:
		if (!(k->mod & KMOD_ALT)) break;
		if (status.flags & DISKWRITER_ACTIVE) break;
		if (k->state == KEY_RELEASE)
			return 0;
		kbd_set_current_octave(kbd_get_current_octave() + 1);
		return 1;
	default:
		break;
	}

	/* next, if there's no dialog, check the rest of the keys */
	if (status.flags & DISKWRITER_ACTIVE) return 0;

	switch (k->sym) {
	case SDLK_q:
		if (status.dialog_type != DIALOG_NONE)
			return 0;
		if (k->mod & KMOD_CTRL) {
			_mp_finish(NULL);
			if (k->state == KEY_PRESS)
				show_exit_prompt();
			return 1;
		}
		break;
	case SDLK_n:
		if (status.dialog_type != DIALOG_NONE)
			return 0;
		if (k->mod & KMOD_CTRL) {
			_mp_finish(NULL);
			if (k->state == KEY_PRESS)
				new_song_dialog();
			return 1;
		}
		break;
	case SDLK_g:
		if (status.dialog_type != DIALOG_NONE)
			return 0;
		if (k->mod & KMOD_CTRL) {
			_mp_finish(NULL);
			if (k->state == KEY_PRESS)
				show_song_timejump();
			return 1;
		}
		break;
	case SDLK_p:
		if (status.dialog_type != DIALOG_NONE)
			return 0;
		if (k->mod & KMOD_CTRL) {
			_mp_finish(NULL);
			if (k->state == KEY_PRESS)
				show_song_length();
			return 1;
		}
		break;
	case SDLK_F1:
		if (status.dialog_type != DIALOG_NONE)
			return 0;
		if (k->mod & KMOD_CTRL) {
			_mp_finish(NULL);
			if (k->state == KEY_PRESS)
				set_page(PAGE_CONFIG);
		} else if (k->mod & KMOD_SHIFT) {
			_mp_finish(NULL);
			if (k->state == KEY_PRESS)
				set_page(status.current_page == PAGE_MIDI ? PAGE_MIDI_OUTPUT : PAGE_MIDI);
		} else if (NO_MODIFIER(k->mod)) {
			_mp_finish(NULL);
			if (k->state == KEY_PRESS)
				set_page(PAGE_HELP);
		} else {
			break;
		}
		return 1;
	case SDLK_F2:
		if (k->mod & KMOD_CTRL) {
			if (status.current_page == PAGE_PATTERN_EDITOR) {
				_mp_finish(NULL);
				if (k->state == KEY_PRESS && status.dialog_type == DIALOG_NONE) {
					pattern_editor_length_edit();
				}
				return 1;
			}
			if (status.dialog_type != DIALOG_NONE)
				return 0;
		} else if (NO_MODIFIER(k->mod)) {
			if (status.current_page == PAGE_PATTERN_EDITOR) {
				if (k->state == KEY_PRESS) {
					if (status.dialog_type & DIALOG_MENU) {
						return 0;
					} else if (status.dialog_type != DIALOG_NONE) {
						dialog_yes_NULL();
						status.flags |= NEED_UPDATE;
					} else {
						_mp_finish(NULL);
						pattern_editor_display_options();
					}
				}
			} else {
				if (status.dialog_type != DIALOG_NONE)
					return 0;
				_mp_finish(NULL);
				if (k->state == KEY_PRESS)
					set_page(PAGE_PATTERN_EDITOR);
			}
			return 1;
		}
		break;
	case SDLK_F3:
		if (status.dialog_type != DIALOG_NONE)
			return 0;
		if (NO_MODIFIER(k->mod)) {
			_mp_finish(NULL);
			if (k->state == KEY_PRESS)
				set_page(PAGE_SAMPLE_LIST);
		} else {
			_mp_finish(NULL);
			if (k->mod & KMOD_CTRL) set_page(PAGE_LIBRARY_SAMPLE);
			break;
		}
		return 1;
	case SDLK_F4:
		if (status.dialog_type != DIALOG_NONE)
			return 0;
		if (NO_MODIFIER(k->mod)) {
			if (status.current_page == PAGE_INSTRUMENT_LIST) return 0;
			_mp_finish(NULL);
			if (k->state == KEY_PRESS)
				set_page(PAGE_INSTRUMENT_LIST);
		} else {
			if (k->mod & KMOD_SHIFT) return 0;
			_mp_finish(NULL);
			if (k->mod & KMOD_CTRL) set_page(PAGE_LIBRARY_INSTRUMENT);
			break;
		}
		return 1;
	case SDLK_F5:
		if (k->mod & KMOD_CTRL) {
			_mp_finish(NULL);
			if (k->state == KEY_PRESS)
				song_start();
		} else if (k->mod & KMOD_SHIFT) {
			if (status.dialog_type != DIALOG_NONE)
				return 0;
			_mp_finish(NULL);
			if (k->state == KEY_RELEASE)
				set_page(PAGE_PREFERENCES);
		} else if (NO_MODIFIER(k->mod)) {
			if (song_get_mode() == MODE_STOPPED
			|| (song_get_mode() == MODE_SINGLE_STEP && status.current_page == PAGE_INFO)) {
				_mp_finish(NULL);
				if (k->state == KEY_PRESS)
					song_start();
			}
			if (k->state == KEY_PRESS) {
				if (status.dialog_type != DIALOG_NONE)
					return 0;
				_mp_finish(NULL);
				set_page(PAGE_INFO);
			}
		} else {
			break;
		}
		return 1;
	case SDLK_F6:
		if (k->mod & KMOD_SHIFT) {
			_mp_finish(NULL);
			if (k->state == KEY_PRESS)
				song_start_at_order(get_current_order(), 0);
		} else if (NO_MODIFIER(k->mod)) {
			_mp_finish(NULL);
			if (k->state == KEY_PRESS)
				song_loop_pattern(get_current_pattern(), 0);
		} else {
			break;
		}
		return 1;
	case SDLK_F7:
		if (NO_MODIFIER(k->mod)) {
			_mp_finish(NULL);
			if (k->state == KEY_PRESS)
				play_song_from_mark();
		} else {
			break;
		}
		return 1;
	case SDLK_F8:
		if (k->mod & KMOD_SHIFT) {
			if (k->state == KEY_PRESS)
				song_pause();
		} else if (NO_MODIFIER(k->mod)) {
			_mp_finish(NULL);
			if (k->state == KEY_PRESS)
				song_stop();
			status.flags |= NEED_UPDATE;
		} else {
			break;
		}
		return 1;
	case SDLK_F9:
		if (status.dialog_type != DIALOG_NONE)
			return 0;
		if (k->mod & KMOD_SHIFT) {
			_mp_finish(NULL);
			if (k->state == KEY_PRESS)
				set_page(PAGE_MESSAGE);
		} else if (NO_MODIFIER(k->mod)) {
			_mp_finish(NULL);
			if (k->state == KEY_PRESS)
				set_page(PAGE_LOAD_MODULE);
		} else {
			break;
		}
		return 1;
	case SDLK_l:
	case SDLK_r:
		if (status.dialog_type != DIALOG_NONE)
			return 0;
		if (k->mod & KMOD_CTRL) {
			_mp_finish(NULL);
			if (k->state == KEY_RELEASE)
				set_page(PAGE_LOAD_MODULE);
		} else {
			break;
		}
		return 1;
	case SDLK_s:
		if (status.dialog_type != DIALOG_NONE)
			return 0;
		if (k->mod & KMOD_CTRL) {
			_mp_finish(NULL);
			if (k->state == KEY_RELEASE)
				save_song_or_save_as();
		} else {
			break;
		}
		return 1;
	case SDLK_w:
		/* Ctrl-W _IS_ in IT, and hands don't leave home row :) */
		if (status.dialog_type != DIALOG_NONE)
			return 0;
		if (k->mod & KMOD_CTRL) {
			_mp_finish(NULL);
			if (k->state == KEY_RELEASE)
				set_page(PAGE_SAVE_MODULE);
		} else {
			break;
		}
		return 1;
	case SDLK_F10:
		if (status.dialog_type != DIALOG_NONE)
			return 0;
		if (k->mod & KMOD_ALT) break;
		if (k->mod & KMOD_CTRL) break;

		_mp_finish(NULL);
		if (k->mod & KMOD_SHIFT) {
			if (k->state == KEY_PRESS)
				set_page(PAGE_EXPORT_MODULE);
		} else {
			if (k->state == KEY_PRESS)
				set_page(PAGE_SAVE_MODULE);
		}
		return 1;
	case SDLK_F11:
		if (status.dialog_type != DIALOG_NONE)
			return 0;
		if (NO_MODIFIER(k->mod)) {
			_mp_finish(NULL);
			if (status.current_page == PAGE_ORDERLIST_PANNING) {
				if (k->state == KEY_PRESS)
					set_page(PAGE_ORDERLIST_VOLUMES);
			} else {
				if (k->state == KEY_PRESS)
					set_page(PAGE_ORDERLIST_PANNING);
			}
		} else if (k->mod & KMOD_CTRL) {
			if (k->state == KEY_PRESS) {
				_mp_finish(NULL);
				if (status.current_page == PAGE_LOG) {
					show_about();
				} else {
					set_page(PAGE_LOG);
				}
			}
		} else if (k->state == KEY_PRESS && (k->mod & KMOD_ALT)) {
			_mp_finish(NULL);
			if (song_toggle_orderlist_locked())
				status_text_flash("Order list locked");
			else
				status_text_flash("Order list unlocked");
		} else {
			break;
		}
		return 1;
	case SDLK_F12:
		if (status.dialog_type != DIALOG_NONE)
			return 0;
		if ((k->mod & KMOD_ALT) && status.current_page == PAGE_INFO) {
			_mp_finish(NULL);
			if (k->state == KEY_PRESS)
				set_page(PAGE_WATERFALL);
		} else if (k->mod & KMOD_CTRL) {
			_mp_finish(NULL);
			if (k->state == KEY_PRESS)
				set_page(PAGE_PALETTE_EDITOR);
		} else if (k->mod & KMOD_SHIFT) {
			_mp_finish(NULL);
			if (k->state == KEY_PRESS) {
				fontedit_return_page = status.current_page;
				set_page(PAGE_FONT_EDIT);
			}

		} else if (NO_MODIFIER(k->mod)) {
			_mp_finish(NULL);
			if (k->state == KEY_PRESS)
				set_page(PAGE_SONG_VARIABLES);
		} else {
			break;
		}
		return 1;
	/* hack alert */
	case SDLK_f:
		if (!(k->mod & KMOD_CTRL))
			return 0;
		/* fall through */
	case SDLK_SCROLLOCK:
		if (status.dialog_type != DIALOG_NONE)
			return 0;
		_mp_finish(NULL);
		if (k->mod & KMOD_ALT) {
			if (k->state == KEY_PRESS) {
				midi_flags ^= (MIDI_DISABLE_RECORD);
				status_text_flash("MIDI Input %s",
					(midi_flags & MIDI_DISABLE_RECORD)
					? "Disabled" : "Enabled");
			}
			return 1;
		} else {
			/* os x steals plain scroll lock for brightness,
			 * so catch ctrl+scroll lock here as well */
			if (k->state == KEY_PRESS) {
				midi_playback_tracing = (playback_tracing = !playback_tracing);
				status_text_flash("Playback tracing %s",
						  (playback_tracing ? "enabled" : "disabled"));
			}
			return 1;
		}
	default:
		if (status.dialog_type != DIALOG_NONE)
			return 0;
		break;
	}

	/* got a bit ugly here, sorry */
	i = k->sym;
	if (k->mod & KMOD_ALT) {
		switch (i) {
		case SDLK_F1: i = 0; break;
		case SDLK_F2: i = 1; break;
		case SDLK_F3: i = 2; break;
		case SDLK_F4: i = 3; break;
		case SDLK_F5: i = 4; break;
		case SDLK_F6: i = 5; break;
		case SDLK_F7: i = 6; break;
		case SDLK_F8: i = 7; break;
		default:
			return 0;
		};
		if (k->state == KEY_RELEASE)
			return 1;

		song_toggle_channel_mute(i);
		status.flags |= NEED_UPDATE;
		return 1;
	}

	/* oh well */
	return 0;
}
int main(int argc, char *argv[]) {
    Cmdline *cmd;
    struct psrfits pfi, pfo; // input and output
    struct subband_info si;
    int stat=0, padding=0, userN=0;

    // Call usage() if we have no command line arguments
    if (argc == 1) {
        Program = argv[0];
        usage();
        exit(0);
    }

    // Parse the command line using the excellent program Clig
    cmd = parseCmdline(argc, argv);

    // Open the input PSRFITs files
    psrfits_set_files(&pfi, cmd->argc, cmd->argv);

    // Use the dynamic filename allocation
    if (pfi.numfiles==0) pfi.filenum = cmd->startfile;
    pfi.tot_rows = pfi.N = pfi.T = pfi.status = 0;
    int rv = psrfits_open(&pfi);
    if (rv) { fits_report_error(stderr, rv); exit(1); }

    // Read the user weights if requested
    si.userwgts = NULL;
    if (cmd->wgtsfileP) {
        read_weights(cmd->wgtsfile, &userN, &si.userwgts);
        if (userN != pfi.hdr.nchan) {
            printf("Error!:  Input data has %d channels, but '%s' contains only %d weights!\n",
                   pfi.hdr.nchan, cmd->wgtsfile, userN);
            exit(0);
        }
        printf("Overriding input channel weights with those in '%s'\n",
               cmd->wgtsfile);
    }

    // Initialize the subbanding
    // (including reading the first row of data and
    //  putting it in si->fbuffer)
    init_subbanding(&pfi, &pfo, &si, cmd);

    if (cmd->outputbasenameP)
      strcpy(pfo.basefilename, cmd->outputbasename);

    // Loop through the data
    do {
        // Put the overlapping parts from the next block into si->buffer
        float *ptr = pfi.sub.fdata + si.buflen * si.bufwid;
        if (padding==0)
            stat = psrfits_read_part_DATA(&pfi, si.max_overlap, si.numunsigned, ptr);
        if (stat || padding) { // Need to use padding since we ran out of data
            printf("Adding a missing row (#%d) of padding to the subbands.\n",
                   pfi.tot_rows);
            // Now fill the last part of si->fbuffer with the chan_avgs so that
            // it acts like a correctly read block (or row)
            fill_chans_with_avgs(si.max_overlap, si.bufwid,
                                 ptr, si.chan_avgs);
        }
        //print_raw_chan_stats(pfi.sub.data, pfi.hdr.nsblk,
        //                     pfi.hdr.nchan, pfi.hdr.npol);

        // if the input data isn't 8 bit, unpack:
        if (pfi.hdr.nbits == 2)
            pf_unpack_2bit_to_8bit(&pfi, si.numunsigned);
        else if (pfi.hdr.nbits == 4)
            pf_unpack_4bit_to_8bit(&pfi, si.numunsigned);

        if ((pfo.hdr.ds_time_fact == 1) &&
            (pfo.hdr.ds_freq_fact == 1)) {
            // No subbanding is needed, so just copy the float buffer
            // This is useful if we are just changing the number of bits
            // Could do it without a copy by simply exchanging pointers
            // to the fdata buffers in pfo and pfi...
            memcpy(pfo.sub.fdata, pfi.sub.fdata,
                   pfi.hdr.nsblk * pfi.hdr.npol * pfi.hdr.nchan * sizeof(float));
        } else {
            // Now create the subbanded row in the output buffer
            make_subbands(&pfi, &si);
        }

        // Output only Stokes I (in place via floats)
        if (pfo.hdr.onlyI && pfo.hdr.npol==4)
            get_stokes_I(&pfo);

        // Downsample in time (in place via floats)
        if (pfo.hdr.ds_time_fact > 1)
            downsample_time(&pfo);

        // Compute new scales and offsets so that we can pack
        // into 8-bits reliably
        if (pfo.rownum == 1)
            new_scales_and_offsets(&pfo, si.numunsigned, cmd);

        // Convert the floats back to bytes in the output array
        un_scale_and_offset_data(&pfo, si.numunsigned);
        //print_raw_chan_stats(pfo.sub.data, pfo.hdr.nsblk / pfo.hdr.ds_time_fact,
        //                     pfo.hdr.nchan / pfo.hdr.ds_freq_fact, pfo.hdr.npol);
        
	// pack into 2 or 4 bits if needed
        if (pfo.hdr.nbits == 2)
            pf_pack_8bit_to_2bit(&pfo, si.numunsigned);
        else if (pfo.hdr.nbits == 4)
            pf_pack_8bit_to_4bit(&pfo, si.numunsigned);

        // Write the new row to the output file
        pfo.sub.offs = (pfo.tot_rows+0.5) * pfo.sub.tsubint;
        psrfits_write_subint(&pfo);

        // Break out of the loop here if stat is set
        if (stat) break;

        // shift the last part of the current row into the "last-row"
        // part of the data buffer
        memcpy(si.fbuffer, si.fbuffer + si.buflen * si.bufwid,
               si.max_overlap * si.bufwid * sizeof(float));

        // Read the next row (or padding)
        padding = get_current_row(&pfi, &si);

        // Set the new weights properly
        new_weights(&pfi, &pfo);
        
    } while (pfi.status == 0);
    
    print_clips(&pfo);
    rv = psrfits_close(&pfi);
    if (rv>100) { fits_report_error(stderr, rv); }
    rv = psrfits_close(&pfo);
    if (rv>100) { fits_report_error(stderr, rv); }
    exit(0);
}
void init_subbanding(struct psrfits *pfi, struct psrfits *pfo,
                     struct subband_info *si, Cmdline *cmd)
{
    int ii, jj, kk, cindex;
    double lofreq, dtmp;

    // If -nsub is not set, do no subbanding
    if (!cmd->nsubP) cmd->nsub = pfi->hdr.nchan;
    // Don't change the number of output bits unless we explicitly ask to
    if (!cmd->outbitsP) cmd->outbits = pfi->hdr.nbits;

    si->nsub = cmd->nsub;
    si->nchan = pfi->hdr.nchan;
    si->npol = pfi->hdr.npol;
    si->numunsigned = si->npol;
    if (si->npol==4) {
        if (strncmp(pfi->hdr.poln_order, "AABBCRCI", 8)==0)
            si->numunsigned = 2;
        if (strncmp(pfi->hdr.poln_order, "IQUV", 4)==0)
            si->numunsigned = 1;
    }
    si->chan_per_sub = si->nchan / si->nsub;
    si->bufwid = si->nchan * si->npol; // Freq * polns
    si->buflen = pfi->hdr.nsblk;  // Number of spectra in each row
    // Check the downsampling factor in time
    if (si->buflen % cmd->dstime) {
        fprintf(stderr,
                "Error!:  %d spectra per row is not evenly divisible by -dstime of %d!\n",
                si->buflen, cmd->dstime);
        exit(1);
    }
    // Check the downsampling factor in frequency
    if (si->nchan % si->nsub) {
        fprintf(stderr,
                "Error!  %d channels is not evenly divisible by %d subbands!\n",
                si->nchan, si->nsub);
        exit(1);
    }
    si->dm = cmd->dm;
    si->sub_df = pfi->hdr.df * si->chan_per_sub;
    si->sub_freqs = (float *)malloc(sizeof(float) * si->nsub);
    si->chan_delays = (double *)malloc(sizeof(double) * si->nchan);
    si->sub_delays = (double *)malloc(sizeof(double) * si->nsub);
    si->idelays = (int *)malloc(sizeof(int) * si->nchan);
    si->weights = (float *)malloc(sizeof(float) * si->nsub);
    si->offsets = (float *)malloc(sizeof(float) * si->nsub * si->npol);
    si->scales = (float *)malloc(sizeof(float) * si->nsub * si->npol);
    si->chan_avgs = (float *)malloc(sizeof(float) * si->bufwid);
    si->chan_stds = (float *)malloc(sizeof(float) * si->bufwid);

    /* Alloc data buffers for the input PSRFITS file */
    pfi->sub.dat_freqs = (float *)malloc(sizeof(float) * pfi->hdr.nchan);
    pfi->sub.dat_weights = (float *)malloc(sizeof(float) * pfi->hdr.nchan);
    pfi->sub.dat_offsets = (float *)malloc(sizeof(float)
                                           * pfi->hdr.nchan * pfi->hdr.npol);
    pfi->sub.dat_scales  = (float *)malloc(sizeof(float)
                                           * pfi->hdr.nchan * pfi->hdr.npol);
    pfi->sub.rawdata = (unsigned char *)malloc(pfi->sub.bytes_per_subint);
    if (pfi->hdr.nbits!=8) {
        pfi->sub.data = (unsigned char *)malloc(pfi->sub.bytes_per_subint *
                                                (8 / pfi->hdr.nbits));
    } else {
        pfi->sub.data = pfi->sub.rawdata;
    }

    // Read the first row of data
    psrfits_read_subint(pfi);
    if (si->userwgts) // Always overwrite if using user weights
        memcpy(pfi->sub.dat_weights, si->userwgts, pfi->hdr.nchan * sizeof(float));

    // Reset the read counters since we'll re-read
    pfi->rownum--;
    pfi->tot_rows--;
    pfi->N -= pfi->hdr.nsblk;

    // Compute the subband properties, DM delays and offsets
    lofreq = pfi->sub.dat_freqs[0] - pfi->hdr.df * 0.5;
    for (ii = 0, cindex = 0 ; ii < si->nsub ; ii++) {
        dtmp = lofreq + ((double)ii + 0.5) * si->sub_df;
        si->sub_freqs[ii] = dtmp;
        si->sub_delays[ii] = delay_from_dm(si->dm, dtmp);
        // Determine the dispersion delays and convert them
        // to offsets in units of sample times
        for (jj = 0 ; jj < si->chan_per_sub ; jj++, cindex++) {
            si->chan_delays[cindex] = delay_from_dm(si->dm,
                                                    pfi->sub.dat_freqs[cindex]);
            si->chan_delays[cindex] -= si->sub_delays[ii];
            si->idelays[cindex] = (int)rint(si->chan_delays[cindex] / pfi->hdr.dt);
        }
    }

    // Now determine the earliest and latest delays
    si->max_early = si->max_late = 0;
    for (ii = 0 ; ii < si->nchan ; ii++) {
        if (si->idelays[ii] < si->max_early)
            si->max_early = si->idelays[ii];
        if (si->idelays[ii] > si->max_late)
            si->max_late = si->idelays[ii];
    }
    si->max_overlap = abs(si->max_early) + si->max_late;

    // This buffer will hold the float-converted input data, plus the bits
    // of data from the previous and next blocks
    si->fbuffer = (float *)calloc((si->buflen + 2 * si->max_overlap) *
                                  si->bufwid, sizeof(float));
    // The input data will be stored directly in the buffer space
    // So the following is really just an offset into the bigger buffer
    pfi->sub.fdata = si->fbuffer + si->max_overlap * si->bufwid;

    // Now start setting values for the output arrays
    *pfo = *pfi;

    // We are changing the number of bits in the data
    if (pfi->hdr.nbits != cmd->outbits)
        pfo->hdr.nbits = cmd->outbits;

    // Determine the length of the outputfiles to use
    if (cmd->filetimeP) {
        pfo->rows_per_file = 10 * \
            (int) rint(0.1 * (cmd->filetime / pfi->sub.tsubint));
    } else if (cmd->filelenP) {
        long long filelen;
        int bytes_per_subint;
        filelen = cmd->filelen * (1L<<30);  // In GB
        bytes_per_subint = (pfo->hdr.nbits * pfo->hdr.nchan *
                            pfo->hdr.npol * pfo->hdr.nsblk) / \
            (8 * si->chan_per_sub * cmd->dstime * (cmd->onlyIP ? 4 : 1));
        pfo->rows_per_file = filelen / bytes_per_subint;
        pfo->sub.bytes_per_subint = bytes_per_subint;
    } else {  // By default, keep the filesize roughly constant
        pfo->rows_per_file = pfi->rows_per_file * si->chan_per_sub *
            cmd->dstime * (cmd->onlyIP ? 4 : 1) *
            pfi->hdr.nbits / pfo->hdr.nbits;
    }

    pfo->filenum = 0; // This causes the output files to be created
    pfo->filename[0] = '\0';
    pfo->rownum = 1;
    pfo->tot_rows = 0;
    pfo->N = 0;
    // Set the "orig" values to those of the input file
    pfo->hdr.orig_nchan = pfi->hdr.nchan;
    pfo->hdr.orig_df = pfi->hdr.df;
    {
        char *inpath, *infile;
        split_path_file(pfi->basefilename, &inpath, &infile);
        sprintf(pfo->basefilename, "%s_subs", infile);
        free(inpath);
        free(infile);
    }
    // Reset different params
    pfo->sub.dat_freqs = si->sub_freqs;
    pfo->sub.dat_weights = si->weights;
    pfo->sub.dat_offsets = si->offsets;
    pfo->sub.dat_scales  = si->scales;
    pfo->hdr.ds_freq_fact = si->chan_per_sub;
    pfo->hdr.ds_time_fact = cmd->dstime;
    pfo->hdr.onlyI = cmd->onlyIP;
    pfo->hdr.chan_dm = si->dm;
    pfo->sub.rawdata = (unsigned char *)malloc(si->nsub * si->npol * si->buflen);
    if (pfo->hdr.nbits!=8) {
        pfo->sub.data = (unsigned char *)malloc(si->nsub * si->npol * si->buflen *
                                                (8 / pfo->hdr.nbits));
    } else {
        pfo->sub.data = pfo->sub.rawdata;
    }
    si->outfbuffer = (float *)calloc(si->nsub * si->npol * si->buflen,
                                     sizeof(float));
    pfo->sub.fdata = si->outfbuffer;

    // Now re-read the first row (i.e. for "real" this time)
    get_current_row(pfi, si);

    // Set the new weights properly
    new_weights(pfi, pfo);

    // Now fill the first part of si->fbuffer with the chan_avgs so that
    // it acts like a previously read block (or row)
    fill_chans_with_avgs(si->max_overlap, si->bufwid,
                         si->fbuffer, si->chan_avgs);
}
    virtual BOOL on_key(HELEMENT he, HELEMENT target, UINT event_type, UINT code, UINT keyboardStates ) 
    { 
      if( event_type != KEY_DOWN )
        return false;
      
      dom::element table = get_table(he);
      switch( code )
      {
        case VK_DOWN: 
          {
             dom::element c = get_current_row( table );
             int idx = c.is_valid()? (c.index() + 1):fixed_rows(table);
             while( idx < (int)table.children_count() )
             {
                 dom::element row = table.child(idx);
                 if( aux::wcseq(row.get_style_attribute("display"),L"none" ))
                 {
                   ++idx;
                   continue;
                 }
                 set_current_row(table, row, keyboardStates); 
                 break;
             }
          }
          return TRUE;
        case VK_UP:             
          {
             dom::element c = get_current_row( table );
             int idx = c.is_valid()? (c.index() - 1):(table.children_count() - 1);
             while( idx >= fixed_rows(table) )
             {
                 dom::element row = table.child(idx);
                 if( aux::wcseq(row.get_style_attribute("display"),L"none" ))
                 {
                   --idx;
                   continue;
                 }
                 set_current_row(table, row, keyboardStates); 
                 break;
             }
          }
          return TRUE;
        case VK_PRIOR:
          {
          }
          return TRUE;

        case VK_NEXT:
          {
          }
          return TRUE;

        case VK_HOME:
          {
          }
          return TRUE;

        case VK_END:
          {
          }
          return TRUE;
      }
      return FALSE; 
    }