blob: 72e4289fc544070df6c4e0badb2adae60ec990bd [file] [log] [blame]
Daniel Stenberg1c0c8612002-05-17 12:22:24 +00001/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2002 Robert E. Hak
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
Björn Stenberg2ac05722002-05-26 17:03:17 +000019#include <stdbool.h>
Linus Nielsen Feltzing10b92c42004-03-12 10:20:33 +000020#include <stdlib.h>
Justin Heinerb5025a82002-08-31 04:58:35 +000021
Linus Nielsen Feltzing0a4b2472002-10-15 12:25:57 +000022#include "hwcompat.h"
Daniel Stenberg1c0c8612002-05-17 12:22:24 +000023#include "lcd.h"
Daniel Stenberg93b231c2002-09-12 13:33:59 +000024#include "font.h"
Justin Heinerb5025a82002-08-31 04:58:35 +000025#include "backlight.h"
Daniel Stenberg1c0c8612002-05-17 12:22:24 +000026#include "menu.h"
Björn Stenbergb21a3bd2002-05-21 14:25:45 +000027#include "button.h"
28#include "kernel.h"
29#include "debug.h"
Justin Heiner26302452002-08-23 02:17:00 +000030#include "usb.h"
Björn Stenbergcd225732002-08-11 09:17:47 +000031#include "panic.h"
Markus Braun5e4c1d22002-08-20 19:37:00 +000032#include "settings.h"
33#include "status.h"
Björn Stenberga4c3b032002-09-24 18:04:15 +000034#include "screens.h"
Jörg Hohensohn4f36ea82004-03-14 21:33:53 +000035#include "talk.h"
Jörg Hohensohnb1403ee2004-07-23 23:01:20 +000036#include "lang.h"
Markus Braun000c2db2002-08-30 13:49:32 +000037
Daniel Stenbergbf603f92002-06-14 08:47:44 +000038#ifdef HAVE_LCD_BITMAP
39#include "icons.h"
Markus Braun000c2db2002-08-30 13:49:32 +000040#include "widgets.h"
Daniel Stenbergbf603f92002-06-14 08:47:44 +000041#endif
Markus Braun000c2db2002-08-30 13:49:32 +000042
Björn Stenberg2ac05722002-05-26 17:03:17 +000043struct menu {
Björn Stenbergf76cee72002-05-28 15:35:33 +000044 int top;
Björn Stenberg2ac05722002-05-26 17:03:17 +000045 int cursor;
Linus Nielsen Feltzing77936e62004-03-16 13:44:56 +000046 struct menu_item* items;
Björn Stenberg2ac05722002-05-26 17:03:17 +000047 int itemcount;
Linus Nielsen Feltzing10b92c42004-03-12 10:20:33 +000048 int (*callback)(int, int);
Linus Nielsen Feltzing77936e62004-03-16 13:44:56 +000049#ifdef HAVE_LCD_BITMAP
50 bool use_buttonbar; /* true if a buttonbar is defined */
51 char *buttonbar[3];
52#endif
Björn Stenberg2ac05722002-05-26 17:03:17 +000053};
54
Hardeep Sidhu107ebc52004-01-26 17:05:21 +000055#define MAX_MENUS 5
Björn Stenberg2ac05722002-05-26 17:03:17 +000056
Björn Stenbergf76cee72002-05-28 15:35:33 +000057#ifdef HAVE_LCD_BITMAP
Markus Braun000c2db2002-08-30 13:49:32 +000058
Björn Stenberg8fb73122002-09-24 19:41:23 +000059/* pixel margins */
60#define MARGIN_X (global_settings.scrollbar && \
61 menu_lines < menus[m].itemcount ? SCROLLBAR_WIDTH : 0) +\
62 CURSOR_WIDTH
63#define MARGIN_Y (global_settings.statusbar ? STATUSBAR_HEIGHT : 0)
Markus Braun000c2db2002-08-30 13:49:32 +000064
Björn Stenberg8fb73122002-09-24 19:41:23 +000065/* position the entry-list starts at */
66#define LINE_X 0
67#define LINE_Y (global_settings.statusbar ? 1 : 0)
Markus Braun000c2db2002-08-30 13:49:32 +000068
Björn Stenberg8fb73122002-09-24 19:41:23 +000069#define CURSOR_X (global_settings.scrollbar && \
70 menu_lines < menus[m].itemcount ? 1 : 0)
71#define CURSOR_Y 0 /* the cursor is not positioned in regard to
72 the margins, so this is the amount of lines
73 we add to the cursor Y position to position
74 it on a line */
Linus Nielsen Feltzinge43b78a2003-04-16 00:12:31 +000075#define CURSOR_WIDTH (global_settings.invert_cursor ? 0 : 4)
Markus Braun000c2db2002-08-30 13:49:32 +000076
77#define SCROLLBAR_X 0
78#define SCROLLBAR_Y lcd_getymargin()
79#define SCROLLBAR_WIDTH 6
80
81#else /* HAVE_LCD_BITMAP */
82
Justin Heinerb5025a82002-08-31 04:58:35 +000083#define LINE_X 1 /* X position the entry-list starts at */
Markus Braun000c2db2002-08-30 13:49:32 +000084
Björn Stenbergf76cee72002-05-28 15:35:33 +000085#define MENU_LINES 2
Markus Braun000c2db2002-08-30 13:49:32 +000086
87#define CURSOR_X 0
88#define CURSOR_Y 0 /* not really used for players */
89
90#endif /* HAVE_LCD_BITMAP */
Björn Stenbergf76cee72002-05-28 15:35:33 +000091
Kjell Ericsonc11b90f2003-01-10 09:55:50 +000092#define CURSOR_CHAR 0x92
Björn Stenberg9314a682002-05-31 09:04:51 +000093
Björn Stenberg2ac05722002-05-26 17:03:17 +000094static struct menu menus[MAX_MENUS];
95static bool inuse[MAX_MENUS] = { false };
Daniel Stenberg1c0c8612002-05-17 12:22:24 +000096
Daniel Stenberg93b231c2002-09-12 13:33:59 +000097/* count in letter positions, NOT pixels */
Daniel Stenbergbf603f92002-06-14 08:47:44 +000098void put_cursorxy(int x, int y, bool on)
99{
Björn Stenberg71f71ef2002-08-11 09:20:53 +0000100#ifdef HAVE_LCD_BITMAP
Daniel Stenberg93b231c2002-09-12 13:33:59 +0000101 int fh, fw;
Björn Stenbergbed3d3f2002-09-20 08:07:51 +0000102 int xpos, ypos;
Björn Stenbergd1a6fa12003-06-05 09:38:26 +0000103
104 /* check here instead of at every call (ugly, but cheap) */
Linus Nielsen Feltzinge43b78a2003-04-16 00:12:31 +0000105 if (global_settings.invert_cursor)
106 return;
Björn Stenbergd1a6fa12003-06-05 09:38:26 +0000107
Björn Stenberga4c3b032002-09-24 18:04:15 +0000108 lcd_getstringsize("A", &fw, &fh);
Björn Stenbergbed3d3f2002-09-20 08:07:51 +0000109 xpos = x*6;
110 ypos = y*fh + lcd_getymargin();
111 if ( fh > 8 )
112 ypos += (fh - 8) / 2;
Björn Stenberg71f71ef2002-08-11 09:20:53 +0000113#endif
Björn Stenbergcd225732002-08-11 09:17:47 +0000114
Daniel Stenbergbf603f92002-06-14 08:47:44 +0000115 /* place the cursor */
116 if(on) {
117#ifdef HAVE_LCD_BITMAP
118 lcd_bitmap ( bitmap_icons_6x8[Cursor],
Björn Stenbergbed3d3f2002-09-20 08:07:51 +0000119 xpos, ypos, 4, 8, true);
Daniel Stenbergbf603f92002-06-14 08:47:44 +0000120#else
Kjell Ericsonc11b90f2003-01-10 09:55:50 +0000121 lcd_putc(x, y, CURSOR_CHAR);
Daniel Stenbergbf603f92002-06-14 08:47:44 +0000122#endif
123 }
124 else {
Daniel Stenbergc4be1ee2002-06-19 13:00:14 +0000125#if defined(HAVE_LCD_BITMAP)
Daniel Stenbergbf603f92002-06-14 08:47:44 +0000126 /* I use xy here since it needs to disregard the margins */
Björn Stenbergbed3d3f2002-09-20 08:07:51 +0000127 lcd_clearrect (xpos, ypos, 4, 8);
Daniel Stenbergbf603f92002-06-14 08:47:44 +0000128#else
Björn Stenberg3b974742002-09-09 23:57:00 +0000129 lcd_putc(x, y, ' ');
Daniel Stenbergbf603f92002-06-14 08:47:44 +0000130#endif
131 }
132}
133
Linus Nielsen Feltzing10b92c42004-03-12 10:20:33 +0000134void menu_draw(int m)
Björn Stenbergf76cee72002-05-28 15:35:33 +0000135{
136 int i = 0;
Eric Linenberg038df5c2002-09-16 03:18:49 +0000137#ifdef HAVE_LCD_BITMAP
Daniel Stenberg93b231c2002-09-12 13:33:59 +0000138 int fw, fh;
Björn Stenbergcd225732002-08-11 09:17:47 +0000139 int menu_lines;
Linus Nielsen Feltzing77936e62004-03-16 13:44:56 +0000140 int height = LCD_HEIGHT;
141
Björn Stenberga4c3b032002-09-24 18:04:15 +0000142 lcd_setfont(FONT_UI);
143 lcd_getstringsize("A", &fw, &fh);
Markus Braun5e4c1d22002-08-20 19:37:00 +0000144 if (global_settings.statusbar)
Linus Nielsen Feltzing77936e62004-03-16 13:44:56 +0000145 height -= STATUSBAR_HEIGHT;
146
147 if(global_settings.buttonbar && menus[m].use_buttonbar) {
148 buttonbar_set(menus[m].buttonbar[0],
149 menus[m].buttonbar[1],
150 menus[m].buttonbar[2]);
151 height -= BUTTONBAR_HEIGHT;
152 }
153
154 menu_lines = height / fh;
155
Björn Stenbergcd225732002-08-11 09:17:47 +0000156#else
157 int menu_lines = MENU_LINES;
158#endif
Björn Stenbergf76cee72002-05-28 15:35:33 +0000159
Linus Nielsen Feltzing361dd292004-04-09 17:47:18 +0000160 lcd_clear_display();
Björn Stenbergf76cee72002-05-28 15:35:33 +0000161#ifdef HAVE_LCD_BITMAP
Markus Braun000c2db2002-08-30 13:49:32 +0000162 lcd_setmargins(MARGIN_X,MARGIN_Y); /* leave room for cursor and icon */
Björn Stenbergf76cee72002-05-28 15:35:33 +0000163#endif
Linus Nielsen Feltzing361dd292004-04-09 17:47:18 +0000164 /* Adjust cursor pos if it's below the screen */
Markus Braun5e4c1d22002-08-20 19:37:00 +0000165 if (menus[m].cursor - menus[m].top >= menu_lines)
166 menus[m].top++;
167
Linus Nielsen Feltzing361dd292004-04-09 17:47:18 +0000168 /* Adjust cursor pos if it's above the screen */
169 if(menus[m].cursor < menus[m].top)
170 menus[m].top = menus[m].cursor;
171
Björn Stenbergf76cee72002-05-28 15:35:33 +0000172 for (i = menus[m].top;
Björn Stenbergcd225732002-08-11 09:17:47 +0000173 (i < menus[m].itemcount) && (i<menus[m].top+menu_lines);
Björn Stenbergf76cee72002-05-28 15:35:33 +0000174 i++) {
Linus Nielsen Feltzing361dd292004-04-09 17:47:18 +0000175
176 /* We want to scroll the line where the cursor is */
Linus Nielsen Feltzing8fa02172002-08-02 07:59:25 +0000177 if((menus[m].cursor - menus[m].top)==(i-menus[m].top))
Linus Nielsen Feltzinge43b78a2003-04-16 00:12:31 +0000178#ifdef HAVE_LCD_BITMAP
179 if (global_settings.invert_cursor)
180 lcd_puts_scroll_style(LINE_X, i-menus[m].top,
Jörg Hohensohnb1403ee2004-07-23 23:01:20 +0000181 P2STR(menus[m].items[i].desc), STYLE_INVERT);
Linus Nielsen Feltzinge43b78a2003-04-16 00:12:31 +0000182 else
183#endif
Jörg Hohensohnb1403ee2004-07-23 23:01:20 +0000184 lcd_puts_scroll(LINE_X, i-menus[m].top, P2STR(menus[m].items[i].desc));
Linus Nielsen Feltzing8fa02172002-08-02 07:59:25 +0000185 else
Jörg Hohensohnb1403ee2004-07-23 23:01:20 +0000186 lcd_puts(LINE_X, i-menus[m].top, P2STR(menus[m].items[i].desc));
Björn Stenbergf76cee72002-05-28 15:35:33 +0000187 }
Robert Hakc501ac72002-05-30 08:06:42 +0000188
Daniel Stenbergbf603f92002-06-14 08:47:44 +0000189 /* place the cursor */
Markus Braun000c2db2002-08-30 13:49:32 +0000190 put_cursorxy(CURSOR_X, menus[m].cursor - menus[m].top, true);
Linus Nielsen Feltzing361dd292004-04-09 17:47:18 +0000191
Markus Braun5e4c1d22002-08-20 19:37:00 +0000192#ifdef HAVE_LCD_BITMAP
Björn Stenberg8fb73122002-09-24 19:41:23 +0000193 if (global_settings.scrollbar && menus[m].itemcount > menu_lines)
Markus Braun000c2db2002-08-30 13:49:32 +0000194 scrollbar(SCROLLBAR_X, SCROLLBAR_Y, SCROLLBAR_WIDTH - 1,
Linus Nielsen Feltzing77936e62004-03-16 13:44:56 +0000195 height, menus[m].itemcount, menus[m].top,
Markus Braun000c2db2002-08-30 13:49:32 +0000196 menus[m].top + menu_lines, VERTICAL);
Linus Nielsen Feltzing77936e62004-03-16 13:44:56 +0000197
198 if(global_settings.buttonbar && menus[m].use_buttonbar)
199 buttonbar_draw();
Markus Braun5e4c1d22002-08-20 19:37:00 +0000200#endif
Björn Stenberg942bc942003-04-23 11:26:25 +0000201 status_draw(true);
Linus Nielsen Feltzing77936e62004-03-16 13:44:56 +0000202
Björn Stenbergf76cee72002-05-28 15:35:33 +0000203 lcd_update();
204}
205
Björn Stenbergb21a3bd2002-05-21 14:25:45 +0000206/*
207 * Move the cursor to a particular id,
208 * target: where you want it to be
209 */
Björn Stenberg2ac05722002-05-26 17:03:17 +0000210static void put_cursor(int m, int target)
Daniel Stenberg1c0c8612002-05-17 12:22:24 +0000211{
Linus Nielsen Feltzing361dd292004-04-09 17:47:18 +0000212 int voice_id;
Linus Nielsen Feltzing77936e62004-03-16 13:44:56 +0000213
Robert Hakc501ac72002-05-30 08:06:42 +0000214 menus[m].cursor = target;
Linus Nielsen Feltzing8fa02172002-08-02 07:59:25 +0000215 menu_draw(m);
Björn Stenbergf76cee72002-05-28 15:35:33 +0000216
Linus Nielsen Feltzing361dd292004-04-09 17:47:18 +0000217 /* "say" the entry under the cursor */
218 if(global_settings.talk_menu)
219 {
Jörg Hohensohnb1403ee2004-07-23 23:01:20 +0000220 voice_id = P2ID(menus[m].items[menus[m].cursor].desc);
Linus Nielsen Feltzing361dd292004-04-09 17:47:18 +0000221 if (voice_id >= 0) /* valid ID given? */
Jörg Hohensohn4f36ea82004-03-14 21:33:53 +0000222 talk_id(voice_id, false); /* say it */
223 }
Daniel Stenberg1c0c8612002-05-17 12:22:24 +0000224}
225
Jörg Hohensohnb1403ee2004-07-23 23:01:20 +0000226int menu_init(const struct menu_item* mitems, int count, int (*callback)(int, int),
Linus Nielsen Feltzing77936e62004-03-16 13:44:56 +0000227 char *button1, char *button2, char *button3)
Daniel Stenberg1c0c8612002-05-17 12:22:24 +0000228{
Björn Stenberg2ac05722002-05-26 17:03:17 +0000229 int i;
230
231 for ( i=0; i<MAX_MENUS; i++ ) {
232 if ( !inuse[i] ) {
233 inuse[i] = true;
234 break;
235 }
236 }
237 if ( i == MAX_MENUS ) {
238 DEBUGF("Out of menus!\n");
239 return -1;
240 }
Jörg Hohensohnb1403ee2004-07-23 23:01:20 +0000241 menus[i].items = (struct menu_item*)mitems; /* de-const */
Björn Stenberg2ac05722002-05-26 17:03:17 +0000242 menus[i].itemcount = count;
Björn Stenbergf76cee72002-05-28 15:35:33 +0000243 menus[i].top = 0;
Björn Stenberg2ac05722002-05-26 17:03:17 +0000244 menus[i].cursor = 0;
Linus Nielsen Feltzing10b92c42004-03-12 10:20:33 +0000245 menus[i].callback = callback;
Linus Nielsen Feltzing77936e62004-03-16 13:44:56 +0000246#ifdef HAVE_LCD_BITMAP
247 menus[i].buttonbar[0] = button1;
248 menus[i].buttonbar[1] = button2;
249 menus[i].buttonbar[2] = button3;
Björn Stenberg2ac05722002-05-26 17:03:17 +0000250
Linus Nielsen Feltzing77936e62004-03-16 13:44:56 +0000251 if(button1 || button2 || button3)
252 menus[i].use_buttonbar = true;
253 else
254 menus[i].use_buttonbar = false;
255#else
256 (void)button1;
257 (void)button2;
258 (void)button3;
259#endif
Björn Stenberg2ac05722002-05-26 17:03:17 +0000260 return i;
Daniel Stenberg1c0c8612002-05-17 12:22:24 +0000261}
262
Björn Stenberg2ac05722002-05-26 17:03:17 +0000263void menu_exit(int m)
Daniel Stenberg1c0c8612002-05-17 12:22:24 +0000264{
Björn Stenberg2ac05722002-05-26 17:03:17 +0000265 inuse[m] = false;
Daniel Stenberg1c0c8612002-05-17 12:22:24 +0000266}
267
Kjell Ericson5cd393c2003-01-29 08:26:11 +0000268int menu_show(int m)
Robert Hak7ec9aa32002-05-18 11:41:37 +0000269{
Björn Stenbergb1b8bd42002-09-24 17:22:12 +0000270 bool exit = false;
Linus Nielsen Feltzing10b92c42004-03-12 10:20:33 +0000271 int key;
Linus Nielsen Feltzingf1659a32003-11-20 01:51:15 +0000272#ifdef HAVE_LCD_BITMAP
273 int fw, fh;
274 int menu_lines;
Linus Nielsen Feltzing77936e62004-03-16 13:44:56 +0000275 int height = LCD_HEIGHT;
276
Linus Nielsen Feltzingf1659a32003-11-20 01:51:15 +0000277 lcd_setfont(FONT_UI);
278 lcd_getstringsize("A", &fw, &fh);
279 if (global_settings.statusbar)
Linus Nielsen Feltzing77936e62004-03-16 13:44:56 +0000280 height -= STATUSBAR_HEIGHT;
281
282 if(global_settings.buttonbar && menus[m].use_buttonbar) {
283 buttonbar_set(menus[m].buttonbar[0],
284 menus[m].buttonbar[1],
285 menus[m].buttonbar[2]);
286 height -= BUTTONBAR_HEIGHT;
287 }
288
289 menu_lines = height / fh;
Linus Nielsen Feltzingf1659a32003-11-20 01:51:15 +0000290#endif
Justin Heiner26302452002-08-23 02:17:00 +0000291
Linus Nielsen Feltzing361dd292004-04-09 17:47:18 +0000292 /* Put the cursor on the first line and draw the menu */
Linus Nielsen Feltzing49ea16e2004-04-14 06:04:38 +0000293 put_cursor(m, menus[m].cursor);
Jörg Hohensohn4f36ea82004-03-14 21:33:53 +0000294
Björn Stenbergb1b8bd42002-09-24 17:22:12 +0000295 while (!exit) {
Linus Nielsen Feltzing10b92c42004-03-12 10:20:33 +0000296 key = button_get_w_tmo(HZ/2);
Jörg Hohensohn4f36ea82004-03-14 21:33:53 +0000297
Linus Nielsen Feltzing10b92c42004-03-12 10:20:33 +0000298 /*
Linus Nielsen Feltzing361dd292004-04-09 17:47:18 +0000299 * "short-circuit" the default keypresses by running the
300 * callback function
301 * The callback may return a new key value, often this will be
302 * BUTTON_NONE or the same key value, but it's perfectly legal
303 * to "simulate" key presses by returning another value.
Linus Nielsen Feltzing10b92c42004-03-12 10:20:33 +0000304 */
305
306 if( menus[m].callback != NULL )
Linus Nielsen Feltzing361dd292004-04-09 17:47:18 +0000307 key = menus[m].callback(key, m);
308
Linus Nielsen Feltzing10b92c42004-03-12 10:20:33 +0000309 switch( key ) {
Jörg Hohensohn4f36ea82004-03-14 21:33:53 +0000310
Björn Stenbergb21a3bd2002-05-21 14:25:45 +0000311#ifdef HAVE_RECORDER_KEYPAD
312 case BUTTON_UP:
Björn Stenbergcbc71792002-08-10 09:04:55 +0000313 case BUTTON_UP | BUTTON_REPEAT:
Robert Hak7ec9aa32002-05-18 11:41:37 +0000314#else
Björn Stenbergb21a3bd2002-05-21 14:25:45 +0000315 case BUTTON_LEFT:
Linus Nielsen Feltzing8fa02172002-08-02 07:59:25 +0000316 case BUTTON_LEFT | BUTTON_REPEAT:
Robert Hak7ec9aa32002-05-18 11:41:37 +0000317#endif
Björn Stenberg4caebab2002-05-29 14:25:06 +0000318 if (menus[m].cursor) {
Björn Stenbergb21a3bd2002-05-21 14:25:45 +0000319 /* move up */
Björn Stenberg2ac05722002-05-26 17:03:17 +0000320 put_cursor(m, menus[m].cursor-1);
Björn Stenbergb21a3bd2002-05-21 14:25:45 +0000321 }
Eric Linenbergc076b272002-09-04 04:21:10 +0000322 else {
323 /* move to bottom */
324#ifdef HAVE_RECORDER_KEYPAD
Linus Nielsen Feltzingf1659a32003-11-20 01:51:15 +0000325 menus[m].top = menus[m].itemcount-(menu_lines+1);
Eric Linenbergc076b272002-09-04 04:21:10 +0000326#else
327 menus[m].top = menus[m].itemcount-3;
328#endif
329 if (menus[m].top < 0)
330 menus[m].top = 0;
331 menus[m].cursor = menus[m].itemcount-1;
332 put_cursor(m, menus[m].itemcount-1);
333 }
Björn Stenbergb21a3bd2002-05-21 14:25:45 +0000334 break;
Robert Hakdfba2102002-05-21 08:47:34 +0000335
Björn Stenbergb21a3bd2002-05-21 14:25:45 +0000336#ifdef HAVE_RECORDER_KEYPAD
337 case BUTTON_DOWN:
Björn Stenbergcbc71792002-08-10 09:04:55 +0000338 case BUTTON_DOWN | BUTTON_REPEAT:
Björn Stenbergb21a3bd2002-05-21 14:25:45 +0000339#else
340 case BUTTON_RIGHT:
Linus Nielsen Feltzing8fa02172002-08-02 07:59:25 +0000341 case BUTTON_RIGHT | BUTTON_REPEAT:
Björn Stenbergb21a3bd2002-05-21 14:25:45 +0000342#endif
Björn Stenberg4caebab2002-05-29 14:25:06 +0000343 if (menus[m].cursor < menus[m].itemcount-1) {
Björn Stenbergb21a3bd2002-05-21 14:25:45 +0000344 /* move down */
Björn Stenberg2ac05722002-05-26 17:03:17 +0000345 put_cursor(m, menus[m].cursor+1);
Björn Stenbergb21a3bd2002-05-21 14:25:45 +0000346 }
Eric Linenbergc076b272002-09-04 04:21:10 +0000347 else {
348 /* move to top */
349 menus[m].top = 0;
350 menus[m].cursor = 0;
351 put_cursor(m, 0);
352 }
Björn Stenbergb21a3bd2002-05-21 14:25:45 +0000353 break;
354
355#ifdef HAVE_RECORDER_KEYPAD
356 case BUTTON_RIGHT:
357#endif
358 case BUTTON_PLAY:
359 /* Erase current display state */
360 lcd_clear_display();
Kjell Ericson5cd393c2003-01-29 08:26:11 +0000361 return menus[m].cursor;
Björn Stenbergb21a3bd2002-05-21 14:25:45 +0000362
363#ifdef HAVE_RECORDER_KEYPAD
364 case BUTTON_LEFT:
Linus Nielsen Feltzinga552f4c2002-07-27 19:53:26 +0000365 case BUTTON_F1:
Björn Stenberg461d6e32003-12-04 00:08:25 +0000366 case BUTTON_OFF | BUTTON_REPEAT:
Björn Stenbergb21a3bd2002-05-21 14:25:45 +0000367#else
368 case BUTTON_STOP:
Björn Stenberg60fad542002-05-29 12:28:08 +0000369 case BUTTON_MENU:
Björn Stenberg461d6e32003-12-04 00:08:25 +0000370 case BUTTON_STOP | BUTTON_REPEAT:
Björn Stenbergb21a3bd2002-05-21 14:25:45 +0000371#endif
Kjell Ericson767d6042003-01-23 14:28:16 +0000372 lcd_stop_scroll();
Björn Stenbergb1b8bd42002-09-24 17:22:12 +0000373 exit = true;
374 break;
Björn Stenbergb21a3bd2002-05-21 14:25:45 +0000375
Justin Heiner26302452002-08-23 02:17:00 +0000376 case SYS_USB_CONNECTED:
Björn Stenbergb1b8bd42002-09-24 17:22:12 +0000377 usb_screen();
Björn Stenberg40d866b2002-09-01 20:08:08 +0000378#ifdef HAVE_LCD_CHARCELLS
Mats Lidell18739872002-10-15 12:56:05 +0000379 status_set_param(false);
Justin Heiner26302452002-08-23 02:17:00 +0000380#endif
Kjell Ericson5cd393c2003-01-29 08:26:11 +0000381 return MENU_ATTACHED_USB;
Björn Stenbergb21a3bd2002-05-21 14:25:45 +0000382 }
383
Björn Stenberg942bc942003-04-23 11:26:25 +0000384 status_draw(false);
Björn Stenbergb21a3bd2002-05-21 14:25:45 +0000385 }
Kjell Ericson5cd393c2003-01-29 08:26:11 +0000386 return MENU_SELECTED_EXIT;
387}
Daniel Stenbergb2850762002-08-23 12:32:52 +0000388
Kjell Ericson5cd393c2003-01-29 08:26:11 +0000389
390bool menu_run(int m)
391{
392 bool stop=false;
393 while (!stop) {
394 int result=menu_show(m);
395 if (result == MENU_SELECTED_EXIT)
396 return false;
397 else if (result == MENU_ATTACHED_USB)
398 return true;
399 if (menus[m].items[menus[m].cursor].function()) {
400 return true;
401 }
402 }
403 return false;
Robert Hak7ec9aa32002-05-18 11:41:37 +0000404}
Linus Nielsen Feltzing10b92c42004-03-12 10:20:33 +0000405
406/*
407 * Property function - return the current cursor for "menu"
408 */
409
410int menu_cursor(int menu)
411{
412 return menus[menu].cursor;
413}
414
415/*
416 * Property function - return the "menu" description at "position"
417 */
418
419char* menu_description(int menu, int position)
420{
Jörg Hohensohnb1403ee2004-07-23 23:01:20 +0000421 return P2STR(menus[menu].items[position].desc);
Linus Nielsen Feltzing10b92c42004-03-12 10:20:33 +0000422}
423
424/*
425 * Delete the element "position" from the menu items in "menu"
426 */
427
428void menu_delete(int menu, int position)
429{
430 int i;
431
432 /* copy the menu item from the one below */
433 for( i = position; i < (menus[menu].itemcount - 1); i++)
434 menus[menu].items[i] = menus[menu].items[i + 1];
435
436 /* reduce the count */
437 menus[menu].itemcount--;
438
439 /* adjust if this was the last menu item and the cursor was on it */
440 if( menus[menu].itemcount <= menus[menu].cursor)
441 menus[menu].cursor = menus[menu].itemcount - 1;
442}
443
Jörg Hohensohnb1403ee2004-07-23 23:01:20 +0000444void menu_insert(int menu, int position, char *desc, bool (*function) (void))
Linus Nielsen Feltzing82586a62004-07-05 14:26:58 +0000445{
446 int i;
447
448 if(position < 0)
449 position = menus[menu].itemcount;
450
451 /* Move the items below one position forward */
452 for( i = menus[menu].itemcount; i > position; i--)
453 menus[menu].items[i] = menus[menu].items[i - 1];
454
455 /* Increase the count */
456 menus[menu].itemcount++;
457
458 /* Update the current item */
459 menus[menu].items[position].desc = desc;
Linus Nielsen Feltzing82586a62004-07-05 14:26:58 +0000460 menus[menu].items[position].function = function;
461}
462
Linus Nielsen Feltzing10b92c42004-03-12 10:20:33 +0000463/*
464 * Property function - return the "count" of menu items in "menu"
465 */
466
467int menu_count(int menu)
468{
469 return menus[menu].itemcount;
470}
471
472/*
473 * Allows a menu item at the current cursor position in "menu" to be moved up the list
474 */
475
476bool menu_moveup(int menu)
477{
Linus Nielsen Feltzing77936e62004-03-16 13:44:56 +0000478 struct menu_item swap;
Linus Nielsen Feltzing10b92c42004-03-12 10:20:33 +0000479
480 /* can't be the first item ! */
481 if( menus[menu].cursor == 0)
482 return false;
483
484 /* use a temporary variable to do the swap */
485 swap = menus[menu].items[menus[menu].cursor - 1];
486 menus[menu].items[menus[menu].cursor - 1] = menus[menu].items[menus[menu].cursor];
487 menus[menu].items[menus[menu].cursor] = swap;
488 menus[menu].cursor--;
489
490 return true;
491}
492
493/*
494 * Allows a menu item at the current cursor position in "menu" to be moved down the list
495 */
496
497bool menu_movedown(int menu)
498{
Linus Nielsen Feltzing77936e62004-03-16 13:44:56 +0000499 struct menu_item swap;
Linus Nielsen Feltzing10b92c42004-03-12 10:20:33 +0000500
501 /* can't be the last item ! */
502 if( menus[menu].cursor == menus[menu].itemcount - 1)
503 return false;
504
505 /* use a temporary variable to do the swap */
506 swap = menus[menu].items[menus[menu].cursor + 1];
507 menus[menu].items[menus[menu].cursor + 1] = menus[menu].items[menus[menu].cursor];
508 menus[menu].items[menus[menu].cursor] = swap;
509 menus[menu].cursor++;
510
511 return true;
512}