/***************************************************************************
 *             __________               __   ___.
 *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
 *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
 *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
 *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
 *                     \/            \/     \/    \/            \/
 * $Id: keyboard.c,v 1.1 2002/06/16 23:21:57 adiamas Exp $
 *
 * Copyright (C) 2002 Robert E. Hak (rhak at ramapo.edu)
 *
 * All files in this archive are subject to the GNU General Public License.
 * See the file COPYING in the source tree root for full license agreement.
 *
 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
 * KIND, either express or implied.
 *
 ****************************************************************************/

#include "config.h"

#ifdef HAVE_LCD_BITMAP

#include "letters.h"
#include "lcd.h"
#include "button.h"
#include "kernel.h"
#include <string.h>

#ifdef SIMULATOR
#include <stdio.h>
#endif

#define MAX_CHARS_PER_LINE    12
#define TOTAL_CHARS           36
#define FONT_SIZE              0
#define KB_LINE                0
#define MENU_OPTIONS           3

char *kboard = "abcdefghijklmnopqrstuvwxyz0123456789-_[]().<> :,";
char *menu = "Del  Shift  Save";
/*char input[256]; */

int font_w, font_h, initial_x;
int current_line;
int current_char;
int lines;
int menu_line;
int text_line_y;
int text_line_x;
bool shifted;
int max_input;
char *input;

/* Len is the count of last char in the buffer
   Index is where you are placing the _current_ char */
int input_index;
int input_len;

void draw_text_entry() {
	int index = 0;

	if ((input_len*font_w) >= LCD_WIDTH)
        index = input_len - (LCD_WIDTH/font_w);
    else
        index = 0;

	lcd_clearrect(text_line_x, text_line_y, LCD_WIDTH, font_h);
    lcd_putsxy(text_line_x, text_line_y, input+index, FONT_SIZE);
	lcd_update_rect(text_line_x, text_line_y, LCD_WIDTH, font_h);
}

/* This _only_ displays the keyboard and menu.  We do not clear display
   because that would clear the entry line */
void display_keyboard()
{
    int i = 0, j = 0;
    unsigned char buf[2];

	lcd_clear_display();

    for(i=KB_LINE, j=0; i < lines+KB_LINE; i++) {
        int k = 0;
        int pad = 0;
        
        for(k = 0; k < MAX_CHARS_PER_LINE; k++) {
			if (shifted && (kboard[j] >= 'a') && (kboard[j] <= 'z'))
				buf[0] = kboard[j++] - 0x20;
			else
				buf[0] = kboard[j++];

            buf[1] = 0;
            lcd_putsxy(LCD_WIDTH/2-initial_x+pad, font_h*i+1, buf, FONT_SIZE); 
            pad+=font_w+2;
        }
    }

    /* draw the menu in */
    j = (LCD_WIDTH/2)-strlen(menu)/2*font_w;
    lcd_putsxy(j, menu_line, menu, FONT_SIZE);

	/* draw cursor */
    lcd_invertrect(LCD_WIDTH/2-initial_x+(current_char*(font_w+2)), 
				   current_line*font_h+1, font_w, font_h);

	lcd_update();

	draw_text_entry();
}

/* Draw a selected key on the entry line */
void select_key() {
    int index = 0;

    if (input_len == (max_input-1)) {
        lcd_clearrect(0, LCD_HEIGHT-(font_h*3), LCD_WIDTH, LCD_HEIGHT); 

        lcd_putsxy(0, LCD_HEIGHT-(font_h*2), "Input Buffer Full", FONT_SIZE);
		lcd_update_rect(text_line_x, text_line_y, LCD_WIDTH, font_h);
        sleep(HZ/2);

        lcd_putsxy(0, LCD_HEIGHT-(font_h*2), input+input_len-LCD_WIDTH, 
                   FONT_SIZE);
		lcd_update_rect(text_line_x, text_line_y, LCD_WIDTH, font_h);

        return;
    }

    index = ((current_line-KB_LINE) * MAX_CHARS_PER_LINE) + current_char;

	if (shifted && (kboard[index] >= 'a') && (kboard[index] <= 'z'))
		input[input_index++] = kboard[index] - 0x20;
	else
		input[input_index++] = kboard[index];

    input_len++;

	draw_text_entry();
}

