diff options
Diffstat (limited to 'apps/gui/splash.c')
-rw-r--r-- | apps/gui/splash.c | 112 |
1 files changed, 82 insertions, 30 deletions
diff --git a/apps/gui/splash.c b/apps/gui/splash.c index b85e4693aa..bf9647cff1 100644 --- a/apps/gui/splash.c +++ b/apps/gui/splash.c | |||
@@ -30,17 +30,18 @@ | |||
30 | #include "splash.h" | 30 | #include "splash.h" |
31 | #include "viewport.h" | 31 | #include "viewport.h" |
32 | #include "strtok_r.h" | 32 | #include "strtok_r.h" |
33 | #include "scrollbar.h" | ||
33 | 34 | ||
34 | #define MAXLINES (LCD_HEIGHT/6) | 35 | #define MAXLINES (LCD_HEIGHT/6) |
35 | #define MAXBUFFER 512 | 36 | #define MAXBUFFER 512 |
36 | #define RECT_SPACING 2 | 37 | #define RECT_SPACING 2 |
37 | #define SPLASH_MEMORY_INTERVAL (HZ) | 38 | #define SPLASH_MEMORY_INTERVAL (HZ) |
38 | 39 | ||
39 | static void splash_internal(struct screen * screen, const char *fmt, va_list ap) | 40 | static bool splash_internal(struct screen * screen, const char *fmt, va_list ap, |
41 | struct viewport *vp, int addl_lines) | ||
40 | { | 42 | { |
41 | char splash_buf[MAXBUFFER]; | 43 | char splash_buf[MAXBUFFER]; |
42 | char *lines[MAXLINES]; | 44 | char *lines[MAXLINES]; |
43 | |||
44 | char *next; | 45 | char *next; |
45 | char *lastbreak = NULL; | 46 | char *lastbreak = NULL; |
46 | char *store = NULL; | 47 | char *store = NULL; |
@@ -48,15 +49,12 @@ static void splash_internal(struct screen * screen, const char *fmt, va_list ap) | |||
48 | int x = 0; | 49 | int x = 0; |
49 | int y, i; | 50 | int y, i; |
50 | int space_w, w, h; | 51 | int space_w, w, h; |
51 | struct viewport vp; | 52 | |
52 | int width, height; | 53 | int width, height; |
53 | int maxw = 0; | 54 | int maxw = 0; |
54 | 55 | ||
55 | viewport_set_defaults(&vp, screen->screen_type); | ||
56 | struct viewport *last_vp = screen->set_viewport(&vp); | ||
57 | |||
58 | screen->getstringsize(" ", &space_w, &h); | 56 | screen->getstringsize(" ", &space_w, &h); |
59 | y = h; | 57 | y = h + (addl_lines * h); |
60 | 58 | ||
61 | vsnprintf(splash_buf, sizeof(splash_buf), fmt, ap); | 59 | vsnprintf(splash_buf, sizeof(splash_buf), fmt, ap); |
62 | va_end(ap); | 60 | va_end(ap); |
@@ -65,7 +63,7 @@ static void splash_internal(struct screen * screen, const char *fmt, va_list ap) | |||
65 | 63 | ||
66 | next = strtok_r(splash_buf, " ", &store); | 64 | next = strtok_r(splash_buf, " ", &store); |
67 | if (!next) | 65 | if (!next) |
68 | goto end; /* nothing to display */ | 66 | return false; /* nothing to display */ |
69 | 67 | ||
70 | lines[0] = next; | 68 | lines[0] = next; |
71 | while (true) | 69 | while (true) |
@@ -73,12 +71,13 @@ static void splash_internal(struct screen * screen, const char *fmt, va_list ap) | |||
73 | screen->getstringsize(next, &w, NULL); | 71 | screen->getstringsize(next, &w, NULL); |
74 | if (lastbreak) | 72 | if (lastbreak) |
75 | { | 73 | { |
76 | if (x + (next - lastbreak) * space_w + w | 74 | int next_w = (next - lastbreak) * space_w; |
77 | > vp.width - RECT_SPACING*2) | 75 | |
76 | if (x + next_w + w > vp->width - RECT_SPACING*2) | ||
78 | { /* too wide, wrap */ | 77 | { /* too wide, wrap */ |
79 | if (x > maxw) | 78 | if (x > maxw) |
80 | maxw = x; | 79 | maxw = x; |
81 | if ((y + h > vp.height) || (line >= (MAXLINES-1))) | 80 | if ((y + h > vp->height) || (line >= (MAXLINES-1))) |
82 | break; /* screen full or out of lines */ | 81 | break; /* screen full or out of lines */ |
83 | x = 0; | 82 | x = 0; |
84 | y += h; | 83 | y += h; |
@@ -88,7 +87,7 @@ static void splash_internal(struct screen * screen, const char *fmt, va_list ap) | |||
88 | { | 87 | { |
89 | /* restore & calculate spacing */ | 88 | /* restore & calculate spacing */ |
90 | *lastbreak = ' '; | 89 | *lastbreak = ' '; |
91 | x += (next - lastbreak) * space_w; | 90 | x += next_w; |
92 | } | 91 | } |
93 | } | 92 | } |
94 | x += w; | 93 | x += w; |
@@ -111,39 +110,39 @@ static void splash_internal(struct screen * screen, const char *fmt, va_list ap) | |||
111 | width = maxw + 2*RECT_SPACING; | 110 | width = maxw + 2*RECT_SPACING; |
112 | height = y + 2*RECT_SPACING; | 111 | height = y + 2*RECT_SPACING; |
113 | 112 | ||
114 | if (width > vp.width) | 113 | if (width > vp->width) |
115 | width = vp.width; | 114 | width = vp->width; |
116 | if (height > vp.height) | 115 | if (height > vp->height) |
117 | height = vp.height; | 116 | height = vp->height; |
118 | 117 | ||
119 | vp.x += (vp.width - width) / 2; | 118 | vp->x += (vp->width - width) / 2; |
120 | vp.y += (vp.height - height) / 2; | 119 | vp->y += (vp->height - height) / 2; |
121 | vp.width = width; | 120 | vp->width = width; |
122 | vp.height = height; | 121 | vp->height = height; |
123 | 122 | ||
124 | vp.flags |= VP_FLAG_ALIGN_CENTER; | 123 | vp->flags |= VP_FLAG_ALIGN_CENTER; |
125 | #if LCD_DEPTH > 1 | 124 | #if LCD_DEPTH > 1 |
126 | if (screen->depth > 1) | 125 | if (screen->depth > 1) |
127 | { | 126 | { |
128 | vp.drawmode = DRMODE_FG; | 127 | vp->drawmode = DRMODE_FG; |
129 | /* can't do vp.fg_pattern here, since set_foreground does a bit more on | 128 | /* can't do vp->fg_pattern here, since set_foreground does a bit more on |
130 | * greyscale */ | 129 | * greyscale */ |
131 | screen->set_foreground(SCREEN_COLOR_TO_NATIVE(screen, LCD_LIGHTGRAY)); | 130 | screen->set_foreground(SCREEN_COLOR_TO_NATIVE(screen, LCD_LIGHTGRAY)); |
132 | } | 131 | } |
133 | else | 132 | else |
134 | #endif | 133 | #endif |
135 | vp.drawmode = (DRMODE_SOLID|DRMODE_INVERSEVID); | 134 | vp->drawmode = (DRMODE_SOLID|DRMODE_INVERSEVID); |
136 | 135 | ||
137 | screen->fill_viewport(); | 136 | screen->fill_viewport(); |
138 | 137 | ||
139 | #if LCD_DEPTH > 1 | 138 | #if LCD_DEPTH > 1 |
140 | if (screen->depth > 1) | 139 | if (screen->depth > 1) |
141 | /* can't do vp.fg_pattern here, since set_foreground does a bit more on | 140 | /* can't do vp->fg_pattern here, since set_foreground does a bit more on |
142 | * greyscale */ | 141 | * greyscale */ |
143 | screen->set_foreground(SCREEN_COLOR_TO_NATIVE(screen, LCD_BLACK)); | 142 | screen->set_foreground(SCREEN_COLOR_TO_NATIVE(screen, LCD_BLACK)); |
144 | else | 143 | else |
145 | #endif | 144 | #endif |
146 | vp.drawmode = DRMODE_SOLID; | 145 | vp->drawmode = DRMODE_SOLID; |
147 | 146 | ||
148 | screen->draw_border_viewport(); | 147 | screen->draw_border_viewport(); |
149 | 148 | ||
@@ -155,9 +154,7 @@ static void splash_internal(struct screen * screen, const char *fmt, va_list ap) | |||
155 | { | 154 | { |
156 | screen->putsxy(0, y, lines[i]); | 155 | screen->putsxy(0, y, lines[i]); |
157 | } | 156 | } |
158 | screen->update_viewport(); | 157 | return true; /* needs update */ |
159 | end: | ||
160 | screen->set_viewport(last_vp); | ||
161 | } | 158 | } |
162 | 159 | ||
163 | void splashf(int ticks, const char *fmt, ...) | 160 | void splashf(int ticks, const char *fmt, ...) |
@@ -169,9 +166,17 @@ void splashf(int ticks, const char *fmt, ...) | |||
169 | fmt = P2STR((unsigned char *)fmt); | 166 | fmt = P2STR((unsigned char *)fmt); |
170 | FOR_NB_SCREENS(i) | 167 | FOR_NB_SCREENS(i) |
171 | { | 168 | { |
169 | struct screen * screen = &(screens[i]); | ||
170 | struct viewport vp; | ||
171 | viewport_set_defaults(&vp, screen->screen_type); | ||
172 | struct viewport *last_vp = screen->set_viewport(&vp); | ||
173 | |||
172 | va_start(ap, fmt); | 174 | va_start(ap, fmt); |
173 | splash_internal(&(screens[i]), fmt, ap); | 175 | if (splash_internal(screen, fmt, ap, &vp, 0)) |
176 | screen->update_viewport(); | ||
174 | va_end(ap); | 177 | va_end(ap); |
178 | |||
179 | screen->set_viewport(last_vp); | ||
175 | } | 180 | } |
176 | if (ticks) | 181 | if (ticks) |
177 | sleep(ticks); | 182 | sleep(ticks); |
@@ -189,3 +194,50 @@ void splash(int ticks, const char *str) | |||
189 | #endif | 194 | #endif |
190 | splashf(ticks, "%s", P2STR((const unsigned char*)str)); | 195 | splashf(ticks, "%s", P2STR((const unsigned char*)str)); |
191 | } | 196 | } |
197 | |||
198 | /* splash a progress meter */ | ||
199 | void splash_progress(int current, int total, const char *fmt, ...) | ||
200 | { | ||
201 | int vp_flag = VP_FLAG_VP_DIRTY; | ||
202 | /* progress update tick */ | ||
203 | static long next_tick = 0; | ||
204 | long now = current_tick; | ||
205 | |||
206 | if (current < total) | ||
207 | { | ||
208 | if(TIME_BEFORE(now, next_tick)) | ||
209 | return; | ||
210 | /* limit to 20fps */ | ||
211 | next_tick = now + HZ/20; | ||
212 | vp_flag = 0; /* don't mark vp dirty to prevent flashing */ | ||
213 | } | ||
214 | |||
215 | va_list ap; | ||
216 | |||
217 | /* If fmt is a lang ID then get the corresponding string (which | ||
218 | still might contain % place holders). */ | ||
219 | fmt = P2STR((unsigned char *)fmt); | ||
220 | FOR_NB_SCREENS(i) | ||
221 | { | ||
222 | struct screen * screen = &(screens[i]); | ||
223 | struct viewport vp; | ||
224 | viewport_set_defaults(&vp, screen->screen_type); | ||
225 | struct viewport *last_vp = screen->set_viewport_ex(&vp, vp_flag); | ||
226 | |||
227 | va_start(ap, fmt); | ||
228 | if (splash_internal(screen, fmt, ap, &vp, 1)) | ||
229 | { | ||
230 | int size = screen->getcharheight(); | ||
231 | int y = vp.height - size - RECT_SPACING; | ||
232 | int w = vp.width - RECT_SPACING * 2; | ||
233 | |||
234 | gui_scrollbar_draw(screen, RECT_SPACING, y, w, size, | ||
235 | total, 0, current, HORIZONTAL | FOREGROUND); | ||
236 | |||
237 | screen->update_viewport(); | ||
238 | } | ||
239 | va_end(ap); | ||
240 | |||
241 | screen->set_viewport(last_vp); | ||
242 | } | ||
243 | } | ||