Also fix the iRiver H10
[kugel-rb.git] / apps / gui / splash.c
blob50355d3a3c3468dc3b89cb8c87d463540ce852a2
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) Daniel Stenberg (2002)
12 * 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.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
21 #include "stdarg.h"
22 #include "string.h"
23 #include "rbunicode.h"
24 #include "stdio.h"
25 #include "kernel.h"
26 #include "screen_access.h"
27 #include "lang.h"
28 #include "settings.h"
29 #include "talk.h"
30 #include "splash.h"
31 #include "viewport.h"
33 #ifdef HAVE_LCD_BITMAP
35 #define MAXLINES (LCD_HEIGHT/6)
36 #define MAXBUFFER 512
38 #else /* HAVE_LCD_CHARCELLS */
40 #define MAXLINES 2
41 #define MAXBUFFER 64
43 #endif
45 #define RECT_SPACING 2
47 static void splash_internal(struct screen * screen, const char *fmt, va_list ap)
49 char splash_buf[MAXBUFFER];
50 short widths[MAXLINES];
51 char *lines[MAXLINES];
53 char *next;
54 char *lastbreak = NULL;
55 char *store = NULL;
56 int line = 0;
57 int x = 0;
58 int y, i;
59 int space_w, w, h;
60 #ifdef HAVE_LCD_BITMAP
61 struct viewport vp;
62 int maxw = 0;
64 viewport_set_defaults(&vp, screen->screen_type);
65 screen->set_viewport(&vp);
67 screen->getstringsize(" ", &space_w, &h);
68 #else /* HAVE_LCD_CHARCELLS */
70 space_w = h = 1;
71 screen->double_height (false);
72 #endif
73 y = h;
75 vsnprintf(splash_buf, sizeof(splash_buf), fmt, ap);
76 va_end(ap);
78 /* break splash string into display lines, doing proper word wrap */
80 next = strtok_r(splash_buf, " ", &store);
81 if (!next)
82 goto end; /* nothing to display */
84 lines[0] = next;
85 while (true)
87 #ifdef HAVE_LCD_BITMAP
88 screen->getstringsize(next, &w, NULL);
89 #else
90 w = utf8length(next);
91 #endif
92 if (lastbreak)
94 if (x + (next - lastbreak) * space_w + w
95 > screen->lcdwidth - RECT_SPACING*2)
96 { /* too wide, wrap */
97 widths[line] = x;
98 #ifdef HAVE_LCD_BITMAP
99 if (x > maxw)
100 maxw = x;
101 #endif
102 if ((y + h > screen->lcdheight) || (line >= (MAXLINES-1)))
103 break; /* screen full or out of lines */
104 x = 0;
105 y += h;
106 lines[++line] = next;
108 else
110 /* restore & calculate spacing */
111 *lastbreak = ' ';
112 x += (next - lastbreak) * space_w;
115 x += w;
116 lastbreak = next + strlen(next);
117 next = strtok_r(NULL, " ", &store);
118 if (!next)
119 { /* no more words */
120 widths[line] = x;
121 #ifdef HAVE_LCD_BITMAP
122 if (x > maxw)
123 maxw = x;
124 #endif
125 break;
129 /* prepare viewport
130 * First boundaries, then the grey filling, then the black border and finally
131 * the text*/
133 screen->stop_scroll();
135 #ifdef HAVE_LCD_BITMAP
136 /* If we center the display, then just clear the box we need and put
137 a nice little frame and put the text in there! */
138 vp.y = (screen->lcdheight - y) / 2 - RECT_SPACING; /* height => y start position */
139 vp.x = (screen->lcdwidth - maxw) / 2 - RECT_SPACING;
140 vp.width = maxw + 2*RECT_SPACING;
141 vp.height = screen->lcdheight - (vp.y*2) + RECT_SPACING;
143 if (vp.y < 0)
144 vp.y = 0;
145 if (vp.x < 0)
146 vp.x = 0;
147 if (vp.width > screen->lcdwidth)
148 vp.width = screen->lcdwidth;
149 if (vp.height > screen->lcdheight)
150 vp.height = screen->lcdheight;
152 #if LCD_DEPTH > 1
153 if (screen->depth > 1)
155 vp.drawmode = DRMODE_FG;
156 /* can't do vp.fg_pattern here, since set_foreground does a bit more on
157 * greyscale */
158 screen->set_foreground(SCREEN_COLOR_TO_NATIVE(screen, LCD_LIGHTGRAY));
160 else
161 #endif
162 vp.drawmode = (DRMODE_SOLID|DRMODE_INVERSEVID);
164 screen->fillrect(0, 0, vp.width, vp.height);
166 #if LCD_DEPTH > 1
167 if (screen->depth > 1)
168 /* can't do vp.fg_pattern here, since set_foreground does a bit more on
169 * greyscale */
170 screen->set_foreground(SCREEN_COLOR_TO_NATIVE(screen, LCD_BLACK));
171 else
172 #endif
173 vp.drawmode = DRMODE_SOLID;
175 screen->drawrect(0, 0, vp.width, vp.height);
177 /* prepare putting the text */
178 y = RECT_SPACING;
179 #else /* HAVE_LCD_CHARCELLS */
180 y = 0; /* vertical centering on 2 lines would be silly */
181 x = 0;
182 screen->clear_display();
183 #endif
185 /* print the message to screen */
186 for (i = 0; i <= line; i++, y+=h)
188 #ifdef HAVE_LCD_BITMAP
189 #define W (vp.width - RECT_SPACING*2)
190 #else
191 #define W (screens->lcdwidth)
192 #endif
193 x = (W - widths[i])/2;
194 if (x < 0)
195 x = 0;
196 #ifdef HAVE_LCD_BITMAP
197 screen->putsxy(x+RECT_SPACING, y, lines[i]);
198 #else
199 screen->puts(x, y, lines[i]);
200 #endif
201 #undef W
203 screen->update_viewport();
204 end:
205 screen->set_viewport(NULL);
208 void splashf(int ticks, const char *fmt, ...)
210 va_list ap;
211 int i;
213 /* If fmt is a lang ID then get the corresponding string (which
214 still might contain % place holders). */
215 fmt = P2STR((unsigned char *)fmt);
216 FOR_NB_SCREENS(i)
218 va_start(ap, fmt);
219 splash_internal(&(screens[i]), fmt, ap);
220 va_end(ap);
222 if (ticks)
223 sleep(ticks);
226 void splash(int ticks, const char *str)
228 #if !defined(SIMULATOR) || CONFIG_CODEC == SWCODEC
229 long id;
230 /* fmt may be a so called virtual pointer. See settings.h. */
231 if((id = P2ID((const unsigned char*)str)) >= 0)
232 /* If fmt specifies a voicefont ID, and voice menus are
233 enabled, then speak it. */
234 cond_talk_ids_fq(id);
235 #endif
236 splashf(ticks, "%s", P2STR((const unsigned char*)str));