/* Move the cursor up, down, left, right */
void move_cursor(int b) {
    int x_loc = 0;
    int y_loc = 0;
    int old_line = current_line;
    int old_char = current_char;
    
    switch(b) {
    case BUTTON_LEFT:
    case BUTTON_LEFT | BUTTON_REPEAT:
        if (current_char == 0)
            current_char = MAX_CHARS_PER_LINE-1;
        else
            current_char--;
        break;
    case BUTTON_RIGHT:
    case BUTTON_RIGHT | BUTTON_REPEAT:
        if (current_char == (MAX_CHARS_PER_LINE - 1))
            current_char=0;
        else
            current_char++;
        break;
    case BUTTON_UP:
    case BUTTON_UP | BUTTON_REPEAT:
        if (current_line == KB_LINE)
            current_line = lines+KB_LINE-1;
        else
            current_line--;
        break;
    case BUTTON_DOWN:
    case BUTTON_DOWN | BUTTON_REPEAT:
        if (current_line == (lines+KB_LINE-1))
            current_line = KB_LINE;
        else
            current_line++;
        break;
    }

    /* Set new cursor on chars */
    /* Initial placement + char widths + padding */
    x_loc = LCD_WIDTH/2-initial_x+(font_w*current_char)+(current_char * 2);
    y_loc = (current_line*font_h)+1;
    lcd_invertrect(x_loc, y_loc, font_w, font_h);
    
    /* Erase old cursor */
    x_loc = LCD_WIDTH/2-initial_x+(font_w*old_char)+(old_char * 2);
    y_loc = (old_line*font_h)+1;
    lcd_invertrect(x_loc, y_loc, font_w, font_h);
    
    lcd_update();
}

/* Delete the last displayed char in the entry text */
void delete_key() {
	int index = 0;

	input[--input_index] = 0;
	input_len--;

    if ((input_len*font_w) >= LCD_WIDTH)
        index = input_len - (LCD_WIDTH/font_w);
    else
        index = 0;

	/* delete the entire line and redraw it */
	lcd_clearrect(0, LCD_HEIGHT-(font_h*3), LCD_WIDTH, font_h); 
    lcd_putsxy(0, LCD_HEIGHT-(font_h*3), input+index, FONT_SIZE);

    lcd_update();
}

void keyboard(char *buffer, int len)

{
    int b = 0, l = 0;

    /* prep all the global values we need */
    lcd_getfontsize(FONT_SIZE, &font_w, &font_h);
    current_line = KB_LINE;
	shifted = false;

	max_input = len;
	input = buffer;

    current_char = 0;
    input_index = 0;
    input_len = 0;

    menu_line = LCD_HEIGHT-font_h;

	text_line_y = LCD_HEIGHT-(font_h*3);
	text_line_x = 0;

    memset(input, 0, max_input);

    l = strlen(kboard);
    lines = l / MAX_CHARS_PER_LINE;

    if ((lines * MAX_CHARS_PER_LINE) != l)
        lines++;

    /* center keyboard */
    /* We add MAX_CHARS_PER_LINE*2 for padding between letters */
    initial_x = (MAX_CHARS_PER_LINE * font_w) + MAX_CHARS_PER_LINE*2;

    if (initial_x%2 != 0)
        initial_x = ((initial_x+1/2)+(font_w/2));
    else
        initial_x /= 2;

    /* Display initial keyboard */
    lcd_clear_display(); 
    display_keyboard();

    while(1) {
        switch(b = button_get_w_tmo(HZ/2)) {
        case BUTTON_OFF:
			memset(input, 0, max_input);
            return;
		case BUTTON_F1:
			delete_key();
			break;
		case BUTTON_F2:
			shifted ? (shifted=false) : (shifted=true);
			display_keyboard();
			break;
		case BUTTON_F3:
			return;
			break;
        case BUTTON_PLAY:
            select_key();
            break;
        default:
            move_cursor(b);
        }
    }
}

#endif














