/***********************************************
 *  keys.c                                 
 *                                            
 *  Copyright 2001 Eric Kratzer.
 *  Includes Xaudio software Copyright (C)
 *           1996-2000 Xaudio Corporation
 *           All Rights Reserved.               
 *
 *  This file is part of imp3sh.
 *                                            
 *  imp3sh is free software; you can distribute
 *  it and/or modify it under the terms of the
 *  GNU General Public License as published by
 *  the Free Software Foundation; either version
 *  2 of the License, or (at your option) any
 *  later version.
 *
 *  imp3sh is distributed in the hope that
 *  it will be useful, but WITHOUT ANY WARRANTY;
 *  without even the implied warranty of 
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR
 *  PURPOSE. See the GNU General Public License
 *  for more details.
 *
 *  You should have recieved a copy of the GNU
 *  General Public License along with imp3sh; if
 *  not, write to the Free Software Foundation,
 *  Inc., 59 Temple Place, Suite 330, Boston MA
 *  02111-1307 USA
 ************************************************/

/************************************
 *          Include Files           *
 ************************************/

#include "imp3sh.h"

/************************************
 *       External References        *
 ************************************/

extern XA_VolumeInfo vinfo;
extern XA_PositionInfo pinfo;
extern XA_TimecodeInfo tinfo, dinfo;

extern DCharBuf *chist_list, *args;

extern DJKeyDef djkeys[];

extern TermCtrl t_ctrl[];

extern char *cmnd, *last_expl;

extern int comm_len, edit_pos;

extern flag_t key_press, auto_report, djmode_enabled;

/*** Special character handling ****/

void do_up_arrow()
{
    if (!outb_empty())
	return;

    if (chist_list->pos) {
	safe_strcpy(cmnd, g_dbuf(chist_list, --chist_list->pos),
		    COMM_SIZE);
	comm_len = edit_pos = get_strlen(cmnd);
	last_expl = NULL;
	update_prompt(TRUE);
    } else
	mybeep();
}

void do_down_arrow()
{
    if (!outb_empty())
	return;

    if (chist_list->pos < chist_list->len - 1) {
	safe_strcpy(cmnd, g_dbuf(chist_list, ++chist_list->pos),
		    COMM_SIZE);
	comm_len = edit_pos = get_strlen(cmnd);
	last_expl = NULL;
	update_prompt(TRUE);
    } else if (chist_list->pos == chist_list->len - 1) {
	clear_comm();
	update_prompt(TRUE);
    } else
	mybeep();
}

void do_right_arrow()
{
    if (edit_pos < comm_len && outb_empty()) {
	edit_pos++;
	last_expl = NULL;
	update_prompt(TRUE);
    } else
	mybeep();
}

void do_left_arrow()
{
    if (edit_pos > 0 && outb_empty()) {
	edit_pos--;
	last_expl = NULL;
	update_prompt(TRUE);
    } else
	mybeep();
}

void fastf_key()
{
    int offset;

    offset = pinfo.offset + OFFSET_JUMP;

    if (pinfo.offset == pinfo.range)
	return;
    else if (offset > pinfo.range)
	offset = pinfo.range;

    seek_internal(offset, pinfo.range);
}

void rewind_key()
{
    int offset;

    offset = pinfo.offset - OFFSET_JUMP;

    if (pinfo.offset == 0)
	return;
    else if (offset < 0)
	offset = 0;

    seek_internal(offset, pinfo.range);
}

void inc_masvol_key()
{
    int mas;

    mas = vinfo.master_level + VOLUME_JUMP;

    if (vinfo.master_level == 100)
	return;
    else if (mas > 100)
	mas = 100;

    mixer_internal(vinfo.balance, vinfo.pcm_level, mas);
}

void dec_masvol_key()
{
    int mas;

    mas = vinfo.master_level - VOLUME_JUMP;

    if (vinfo.master_level == 0)
	return;
    else if (mas < 0)
	mas = 0;

    mixer_internal(vinfo.balance, vinfo.pcm_level, mas);
}

void inc_pcmvol_key()
{
    int pcm;

    pcm = vinfo.pcm_level + VOLUME_JUMP;

    if (vinfo.pcm_level == 100)
	return;
    else if (pcm > 100)
	pcm = 100;

    mixer_internal(vinfo.balance, pcm, vinfo.master_level);
}

void dec_pcmvol_key()
{
    int pcm;

    pcm = vinfo.pcm_level - VOLUME_JUMP;

    if (vinfo.pcm_level == 0)
	return;
    else if (pcm < 0)
	pcm = 0;

    mixer_internal(vinfo.balance, pcm, vinfo.master_level);
}

