2005-10-28 00:00:00 +00:00
|
|
|
/***************************************************************************
|
|
|
|
* __________ __ ___.
|
|
|
|
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
|
|
|
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
|
|
|
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
|
|
|
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
|
|
|
* \/ \/ \/ \/ \/
|
|
|
|
* $Id$
|
|
|
|
*
|
2005-10-30 01:24:35 +00:00
|
|
|
* Copyright (C) Daniel Stenberg (2002)
|
2005-10-28 00:00:00 +00:00
|
|
|
*
|
2008-06-28 18:10:04 +00:00
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
* as published by the Free Software Foundation; either version 2
|
|
|
|
* of the License, or (at your option) any later version.
|
2005-10-28 00:00:00 +00:00
|
|
|
*
|
|
|
|
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
|
|
|
* KIND, either express or implied.
|
|
|
|
*
|
|
|
|
****************************************************************************/
|
|
|
|
#include "stdarg.h"
|
|
|
|
#include "string.h"
|
2006-10-07 16:37:30 +00:00
|
|
|
#include "rbunicode.h"
|
2005-10-28 00:00:00 +00:00
|
|
|
#include "stdio.h"
|
|
|
|
#include "kernel.h"
|
|
|
|
#include "screen_access.h"
|
2007-08-06 13:08:36 +00:00
|
|
|
#include "lang.h"
|
|
|
|
#include "settings.h"
|
|
|
|
#include "talk.h"
|
2008-05-03 08:35:14 +00:00
|
|
|
#include "splash.h"
|
2009-05-08 00:28:33 +00:00
|
|
|
#include "viewport.h"
|
2022-11-10 14:38:50 +00:00
|
|
|
#include "strptokspn_r.h"
|
2022-10-09 04:47:44 +00:00
|
|
|
#include "scrollbar.h"
|
2022-11-10 14:38:50 +00:00
|
|
|
#include "font.h"
|
2005-10-28 00:00:00 +00:00
|
|
|
|
2022-10-13 04:05:34 +00:00
|
|
|
static long progress_next_tick = 0;
|
|
|
|
|
2006-10-07 16:37:30 +00:00
|
|
|
#define MAXLINES (LCD_HEIGHT/6)
|
|
|
|
#define MAXBUFFER 512
|
2009-09-21 19:40:07 +00:00
|
|
|
#define RECT_SPACING 2
|
2010-04-29 10:27:35 +00:00
|
|
|
#define SPLASH_MEMORY_INTERVAL (HZ)
|
2005-10-28 00:00:00 +00:00
|
|
|
|
2022-10-09 04:47:44 +00:00
|
|
|
static bool splash_internal(struct screen * screen, const char *fmt, va_list ap,
|
|
|
|
struct viewport *vp, int addl_lines)
|
2005-10-28 00:00:00 +00:00
|
|
|
{
|
2006-10-07 16:37:30 +00:00
|
|
|
char splash_buf[MAXBUFFER];
|
2022-11-10 14:38:50 +00:00
|
|
|
struct splash_lines {
|
|
|
|
const char *str;
|
|
|
|
size_t len;
|
|
|
|
} lines[MAXLINES];
|
2022-11-12 12:15:13 +00:00
|
|
|
const char *next;
|
|
|
|
const char *lastbreak = NULL;
|
|
|
|
const char *store = NULL;
|
2006-10-07 16:37:30 +00:00
|
|
|
int line = 0;
|
2006-10-02 23:54:28 +00:00
|
|
|
int x = 0;
|
2006-10-07 16:37:30 +00:00
|
|
|
int y, i;
|
2022-11-10 14:38:50 +00:00
|
|
|
int space_w, w, chr_h;
|
2010-04-29 10:38:03 +00:00
|
|
|
int width, height;
|
2006-10-07 16:37:30 +00:00
|
|
|
int maxw = 0;
|
2022-11-10 14:38:50 +00:00
|
|
|
int fontnum = vp->font;
|
2006-10-07 16:37:30 +00:00
|
|
|
|
2022-11-10 14:38:50 +00:00
|
|
|
char lastbrkchr;
|
|
|
|
size_t len, next_len;
|
|
|
|
const char matchstr[] = "\r\n\f\v\t ";
|
|
|
|
font_getstringsize(" ", &space_w, &chr_h, fontnum);
|
|
|
|
y = chr_h + (addl_lines * chr_h);
|
2006-10-07 16:37:30 +00:00
|
|
|
|
|
|
|
vsnprintf(splash_buf, sizeof(splash_buf), fmt, ap);
|
|
|
|
va_end(ap);
|
|
|
|
|
|
|
|
/* break splash string into display lines, doing proper word wrap */
|
2022-11-10 14:38:50 +00:00
|
|
|
next = strptokspn_r(splash_buf, matchstr, &next_len, &store);
|
2006-10-07 16:37:30 +00:00
|
|
|
if (!next)
|
2022-10-09 04:47:44 +00:00
|
|
|
return false; /* nothing to display */
|
2006-10-13 11:53:57 +00:00
|
|
|
|
2022-11-13 05:43:43 +00:00
|
|
|
lines[line].len = next_len;
|
2022-11-10 14:38:50 +00:00
|
|
|
lines[line].str = next;
|
2006-10-07 16:37:30 +00:00
|
|
|
while (true)
|
|
|
|
{
|
2022-11-13 05:43:43 +00:00
|
|
|
w = font_getstringnsize(next, next_len, NULL, NULL, fontnum);
|
2006-10-07 16:37:30 +00:00
|
|
|
if (lastbreak)
|
|
|
|
{
|
2022-11-10 14:38:50 +00:00
|
|
|
len = next - lastbreak;
|
|
|
|
int next_w = len * space_w;
|
|
|
|
if (x + next_w + w > vp->width - RECT_SPACING*2 || lastbrkchr != ' ')
|
|
|
|
{ /* too wide, or control character wrap */
|
2006-10-07 16:37:30 +00:00
|
|
|
if (x > maxw)
|
|
|
|
maxw = x;
|
2022-11-10 14:38:50 +00:00
|
|
|
if ((y + chr_h * 2 > vp->height) || (line >= (MAXLINES-1)))
|
2006-10-07 16:37:30 +00:00
|
|
|
break; /* screen full or out of lines */
|
2006-10-02 23:54:28 +00:00
|
|
|
x = 0;
|
2022-11-10 14:38:50 +00:00
|
|
|
y += chr_h;
|
2022-11-13 05:43:43 +00:00
|
|
|
lines[++line].len = next_len;
|
2022-11-10 14:38:50 +00:00
|
|
|
lines[line].str = next;
|
2005-10-28 00:00:00 +00:00
|
|
|
}
|
|
|
|
else
|
2006-10-07 16:37:30 +00:00
|
|
|
{
|
|
|
|
/* restore & calculate spacing */
|
2022-11-13 05:43:43 +00:00
|
|
|
lines[line].len += next_len + 1;
|
2022-10-09 04:47:44 +00:00
|
|
|
x += next_w;
|
2006-10-07 16:37:30 +00:00
|
|
|
}
|
2006-10-02 23:54:28 +00:00
|
|
|
}
|
2006-10-07 16:37:30 +00:00
|
|
|
x += w;
|
2022-11-13 05:43:43 +00:00
|
|
|
|
|
|
|
lastbreak = next + next_len;
|
2022-11-10 14:38:50 +00:00
|
|
|
lastbrkchr = *lastbreak;
|
|
|
|
|
|
|
|
next = strptokspn_r(NULL, matchstr, &next_len, &store);
|
|
|
|
|
2006-10-07 16:37:30 +00:00
|
|
|
if (!next)
|
|
|
|
{ /* no more words */
|
|
|
|
if (x > maxw)
|
|
|
|
maxw = x;
|
|
|
|
break;
|
|
|
|
}
|
2006-10-02 23:54:28 +00:00
|
|
|
}
|
2005-10-28 00:00:00 +00:00
|
|
|
|
2009-05-08 00:28:33 +00:00
|
|
|
/* prepare viewport
|
|
|
|
* First boundaries, then the grey filling, then the black border and finally
|
|
|
|
* the text*/
|
2005-10-28 00:00:00 +00:00
|
|
|
|
2013-04-03 14:33:23 +00:00
|
|
|
screen->scroll_stop();
|
2006-10-07 16:37:30 +00:00
|
|
|
|
2010-04-29 10:27:35 +00:00
|
|
|
width = maxw + 2*RECT_SPACING;
|
|
|
|
height = y + 2*RECT_SPACING;
|
2009-05-08 00:28:33 +00:00
|
|
|
|
2022-10-09 04:47:44 +00:00
|
|
|
if (width > vp->width)
|
|
|
|
width = vp->width;
|
|
|
|
if (height > vp->height)
|
|
|
|
height = vp->height;
|
2010-07-10 13:40:35 +00:00
|
|
|
|
2022-10-09 04:47:44 +00:00
|
|
|
vp->x += (vp->width - width) / 2;
|
|
|
|
vp->y += (vp->height - height) / 2;
|
|
|
|
vp->width = width;
|
|
|
|
vp->height = height;
|
2020-10-26 16:38:22 +00:00
|
|
|
|
2022-10-09 04:47:44 +00:00
|
|
|
vp->flags |= VP_FLAG_ALIGN_CENTER;
|
2005-10-28 00:00:00 +00:00
|
|
|
#if LCD_DEPTH > 1
|
2007-03-16 21:56:08 +00:00
|
|
|
if (screen->depth > 1)
|
|
|
|
{
|
2022-10-09 04:47:44 +00:00
|
|
|
vp->drawmode = DRMODE_FG;
|
|
|
|
/* can't do vp->fg_pattern here, since set_foreground does a bit more on
|
2009-05-15 15:27:32 +00:00
|
|
|
* greyscale */
|
|
|
|
screen->set_foreground(SCREEN_COLOR_TO_NATIVE(screen, LCD_LIGHTGRAY));
|
2007-03-16 21:56:08 +00:00
|
|
|
}
|
|
|
|
else
|
2005-10-28 00:00:00 +00:00
|
|
|
#endif
|
2022-10-09 04:47:44 +00:00
|
|
|
vp->drawmode = (DRMODE_SOLID|DRMODE_INVERSEVID);
|
2006-10-13 11:53:57 +00:00
|
|
|
|
2010-10-11 01:19:55 +00:00
|
|
|
screen->fill_viewport();
|
2006-10-13 11:53:57 +00:00
|
|
|
|
|
|
|
#if LCD_DEPTH > 1
|
2007-03-16 21:56:08 +00:00
|
|
|
if (screen->depth > 1)
|
2022-10-09 04:47:44 +00:00
|
|
|
/* can't do vp->fg_pattern here, since set_foreground does a bit more on
|
2009-05-15 15:27:32 +00:00
|
|
|
* greyscale */
|
|
|
|
screen->set_foreground(SCREEN_COLOR_TO_NATIVE(screen, LCD_BLACK));
|
2007-03-16 21:56:08 +00:00
|
|
|
else
|
2006-10-13 11:53:57 +00:00
|
|
|
#endif
|
2022-10-09 04:47:44 +00:00
|
|
|
vp->drawmode = DRMODE_SOLID;
|
2009-05-08 00:28:33 +00:00
|
|
|
|
2010-10-11 01:19:55 +00:00
|
|
|
screen->draw_border_viewport();
|
2006-10-13 11:53:57 +00:00
|
|
|
|
2006-10-07 16:37:30 +00:00
|
|
|
/* print the message to screen */
|
2022-11-10 14:38:50 +00:00
|
|
|
for(i = 0, y = RECT_SPACING; i <= line; i++, y+= chr_h)
|
2006-10-07 16:37:30 +00:00
|
|
|
{
|
2022-11-10 14:38:50 +00:00
|
|
|
screen->putsxyf(0, y, "%.*s", lines[i].len, lines[i].str);
|
2006-10-07 16:37:30 +00:00
|
|
|
}
|
2022-10-09 04:47:44 +00:00
|
|
|
return true; /* needs update */
|
2005-10-28 00:00:00 +00:00
|
|
|
}
|
|
|
|
|
2008-08-15 08:27:39 +00:00
|
|
|
void splashf(int ticks, const char *fmt, ...)
|
2005-10-28 00:00:00 +00:00
|
|
|
{
|
|
|
|
va_list ap;
|
2008-08-15 08:27:39 +00:00
|
|
|
|
|
|
|
/* If fmt is a lang ID then get the corresponding string (which
|
|
|
|
still might contain % place holders). */
|
|
|
|
fmt = P2STR((unsigned char *)fmt);
|
|
|
|
FOR_NB_SCREENS(i)
|
|
|
|
{
|
2022-10-09 04:47:44 +00:00
|
|
|
struct screen * screen = &(screens[i]);
|
|
|
|
struct viewport vp;
|
|
|
|
viewport_set_defaults(&vp, screen->screen_type);
|
|
|
|
struct viewport *last_vp = screen->set_viewport(&vp);
|
|
|
|
|
2008-08-15 08:27:39 +00:00
|
|
|
va_start(ap, fmt);
|
2022-10-09 04:47:44 +00:00
|
|
|
if (splash_internal(screen, fmt, ap, &vp, 0))
|
|
|
|
screen->update_viewport();
|
2008-08-15 08:27:39 +00:00
|
|
|
va_end(ap);
|
2022-10-09 04:47:44 +00:00
|
|
|
|
|
|
|
screen->set_viewport(last_vp);
|
2008-08-15 08:27:39 +00:00
|
|
|
}
|
2009-05-08 00:28:33 +00:00
|
|
|
if (ticks)
|
2005-10-28 00:00:00 +00:00
|
|
|
sleep(ticks);
|
|
|
|
}
|
|
|
|
|
2008-08-15 08:27:39 +00:00
|
|
|
void splash(int ticks, const char *str)
|
2005-10-28 00:00:00 +00:00
|
|
|
{
|
2020-07-17 04:01:32 +00:00
|
|
|
#if !defined(SIMULATOR)
|
2007-08-06 13:08:36 +00:00
|
|
|
long id;
|
|
|
|
/* fmt may be a so called virtual pointer. See settings.h. */
|
2008-08-15 08:27:39 +00:00
|
|
|
if((id = P2ID((const unsigned char*)str)) >= 0)
|
2007-08-06 13:08:36 +00:00
|
|
|
/* If fmt specifies a voicefont ID, and voice menus are
|
|
|
|
enabled, then speak it. */
|
|
|
|
cond_talk_ids_fq(id);
|
2007-08-06 15:01:45 +00:00
|
|
|
#endif
|
2008-08-15 08:27:39 +00:00
|
|
|
splashf(ticks, "%s", P2STR((const unsigned char*)str));
|
2005-10-28 00:00:00 +00:00
|
|
|
}
|
2022-10-09 04:47:44 +00:00
|
|
|
|
2022-10-13 04:05:34 +00:00
|
|
|
/* set delay before progress meter is shown */
|
|
|
|
void splash_progress_set_delay(long delay_ticks)
|
|
|
|
{
|
|
|
|
progress_next_tick = current_tick + delay_ticks;
|
|
|
|
}
|
|
|
|
|
2022-10-09 04:47:44 +00:00
|
|
|
/* splash a progress meter */
|
|
|
|
void splash_progress(int current, int total, const char *fmt, ...)
|
|
|
|
{
|
2022-10-09 15:00:40 +00:00
|
|
|
va_list ap;
|
2022-10-09 04:47:44 +00:00
|
|
|
int vp_flag = VP_FLAG_VP_DIRTY;
|
|
|
|
/* progress update tick */
|
|
|
|
long now = current_tick;
|
|
|
|
|
|
|
|
if (current < total)
|
|
|
|
{
|
2022-10-13 04:05:34 +00:00
|
|
|
if(TIME_BEFORE(now, progress_next_tick))
|
2022-10-09 04:47:44 +00:00
|
|
|
return;
|
|
|
|
/* limit to 20fps */
|
2022-10-13 04:05:34 +00:00
|
|
|
progress_next_tick = now + HZ/20;
|
2022-10-09 04:47:44 +00:00
|
|
|
vp_flag = 0; /* don't mark vp dirty to prevent flashing */
|
|
|
|
}
|
|
|
|
|
|
|
|
/* If fmt is a lang ID then get the corresponding string (which
|
|
|
|
still might contain % place holders). */
|
|
|
|
fmt = P2STR((unsigned char *)fmt);
|
|
|
|
FOR_NB_SCREENS(i)
|
|
|
|
{
|
|
|
|
struct screen * screen = &(screens[i]);
|
|
|
|
struct viewport vp;
|
|
|
|
viewport_set_defaults(&vp, screen->screen_type);
|
|
|
|
struct viewport *last_vp = screen->set_viewport_ex(&vp, vp_flag);
|
|
|
|
|
|
|
|
va_start(ap, fmt);
|
|
|
|
if (splash_internal(screen, fmt, ap, &vp, 1))
|
|
|
|
{
|
|
|
|
int size = screen->getcharheight();
|
2022-10-09 15:00:40 +00:00
|
|
|
int x = RECT_SPACING;
|
2022-10-09 04:47:44 +00:00
|
|
|
int y = vp.height - size - RECT_SPACING;
|
|
|
|
int w = vp.width - RECT_SPACING * 2;
|
2022-10-09 15:00:40 +00:00
|
|
|
int h = size;
|
|
|
|
#ifdef HAVE_LCD_COLOR
|
|
|
|
const int sb_flags = HORIZONTAL | FOREGROUND;
|
|
|
|
#else
|
|
|
|
const int sb_flags = HORIZONTAL;
|
|
|
|
#endif
|
|
|
|
gui_scrollbar_draw(screen, x, y, w, h, total, 0, current, sb_flags);
|
2022-10-09 04:47:44 +00:00
|
|
|
|
|
|
|
screen->update_viewport();
|
|
|
|
}
|
|
|
|
va_end(ap);
|
|
|
|
|
|
|
|
screen->set_viewport(last_vp);
|
|
|
|
}
|
|
|
|
}
|