blob: 32933cdcfdc5118eb703c52c5a17a187d8d81417 [file] [log] [blame]
Björn Stenbergc8cb6ff2002-12-04 15:04:43 +00001/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
Nicolas Pennequin396aeaf2009-03-23 17:08:46 +000010 * Copyright (C) 2002 by Björn Stenberg
Björn Stenbergc8cb6ff2002-12-04 15:04:43 +000011 *
Daniel Stenberg2acc0ac2008-06-28 18:10:04 +000012 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
Björn Stenbergc8cb6ff2002-12-04 15:04:43 +000016 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
Björn Stenbergc8cb6ff2002-12-04 15:04:43 +000021#include "kernel.h"
Jens Arnold0b31a002005-02-07 00:56:26 +000022#include "system.h"
Björn Stenbergc8cb6ff2002-12-04 15:04:43 +000023#include "version.h"
Björn Stenbergc8cb6ff2002-12-04 15:04:43 +000024#include <string.h>
Björn Stenbergc8cb6ff2002-12-04 15:04:43 +000025#include "font.h"
Björn Stenbergaa2972d2003-03-10 15:09:27 +000026#include "screens.h"
Jörg Hohensohn9e049572004-05-21 06:29:55 +000027#include "talk.h"
28#include "settings.h"
Linus Nielsen Feltzingade5d7b2004-07-26 16:06:59 +000029#include "misc.h"
Marcoen Hirschbergb0fee172005-12-06 13:27:15 +000030#include "rbunicode.h"
Kevin Ferrare1a1abf22005-11-20 01:02:14 +000031#include "buttonbar.h"
Miika Pekkarinen9d918c92005-12-02 19:41:09 +000032#include "logf.h"
Frank Dischner75c3d0b2006-03-29 16:21:42 +000033#include "hangul.h"
Martin Scarratt0ba22042006-08-22 13:21:13 +000034#include "action.h"
Jonathan Gordon6a5cc0b2007-04-16 09:14:36 +000035#include "icon.h"
Stéphane Doyond529a382007-10-10 02:28:58 +000036#include "pcmbuf.h"
37#include "lang.h"
Bertrik Sikkene15f8a22008-05-03 08:35:14 +000038#include "keyboard.h"
Jonathan Gordon45aa9a22009-01-05 10:25:41 +000039#include "viewport.h"
Bertrik Sikken4a70a072009-03-08 20:57:37 +000040#include "file.h"
Björn Stenbergc8cb6ff2002-12-04 15:04:43 +000041
Frank Dischner75c3d0b2006-03-29 16:21:42 +000042#ifndef O_BINARY
43#define O_BINARY 0
Jens Arnold13fcd682005-10-08 07:12:28 +000044#endif
45
Frank Dischner75c3d0b2006-03-29 16:21:42 +000046
Frank Dischner75c3d0b2006-03-29 16:21:42 +000047#define DEFAULT_MARGIN 6
48#define KBD_BUF_SIZE 500
Jörg Hohensohn705ad512004-10-22 17:00:30 +000049
Daniel Stenberg01377e22005-06-29 12:47:24 +000050#if (CONFIG_KEYPAD == IRIVER_H100_PAD) || \
51 (CONFIG_KEYPAD == IRIVER_H300_PAD)
Michael Sevakis97019542007-03-05 02:07:17 +000052#define KBD_CURSOR_KEYS /* certain key combos move the cursor even if not
53 in line edit mode */
54#define KBD_MODES /* I-Rivers can use picker, line edit and cursor keys */
Martin Scarratt0ba22042006-08-22 13:21:13 +000055#define KBD_MORSE_INPUT /* I-Rivers have a Morse input mode */
Jens Arnold259e3542005-01-23 01:01:14 +000056
Jörg Hohensohn705ad512004-10-22 17:00:30 +000057#elif CONFIG_KEYPAD == ONDIO_PAD /* restricted Ondio keypad */
Jens Arnold7b95e602004-11-14 23:08:08 +000058#define KBD_MODES /* Ondio uses 2 modes, picker and line edit */
Jens Arnold259e3542005-01-23 01:01:14 +000059
Jens Arnold9afdf992007-10-10 06:19:54 +000060#elif (CONFIG_KEYPAD == IPOD_1G2G_PAD) || (CONFIG_KEYPAD == IPOD_3G_PAD) \
61 || (CONFIG_KEYPAD == IPOD_4G_PAD)
Dave Chapmanfe772402005-11-19 03:19:12 +000062#define KBD_MODES /* iPod uses 2 modes, picker and line edit */
Martin Scarratt8ab6ac72006-12-18 16:57:48 +000063#define KBD_MORSE_INPUT
Dave Chapman64e52392005-11-12 16:07:17 +000064
Dave Chapmand83e9292006-01-12 00:35:50 +000065#elif CONFIG_KEYPAD == IRIVER_IFP7XX_PAD
Dave Chapmand83e9292006-01-12 00:35:50 +000066#define KBD_MODES /* iFP7xx uses 2 modes, picker and line edit */
Dave Chapmand83e9292006-01-12 00:35:50 +000067
Jens Arnold76614b32008-03-18 22:59:39 +000068#elif (CONFIG_KEYPAD == IAUDIO_X5M5_PAD) || (CONFIG_KEYPAD == IAUDIO_M3_PAD)
69#define KBD_MODES /* iAudios use 2 modes, picker and line edit */
Marcoen Hirschberg338e2bb2006-02-24 15:42:52 +000070
Daniel Stenberg1e88be52006-08-03 20:17:25 +000071#elif CONFIG_KEYPAD == IRIVER_H10_PAD
Daniel Stenberg1e88be52006-08-03 20:17:25 +000072#define KBD_MODES /* iriver H10 uses 2 modes, picker and line edit */
Nils Wallménius8a71f1a2007-01-04 14:36:04 +000073#define KBD_MORSE_INPUT
Nils Wallménius0eb14432007-03-04 21:59:00 +000074
75#elif CONFIG_KEYPAD == GIGABEAT_PAD
Michael Sevakisa8140eb2007-05-04 17:15:55 +000076#define KBD_CURSOR_KEYS
77#define KBD_MODES
Nils Wallménius0eb14432007-03-04 21:59:00 +000078#define KBD_MORSE_INPUT
Michael Sevakis3d7ce022007-06-03 16:27:23 +000079
Thomas Martitz842d2bc2009-03-30 15:45:15 +000080#elif CONFIG_KEYPAD == SANSA_E200_PAD \
81 || CONFIG_KEYPAD == SANSA_FUZE_PAD
Michael Sevakis3d7ce022007-06-03 16:27:23 +000082#define KBD_CURSOR_KEYS
83#define KBD_MODES
Marcoen Hirschberg88c60e62008-10-08 11:02:51 +000084
Marianne Arnold78c3f1c2009-06-20 11:03:52 +000085#elif CONFIG_KEYPAD == SANSA_C200_PAD
86#define KBD_CURSOR_KEYS
87#define KBD_MODES
88
Marcoen Hirschberg88c60e62008-10-08 11:02:51 +000089#elif CONFIG_KEYPAD == MROBE100_PAD
90#define KBD_MORSE_INPUT
Jörg Hohensohn705ad512004-10-22 17:00:30 +000091#endif
92
Michael Sevakis82b26d22007-03-06 07:59:25 +000093struct keyboard_parameters
94{
Martin Scarrattef8317b2006-07-19 12:07:51 +000095 const unsigned char* default_kbd;
96 int DEFAULT_LINES;
97 unsigned short kbd_buf[KBD_BUF_SIZE];
98 int nchars;
99 int font_w;
100 int font_h;
101 struct font* font;
102 int curfont;
103 int main_x;
104 int main_y;
105 int max_chars;
106 int max_chars_text;
107 int lines;
108 int pages;
109 int keyboard_margin;
110 int old_main_y;
111 int curpos;
112 int leftpos;
113 int page;
114 int x;
115 int y;
Michael Sevakis11e45a32007-03-06 05:43:04 +0000116#ifdef KBD_MODES
117 bool line_edit;
118#endif
119 bool hangul;
120 unsigned short hlead, hvowel, htail;
Martin Scarrattef8317b2006-07-19 12:07:51 +0000121};
Jörg Hohensohn705ad512004-10-22 17:00:30 +0000122
Michael Sevakis82b26d22007-03-06 07:59:25 +0000123static struct keyboard_parameters kbd_param[NB_SCREENS];
Frank Dischner75c3d0b2006-03-29 16:21:42 +0000124static bool kbd_loaded = false;
Frank Dischner75c3d0b2006-03-29 16:21:42 +0000125
126#ifdef KBD_MORSE_INPUT
Miika Pekkarinen9d918c92005-12-02 19:41:09 +0000127/* FIXME: We should put this to a configuration file. */
Zakk Robertsa1db4312006-04-22 09:43:43 +0000128static const char *morse_alphabets =
Miika Pekkarinen783428d2005-12-21 12:46:50 +0000129 "abcdefghijklmnopqrstuvwxyz1234567890,.?-@ ";
Miika Pekkarinen9d918c92005-12-02 19:41:09 +0000130static const unsigned char morse_codes[] = {
131 0x05,0x18,0x1a,0x0c,0x02,0x12,0x0e,0x10,0x04,0x17,0x0d,0x14,0x07,
132 0x06,0x0f,0x16,0x1d,0x0a,0x08,0x03,0x09,0x11,0x0b,0x19,0x1b,0x1c,
Miika Pekkarinen783428d2005-12-21 12:46:50 +0000133 0x2f,0x27,0x23,0x21,0x20,0x30,0x38,0x3c,0x3e,0x3f,
Miika Pekkarinenda932dc2005-12-04 08:45:24 +0000134 0x73,0x55,0x4c,0x61,0x5a,0x80 };
Miika Pekkarinen9d918c92005-12-02 19:41:09 +0000135
136static bool morse_mode = false;
137#endif
138
Frank Dischner75c3d0b2006-03-29 16:21:42 +0000139/* Loads a custom keyboard into memory
140 call with NULL to reset keyboard */
141int load_kbd(unsigned char* filename)
142{
Michael Sevakis11e45a32007-03-06 05:43:04 +0000143 int fd, l;
Martin Scarrattaf5393c2006-07-23 18:33:43 +0000144 int i = 0;
Antoine Cellerier4735e8e2006-07-23 18:54:00 +0000145 unsigned char buf[4];
Frank Dischner75c3d0b2006-03-29 16:21:42 +0000146
Michael Sevakis11e45a32007-03-06 05:43:04 +0000147 if (filename == NULL)
148 {
Frank Dischner75c3d0b2006-03-29 16:21:42 +0000149 kbd_loaded = false;
150 return 0;
151 }
152
Dominik Riebeling02103a22008-08-02 20:39:03 +0000153 fd = open_utf8(filename, O_RDONLY|O_BINARY);
Frank Dischner75c3d0b2006-03-29 16:21:42 +0000154 if (fd < 0)
155 return 1;
156
Michael Sevakis11e45a32007-03-06 05:43:04 +0000157 while (read(fd, buf, 1) == 1 && i < KBD_BUF_SIZE)
158 {
159 /* check how many bytes to read for this character */
160 static const unsigned char sizes[4] = { 0x80, 0xe0, 0xf0, 0xf5 };
161 size_t count;
162
163 for (count = 0; count < ARRAYLEN(sizes); count++)
164 {
165 if (buf[0] < sizes[count])
166 break;
Martin Scarrattef8317b2006-07-19 12:07:51 +0000167 }
Martin Scarrattaf5393c2006-07-23 18:33:43 +0000168
Michael Sevakis11e45a32007-03-06 05:43:04 +0000169 if (count >= ARRAYLEN(sizes))
170 continue; /* Invalid size. */
171
172 if (read(fd, &buf[1], count) != (ssize_t)count)
173 {
Martin Scarrattaf5393c2006-07-23 18:33:43 +0000174 close(fd);
175 kbd_loaded = false;
176 return 1;
177 }
Antoine Cellerier4735e8e2006-07-23 18:54:00 +0000178
Martin Scarrattaf5393c2006-07-23 18:33:43 +0000179 FOR_NB_SCREENS(l)
Michael Sevakis82b26d22007-03-06 07:59:25 +0000180 utf8decode(buf, &kbd_param[l].kbd_buf[i]);
Antoine Cellerier4735e8e2006-07-23 18:54:00 +0000181
Michael Sevakis82b26d22007-03-06 07:59:25 +0000182 if (kbd_param[0].kbd_buf[i] != 0xFEFF &&
183 kbd_param[0].kbd_buf[i] != '\r') /*skip BOM & carriage returns */
Michael Sevakis11e45a32007-03-06 05:43:04 +0000184 {
Martin Scarrattaf5393c2006-07-23 18:33:43 +0000185 i++;
Michael Sevakis11e45a32007-03-06 05:43:04 +0000186 }
Frank Dischner75c3d0b2006-03-29 16:21:42 +0000187 }
188
189 close(fd);
190 kbd_loaded = true;
Michael Sevakis11e45a32007-03-06 05:43:04 +0000191
Martin Scarrattef8317b2006-07-19 12:07:51 +0000192 FOR_NB_SCREENS(l)
Michael Sevakis82b26d22007-03-06 07:59:25 +0000193 kbd_param[l].nchars = i;
Frank Dischner75c3d0b2006-03-29 16:21:42 +0000194
Michael Sevakis11e45a32007-03-06 05:43:04 +0000195 return 0;
Frank Dischner75c3d0b2006-03-29 16:21:42 +0000196}
197
Jörg Hohensohn9e049572004-05-21 06:29:55 +0000198/* helper function to spell a char if voice UI is enabled */
Frank Dischner75c3d0b2006-03-29 16:21:42 +0000199static void kbd_spellchar(unsigned short c)
Jörg Hohensohn9e049572004-05-21 06:29:55 +0000200{
Steve Bavin32a95752007-10-19 15:31:42 +0000201 if (global_settings.talk_menu) /* voice UI? */
Jörg Hohensohn9e049572004-05-21 06:29:55 +0000202 {
Jens Arnold064de4c2007-10-10 06:02:08 +0000203 unsigned char tmp[5];
204 /* store char to pass to talk_spell */
205 unsigned char* utf8 = utf8encode(c, tmp);
206 *utf8 = 0;
Stéphane Doyond529a382007-10-10 02:28:58 +0000207
Jens Arnold064de4c2007-10-10 06:02:08 +0000208 if(c == ' ')
209 talk_id(VOICE_BLANK, false);
Jens Arnold9afdf992007-10-10 06:19:54 +0000210 else
Jens Arnold064de4c2007-10-10 06:02:08 +0000211 talk_spell(tmp, false);
Jörg Hohensohn9e049572004-05-21 06:29:55 +0000212 }
213}
214
Stéphane Doyond529a382007-10-10 02:28:58 +0000215#ifdef KBD_MODES
216static void say_edit(void)
217{
Steve Bavin32a95752007-10-19 15:31:42 +0000218 if(global_settings.talk_menu)
Stéphane Doyond529a382007-10-10 02:28:58 +0000219 talk_id(VOICE_EDIT, false);
220}
221#endif
222
Michael Sevakis11e45a32007-03-06 05:43:04 +0000223static void kbd_inschar(unsigned char* text, int buflen,
224 int* editpos, unsigned short ch)
Frank Dischner75c3d0b2006-03-29 16:21:42 +0000225{
226 int i, j, k, len;
227 unsigned char tmp[4];
228 unsigned char* utf8;
229
230 len = strlen(text);
231 k = utf8length(text);
232 utf8 = utf8encode(ch, tmp);
233 j = (long)utf8 - (long)tmp;
234
235 if (len + j < buflen)
Michael Sevakis11e45a32007-03-06 05:43:04 +0000236 {
237 for (i = len+j; k >= *editpos; i--)
Frank Dischner75c3d0b2006-03-29 16:21:42 +0000238 {
Frank Dischner75c3d0b2006-03-29 16:21:42 +0000239 text[i] = text[i-j];
240 if ((text[i] & MASK) != COMP)
241 k--;
242 }
Michael Sevakis11e45a32007-03-06 05:43:04 +0000243
Frank Dischner75c3d0b2006-03-29 16:21:42 +0000244 while (j--)
245 text[i--] = tmp[j];
Michael Sevakis11e45a32007-03-06 05:43:04 +0000246
Frank Dischner75c3d0b2006-03-29 16:21:42 +0000247 (*editpos)++;
248 }
Frank Dischner75c3d0b2006-03-29 16:21:42 +0000249}
250
Nils Wallméniusb757b502006-12-17 19:51:30 +0000251static void kbd_delchar(unsigned char* text, int* editpos)
Frank Dischner75c3d0b2006-03-29 16:21:42 +0000252{
253 int i = 0;
254 unsigned char* utf8;
255
256 if (*editpos > 0)
257 {
258 utf8 = text + utf8seek(text, *editpos);
Michael Sevakis11e45a32007-03-06 05:43:04 +0000259
260 do
261 {
Frank Dischner75c3d0b2006-03-29 16:21:42 +0000262 i++;
263 utf8--;
Michael Sevakis11e45a32007-03-06 05:43:04 +0000264 }
265 while ((*utf8 & MASK) == COMP);
266
267 while (utf8[i])
268 {
Frank Dischner75c3d0b2006-03-29 16:21:42 +0000269 *utf8 = utf8[i];
270 utf8++;
271 }
Michael Sevakis11e45a32007-03-06 05:43:04 +0000272
Frank Dischner75c3d0b2006-03-29 16:21:42 +0000273 *utf8 = 0;
274 (*editpos)--;
275 }
Michael Sevakis11e45a32007-03-06 05:43:04 +0000276}
Frank Dischner75c3d0b2006-03-29 16:21:42 +0000277
Michael Sevakis11e45a32007-03-06 05:43:04 +0000278/* Lookup k value based on state of param (pm) */
279static int get_param_k(const struct keyboard_parameters *pm)
280{
281 return (pm->page*pm->lines + pm->y)*pm->max_chars + pm->x;
Frank Dischner75c3d0b2006-03-29 16:21:42 +0000282}
283
Björn Stenbergc8cb6ff2002-12-04 15:04:43 +0000284int kbd_input(char* text, int buflen)
285{
Miika Pekkarinen5da90fa2005-12-04 07:37:24 +0000286 bool done = false;
Michael Sevakis38be0e62007-03-06 08:19:00 +0000287#ifdef CPU_ARM
288 /* This seems to keep the sizes for ARM way down */
Michael Sevakis82b26d22007-03-06 07:59:25 +0000289 struct keyboard_parameters * volatile param = kbd_param;
Michael Sevakis38be0e62007-03-06 08:19:00 +0000290#else
291 struct keyboard_parameters * const param = kbd_param;
292#endif
Michael Sevakis11e45a32007-03-06 05:43:04 +0000293 int l; /* screen loop variable */
Martin Scarrattef8317b2006-07-19 12:07:51 +0000294 int text_w = 0;
Michael Sevakis11e45a32007-03-06 05:43:04 +0000295 int editpos; /* Edit position on all screens */
Jonathan Gordon45aa9a22009-01-05 10:25:41 +0000296 const int statusbar_size = 0;
Michael Sevakis11e45a32007-03-06 05:43:04 +0000297 unsigned short ch;
Marcoen Hirschbergb0fee172005-12-06 13:27:15 +0000298 unsigned char *utf8;
Michael Sevakis11e45a32007-03-06 05:43:04 +0000299 bool cur_blink = true; /* Cursor on/off flag */
Frank Dischner75c3d0b2006-03-29 16:21:42 +0000300#ifdef KBD_MORSE_INPUT
Miika Pekkarinen9d918c92005-12-02 19:41:09 +0000301 bool morse_reading = false;
302 unsigned char morse_code = 0;
Michael Sevakis11e45a32007-03-06 05:43:04 +0000303 int morse_tick = 0;
Miika Pekkarinen9d918c92005-12-02 19:41:09 +0000304 char buf[2];
Antoine Cellerier8eba20a2006-07-23 17:16:38 +0000305#endif
Jonathan Gordon701a5932009-02-02 03:14:51 +0000306 int oldbars = viewportmanager_set_statusbar(VP_SB_HIDE_ALL);
Martin Scarrattef8317b2006-07-19 12:07:51 +0000307 FOR_NB_SCREENS(l)
308 {
Michael Sevakis11e45a32007-03-06 05:43:04 +0000309 struct keyboard_parameters *pm = &param[l];
Michael Sevakis11e45a32007-03-06 05:43:04 +0000310#if LCD_WIDTH >= 160 && LCD_HEIGHT >= 96
Michael Sevakis00af7c72007-03-06 05:55:23 +0000311 struct screen *sc = &screens[l];
Michael Sevakis11e45a32007-03-06 05:43:04 +0000312
Peter D'Hoye205f3df2008-06-28 20:45:21 +0000313 if (sc->getwidth() >= 160 && sc->getheight() >= 96)
Michael Sevakis11e45a32007-03-06 05:43:04 +0000314 {
315 pm->default_kbd =
316 "ABCDEFG abcdefg !?\" @#$%+'\n"
317 "HIJKLMN hijklmn 789 &_()-`\n"
318 "OPQRSTU opqrstu 456 §|{}/<\n"
319 "VWXYZ., vwxyz.,0123 ~=[]*>\n"
320 "ÀÁÂÃÄÅÆ ÌÍÎÏ ÈÉÊË ¢£¤¥¦§©®\n"
321 "àáâãäåæ ìíîï èéêë «»°ºª¹²³\n"
322 "ÓÒÔÕÖØ ÇÐÞÝß ÙÚÛÜ ¯±×÷¡¿µ·\n"
323 "òóôõöø çðþýÿ ùúûü ¼½¾¬¶¨:;";
324
325 pm->DEFAULT_LINES = 8;
Martin Scarrattef8317b2006-07-19 12:07:51 +0000326 }
327 else
Michael Sevakis11e45a32007-03-06 05:43:04 +0000328#endif /* LCD_WIDTH >= 160 && LCD_HEIGHT >= 96 */
Nils Wallménius57747092006-12-17 22:53:25 +0000329 {
Michael Sevakis11e45a32007-03-06 05:43:04 +0000330 pm->default_kbd =
331 "ABCDEFG !?\" @#$%+'\n"
332 "HIJKLMN 789 &_()-`\n"
333 "OPQRSTU 456 §|{}/<\n"
334 "VWXYZ.,0123 ~=[]*>\n"
Martin Scarrattef8317b2006-07-19 12:07:51 +0000335
Michael Sevakis11e45a32007-03-06 05:43:04 +0000336 "abcdefg ¢£¤¥¦§©®¬\n"
337 "hijklmn «»°ºª¹²³¶\n"
338 "opqrstu ¯±×÷¡¿µ·¨\n"
339 "vwxyz., :;¼½¾ \n"
Martin Scarrattef8317b2006-07-19 12:07:51 +0000340
Michael Sevakis11e45a32007-03-06 05:43:04 +0000341 "ÀÁÂÃÄÅÆ ÌÍÎÏ ÈÉÊË\n"
342 "àáâãäåæ ìíîï èéêë\n"
343 "ÓÒÔÕÖØ ÇÐÞÝß ÙÚÛÜ\n"
344 "òóôõöø çðþýÿ ùúûü";
Antoine Cellerier8eba20a2006-07-23 17:16:38 +0000345
Michael Sevakis11e45a32007-03-06 05:43:04 +0000346 pm->DEFAULT_LINES = 4;
347 }
Martin Scarrattef8317b2006-07-19 12:07:51 +0000348 }
Björn Stenbergc8cb6ff2002-12-04 15:04:43 +0000349
Björn Stenbergaa2972d2003-03-10 15:09:27 +0000350 char outline[256];
Peter D'Hoyef76122f2008-05-29 20:32:39 +0000351#ifdef HAVE_BUTTONBAR
Kevin Ferrare1a1abf22005-11-20 01:02:14 +0000352 struct gui_buttonbar buttonbar;
Linus Nielsen Feltzingdd939aa2006-03-11 22:31:53 +0000353 bool buttonbar_config = global_settings.buttonbar;
Michael Sevakis11e45a32007-03-06 05:43:04 +0000354
Linus Nielsen Feltzingdd939aa2006-03-11 22:31:53 +0000355 global_settings.buttonbar = true;
Kevin Ferrare1a1abf22005-11-20 01:02:14 +0000356 gui_buttonbar_init(&buttonbar);
Michael Sevakis11e45a32007-03-06 05:43:04 +0000357
Martin Scarrattef8317b2006-07-19 12:07:51 +0000358 FOR_NB_SCREENS(l)
Michael Sevakis11e45a32007-03-06 05:43:04 +0000359 gui_buttonbar_set_display(&buttonbar, &screens[l]);
Kevin Ferrare1a1abf22005-11-20 01:02:14 +0000360#endif
Michael Sevakis11e45a32007-03-06 05:43:04 +0000361
Martin Scarrattef8317b2006-07-19 12:07:51 +0000362 FOR_NB_SCREENS(l)
363 {
Michael Sevakis11e45a32007-03-06 05:43:04 +0000364 struct keyboard_parameters *pm = &param[l];
365
366 if ( !kbd_loaded )
Antoine Cellerier8eba20a2006-07-23 17:16:38 +0000367 {
368 /* Copy default keyboard to buffer */
Michael Sevakis11e45a32007-03-06 05:43:04 +0000369 const unsigned char *p = pm->default_kbd;
370 int i = 0;
371
372 pm->curfont = FONT_SYSFIXED;
373
Antoine Cellerier8eba20a2006-07-23 17:16:38 +0000374 while (*p != 0)
Michael Sevakis11e45a32007-03-06 05:43:04 +0000375 p = utf8decode(p, &pm->kbd_buf[i++]);
376
377 pm->nchars = i;
Frank Dischner75c3d0b2006-03-29 16:21:42 +0000378 }
Martin Scarrattef8317b2006-07-19 12:07:51 +0000379 else
Michael Sevakis11e45a32007-03-06 05:43:04 +0000380 {
381 pm->curfont = FONT_UI;
382 }
Frank Dischner75c3d0b2006-03-29 16:21:42 +0000383 }
Michael Sevakis11e45a32007-03-06 05:43:04 +0000384
Martin Scarrattef8317b2006-07-19 12:07:51 +0000385 FOR_NB_SCREENS(l)
386 {
Michael Sevakis11e45a32007-03-06 05:43:04 +0000387 struct keyboard_parameters *pm = &param[l];
388 struct screen *sc = &screens[l];
389 int i, w;
Frank Dischner75c3d0b2006-03-29 16:21:42 +0000390
Michael Sevakis11e45a32007-03-06 05:43:04 +0000391 pm->font = font_get(pm->curfont);
392 pm->font_h = pm->font->height;
393
394 /* check if FONT_UI fits the screen */
Peter D'Hoye205f3df2008-06-28 20:45:21 +0000395 if (2*pm->font_h + 3 + statusbar_size +
396 BUTTONBAR_HEIGHT > sc->getheight())
Michael Sevakis11e45a32007-03-06 05:43:04 +0000397 {
398 pm->font = font_get(FONT_SYSFIXED);
399 pm->font_h = pm->font->height;
400 pm->curfont = FONT_SYSFIXED;
Martin Scarrattef8317b2006-07-19 12:07:51 +0000401 }
Björn Stenbergc8cb6ff2002-12-04 15:04:43 +0000402
Michael Sevakis11e45a32007-03-06 05:43:04 +0000403 sc->setfont(pm->curfont);
Nils Wallméniusc023cb82007-08-19 21:33:57 +0000404 pm->font_w = 0; /* reset font width */
Martin Scarrattef8317b2006-07-19 12:07:51 +0000405 /* find max width of keyboard glyphs */
Michael Sevakis11e45a32007-03-06 05:43:04 +0000406 for (i = 0; i < pm->nchars; i++)
407 {
Nils Wallméniusc023cb82007-08-19 21:33:57 +0000408 w = font_get_width(pm->font, pm->kbd_buf[i]);
409 if ( w > pm->font_w )
410 pm->font_w = w;
Martin Scarrattef8317b2006-07-19 12:07:51 +0000411 }
Michael Sevakis11e45a32007-03-06 05:43:04 +0000412
Antoine Cellerier8eba20a2006-07-23 17:16:38 +0000413 /* Since we're going to be adding spaces, make sure that we check
414 * their width too */
Michael Sevakis11e45a32007-03-06 05:43:04 +0000415 w = font_get_width( pm->font, ' ' );
416 if ( w > pm->font_w )
417 pm->font_w = w;
Antoine Cellerier8eba20a2006-07-23 17:16:38 +0000418 }
Michael Sevakis11e45a32007-03-06 05:43:04 +0000419
Antoine Cellerier8eba20a2006-07-23 17:16:38 +0000420 FOR_NB_SCREENS(l)
421 {
Michael Sevakis11e45a32007-03-06 05:43:04 +0000422 struct keyboard_parameters *pm = &param[l];
423 struct screen *sc = &screens[l];
424 int i = 0;
425
Antoine Cellerier8eba20a2006-07-23 17:16:38 +0000426 /* Pad lines with spaces */
Michael Sevakis11e45a32007-03-06 05:43:04 +0000427 while (i < pm->nchars)
Antoine Cellerier8eba20a2006-07-23 17:16:38 +0000428 {
Michael Sevakis11e45a32007-03-06 05:43:04 +0000429 if (pm->kbd_buf[i] == '\n')
Antoine Cellerier8eba20a2006-07-23 17:16:38 +0000430 {
Peter D'Hoye205f3df2008-06-28 20:45:21 +0000431 int k = sc->getwidth() / pm->font_w
432 - i % ( sc->getwidth() / pm->font_w ) - 1;
Michael Sevakis11e45a32007-03-06 05:43:04 +0000433 int j;
434
Peter D'Hoye205f3df2008-06-28 20:45:21 +0000435 if (k == sc->getwidth() / pm->font_w - 1)
Antoine Cellerier8eba20a2006-07-23 17:16:38 +0000436 {
Michael Sevakis11e45a32007-03-06 05:43:04 +0000437 pm->nchars--;
438
439 for (j = i; j < pm->nchars; j++)
Antoine Cellerier8eba20a2006-07-23 17:16:38 +0000440 {
Michael Sevakis82b26d22007-03-06 07:59:25 +0000441 pm->kbd_buf[j] = pm->kbd_buf[j + 1];
Antoine Cellerier8eba20a2006-07-23 17:16:38 +0000442 }
443 }
444 else
445 {
Michael Sevakis11e45a32007-03-06 05:43:04 +0000446 if (pm->nchars + k - 1 >= KBD_BUF_SIZE)
Antoine Cellerier8eba20a2006-07-23 17:16:38 +0000447 { /* We don't want to overflow the buffer */
Michael Sevakis11e45a32007-03-06 05:43:04 +0000448 k = KBD_BUF_SIZE - pm->nchars;
Antoine Cellerier8eba20a2006-07-23 17:16:38 +0000449 }
Michael Sevakis11e45a32007-03-06 05:43:04 +0000450
451 for (j = pm->nchars + k - 1; j > i + k; j--)
Antoine Cellerier8eba20a2006-07-23 17:16:38 +0000452 {
Michael Sevakis11e45a32007-03-06 05:43:04 +0000453 pm->kbd_buf[j] = pm->kbd_buf[j-k];
Antoine Cellerier8eba20a2006-07-23 17:16:38 +0000454 }
Michael Sevakis11e45a32007-03-06 05:43:04 +0000455
456 pm->nchars += k;
Antoine Cellerier8eba20a2006-07-23 17:16:38 +0000457 k++;
Michael Sevakis11e45a32007-03-06 05:43:04 +0000458
459 while (k--)
Antoine Cellerier8eba20a2006-07-23 17:16:38 +0000460 {
Michael Sevakis11e45a32007-03-06 05:43:04 +0000461 pm->kbd_buf[i++] = ' ';
Antoine Cellerier8eba20a2006-07-23 17:16:38 +0000462 }
463 }
464 }
465 else
Michael Sevakis11e45a32007-03-06 05:43:04 +0000466 {
Antoine Cellerier8eba20a2006-07-23 17:16:38 +0000467 i++;
Michael Sevakis11e45a32007-03-06 05:43:04 +0000468 }
Antoine Cellerier8eba20a2006-07-23 17:16:38 +0000469 }
Frank Dischner75c3d0b2006-03-29 16:21:42 +0000470 }
471
Michael Sevakis11e45a32007-03-06 05:43:04 +0000472 /* Find max width for text string */
Frank Dischner75c3d0b2006-03-29 16:21:42 +0000473 utf8 = text;
Martin Scarrattef8317b2006-07-19 12:07:51 +0000474 FOR_NB_SCREENS(l)
475 {
Michael Sevakis11e45a32007-03-06 05:43:04 +0000476 struct keyboard_parameters *pm = &param[l];
477 struct screen *sc = &screens[l];
478
479 text_w = pm->font_w;
480
481 while (*utf8)
482 {
483 int w = font_get_width(pm->font, ch);
Martin Scarrattef8317b2006-07-19 12:07:51 +0000484 utf8 = (unsigned char*)utf8decode(utf8, &ch);
Michael Sevakis11e45a32007-03-06 05:43:04 +0000485
Martin Scarrattef8317b2006-07-19 12:07:51 +0000486 if (w > text_w)
Antoine Cellerier8eba20a2006-07-23 17:16:38 +0000487 text_w = w;
Martin Scarrattef8317b2006-07-19 12:07:51 +0000488 }
Frank Dischner75c3d0b2006-03-29 16:21:42 +0000489
Peter D'Hoye205f3df2008-06-28 20:45:21 +0000490 pm->max_chars_text = sc->getwidth() / text_w - 2;
Michael Sevakis11e45a32007-03-06 05:43:04 +0000491
492 /* Calculate keyboard grid size */
Peter D'Hoye205f3df2008-06-28 20:45:21 +0000493 pm->max_chars = sc->getwidth() / pm->font_w;
Michael Sevakis11e45a32007-03-06 05:43:04 +0000494
495 if (!kbd_loaded)
496 {
497 pm->lines = pm->DEFAULT_LINES;
498 pm->keyboard_margin = DEFAULT_MARGIN;
499 }
500 else
501 {
Peter D'Hoye205f3df2008-06-28 20:45:21 +0000502 pm->lines = (sc->getheight() - BUTTONBAR_HEIGHT - statusbar_size)
Michael Sevakis11e45a32007-03-06 05:43:04 +0000503 / pm->font_h - 1;
Peter D'Hoye205f3df2008-06-28 20:45:21 +0000504 pm->keyboard_margin = sc->getheight() - BUTTONBAR_HEIGHT -
Michael Sevakis11e45a32007-03-06 05:43:04 +0000505 statusbar_size - (pm->lines+1)*pm->font_h;
506
507 if (pm->keyboard_margin < 3)
508 {
509 pm->lines--;
510 pm->keyboard_margin += pm->font_h;
Martin Scarrattef8317b2006-07-19 12:07:51 +0000511 }
Michael Sevakis11e45a32007-03-06 05:43:04 +0000512
513 if (pm->keyboard_margin > 6)
514 pm->keyboard_margin = 6;
Frank Dischner75c3d0b2006-03-29 16:21:42 +0000515 }
Frank Dischner75c3d0b2006-03-29 16:21:42 +0000516
Michael Sevakis11e45a32007-03-06 05:43:04 +0000517 pm->pages = (pm->nchars + (pm->lines*pm->max_chars-1))
518 / (pm->lines*pm->max_chars);
Frank Dischner75c3d0b2006-03-29 16:21:42 +0000519
Michael Sevakis11e45a32007-03-06 05:43:04 +0000520 if (pm->pages == 1 && kbd_loaded)
521 pm->lines = (pm->nchars + pm->max_chars - 1) / pm->max_chars;
522
523 pm->main_y = pm->font_h*pm->lines + pm->keyboard_margin + statusbar_size;
524 pm->main_x = 0;
525 pm->keyboard_margin -= pm->keyboard_margin/2;
Frank Dischner75c3d0b2006-03-29 16:21:42 +0000526
527#ifdef KBD_MORSE_INPUT
Michael Sevakis11e45a32007-03-06 05:43:04 +0000528 pm->old_main_y = pm->main_y;
Martin Scarrattef8317b2006-07-19 12:07:51 +0000529 if (morse_mode)
Peter D'Hoye205f3df2008-06-28 20:45:21 +0000530 pm->main_y = sc->getheight() - pm->font_h;
Miika Pekkarinenda932dc2005-12-04 08:45:24 +0000531#endif
Martin Scarrattef8317b2006-07-19 12:07:51 +0000532 }
Björn Stenbergc8cb6ff2002-12-04 15:04:43 +0000533
Michael Sevakis11e45a32007-03-06 05:43:04 +0000534 /* Initial edit position is after last character */
535 editpos = utf8length(text);
Martin Scarrattef8317b2006-07-19 12:07:51 +0000536
Steve Bavin32a95752007-10-19 15:31:42 +0000537 if (global_settings.talk_menu) /* voice UI? */
Miika Pekkarinen9d918c92005-12-02 19:41:09 +0000538 talk_spell(text, true); /* spell initial text */
Jörg Hohensohn9e049572004-05-21 06:29:55 +0000539
Michael Sevakis11e45a32007-03-06 05:43:04 +0000540
541 while (!done)
Björn Stenbergc8cb6ff2002-12-04 15:04:43 +0000542 {
Michael Sevakis11e45a32007-03-06 05:43:04 +0000543 /* These declarations are assigned to the screen on which the key
544 action occurred - pointers save a lot of space over array notation
545 when accessing the same array element countless times */
546 int button;
547#if NB_SCREENS > 1
548 int button_screen;
549#else
550 const int button_screen = 0;
551#endif
552 struct keyboard_parameters *pm;
553 struct screen *sc;
554
555 int len_utf8 = utf8length(text);
556
Martin Scarrattef8317b2006-07-19 12:07:51 +0000557 FOR_NB_SCREENS(l)
558 screens[l].clear_display();
Marcoen Hirschbergb0fee172005-12-06 13:27:15 +0000559
Frank Dischner75c3d0b2006-03-29 16:21:42 +0000560#ifdef KBD_MORSE_INPUT
Jens Arnoldb5991b22006-04-22 13:06:57 +0000561 if (morse_mode)
562 {
Martin Scarrattef8317b2006-07-19 12:07:51 +0000563 FOR_NB_SCREENS(l)
Miika Pekkarinen9d918c92005-12-02 19:41:09 +0000564 {
Michael Sevakis11e45a32007-03-06 05:43:04 +0000565 /* declare scoped pointers inside screen loops - hide the
566 declarations from previous block level */
567 const int w = 6; /* sysfixed font width */
568 struct keyboard_parameters *pm = &param[l];
569 struct screen *sc = &screens[l];
570 int i;
571
572 sc->setfont(FONT_SYSFIXED); /* Draw morse code screen with sysfont */
573 pm->x = 0;
574 pm->y = statusbar_size;
Martin Scarrattef8317b2006-07-19 12:07:51 +0000575 buf[1] = '\0';
Michael Sevakis11e45a32007-03-06 05:43:04 +0000576
Martin Scarrattef8317b2006-07-19 12:07:51 +0000577 /* Draw morse code table with code descriptions. */
578 for (i = 0; morse_alphabets[i] != '\0'; i++)
Miika Pekkarinen9d918c92005-12-02 19:41:09 +0000579 {
Michael Sevakis11e45a32007-03-06 05:43:04 +0000580 int morse_len;
581 int j;
582
Martin Scarrattef8317b2006-07-19 12:07:51 +0000583 buf[0] = morse_alphabets[i];
Michael Sevakis11e45a32007-03-06 05:43:04 +0000584 sc->putsxy(pm->x, pm->y, buf);
Miika Pekkarinen9d918c92005-12-02 19:41:09 +0000585
Martin Scarrattef8317b2006-07-19 12:07:51 +0000586 for (j = 0; (morse_codes[i] >> j) > 0x01; j++) ;
587 morse_len = j;
588
Michael Sevakis11e45a32007-03-06 05:43:04 +0000589 pm->x += w + 3;
Martin Scarrattef8317b2006-07-19 12:07:51 +0000590 for (j = 0; j < morse_len; j++)
591 {
592 if ((morse_codes[i] >> (morse_len-j-1)) & 0x01)
Michael Sevakis11e45a32007-03-06 05:43:04 +0000593 sc->fillrect(pm->x + j*4, pm->y + 2, 3, 4);
Martin Scarrattef8317b2006-07-19 12:07:51 +0000594 else
Michael Sevakis11e45a32007-03-06 05:43:04 +0000595 sc->fillrect(pm->x + j*4, pm->y + 3, 1, 2);
Martin Scarrattef8317b2006-07-19 12:07:51 +0000596 }
597
Michael Sevakis11e45a32007-03-06 05:43:04 +0000598 pm->x += w*5 - 3;
Peter D'Hoye205f3df2008-06-28 20:45:21 +0000599 if (pm->x >= sc->getwidth() - w*6)
Martin Scarrattef8317b2006-07-19 12:07:51 +0000600 {
Michael Sevakis11e45a32007-03-06 05:43:04 +0000601 pm->x = 0;
602 pm->y += 8; /* sysfixed font height */
Martin Scarrattef8317b2006-07-19 12:07:51 +0000603 }
Miika Pekkarinen9d918c92005-12-02 19:41:09 +0000604 }
605 }
Jens Arnoldb5991b22006-04-22 13:06:57 +0000606 }
607 else
Michael Sevakis11e45a32007-03-06 05:43:04 +0000608#endif /* KBD_MORSE_INPUT */
Jens Arnoldb5991b22006-04-22 13:06:57 +0000609 {
610 /* draw page */
Martin Scarrattef8317b2006-07-19 12:07:51 +0000611 FOR_NB_SCREENS(l)
612 {
Michael Sevakis11e45a32007-03-06 05:43:04 +0000613 struct keyboard_parameters *pm = &param[l];
614 struct screen *sc = &screens[l];
615 int i, j, k;
616
617 sc->setfont(pm->curfont);
618
619 k = pm->page*pm->max_chars*pm->lines;
620
621 for (i = j = 0; j < pm->lines && k < pm->nchars; k++)
622 {
623 int w;
624 utf8 = utf8encode(pm->kbd_buf[k], outline);
Martin Scarrattef8317b2006-07-19 12:07:51 +0000625 *utf8 = 0;
Michael Sevakis11e45a32007-03-06 05:43:04 +0000626
627 sc->getstringsize(outline, &w, NULL);
628 sc->putsxy(i*pm->font_w + (pm->font_w-w) / 2,
629 j*pm->font_h + statusbar_size, outline);
630
631 if (++i >= pm->max_chars)
632 {
Martin Scarrattef8317b2006-07-19 12:07:51 +0000633 i = 0;
634 j++;
635 }
Frank Dischner75c3d0b2006-03-29 16:21:42 +0000636 }
637 }
Björn Stenbergc8cb6ff2002-12-04 15:04:43 +0000638 }
639
Jens Arnoldb5991b22006-04-22 13:06:57 +0000640 /* separator */
Martin Scarrattef8317b2006-07-19 12:07:51 +0000641 FOR_NB_SCREENS(l)
642 {
Michael Sevakis11e45a32007-03-06 05:43:04 +0000643 struct keyboard_parameters *pm = &param[l];
644 struct screen *sc = &screens[l];
645 int i = 0, j = 0;
Linus Nielsen Feltzingade5d7b2004-07-26 16:06:59 +0000646
Michael Sevakis11e45a32007-03-06 05:43:04 +0000647 /* Clear text area one pixel above separator line so any overdraw
648 doesn't collide */
649 sc->set_drawmode(DRMODE_SOLID | DRMODE_INVERSEVID);
650 sc->fillrect(0, pm->main_y - pm->keyboard_margin - 1,
Peter D'Hoye205f3df2008-06-28 20:45:21 +0000651 sc->getwidth(), pm->font_h + 4);
Michael Sevakis11e45a32007-03-06 05:43:04 +0000652 sc->set_drawmode(DRMODE_SOLID);
Antoine Cellerier8eba20a2006-07-23 17:16:38 +0000653
Peter D'Hoye205f3df2008-06-28 20:45:21 +0000654 sc->hline(0, sc->getwidth() - 1, pm->main_y - pm->keyboard_margin);
Michael Sevakis11e45a32007-03-06 05:43:04 +0000655
656 /* write out the text */
657 sc->setfont(pm->curfont);
658
659 pm->curpos = MIN(editpos, pm->max_chars_text
Martin Scarrattef8317b2006-07-19 12:07:51 +0000660 - MIN(len_utf8 - editpos, 2));
Michael Sevakis11e45a32007-03-06 05:43:04 +0000661 pm->leftpos = editpos - pm->curpos;
662 utf8 = text + utf8seek(text, pm->leftpos);
Jens Arnoldb5991b22006-04-22 13:06:57 +0000663
Michael Sevakis11e45a32007-03-06 05:43:04 +0000664 text_w = pm->font_w;
665
666 while (*utf8 && i < pm->max_chars_text)
667 {
Martin Scarrattef8317b2006-07-19 12:07:51 +0000668 outline[j++] = *utf8++;
Michael Sevakis11e45a32007-03-06 05:43:04 +0000669
670 if ((*utf8 & MASK) != COMP)
671 {
672 int w;
Martin Scarrattef8317b2006-07-19 12:07:51 +0000673 outline[j] = 0;
674 j=0;
675 i++;
Michael Sevakis11e45a32007-03-06 05:43:04 +0000676 sc->getstringsize(outline, &w, NULL);
677 sc->putsxy(i*text_w + (text_w-w)/2, pm->main_y, outline);
Martin Scarrattef8317b2006-07-19 12:07:51 +0000678 }
Jens Arnoldb5991b22006-04-22 13:06:57 +0000679 }
Jens Arnoldb5991b22006-04-22 13:06:57 +0000680
Michael Sevakis11e45a32007-03-06 05:43:04 +0000681 if (pm->leftpos > 0)
682 {
683 /* Draw nicer bitmap arrow if room, else settle for "<". */
684 if (text_w >= 6 && pm->font_h >= 8)
685 {
Jonathan Gordon6a5cc0b2007-04-16 09:14:36 +0000686 screen_put_iconxy(sc, (text_w - 6) / 2,
687 pm->main_y + (pm->font_h - 8) / 2 ,
688 Icon_Reverse_Cursor);
Michael Sevakis11e45a32007-03-06 05:43:04 +0000689 }
690 else
691 {
692 int w;
693 sc->getstringsize("<", &w, NULL);
694 sc->putsxy(text_w - w, pm->main_y, "<");
695 }
Martin Scarrattef8317b2006-07-19 12:07:51 +0000696 }
Michael Sevakis11e45a32007-03-06 05:43:04 +0000697
698 if (len_utf8 - pm->leftpos > pm->max_chars_text)
699 {
700 /* Draw nicer bitmap arrow if room, else settle for ">". */
701 if (text_w >= 6 && pm->font_h >= 8)
702 {
Peter D'Hoye205f3df2008-06-28 20:45:21 +0000703 screen_put_iconxy(sc, sc->getwidth() - text_w +
704 (text_w - 6) / 2,
Jonathan Gordon6a5cc0b2007-04-16 09:14:36 +0000705 pm->main_y + (pm->font_h - 8) / 2,
706 Icon_Cursor);
Michael Sevakis11e45a32007-03-06 05:43:04 +0000707 }
708 else
709 {
Peter D'Hoye205f3df2008-06-28 20:45:21 +0000710 sc->putsxy(sc->getwidth() - text_w, pm->main_y, ">");
Michael Sevakis11e45a32007-03-06 05:43:04 +0000711 }
712 }
Jens Arnoldb5991b22006-04-22 13:06:57 +0000713
Martin Scarrattef8317b2006-07-19 12:07:51 +0000714 /* cursor */
Michael Sevakis11e45a32007-03-06 05:43:04 +0000715 i = (pm->curpos + 1) * text_w;
Martin Scarrattef8317b2006-07-19 12:07:51 +0000716
Michael Sevakis11e45a32007-03-06 05:43:04 +0000717 if (cur_blink)
718 sc->vline(i, pm->main_y, pm->main_y + pm->font_h - 1);
719
720 if (pm->hangul) /* draw underbar */
721 sc->hline(pm->curpos*text_w, (pm->curpos+1)*text_w,
722 pm->main_y + pm->font_h - 1);
Martin Scarrattef8317b2006-07-19 12:07:51 +0000723 }
Michael Sevakis11e45a32007-03-06 05:43:04 +0000724
Jens Arnoldb5991b22006-04-22 13:06:57 +0000725 cur_blink = !cur_blink;
Michael Sevakis11e45a32007-03-06 05:43:04 +0000726
Peter D'Hoyef76122f2008-05-29 20:32:39 +0000727#ifdef HAVE_BUTTONBAR
Jens Arnoldb5991b22006-04-22 13:06:57 +0000728 /* draw the button bar */
729 gui_buttonbar_set(&buttonbar, "Shift", "OK", "Del");
730 gui_buttonbar_draw(&buttonbar);
731#endif
732
Michael Sevakis11e45a32007-03-06 05:43:04 +0000733 FOR_NB_SCREENS(l)
Jens Arnoldb5991b22006-04-22 13:06:57 +0000734 {
Michael Sevakis11e45a32007-03-06 05:43:04 +0000735 struct keyboard_parameters *pm = &param[l];
736 struct screen *sc = &screens[l];
737
738 sc->set_drawmode(DRMODE_COMPLEMENT);
Jens Arnoldb5991b22006-04-22 13:06:57 +0000739#ifdef KBD_MODES
Michael Sevakis11e45a32007-03-06 05:43:04 +0000740 if (pm->line_edit)
741 sc->fillrect(0, pm->main_y - pm->keyboard_margin + 2,
Peter D'Hoye205f3df2008-06-28 20:45:21 +0000742 sc->getwidth(), pm->font_h + 2);
Michael Sevakis11e45a32007-03-06 05:43:04 +0000743 else /* highlight the key that has focus */
Jens Arnoldb5991b22006-04-22 13:06:57 +0000744#endif
Michael Sevakis11e45a32007-03-06 05:43:04 +0000745 sc->fillrect(pm->font_w*pm->x,
746 statusbar_size + pm->font_h*pm->y,
747 pm->font_w, pm->font_h);
748 sc->set_drawmode(DRMODE_SOLID);
749 }
Jens Arnoldb5991b22006-04-22 13:06:57 +0000750
Martin Scarrattef8317b2006-07-19 12:07:51 +0000751 FOR_NB_SCREENS(l)
Michael Sevakis11e45a32007-03-06 05:43:04 +0000752 screens[l].update();
Jens Arnoldb5991b22006-04-22 13:06:57 +0000753
Michael Sevakis11e45a32007-03-06 05:43:04 +0000754 button = get_action(CONTEXT_KEYBOARD, HZ/2);
Michael Sevakis00af7c72007-03-06 05:55:23 +0000755#if NB_SCREENS > 1
Michael Sevakis11e45a32007-03-06 05:43:04 +0000756 button_screen = (get_action_statuscode(NULL) & ACTION_REMOTE) ? 1 : 0;
757#endif
758 pm = &param[button_screen];
759 sc = &screens[button_screen];
760
Martin Scarratt3cf50c02007-02-10 22:39:45 +0000761#if defined KBD_MORSE_INPUT && !defined KBD_MODES
Miika Pekkarinenda932dc2005-12-04 08:45:24 +0000762 if (morse_mode)
763 {
764 /* Remap some buttons for morse mode. */
Martin Scarratt0ba22042006-08-22 13:21:13 +0000765 if (button == ACTION_KBD_LEFT)
766 button = ACTION_KBD_CURSOR_LEFT;
767 if (button == ACTION_KBD_RIGHT)
768 button = ACTION_KBD_CURSOR_RIGHT;
Miika Pekkarinenda932dc2005-12-04 08:45:24 +0000769 }
770#endif
Zakk Robertsa1db4312006-04-22 09:43:43 +0000771
Michael Sevakis11e45a32007-03-06 05:43:04 +0000772 switch ( button )
773 {
Martin Scarratt0ba22042006-08-22 13:21:13 +0000774 case ACTION_KBD_ABORT:
Martin Scarrattef8317b2006-07-19 12:07:51 +0000775 FOR_NB_SCREENS(l)
776 screens[l].setfont(FONT_UI);
Antoine Cellerier8eba20a2006-07-23 17:16:38 +0000777
Peter D'Hoyef76122f2008-05-29 20:32:39 +0000778#ifdef HAVE_BUTTONBAR
Linus Nielsen Feltzingdd939aa2006-03-11 22:31:53 +0000779 global_settings.buttonbar=buttonbar_config;
780#endif
Jonathan Gordon45aa9a22009-01-05 10:25:41 +0000781 viewportmanager_set_statusbar(oldbars);
Björn Stenberg58dff172003-01-15 13:48:54 +0000782 return -1;
783 break;
Björn Stenbergc8cb6ff2002-12-04 15:04:43 +0000784
Martin Scarratt0ba22042006-08-22 13:21:13 +0000785 case ACTION_KBD_PAGE_FLIP:
Michael Sevakis11e45a32007-03-06 05:43:04 +0000786 {
787 int k;
Frank Dischner75c3d0b2006-03-29 16:21:42 +0000788#ifdef KBD_MORSE_INPUT
Miika Pekkarinen9d918c92005-12-02 19:41:09 +0000789 if (morse_mode)
Frank Dischner75c3d0b2006-03-29 16:21:42 +0000790 break;
Miika Pekkarinen9d918c92005-12-02 19:41:09 +0000791#endif
Michael Sevakis11e45a32007-03-06 05:43:04 +0000792 if (++pm->page >= pm->pages)
793 pm->page = 0;
794
795 k = get_param_k(pm);
796 kbd_spellchar(pm->kbd_buf[k]);
Björn Stenberg58dff172003-01-15 13:48:54 +0000797 break;
Michael Sevakis11e45a32007-03-06 05:43:04 +0000798 }
Björn Stenbergc8cb6ff2002-12-04 15:04:43 +0000799
Frank Dischner75c3d0b2006-03-29 16:21:42 +0000800#ifdef KBD_MORSE_INPUT
Martin Scarratt0ba22042006-08-22 13:21:13 +0000801 case ACTION_KBD_MORSE_INPUT:
Frank Dischner75c3d0b2006-03-29 16:21:42 +0000802 morse_mode = !morse_mode;
Michael Sevakis11e45a32007-03-06 05:43:04 +0000803
Martin Scarrattef8317b2006-07-19 12:07:51 +0000804 FOR_NB_SCREENS(l)
805 {
Michael Sevakis11e45a32007-03-06 05:43:04 +0000806 struct keyboard_parameters *pm = &param[l];
807 struct screen *sc = &screens[l];
808
809 pm->x = pm->y = pm->page = 0;
810
811 if (morse_mode)
812 {
813 pm->old_main_y = pm->main_y;
Peter D'Hoye205f3df2008-06-28 20:45:21 +0000814 pm->main_y = sc->getheight() - pm->font_h;
Michael Sevakis11e45a32007-03-06 05:43:04 +0000815 }
816 else
817 {
818 pm->main_y = pm->old_main_y;
819 }
Martin Scarrattef8317b2006-07-19 12:07:51 +0000820 }
Frank Dischner75c3d0b2006-03-29 16:21:42 +0000821 /* FIXME: We should talk something like Morse mode.. */
822 break;
Michael Sevakis11e45a32007-03-06 05:43:04 +0000823#endif /* KBD_MORSE_INPUT */
Martin Scarratt0ba22042006-08-22 13:21:13 +0000824
825 case ACTION_KBD_RIGHT:
Jens Arnold7b95e602004-11-14 23:08:08 +0000826#ifdef KBD_MODES
Martin Scarratt3cf50c02007-02-10 22:39:45 +0000827#ifdef KBD_MORSE_INPUT
Michael Sevakis11e45a32007-03-06 05:43:04 +0000828 /* allow cursor change in non line edit morse mode */
829 if (pm->line_edit || morse_mode)
Martin Scarratt3cf50c02007-02-10 22:39:45 +0000830#else
Michael Sevakis11e45a32007-03-06 05:43:04 +0000831 /* right doubles as cursor_right in line_edit */
832 if (pm->line_edit)
Martin Scarratt3cf50c02007-02-10 22:39:45 +0000833#endif
Jens Arnold7b95e602004-11-14 23:08:08 +0000834 {
Michael Sevakis11e45a32007-03-06 05:43:04 +0000835 pm->hangul = false;
Martin Scarrattef8317b2006-07-19 12:07:51 +0000836
Marcoen Hirschbergb0fee172005-12-06 13:27:15 +0000837 if (editpos < len_utf8)
Jens Arnold0b31a002005-02-07 00:56:26 +0000838 {
Michael Sevakis11e45a32007-03-06 05:43:04 +0000839 int c = utf8seek(text, ++editpos);
Marcoen Hirschbergb0fee172005-12-06 13:27:15 +0000840 kbd_spellchar(text[c]);
Jens Arnold100d3432007-10-10 05:56:53 +0000841 }
842#if CONFIG_CODEC == SWCODEC
Steve Bavin32a95752007-10-19 15:31:42 +0000843 else if (global_settings.talk_menu)
Stéphane Doyon1b89d582007-10-10 03:57:42 +0000844 pcmbuf_beep(1000, 150, 1500);
Jens Arnold100d3432007-10-10 05:56:53 +0000845#endif
Jens Arnold7b95e602004-11-14 23:08:08 +0000846 }
Björn Stenbergaa2972d2003-03-10 15:09:27 +0000847 else
Michael Sevakis11e45a32007-03-06 05:43:04 +0000848#endif /* KBD_MODES */
Zakk Robertsa1db4312006-04-22 09:43:43 +0000849 {
Michael Sevakis11e45a32007-03-06 05:43:04 +0000850 int k;
Martin Scarratt3cf50c02007-02-10 22:39:45 +0000851#ifdef KBD_MORSE_INPUT
852 if (morse_mode)
853 break;
854#endif
Michael Sevakis11e45a32007-03-06 05:43:04 +0000855 if (++pm->x >= pm->max_chars)
Martin Scarrattef8317b2006-07-19 12:07:51 +0000856 {
Michael Sevakis11e45a32007-03-06 05:43:04 +0000857#ifndef KBD_PAGE_FLIP
Jens Arnold13fcd682005-10-08 07:12:28 +0000858 /* no dedicated flip key - flip page on wrap */
Michael Sevakis11e45a32007-03-06 05:43:04 +0000859 if (++pm->page >= pm->pages)
860 pm->page = 0;
Jens Arnold7b95e602004-11-14 23:08:08 +0000861#endif
Michael Sevakis11e45a32007-03-06 05:43:04 +0000862 pm->x = 0;
Jens Arnold7b95e602004-11-14 23:08:08 +0000863 }
Michael Sevakis11e45a32007-03-06 05:43:04 +0000864
865 k = get_param_k(pm);
866 kbd_spellchar(pm->kbd_buf[k]);
Jens Arnold7b95e602004-11-14 23:08:08 +0000867 }
Björn Stenberg58dff172003-01-15 13:48:54 +0000868 break;
Martin Scarratt0ba22042006-08-22 13:21:13 +0000869
870 case ACTION_KBD_LEFT:
Jens Arnold7b95e602004-11-14 23:08:08 +0000871#ifdef KBD_MODES
Martin Scarratt3cf50c02007-02-10 22:39:45 +0000872#ifdef KBD_MORSE_INPUT
Michael Sevakis11e45a32007-03-06 05:43:04 +0000873 /* allow cursor change in non line edit morse mode */
874 if (pm->line_edit || morse_mode)
Martin Scarratt3cf50c02007-02-10 22:39:45 +0000875#else
Michael Sevakis11e45a32007-03-06 05:43:04 +0000876 /* left doubles as cursor_left in line_edit */
877 if (pm->line_edit)
Martin Scarratt3cf50c02007-02-10 22:39:45 +0000878#endif
Jens Arnold7b95e602004-11-14 23:08:08 +0000879 {
Michael Sevakis11e45a32007-03-06 05:43:04 +0000880 pm->hangul = false;
Martin Scarrattef8317b2006-07-19 12:07:51 +0000881
Michael Sevakis11e45a32007-03-06 05:43:04 +0000882 if (editpos > 0)
Jens Arnold0b31a002005-02-07 00:56:26 +0000883 {
Michael Sevakis11e45a32007-03-06 05:43:04 +0000884 int c = utf8seek(text, --editpos);
Marcoen Hirschbergb0fee172005-12-06 13:27:15 +0000885 kbd_spellchar(text[c]);
Jens Arnold100d3432007-10-10 05:56:53 +0000886 }
887#if CONFIG_CODEC == SWCODEC
Steve Bavin32a95752007-10-19 15:31:42 +0000888 else if (global_settings.talk_menu)
Stéphane Doyon1b89d582007-10-10 03:57:42 +0000889 pcmbuf_beep(1000, 150, 1500);
Jens Arnold100d3432007-10-10 05:56:53 +0000890#endif
Jens Arnold7b95e602004-11-14 23:08:08 +0000891 }
Björn Stenberg58dff172003-01-15 13:48:54 +0000892 else
Michael Sevakis11e45a32007-03-06 05:43:04 +0000893#endif /* KBD_MODES */
Frank Dischner75c3d0b2006-03-29 16:21:42 +0000894 {
Michael Sevakis11e45a32007-03-06 05:43:04 +0000895 int k;
Martin Scarratt3cf50c02007-02-10 22:39:45 +0000896#ifdef KBD_MORSE_INPUT
897 if (morse_mode)
898 break;
899#endif
Michael Sevakis11e45a32007-03-06 05:43:04 +0000900 if (--pm->x < 0)
Jens Arnold7b95e602004-11-14 23:08:08 +0000901 {
Michael Sevakis11e45a32007-03-06 05:43:04 +0000902#ifndef KBD_PAGE_FLIP
Jens Arnold13fcd682005-10-08 07:12:28 +0000903 /* no dedicated flip key - flip page on wrap */
Michael Sevakis11e45a32007-03-06 05:43:04 +0000904 if (--pm->page < 0)
905 pm->page = pm->pages - 1;
Jens Arnold7b95e602004-11-14 23:08:08 +0000906#endif
Michael Sevakis11e45a32007-03-06 05:43:04 +0000907 pm->x = pm->max_chars - 1;
Jens Arnold7b95e602004-11-14 23:08:08 +0000908 }
Michael Sevakis11e45a32007-03-06 05:43:04 +0000909
910 k = get_param_k(pm);
911 kbd_spellchar(pm->kbd_buf[k]);
Jens Arnold7b95e602004-11-14 23:08:08 +0000912 }
Björn Stenberg58dff172003-01-15 13:48:54 +0000913 break;
Björn Stenbergc8cb6ff2002-12-04 15:04:43 +0000914
Martin Scarratt0ba22042006-08-22 13:21:13 +0000915 case ACTION_KBD_DOWN:
Michael Sevakis11e45a32007-03-06 05:43:04 +0000916#ifdef KBD_MORSE_INPUT
917#ifdef KBD_MODES
918 if (morse_mode)
Stéphane Doyond529a382007-10-10 02:28:58 +0000919 {
Michael Sevakis11e45a32007-03-06 05:43:04 +0000920 pm->line_edit = !pm->line_edit;
Stéphane Doyond529a382007-10-10 02:28:58 +0000921 if(pm->line_edit)
922 say_edit();
923 }
Michael Sevakis11e45a32007-03-06 05:43:04 +0000924 else
925#else
Miika Pekkarinen9d918c92005-12-02 19:41:09 +0000926 if (morse_mode)
927 break;
928#endif
Michael Sevakis11e45a32007-03-06 05:43:04 +0000929#endif /* KBD_MORSE_INPUT */
930 {
Jens Arnold7b95e602004-11-14 23:08:08 +0000931#ifdef KBD_MODES
Michael Sevakis11e45a32007-03-06 05:43:04 +0000932 if (pm->line_edit)
Martin Scarrattef8317b2006-07-19 12:07:51 +0000933 {
Michael Sevakis11e45a32007-03-06 05:43:04 +0000934 pm->y = 0;
935 pm->line_edit = false;
936 }
937 else
938#endif
939 if (++pm->y >= pm->lines)
940#ifdef KBD_MODES
Stéphane Doyond529a382007-10-10 02:28:58 +0000941 {
Michael Sevakis11e45a32007-03-06 05:43:04 +0000942 pm->line_edit = true;
Stéphane Doyond529a382007-10-10 02:28:58 +0000943 say_edit();
944 }
Jens Arnold7b95e602004-11-14 23:08:08 +0000945#else
Michael Sevakis11e45a32007-03-06 05:43:04 +0000946 pm->y = 0;
947#endif
Jens Arnold7b95e602004-11-14 23:08:08 +0000948 }
Michael Sevakis11e45a32007-03-06 05:43:04 +0000949#ifdef KBD_MODES
950 if (!pm->line_edit)
Jens Arnold7b95e602004-11-14 23:08:08 +0000951#endif
Frank Dischner75c3d0b2006-03-29 16:21:42 +0000952 {
Michael Sevakis11e45a32007-03-06 05:43:04 +0000953 int k = get_param_k(pm);
954 kbd_spellchar(pm->kbd_buf[k]);
Frank Dischner75c3d0b2006-03-29 16:21:42 +0000955 }
Björn Stenberg58dff172003-01-15 13:48:54 +0000956 break;
Björn Stenbergc8cb6ff2002-12-04 15:04:43 +0000957
Martin Scarratt0ba22042006-08-22 13:21:13 +0000958 case ACTION_KBD_UP:
Michael Sevakis11e45a32007-03-06 05:43:04 +0000959#ifdef KBD_MORSE_INPUT
960#ifdef KBD_MODES
961 if (morse_mode)
Stéphane Doyond529a382007-10-10 02:28:58 +0000962 {
Michael Sevakis11e45a32007-03-06 05:43:04 +0000963 pm->line_edit = !pm->line_edit;
Stéphane Doyond529a382007-10-10 02:28:58 +0000964 if(pm->line_edit)
965 say_edit();
966 }
Michael Sevakis11e45a32007-03-06 05:43:04 +0000967 else
968#else
Miika Pekkarinen9d918c92005-12-02 19:41:09 +0000969 if (morse_mode)
970 break;
971#endif
Michael Sevakis11e45a32007-03-06 05:43:04 +0000972#endif /* KBD_MORSE_INPUT */
973 {
Jens Arnold7b95e602004-11-14 23:08:08 +0000974#ifdef KBD_MODES
Michael Sevakis11e45a32007-03-06 05:43:04 +0000975 if (pm->line_edit)
Martin Scarrattef8317b2006-07-19 12:07:51 +0000976 {
Michael Sevakis11e45a32007-03-06 05:43:04 +0000977 pm->y = pm->lines - 1;
978 pm->line_edit = false;
Martin Scarrattef8317b2006-07-19 12:07:51 +0000979 }
Michael Sevakis11e45a32007-03-06 05:43:04 +0000980 else
981#endif
982 if (--pm->y < 0)
983#ifdef KBD_MODES
Stéphane Doyond529a382007-10-10 02:28:58 +0000984 {
Michael Sevakis11e45a32007-03-06 05:43:04 +0000985 pm->line_edit = true;
Stéphane Doyond529a382007-10-10 02:28:58 +0000986 say_edit();
987 }
Michael Sevakis11e45a32007-03-06 05:43:04 +0000988#else
989 pm->y = pm->lines - 1;
990#endif
Jens Arnold7b95e602004-11-14 23:08:08 +0000991 }
Michael Sevakis11e45a32007-03-06 05:43:04 +0000992#ifdef KBD_MODES
993 if (!pm->line_edit)
Jens Arnold7b95e602004-11-14 23:08:08 +0000994#endif
Frank Dischner75c3d0b2006-03-29 16:21:42 +0000995 {
Michael Sevakis11e45a32007-03-06 05:43:04 +0000996 int k = get_param_k(pm);
997 kbd_spellchar(pm->kbd_buf[k]);
Frank Dischner75c3d0b2006-03-29 16:21:42 +0000998 }
Björn Stenberg58dff172003-01-15 13:48:54 +0000999 break;
Björn Stenbergc8cb6ff2002-12-04 15:04:43 +00001000
Martin Scarratt0ba22042006-08-22 13:21:13 +00001001 case ACTION_KBD_DONE:
Jörg Hohensohn705ad512004-10-22 17:00:30 +00001002 /* accepts what was entered and continues */
Björn Stenberg58dff172003-01-15 13:48:54 +00001003 done = true;
1004 break;
Björn Stenbergc8cb6ff2002-12-04 15:04:43 +00001005
Frank Dischner75c3d0b2006-03-29 16:21:42 +00001006#ifdef KBD_MORSE_INPUT
Martin Scarratt0ba22042006-08-22 13:21:13 +00001007 case ACTION_KBD_MORSE_SELECT:
Miika Pekkarinen9d918c92005-12-02 19:41:09 +00001008 if (morse_mode && morse_reading)
1009 {
1010 morse_code <<= 1;
1011 if ((current_tick - morse_tick) > HZ/5)
1012 morse_code |= 0x01;
1013 }
Zakk Robertsa1db4312006-04-22 09:43:43 +00001014
Miika Pekkarinen9d918c92005-12-02 19:41:09 +00001015 break;
Michael Sevakis11e45a32007-03-06 05:43:04 +00001016#endif /* KBD_MORSE_INPUT */
Zakk Robertsa1db4312006-04-22 09:43:43 +00001017
Martin Scarratt0ba22042006-08-22 13:21:13 +00001018 case ACTION_KBD_SELECT:
1019 case ACTION_KBD_SELECT_REM:
Frank Dischner75c3d0b2006-03-29 16:21:42 +00001020#ifdef KBD_MORSE_INPUT
Nils Wallménius8a71f1a2007-01-04 14:36:04 +00001021#ifdef KBD_MODES
Michael Sevakis11e45a32007-03-06 05:43:04 +00001022 if (morse_mode && !pm->line_edit)
Nils Wallménius8a71f1a2007-01-04 14:36:04 +00001023#else
Miika Pekkarinen9d918c92005-12-02 19:41:09 +00001024 if (morse_mode)
Nils Wallménius8a71f1a2007-01-04 14:36:04 +00001025#endif
Miika Pekkarinen9d918c92005-12-02 19:41:09 +00001026 {
1027 morse_tick = current_tick;
Michael Sevakis11e45a32007-03-06 05:43:04 +00001028
Miika Pekkarinen9d918c92005-12-02 19:41:09 +00001029 if (!morse_reading)
1030 {
1031 morse_reading = true;
1032 morse_code = 1;
1033 }
1034 break;
1035 }
Michael Sevakis11e45a32007-03-06 05:43:04 +00001036#endif /* KBD_MORSE_INPUT */
Zakk Robertsa1db4312006-04-22 09:43:43 +00001037
Jörg Hohensohn705ad512004-10-22 17:00:30 +00001038 /* inserts the selected char */
Jens Arnold7b95e602004-11-14 23:08:08 +00001039#ifdef KBD_MODES
Michael Sevakis11e45a32007-03-06 05:43:04 +00001040 if (pm->line_edit)
1041 { /* select doubles as backspace in line_edit */
1042 if (pm->hangul)
1043 {
1044 if (pm->htail)
1045 pm->htail = 0;
1046 else if (pm->hvowel)
1047 pm->hvowel = 0;
Frank Dischner367b8ec2006-03-31 13:59:04 +00001048 else
Michael Sevakis11e45a32007-03-06 05:43:04 +00001049 pm->hangul = false;
Frank Dischner75c3d0b2006-03-29 16:21:42 +00001050 }
Michael Sevakis11e45a32007-03-06 05:43:04 +00001051
Frank Dischner75c3d0b2006-03-29 16:21:42 +00001052 kbd_delchar(text, &editpos);
Michael Sevakis11e45a32007-03-06 05:43:04 +00001053
1054 if (pm->hangul)
1055 {
1056 if (pm->hvowel)
1057 ch = hangul_join(pm->hlead, pm->hvowel, pm->htail);
Frank Dischner75c3d0b2006-03-29 16:21:42 +00001058 else
Michael Sevakis11e45a32007-03-06 05:43:04 +00001059 ch = pm->hlead;
1060 kbd_inschar(text, buflen, &editpos, ch);
Björn Stenbergaa2972d2003-03-10 15:09:27 +00001061 }
Björn Stenberg58dff172003-01-15 13:48:54 +00001062 }
Jens Arnold7b95e602004-11-14 23:08:08 +00001063 else
Michael Sevakis11e45a32007-03-06 05:43:04 +00001064#endif /* KBD_MODES */
Jens Arnold7b95e602004-11-14 23:08:08 +00001065 {
Frank Dischner75c3d0b2006-03-29 16:21:42 +00001066 /* find input char */
Michael Sevakis11e45a32007-03-06 05:43:04 +00001067 int k = get_param_k(pm);
1068 ch = (k < pm->nchars) ? pm->kbd_buf[k] : ' ';
1069
Frank Dischner75c3d0b2006-03-29 16:21:42 +00001070 /* check for hangul input */
Martin Scarrattef8317b2006-07-19 12:07:51 +00001071 if (ch >= 0x3131 && ch <= 0x3163)
1072 {
Michael Sevakis11e45a32007-03-06 05:43:04 +00001073 unsigned short tmp;
1074
1075 if (!pm->hangul)
Martin Scarrattef8317b2006-07-19 12:07:51 +00001076 {
Michael Sevakis11e45a32007-03-06 05:43:04 +00001077 pm->hlead = pm->hvowel = pm->htail = 0;
1078 pm->hangul = true;
Frank Dischner75c3d0b2006-03-29 16:21:42 +00001079 }
Michael Sevakis11e45a32007-03-06 05:43:04 +00001080
1081 if (!pm->hvowel)
1082 {
1083 pm->hvowel = ch;
1084 }
1085 else if (!pm->htail)
1086 {
1087 pm->htail = ch;
1088 }
Antoine Cellerier8eba20a2006-07-23 17:16:38 +00001089 else
Martin Scarrattef8317b2006-07-19 12:07:51 +00001090 { /* previous hangul complete */
Frank Dischner367b8ec2006-03-31 13:59:04 +00001091 /* check whether tail is actually lead of next char */
Michael Sevakis11e45a32007-03-06 05:43:04 +00001092 tmp = hangul_join(pm->htail, ch, 0);
1093
1094 if (tmp != 0xfffd)
Martin Scarrattef8317b2006-07-19 12:07:51 +00001095 {
Michael Sevakis11e45a32007-03-06 05:43:04 +00001096 tmp = hangul_join(pm->hlead, pm->hvowel, 0);
Frank Dischner367b8ec2006-03-31 13:59:04 +00001097 kbd_delchar(text, &editpos);
1098 kbd_inschar(text, buflen, &editpos, tmp);
1099 /* insert dummy char */
1100 kbd_inschar(text, buflen, &editpos, ' ');
Michael Sevakis11e45a32007-03-06 05:43:04 +00001101 pm->hlead = pm->htail;
1102 pm->hvowel = ch;
1103 pm->htail = 0;
Martin Scarrattef8317b2006-07-19 12:07:51 +00001104 }
Antoine Cellerier8eba20a2006-07-23 17:16:38 +00001105 else
Martin Scarrattef8317b2006-07-19 12:07:51 +00001106 {
Michael Sevakis11e45a32007-03-06 05:43:04 +00001107 pm->hvowel = pm->htail = 0;
1108 pm->hlead = ch;
Frank Dischner367b8ec2006-03-31 13:59:04 +00001109 }
Frank Dischner75c3d0b2006-03-29 16:21:42 +00001110 }
Michael Sevakis11e45a32007-03-06 05:43:04 +00001111
Frank Dischner367b8ec2006-03-31 13:59:04 +00001112 /* combine into hangul */
Michael Sevakis11e45a32007-03-06 05:43:04 +00001113 tmp = hangul_join(pm->hlead, pm->hvowel, pm->htail);
1114
1115 if (tmp != 0xfffd)
Martin Scarrattef8317b2006-07-19 12:07:51 +00001116 {
Frank Dischner367b8ec2006-03-31 13:59:04 +00001117 kbd_delchar(text, &editpos);
1118 ch = tmp;
Antoine Cellerier8eba20a2006-07-23 17:16:38 +00001119 }
Martin Scarrattef8317b2006-07-19 12:07:51 +00001120 else
1121 {
Michael Sevakis11e45a32007-03-06 05:43:04 +00001122 pm->hvowel = pm->htail = 0;
1123 pm->hlead = ch;
Frank Dischner367b8ec2006-03-31 13:59:04 +00001124 }
Antoine Cellerier8eba20a2006-07-23 17:16:38 +00001125 }
Martin Scarrattef8317b2006-07-19 12:07:51 +00001126 else
Michael Sevakis11e45a32007-03-06 05:43:04 +00001127 {
1128 pm->hangul = false;
1129 }
Antoine Cellerier8eba20a2006-07-23 17:16:38 +00001130
Frank Dischner75c3d0b2006-03-29 16:21:42 +00001131 /* insert char */
1132 kbd_inschar(text, buflen, &editpos, ch);
Jens Arnold7b95e602004-11-14 23:08:08 +00001133 }
Michael Sevakis11e45a32007-03-06 05:43:04 +00001134
Steve Bavin32a95752007-10-19 15:31:42 +00001135 if (global_settings.talk_menu) /* voice UI? */
Antoine Cellerier8eba20a2006-07-23 17:16:38 +00001136 talk_spell(text, false);
1137
Martin Scarrattef8317b2006-07-19 12:07:51 +00001138 /* speak revised text */
Jens Arnold7b95e602004-11-14 23:08:08 +00001139 break;
1140
Michael Sevakis97019542007-03-05 02:07:17 +00001141#if !defined (KBD_MODES) || defined (KBD_CURSOR_KEYS)
Martin Scarratt0ba22042006-08-22 13:21:13 +00001142 case ACTION_KBD_BACKSPACE:
Michael Sevakis11e45a32007-03-06 05:43:04 +00001143 if (pm->hangul)
Martin Scarrattef8317b2006-07-19 12:07:51 +00001144 {
Michael Sevakis11e45a32007-03-06 05:43:04 +00001145 if (pm->htail)
1146 pm->htail = 0;
1147 else if (pm->hvowel)
1148 pm->hvowel = 0;
Frank Dischner367b8ec2006-03-31 13:59:04 +00001149 else
Michael Sevakis11e45a32007-03-06 05:43:04 +00001150 pm->hangul = false;
Frank Dischner75c3d0b2006-03-29 16:21:42 +00001151 }
Michael Sevakis11e45a32007-03-06 05:43:04 +00001152
Frank Dischner75c3d0b2006-03-29 16:21:42 +00001153 kbd_delchar(text, &editpos);
Michael Sevakis11e45a32007-03-06 05:43:04 +00001154
1155 if (pm->hangul)
Martin Scarrattef8317b2006-07-19 12:07:51 +00001156 {
Michael Sevakis11e45a32007-03-06 05:43:04 +00001157 if (pm->hvowel)
1158 ch = hangul_join(pm->hlead, pm->hvowel, pm->htail);
Frank Dischner75c3d0b2006-03-29 16:21:42 +00001159 else
Michael Sevakis11e45a32007-03-06 05:43:04 +00001160 ch = pm->hlead;
Frank Dischner75c3d0b2006-03-29 16:21:42 +00001161 kbd_inschar(text, buflen, &editpos, ch);
Jens Arnold7b95e602004-11-14 23:08:08 +00001162 }
Michael Sevakis11e45a32007-03-06 05:43:04 +00001163
Steve Bavin32a95752007-10-19 15:31:42 +00001164 if (global_settings.talk_menu) /* voice UI? */
Jens Arnold0b31a002005-02-07 00:56:26 +00001165 talk_spell(text, false); /* speak revised text */
Björn Stenberg58dff172003-01-15 13:48:54 +00001166 break;
Björn Stenbergaa2972d2003-03-10 15:09:27 +00001167
Martin Scarratt0ba22042006-08-22 13:21:13 +00001168 case ACTION_KBD_CURSOR_RIGHT:
Michael Sevakis11e45a32007-03-06 05:43:04 +00001169 pm->hangul = false;
Martin Scarrattef8317b2006-07-19 12:07:51 +00001170
Marcoen Hirschbergb0fee172005-12-06 13:27:15 +00001171 if (editpos < len_utf8)
Jens Arnold0b31a002005-02-07 00:56:26 +00001172 {
Michael Sevakis11e45a32007-03-06 05:43:04 +00001173 int c = utf8seek(text, ++editpos);
Marcoen Hirschbergb0fee172005-12-06 13:27:15 +00001174 kbd_spellchar(text[c]);
Jens Arnold0b31a002005-02-07 00:56:26 +00001175 }
Jens Arnold9afdf992007-10-10 06:19:54 +00001176#if CONFIG_CODEC == SWCODEC
Steve Bavin32a95752007-10-19 15:31:42 +00001177 else if (global_settings.talk_menu)
Jens Arnold9afdf992007-10-10 06:19:54 +00001178 pcmbuf_beep(1000, 150, 1500);
1179#endif
Björn Stenbergaa2972d2003-03-10 15:09:27 +00001180 break;
1181
Martin Scarratt0ba22042006-08-22 13:21:13 +00001182 case ACTION_KBD_CURSOR_LEFT:
Michael Sevakis11e45a32007-03-06 05:43:04 +00001183 pm->hangul = false;
Martin Scarratt0ba22042006-08-22 13:21:13 +00001184
Michael Sevakis11e45a32007-03-06 05:43:04 +00001185 if (editpos > 0)
Jens Arnold0b31a002005-02-07 00:56:26 +00001186 {
Michael Sevakis11e45a32007-03-06 05:43:04 +00001187 int c = utf8seek(text, --editpos);
Marcoen Hirschbergb0fee172005-12-06 13:27:15 +00001188 kbd_spellchar(text[c]);
Jens Arnold0b31a002005-02-07 00:56:26 +00001189 }
Jens Arnold9afdf992007-10-10 06:19:54 +00001190#if CONFIG_CODEC == SWCODEC
Steve Bavin32a95752007-10-19 15:31:42 +00001191 else if (global_settings.talk_menu)
Jens Arnold9afdf992007-10-10 06:19:54 +00001192 pcmbuf_beep(1000, 150, 1500);
1193#endif
Björn Stenbergaa2972d2003-03-10 15:09:27 +00001194 break;
Michael Sevakis97019542007-03-05 02:07:17 +00001195#endif /* !defined (KBD_MODES) || defined (KBD_CURSOR_KEYS) */
Björn Stenbergaa2972d2003-03-10 15:09:27 +00001196
Linus Nielsen Feltzing6afd0a72003-11-04 12:36:55 +00001197 case BUTTON_NONE:
Frank Dischner75c3d0b2006-03-29 16:21:42 +00001198#ifdef KBD_MORSE_INPUT
Miika Pekkarinen9d918c92005-12-02 19:41:09 +00001199 if (morse_reading)
1200 {
Michael Sevakis11e45a32007-03-06 05:43:04 +00001201 int j;
Miika Pekkarinen9d918c92005-12-02 19:41:09 +00001202 logf("Morse: 0x%02x", morse_code);
1203 morse_reading = false;
1204
1205 for (j = 0; morse_alphabets[j] != '\0'; j++)
1206 {
1207 if (morse_codes[j] == morse_code)
1208 break ;
1209 }
1210
1211 if (morse_alphabets[j] == '\0')
1212 {
1213 logf("Morse code not found");
1214 break ;
1215 }
Frank Dischner75c3d0b2006-03-29 16:21:42 +00001216
Frank Dischner367b8ec2006-03-31 13:59:04 +00001217 /* turn off hangul input */
Michael Sevakis11e45a32007-03-06 05:43:04 +00001218 FOR_NB_SCREENS(l)
1219 param[l].hangul = false;
Frank Dischner75c3d0b2006-03-29 16:21:42 +00001220 kbd_inschar(text, buflen, &editpos, morse_alphabets[j]);
1221
Steve Bavin32a95752007-10-19 15:31:42 +00001222 if (global_settings.talk_menu) /* voice UI? */
Miika Pekkarinen9d918c92005-12-02 19:41:09 +00001223 talk_spell(text, false); /* speak revised text */
Miika Pekkarinen9d918c92005-12-02 19:41:09 +00001224 }
Michael Sevakis11e45a32007-03-06 05:43:04 +00001225#endif /* KBD_MORSE_INPUT */
Linus Nielsen Feltzing6afd0a72003-11-04 12:36:55 +00001226 break;
Linus Nielsen Feltzingade5d7b2004-07-26 16:06:59 +00001227
1228 default:
Michael Sevakis11e45a32007-03-06 05:43:04 +00001229 if (default_event_handler(button) == SYS_USB_CONNECTED)
1230 {
Martin Scarrattef8317b2006-07-19 12:07:51 +00001231 FOR_NB_SCREENS(l)
1232 screens[l].setfont(FONT_SYSFIXED);
Michael Sevakis11e45a32007-03-06 05:43:04 +00001233 }
Linus Nielsen Feltzingade5d7b2004-07-26 16:06:59 +00001234 break;
1235
Michael Sevakis11e45a32007-03-06 05:43:04 +00001236 } /* end switch */
1237
Jörg Hohensohn705ad512004-10-22 17:00:30 +00001238 if (button != BUTTON_NONE)
Jens Arnoldb5991b22006-04-22 13:06:57 +00001239 {
Jens Arnoldb5991b22006-04-22 13:06:57 +00001240 cur_blink = true;
1241 }
Björn Stenbergc8cb6ff2002-12-04 15:04:43 +00001242 }
Michael Sevakis11e45a32007-03-06 05:43:04 +00001243
Peter D'Hoyef76122f2008-05-29 20:32:39 +00001244#ifdef HAVE_BUTTONBAR
Michael Sevakis11e45a32007-03-06 05:43:04 +00001245 global_settings.buttonbar = buttonbar_config;
Linus Nielsen Feltzingdd939aa2006-03-11 22:31:53 +00001246#endif
Michael Sevakis11e45a32007-03-06 05:43:04 +00001247
Martin Scarrattef8317b2006-07-19 12:07:51 +00001248 FOR_NB_SCREENS(l)
1249 screens[l].setfont(FONT_UI);
Jonathan Gordon45aa9a22009-01-05 10:25:41 +00001250 viewportmanager_set_statusbar(oldbars);
Michael Sevakis11e45a32007-03-06 05:43:04 +00001251
Björn Stenbergc8cb6ff2002-12-04 15:04:43 +00001252 return 0;
Björn Stenbergc8cb6ff2002-12-04 15:04:43 +00001253}