void bal_right_key()
{
    int bal;

    bal = vinfo.balance + BALANCE_JUMP;

    if (vinfo.balance == 100)
	return;
    else if (bal > 100)
	bal = 100;

    mixer_internal(bal, vinfo.pcm_level, vinfo.master_level);
}

void bal_left_key()
{
    int bal;

    bal = vinfo.balance - BALANCE_JUMP;

    if (vinfo.balance == 0)
	return;
    else if (bal < 0)
	bal = 0;

    mixer_internal(bal, vinfo.pcm_level, vinfo.master_level);
}

/* dj mode keys */

void dj_get_position(int ndx)
{
    if (ndx >= 0 && ndx < MAX_DJ_KEYS) {
	djkeys[ndx].set = TRUE;
	djkeys[ndx].offset = (tinfo.h * 3600) + (tinfo.m * 60) + tinfo.s;
	djkeys[ndx].offset *= 100;

	if (djkeys[ndx].offset > 35)
	    djkeys[ndx].offset += (tinfo.f - 35);
	else
	    djkeys[ndx].offset += tinfo.f;

	djkeys[ndx].range = (dinfo.h * 3600) + (dinfo.m * 60) + dinfo.s;
	djkeys[ndx].range *= 100;
	djkeys[ndx].range += dinfo.f;
    }
}

void dj_set_position(int ndx)
{
    if (ndx >= 0 && ndx < MAX_DJ_KEYS && djkeys[ndx].set)
	seek_internal(djkeys[ndx].offset, djkeys[ndx].range);
}

void handle_special_char(int spec)
{
    switch (spec) {
    case UP_ARROW:
    case UP_ARROW_2:
	do_up_arrow();
	break;
    case DOWN_ARROW:
    case DOWN_ARROW_2:
	do_down_arrow();
	break;
    case RIGHT_ARROW:
    case RIGHT_ARROW_2:
	do_right_arrow();
	break;
    case LEFT_ARROW:
    case LEFT_ARROW_2:
	do_left_arrow();
	break;
    case DELETE_KEY:
	delete_char();
	break;
    case PAGEUP_KEY:
	next_file();
	break;
    case PAGEDOWN_KEY:
	previous_file();
	break;
    case HOME_KEY:
	fastf_key();
	break;
    case END_KEY:
	rewind_key();
	break;
    case F1_KEY:
	if (djmode_enabled)
	    dj_get_position(0);
	else {
	    c_dbuf(args);
	    play_comm();
	}
	break;
    case F2_KEY:
	if (djmode_enabled)
	    dj_get_position(1);
	else
	    pause_file();
	break;
    case F3_KEY:
	if (djmode_enabled)
	    dj_get_position(2);
	else
	    resume_file();
	break;
    case F4_KEY:
	if (djmode_enabled)
	    dj_get_position(3);
	else
	    stop_file();
	break;
    case F5_KEY:
	if (djmode_enabled)
	    dj_get_position(4);
	else
	    inc_masvol_key();
	break;
    case F6_KEY:
	if (djmode_enabled)
	    dj_get_position(5);
	else
	    dec_masvol_key();
	break;
    case F7_KEY:
	if (djmode_enabled)
	    dj_set_position(0);
	else
	    inc_pcmvol_key();
	break;
    case F8_KEY:
	if (djmode_enabled)
	    dj_set_position(1);
	else
	    dec_pcmvol_key();
	break;
    case F9_KEY:
	if (djmode_enabled)
	    dj_set_position(2);
	else
	    bal_left_key();
	break;
    case F10_KEY:
	if (djmode_enabled)
	    dj_set_position(3);
	else
	    bal_right_key();
	break;
    case F11_KEY:
	if (djmode_enabled)
	    dj_set_position(4);
	else if (outb_empty()) {
	    outstr("\n");
	    print_status();
	    update_prompt(FALSE);
	}
	break;
    case F12_KEY:
	if (djmode_enabled)
	    dj_set_position(5);
	else if (outb_empty()) {
	    outstr("\n");
	    c_dbuf(args);
	    print_list_status();
	    update_prompt(FALSE);
	}
	break;
    default:
	break;
    }
}

int check_special_chars(char *ins)
{
    int i, ln;

    for (i = UP_ARROW; i < NUM_TERM_CTRL; i++) {
	ln = get_strlen(t_ctrl[i].string);

	if (ln && strncmp(ins, t_ctrl[i].string, ln) == 0) {
	    key_press = TRUE;
	    handle_special_char(i);
	    key_press = FALSE;
	    return TRUE;
	}
    }

    return FALSE;
}
