summaryrefslogtreecommitdiff
path: root/apps
diff options
context:
space:
mode:
authorJens Arnold <amiconn@rockbox.org>2006-10-07 16:37:30 +0000
committerJens Arnold <amiconn@rockbox.org>2006-10-07 16:37:30 +0000
commit803331841e3fa14cb84cf23794c282b250e7068d (patch)
tree5a3a91c4adecee392eb1ac9de99273375824999a /apps
parent5c6f32af9563764cf7b3f9529956ac27808246cf (diff)
downloadrockbox-803331841e3fa14cb84cf23794c282b250e7068d.tar.gz
rockbox-803331841e3fa14cb84cf23794c282b250e7068d.zip
Splash function: Fixed several bugs and problems: (1) Off-by-one bug caused a buffer overflow with splash text longer than the screen. (2) Last line wasn't centered properly in the same situation. (3) On player, string display length must be calculated using utf8length() instead of strlen() since unicode support was added (old bug). (4) Handle splash texts with multiple spaces properly, including correct length calculation and stripping on wrap. (5) Don't reset fg/bg colours to default if not centering (old bug). * Increased buffer sizes to account for (a) larger screens (b) utf-8 (c) words wider than the screen. * More efficient code.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@11144 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps')
-rw-r--r--apps/gui/splash.c187
1 files changed, 106 insertions, 81 deletions
diff --git a/apps/gui/splash.c b/apps/gui/splash.c
index f41d174881..0995968415 100644
--- a/apps/gui/splash.c
+++ b/apps/gui/splash.c
@@ -18,105 +18,123 @@
18 ****************************************************************************/ 18 ****************************************************************************/
19#include "stdarg.h" 19#include "stdarg.h"
20#include "string.h" 20#include "string.h"
21#include "rbunicode.h"
21#include "stdio.h" 22#include "stdio.h"
22#include "kernel.h" 23#include "kernel.h"
23#include "screen_access.h" 24#include "screen_access.h"
24 25
26#ifndef MAX
27#define MAX(a, b) (((a)>(b))?(a):(b))
28#endif
25 29
26#ifdef HAVE_LCD_BITMAP 30#ifdef HAVE_LCD_BITMAP
27 31
28#define MAXLETTERS 128 /* 16*8 */ 32#define MAXLINES (LCD_HEIGHT/6)
29#define MAXLINES 10 33#define MAXBUFFER 512
30 34
31#else 35#else /* HAVE_LCD_CHARCELLS */
32 36
33#define MAXLETTERS 22 /* 11 * 2 */ 37#define MAXLINES 2
34#define MAXLINES 2 38#define MAXBUFFER 64
35 39
36#endif 40#endif
37 41
38static void splash(struct screen * screen, 42static void splash(struct screen * screen, bool center,
39 bool center, const char *fmt, va_list ap) 43 const char *fmt, va_list ap)
40{ 44{
45 char splash_buf[MAXBUFFER];
46 short widths[MAXLINES];
47 char *lines[MAXLINES];
48
41 char *next; 49 char *next;
42 char *store=NULL; 50 char *lastbreak = NULL;
51 char *store = NULL;
52 int line = 0;
43 int x = 0; 53 int x = 0;
44 int w, h = 1; 54 int y, i;
45 unsigned char splash_buf[MAXLETTERS]; 55 int space_w, w, h;
46 unsigned short widths[MAXLINES];
47 unsigned char *text = splash_buf;
48 int line = 0, i_line = 0;
49 bool first=true;
50#ifdef HAVE_LCD_BITMAP 56#ifdef HAVE_LCD_BITMAP
51 int maxw=0; 57 int maxw = 0;
52 int space;
53 int y;
54 screen->getstringsize(" ", &space, &y);
55#if LCD_DEPTH > 1 58#if LCD_DEPTH > 1
56 unsigned prevbg = LCD_DEFAULT_BG; 59 unsigned prevbg = 0;
57 unsigned prevfg = LCD_DEFAULT_FG; 60 unsigned prevfg = 0;
58#endif 61#endif
59#else 62
60 screen->double_height (false); /* HAVE_LCD_CHARCELLS */ 63 screen->getstringsize(" ", &space_w, &h);
61 int space = 1; 64#else /* HAVE_LCD_CHARCELLS */
62 int y = 0; 65
66 space_w = h = 1;
67 screen->double_height (false);
63#endif 68#endif
64 screen->stop_scroll(); 69 y = h;
65 vsnprintf( splash_buf, sizeof(splash_buf), fmt, ap ); 70
66 va_end( ap ); 71 vsnprintf(splash_buf, sizeof(splash_buf), fmt, ap);
67 72 va_end(ap);
68 /* measure sizes & concatenates tokenise words into lines. */ 73
74 /* break splash string into display lines, doing proper word wrap */
75
69 next = strtok_r(splash_buf, " ", &store); 76 next = strtok_r(splash_buf, " ", &store);
70 while (next) { 77 if (!next)
78 return; /* nothing to display */
79
80 lines[0] = next;
81 while (true)
82 {
71#ifdef HAVE_LCD_BITMAP 83#ifdef HAVE_LCD_BITMAP
72 screen->getstringsize(next, &w, &h); 84 screen->getstringsize(next, &w, NULL);
73#else 85#else
74 w = strlen(next); 86 w = utf8length(next);
75 h = 1; /* store height in characters */
76#endif 87#endif
77 if(!first) { 88 if (lastbreak)
78 if(x + w > screen->width) { /* Too wide, wrap */ 89 {
79 y += h; 90 if (x + (next - lastbreak) * space_w + w > screen->width)
80 line++; 91 { /* too wide, wrap */
92 widths[line] = x;
93#ifdef HAVE_LCD_BITMAP
94 if (x > maxw)
95 maxw = x;
96#endif
97 if ((y + h > screen->height) || (line >= (MAXLINES-1)))
98 break; /* screen full or out of lines */
81 x = 0; 99 x = 0;
82 if((y > (screen->height-h)) || (line > screen->nb_lines)) 100 y += h;
83 /* STOP */ 101 lines[++line] = next;
84 break;
85 } 102 }
86 else 103 else
87 next[-1] = ' '; /* re-concatenate string */ 104 {
105 /* restore & calculate spacing */
106 *lastbreak = ' ';
107 x += (next - lastbreak) * space_w;
108 }
88 } 109 }
89 else 110 x += w;
90 first = false; 111 lastbreak = next + strlen(next);
91 112 next = strtok_r(NULL, " ", &store);
92 x += w + space; 113 if (!next)
93 widths[line] = x - space; /* don't count the trailing space */ 114 { /* no more words */
115 widths[line] = x;
94#ifdef HAVE_LCD_BITMAP 116#ifdef HAVE_LCD_BITMAP
95 /* store the widest line */ 117 if (x > maxw)
96 if(widths[line]>maxw) 118 maxw = x;
97 maxw = widths[line];
98#endif 119#endif
99 next = strtok_r(NULL, " ", &store); 120 break;
121 }
100 } 122 }
101 123
102 if(center) { 124 /* prepare screen */
103#ifdef HAVE_LCD_BITMAP
104 /* Start displaying the message at position y. */
105 y = (screen->height - y)/2;
106#else
107 y = 0; /* vertical center on 2 lines would be silly */
108#endif
109 } else
110 y = 0;
111 125
126 screen->stop_scroll();
127
128#ifdef HAVE_LCD_BITMAP
112 /* If we center the display, then just clear the box we need and put 129 /* If we center the display, then just clear the box we need and put
113 a nice little frame and put the text in there! */ 130 a nice little frame and put the text in there! */
114#ifdef HAVE_LCD_BITMAP 131 if (center)
115 if(center && (y > 2)) { 132 {
116 int xx = (screen->width - maxw)/2 - 2; 133 y = (screen->height - y) / 2; /* height => y start position */
117 /* The new graphics routines handle clipping, so no need to check */ 134 x = (screen->width - maxw) / 2 - 2;
118#if LCD_DEPTH > 1 135#if LCD_DEPTH > 1
119 if(screen->depth>1) { 136 if (screen->depth > 1)
137 {
120 prevbg = screen->get_background(); 138 prevbg = screen->get_background();
121 prevfg = screen->get_foreground(); 139 prevfg = screen->get_foreground();
122 screen->set_background(LCD_LIGHTGRAY); 140 screen->set_background(LCD_LIGHTGRAY);
@@ -124,33 +142,40 @@ static void splash(struct screen * screen,
124 } 142 }
125#endif 143#endif
126 screen->set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID); 144 screen->set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
127 screen->fillrect(xx, y-2, maxw+4, screen->height-y*2+4); 145 screen->fillrect(x, y-2, maxw+4, screen->height-y*2+4);
128 screen->set_drawmode(DRMODE_SOLID); 146 screen->set_drawmode(DRMODE_SOLID);
129 screen->drawrect(xx, y-2, maxw+4, screen->height-y*2+4); 147 screen->drawrect(x, y-2, maxw+4, screen->height-y*2+4);
130 } 148 }
131 else 149 else
132#endif 150 {
151 y = 0;
152 x = 0;
133 screen->clear_display(); 153 screen->clear_display();
154 }
155#else /* HAVE_LCD_CHARCELLS */
156 y = 0; /* vertical center on 2 lines would be silly */
157 x = 0;
158 screen->clear_display();
159#endif
160
161 /* print the message to screen */
162
163 for (i = 0; i <= line; i++)
164 {
165 if (center)
166 x = MAX((screen->width - widths[i]) / 2, 0);
134 167
135 /* print the message to screen */
136 while(line-- >= 0) {
137 if (center) {
138 x = (screen->width-widths[i_line++])/2;
139 if(x < 0)
140 x = 0;
141 } else
142 x = 0;
143#ifdef HAVE_LCD_BITMAP 168#ifdef HAVE_LCD_BITMAP
144 screen->putsxy(x, y, text); 169 screen->putsxy(x, y, lines[i]);
145#else 170#else
146 screen->puts(x, y, text); 171 screen->puts(x, y, lines[i]);
147#endif 172#endif
148 text += strlen(text) + 1; 173 y += h;
149 y +=h; 174 }
150 }
151 175
152#if defined(HAVE_LCD_BITMAP) && (LCD_DEPTH > 1) 176#if defined(HAVE_LCD_BITMAP) && (LCD_DEPTH > 1)
153 if(screen->depth > 1) { 177 if (center && (screen->depth > 1))
178 {
154 screen->set_background(prevbg); 179 screen->set_background(prevbg);
155 screen->set_foreground(prevfg); 180 screen->set_foreground(prevfg);
156 } 181 }