/*************************************************************************** * __________ __ ___. * Open \______ \ ____ ____ | | _\_ |__ _______ ___ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ * \/ \/ \/ \/ \/ * $Id$ * * Copyright (C) 2003 by Francois Boucher * * 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 #include "lcd.h" #include "button.h" #include "kernel.h" #include "version.h" #include "sprintf.h" #include "lcd-charset.h" #include "lang.h" #include "debug.h" /* Two functions that are part of the firmware for the Neo-builds only. TODO: make them proper "official" firmware functions or replace them with apps code */ extern void lcd_cursor(int x, int y); extern int button_add(unsigned int button); #define KEYBOARD_MAX_LENGTH 255 static unsigned char* kbd_screens[3] = { "ABCDEFGHIJKLMNOPQRSTUVWXYZ", "abcdefghijklmnopqrstuvwxyz", " !\"#$%&'()*+,-./0123456789;<=>?@[]^_`{|}" }; static unsigned char* kbd_screens_names[3] = { "Capitals", "Small", "Others" }; static void kbd_show_legend( int nb ) { char buf[24]; snprintf(buf, sizeof(buf), "[%s]", kbd_screens_names[nb] ); lcd_puts( 0, 1, buf ); lcd_puts( 0, 2, kbd_screens[nb] ); lcd_puts( 0, 3, &kbd_screens[nb][20] ); } /* Returns text len Max = KEYBOARD_MAX_LENGTH characters. This function MUST NOT fill in more than 'buflen' bytes into the given buffer! */ static char kbdbuffer[KEYBOARD_MAX_LENGTH+1]; /* no use to alloc this huge one on the stack */ int kbd_input(char* text, int buflen) { char* pstart; char* pcursor; char* pold; int bufferlen; char cursorpos = 0; int ret = 0; bool done = false; int key; int screen = 0; int screenidx = -1; unsigned char * pcurscreen = kbd_screens[0]; bool ctl; bufferlen = strlen(text); if(bufferlen > KEYBOARD_MAX_LENGTH) bufferlen = KEYBOARD_MAX_LENGTH; strncpy(kbdbuffer, text, bufferlen); kbdbuffer[bufferlen] = 0; lcd_clear_display(); /* Initial setup */ lcd_puts(0, 0, kbdbuffer); kbd_show_legend(screen); lcd_cursor(cursorpos, 0); lcd_write(true, LCD_BLINKCUR); pstart = pcursor = kbdbuffer; while(!done) { /* We want all the keys except the releases and the repeats */ key = button_get(true); if( key & BUTTON_IR) ctl = key & (NEO_IR_BUTTON_PLAY|NEO_IR_BUTTON_STOP|NEO_IR_BUTTON_BROWSE); else ctl = key & (BUTTON_PLAY|BUTTON_STOP|BUTTON_MENU); if( ctl ) { /* These key do not change the first line */ switch( key ) { case BUTTON_MENU: case BUTTON_IR|NEO_IR_BUTTON_BROWSE: /* Toggle legend screen */ screen++; if( screen == 3 ) screen = 0; pcurscreen = kbd_screens[screen]; screenidx = -1; kbd_show_legend( screen ); /* Restore cursor */ lcd_cursor( cursorpos, 0 ); break; case BUTTON_PLAY: case BUTTON_IR|NEO_IR_BUTTON_PLAY: if( bufferlen ) { strncpy(text, kbdbuffer, bufferlen); text[bufferlen] = 0; ret = bufferlen; } /* fallthrough */ case BUTTON_STOP: case BUTTON_IR|NEO_IR_BUTTON_STOP: /* Remove blinking cursor */ lcd_write(true,LCD_OFFCUR); done = true; } } else { switch( key ) { case BUTTON_PROGRAM: case BUTTON_PROGRAM|BUTTON_REPEAT: case BUTTON_IR|NEO_IR_BUTTON_PROGRAM: /* Delete char at pcursor */ /* Check if we are at the last char */ if( *(pcursor+1) != 0 ) { /* move rest of the string to the left in buffer */ pold = pcursor; while( *pcursor ){ *pcursor = *(pcursor+1); pcursor++; } /* Restore position */ pcursor = pold; } else { *pcursor = 0; pcursor--; cursorpos--; } bufferlen--; break; case BUTTON_IR|NEO_IR_BUTTON_EQ: case BUTTON_SELECT|BUTTON_LEFT: /* Insert left */ if(bufferlen >= buflen) break; pold = pcursor; /* Goto end */ while( *pcursor ) pcursor++; /* Move string content to the right */ while( pcursor >= pold ){ *(pcursor+1) = *pcursor; pcursor--; } pcursor = pold; *pcursor = ' '; bufferlen++; break; case BUTTON_IR|NEO_IR_BUTTON_MUTE: case BUTTON_SELECT|BUTTON_RIGHT: /* Insert Right */ if(bufferlen >= buflen) break; pold = pcursor; /* Goto end */ while(*pcursor) pcursor++; /* Move string content to the right */ while(pcursor > pold){ *(pcursor+1) = *pcursor; pcursor--; } pcursor = pold; *(pcursor+1) = ' '; bufferlen++; button_add( BUTTON_RIGHT ); break; case BUTTON_LEFT: case BUTTON_REPEAT|BUTTON_LEFT: case BUTTON_IR|NEO_IR_BUTTON_REWIND: case BUTTON_IR|NEO_IR_BUTTON_REWIND|BUTTON_REPEAT: /* Move cursor left. Shift text right if all the way to the left */ /* Check for start of string */ if(pcursor > kbdbuffer) { screenidx = -1; cursorpos--; pcursor--; /* Check if were going off the screen */ if( cursorpos == -1 ) { cursorpos = 0; /* Shift text right if we are */ pstart--; } } break; case BUTTON_RIGHT: case BUTTON_REPEAT|BUTTON_RIGHT: case BUTTON_IR|NEO_IR_BUTTON_FFORWARD: case BUTTON_IR|NEO_IR_BUTTON_FFORWARD|BUTTON_REPEAT: /* Move cursor right. Shift text left if all the way to the right */ /* Check for end of string */ if( *(pcursor+1) != 0 ) { screenidx = -1; cursorpos++; pcursor++; /* Check if were going of the screen */ if( cursorpos == 20 ) { cursorpos = 19; /* Shift text left if we are */ pstart++; } } break; case BUTTON_UP: case BUTTON_UP|BUTTON_REPEAT: case BUTTON_IR|NEO_IR_BUTTON_VOLUP: case BUTTON_IR|NEO_IR_BUTTON_VOLUP|BUTTON_REPEAT: screenidx += 2; /* fallthrough */ case BUTTON_DOWN: case BUTTON_DOWN|BUTTON_REPEAT: case BUTTON_IR|NEO_IR_BUTTON_VOLDN: case BUTTON_IR|NEO_IR_BUTTON_VOLDN|BUTTON_REPEAT: screenidx--; if( screenidx < 0 ) screenidx = strlen(pcurscreen)-1; if( pcurscreen[screenidx] == 0 ) screenidx = 0; /* Changes the character over the cursor */ *pcursor = pcurscreen[screenidx]; } lcd_puts( 0, 0, pstart); lcd_cursor( cursorpos, 0 ); } } return ret; }