summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWilliam Wilgus <wilgus.william@gmail.com>2022-11-10 09:38:50 -0500
committerWilliam Wilgus <me.theuser@yahoo.com>2022-11-12 06:22:16 -0500
commitc756a8a89d6970090b060a179dcabb93a67d8f21 (patch)
tree868fa2b1393c512ecfa445688635ada71086dea7
parentdd1fbd51fc7bb3fa7237b3bc34335e99bef29e35 (diff)
downloadrockbox-c756a8a89d6970090b060a179dcabb93a67d8f21.tar.gz
rockbox-c756a8a89d6970090b060a179dcabb93a67d8f21.zip
make splash split on control characters
splits on spaces also considers \r\n\f\v\t as mandatory breaks I'm still working on the strptokspn function my goal is to use it directly rather than storing the matched char and modifying the source string with \0 in order to tokenize the output --Done Change-Id: I7f378b5b9c4df8f10899b9a55a98950afb3931dc
-rw-r--r--apps/gui/splash.c57
-rw-r--r--apps/screen_access.c2
-rw-r--r--apps/screen_access.h1
-rw-r--r--firmware/SOURCES64
-rw-r--r--firmware/common/strptokspn.c88
-rw-r--r--firmware/export/font.h2
-rw-r--r--firmware/font.c24
-rw-r--r--firmware/include/strptokspn_r.h26
8 files changed, 202 insertions, 62 deletions
diff --git a/apps/gui/splash.c b/apps/gui/splash.c
index efb4b1cda2..3f361f5a04 100644
--- a/apps/gui/splash.c
+++ b/apps/gui/splash.c
@@ -29,8 +29,9 @@
29#include "talk.h" 29#include "talk.h"
30#include "splash.h" 30#include "splash.h"
31#include "viewport.h" 31#include "viewport.h"
32#include "strtok_r.h" 32#include "strptokspn_r.h"
33#include "scrollbar.h" 33#include "scrollbar.h"
34#include "font.h"
34 35
35static long progress_next_tick = 0; 36static long progress_next_tick = 0;
36 37
@@ -43,57 +44,68 @@ static bool splash_internal(struct screen * screen, const char *fmt, va_list ap,
43 struct viewport *vp, int addl_lines) 44 struct viewport *vp, int addl_lines)
44{ 45{
45 char splash_buf[MAXBUFFER]; 46 char splash_buf[MAXBUFFER];
46 char *lines[MAXLINES]; 47 struct splash_lines {
48 const char *str;
49 size_t len;
50 } lines[MAXLINES];
47 char *next; 51 char *next;
48 char *lastbreak = NULL; 52 char *lastbreak = NULL;
49 char *store = NULL; 53 char *store = NULL;
50 int line = 0; 54 int line = 0;
51 int x = 0; 55 int x = 0;
52 int y, i; 56 int y, i;
53 int space_w, w, h; 57 int space_w, w, chr_h;
54 int width, height; 58 int width, height;
55 int maxw = 0; 59 int maxw = 0;
60 int fontnum = vp->font;
56 61
57 screen->getstringsize(" ", &space_w, &h); 62 char lastbrkchr;
58 y = h + (addl_lines * h); 63 size_t len, next_len;
64 const char matchstr[] = "\r\n\f\v\t ";
65 font_getstringsize(" ", &space_w, &chr_h, fontnum);
66 y = chr_h + (addl_lines * chr_h);
59 67
60 vsnprintf(splash_buf, sizeof(splash_buf), fmt, ap); 68 vsnprintf(splash_buf, sizeof(splash_buf), fmt, ap);
61 va_end(ap); 69 va_end(ap);
62 70
63 /* break splash string into display lines, doing proper word wrap */ 71 /* break splash string into display lines, doing proper word wrap */
64 72 next = strptokspn_r(splash_buf, matchstr, &next_len, &store);
65 next = strtok_r(splash_buf, " ", &store);
66 if (!next) 73 if (!next)
67 return false; /* nothing to display */ 74 return false; /* nothing to display */
68 75
69 lines[0] = next; 76 lines[line].len = next_len + 1;
77 lines[line].str = next;
70 while (true) 78 while (true)
71 { 79 {
72 screen->getstringsize(next, &w, NULL); 80 w = font_getstringnsize(next, next_len + 1, NULL, NULL, fontnum);
73 if (lastbreak) 81 if (lastbreak)
74 { 82 {
75 int next_w = (next - lastbreak) * space_w; 83 len = next - lastbreak;
76 84 int next_w = len * space_w;
77 if (x + next_w + w > vp->width - RECT_SPACING*2) 85 if (x + next_w + w > vp->width - RECT_SPACING*2 || lastbrkchr != ' ')
78 { /* too wide, wrap */ 86 { /* too wide, or control character wrap */
79 if (x > maxw) 87 if (x > maxw)
80 maxw = x; 88 maxw = x;
81 if ((y + h > vp->height) || (line >= (MAXLINES-1))) 89 if ((y + chr_h * 2 > vp->height) || (line >= (MAXLINES-1)))
82 break; /* screen full or out of lines */ 90 break; /* screen full or out of lines */
83 x = 0; 91 x = 0;
84 y += h; 92 y += chr_h;
85 lines[++line] = next; 93 lines[++line].len = next_len + len;
94 lines[line].str = next;
86 } 95 }
87 else 96 else
88 { 97 {
89 /* restore & calculate spacing */ 98 /* restore & calculate spacing */
90 *lastbreak = ' '; 99 lines[line].len += next_len + len + 1;
91 x += next_w; 100 x += next_w;
92 } 101 }
93 } 102 }
94 x += w; 103 x += w;
95 lastbreak = next + strlen(next); 104 lastbreak = next + next_len + 1;
96 next = strtok_r(NULL, " ", &store); 105 lastbrkchr = *lastbreak;
106
107 next = strptokspn_r(NULL, matchstr, &next_len, &store);
108
97 if (!next) 109 if (!next)
98 { /* no more words */ 110 { /* no more words */
99 if (x > maxw) 111 if (x > maxw)
@@ -147,13 +159,10 @@ static bool splash_internal(struct screen * screen, const char *fmt, va_list ap,
147 159
148 screen->draw_border_viewport(); 160 screen->draw_border_viewport();
149 161
150 /* prepare putting the text */
151 y = RECT_SPACING;
152
153 /* print the message to screen */ 162 /* print the message to screen */
154 for (i = 0; i <= line; i++, y+=h) 163 for(i = 0, y = RECT_SPACING; i <= line; i++, y+= chr_h)
155 { 164 {
156 screen->putsxy(0, y, lines[i]); 165 screen->putsxyf(0, y, "%.*s", lines[i].len, lines[i].str);
157 } 166 }
158 return true; /* needs update */ 167 return true; /* needs update */
159} 168}
diff --git a/apps/screen_access.c b/apps/screen_access.c
index a7b902918c..1909ef277c 100644
--- a/apps/screen_access.c
+++ b/apps/screen_access.c
@@ -217,6 +217,7 @@ struct screen screens[NB_SCREENS] =
217 .putsxy=&lcd_putsxy, 217 .putsxy=&lcd_putsxy,
218 .puts=&lcd_puts, 218 .puts=&lcd_puts,
219 .putsf=&lcd_putsf, 219 .putsf=&lcd_putsf,
220 .putsxyf=&lcd_putsxyf,
220 .puts_scroll=&lcd_puts_scroll, 221 .puts_scroll=&lcd_puts_scroll,
221 .putsxy_scroll_func=&lcd_putsxy_scroll_func, 222 .putsxy_scroll_func=&lcd_putsxy_scroll_func,
222 .scroll_speed=&lcd_scroll_speed, 223 .scroll_speed=&lcd_scroll_speed,
@@ -305,6 +306,7 @@ struct screen screens[NB_SCREENS] =
305 .putsxy=&lcd_remote_putsxy, 306 .putsxy=&lcd_remote_putsxy,
306 .puts=&lcd_remote_puts, 307 .puts=&lcd_remote_puts,
307 .putsf=&lcd_remote_putsf, 308 .putsf=&lcd_remote_putsf,
309 .putsxyf=&lcd_remote_putsxyf,
308 .puts_scroll=&lcd_remote_puts_scroll, 310 .puts_scroll=&lcd_remote_puts_scroll,
309 .putsxy_scroll_func=&lcd_remote_putsxy_scroll_func, 311 .putsxy_scroll_func=&lcd_remote_putsxy_scroll_func,
310 .scroll_speed=&lcd_remote_scroll_speed, 312 .scroll_speed=&lcd_remote_scroll_speed,
diff --git a/apps/screen_access.h b/apps/screen_access.h
index 94c0a19670..3e24306636 100644
--- a/apps/screen_access.h
+++ b/apps/screen_access.h
@@ -109,6 +109,7 @@ struct screen
109 void (*putsxy)(int x, int y, const unsigned char *str); 109 void (*putsxy)(int x, int y, const unsigned char *str);
110 void (*puts)(int x, int y, const unsigned char *str); 110 void (*puts)(int x, int y, const unsigned char *str);
111 void (*putsf)(int x, int y, const unsigned char *str, ...); 111 void (*putsf)(int x, int y, const unsigned char *str, ...);
112 void (*putsxyf)(int x, int y, const unsigned char *fmt, ...);
112 bool (*puts_scroll)(int x, int y, const unsigned char *string); 113 bool (*puts_scroll)(int x, int y, const unsigned char *string);
113 bool (*putsxy_scroll_func)(int x, int y, const unsigned char *string, 114 bool (*putsxy_scroll_func)(int x, int y, const unsigned char *string,
114 void (*scroll_func)(struct scrollinfo *), 115 void (*scroll_func)(struct scrollinfo *),
diff --git a/firmware/SOURCES b/firmware/SOURCES
index bbd67631a9..4aa7c38daf 100644
--- a/firmware/SOURCES
+++ b/firmware/SOURCES
@@ -205,39 +205,10 @@ target/hosted/samsungypr/ypr1/wmcodec-ypr1.c
205target/hosted/maemo/maemo-thread.c 205target/hosted/maemo/maemo-thread.c
206#endif 206#endif
207 207
208/* Standard library */
209#if (CONFIG_PLATFORM & PLATFORM_NATIVE) || defined(__MINGW32__) || defined(__CYGWIN__)
210libc/strtok.c
211#endif /* PLATFORM_NATIVE || __MINGW32__ || __CYGWIN__ */
212#if (CONFIG_PLATFORM & PLATFORM_NATIVE) || defined(HAVE_ROCKBOX_C_LIBRARY)
213libc/atoi.c
214libc/errno.c
215#if (CONFIG_PLATFORM & PLATFORM_NATIVE)
216/* our ctype.[ch] comes from newlib and is incompitble with most desktop's ctype */
217libc/ctype.c
218/* alsa on linux requires a more advanced sprintf, i.e. not ours */
219libc/sprintf.c
220#endif
221
222libc/memchr.c
223libc/memcmp.c
224
225libc/qsort.c
226libc/random.c
227libc/strcat.c
228libc/strchr.c
229libc/strcmp.c
230libc/strcpy.c
231
232libc/strncmp.c
233libc/strrchr.c
234libc/strstr.c
235libc/mktime.c
236libc/gmtime.c
237#endif /* CONFIG_PLATFORM || HAVE_ROCKBOX_C_LIBRARY */
238
239/* Common */ 208/* Common */
240#ifndef BOOTLOADER 209#ifndef BOOTLOADER
210common/strptokspn.c
211#define HAVE_STRTOK_R
241common/ap_int.c 212common/ap_int.c
242#endif 213#endif
243common/version.c 214common/version.c
@@ -277,6 +248,37 @@ common/zip.c
277common/adler32.c 248common/adler32.c
278common/inflate.c 249common/inflate.c
279 250
251/* Standard library */
252#if (CONFIG_PLATFORM & PLATFORM_NATIVE) || defined(__MINGW32__) || defined(__CYGWIN__)
253libc/strtok.c
254#endif /* PLATFORM_NATIVE || __MINGW32__ || __CYGWIN__ */
255#if (CONFIG_PLATFORM & PLATFORM_NATIVE) || defined(HAVE_ROCKBOX_C_LIBRARY)
256libc/atoi.c
257libc/errno.c
258#if (CONFIG_PLATFORM & PLATFORM_NATIVE)
259/* our ctype.[ch] comes from newlib and is incompitble with most desktop's ctype */
260libc/ctype.c
261/* alsa on linux requires a more advanced sprintf, i.e. not ours */
262libc/sprintf.c
263#endif
264
265libc/memchr.c
266libc/memcmp.c
267
268libc/qsort.c
269libc/random.c
270libc/strcat.c
271libc/strchr.c
272libc/strcmp.c
273libc/strcpy.c
274
275libc/strncmp.c
276libc/strrchr.c
277libc/strstr.c
278libc/mktime.c
279libc/gmtime.c
280#endif /* CONFIG_PLATFORM || HAVE_ROCKBOX_C_LIBRARY */
281
280/* Display */ 282/* Display */
281scroll_engine.c 283scroll_engine.c
282 284
diff --git a/firmware/common/strptokspn.c b/firmware/common/strptokspn.c
new file mode 100644
index 0000000000..f4b92c0712
--- /dev/null
+++ b/firmware/common/strptokspn.c
@@ -0,0 +1,88 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2022 by William WIlgus
11 *
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.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied. *
19 ****************************************************************************/
20
21#include "config.h"
22
23#include <stddef.h>
24#include <string.h>
25#include "strtok_r.h"
26/* strptokspn_r is a custom implementation of strtok_r that does NOT modify
27 * the source string.
28 *
29 * strptokspn_r reads ptr as a series of zero or more tokens,
30 * and sep as delimiters of the tokens
31 * The tokens can be separated by one or more of the delimiters
32 * first call searches for the first token skipping over any leading delimiters.
33 * Returns pointer to first token
34 * Pointer *len contains the span to the first delimeter
35 * (this would be the resulting strlen had token actually been NULL terminated)
36 * Pointer **end contains pointer to first character after the last delimeter
37 *
38 * When strptokspn_r is called with a ptr == NULL, the next token is read from
39 * Pointer **end
40 *
41 * Note the returned token is NOT NULL terminated by the function as in strtok_r
42 * However the caller can use ret[len+1] = '\0'; to emulate a call to strtok_r
43*/
44
45const char *strptokspn_r(const char *ptr, const char *sep, size_t *len, const char **end)
46{
47 *len = 0;
48 if (!ptr)
49 /* we got NULL input so then we get our last position instead */
50 ptr = *end;
51
52 /* pass all letters that are including in the separator string */
53 while (*ptr && strchr(sep, *ptr))
54 ++ptr;
55
56 if (*ptr) {
57 /* so this is where the next piece of string starts */
58 const char *start = ptr;
59
60 /* set the end pointer to the first byte after the start */
61 *end = start + 1;
62
63 /* scan through the string to find where it ends, it ends on a
64 null byte or a character that exists in the separator string */
65 while (**end && !strchr(sep, **end))
66 ++*end;
67 *len = (*end - start) - 1; /* this would be the string len if there actually was a NULL */
68 if (**end) { /* the end is not a null byte */
69 ++*end; /* advance last pointer to beyond the match */
70 }
71
72 return start; /* return the position where the string starts */
73 }
74
75 /* we ended up on a null byte, there are no more strings to find! */
76 return NULL;
77}
78
79#if !defined(HAVE_STRTOK_R)
80char * strtok_r(char *ptr, const char *sep, char **end)
81{
82 size_t len;
83 char * ret = (char*) strptokspn_r((const char*)ptr, sep, &len, (const char**) end);
84 if (ret)
85 ret[len + 1] = '\0';
86 return ret;
87}
88#endif
diff --git a/firmware/export/font.h b/firmware/export/font.h
index 067c67e43d..38e30187b3 100644
--- a/firmware/export/font.h
+++ b/firmware/export/font.h
@@ -132,7 +132,7 @@ void font_disable_all(void);
132void font_enable_all(void); 132void font_enable_all(void);
133 133
134struct font* font_get(int font); 134struct font* font_get(int font);
135 135int font_getstringnsize(const unsigned char *str, size_t maxbytes, int *w, int *h, int fontnumber);
136int font_getstringsize(const unsigned char *str, int *w, int *h, int fontnumber); 136int font_getstringsize(const unsigned char *str, int *w, int *h, int fontnumber);
137int font_get_width(struct font* ft, unsigned short ch); 137int font_get_width(struct font* ft, unsigned short ch);
138const unsigned char * font_get_bits(struct font* ft, unsigned short ch); 138const unsigned char * font_get_bits(struct font* ft, unsigned short ch);
diff --git a/firmware/font.c b/firmware/font.c
index 7ce64ed47d..97a15221fc 100644
--- a/firmware/font.c
+++ b/firmware/font.c
@@ -1046,16 +1046,20 @@ const unsigned char* font_get_bits(struct font* pf, unsigned short char_code)
1046#endif /* BOOTLOADER */ 1046#endif /* BOOTLOADER */
1047 1047
1048/* 1048/*
1049 * Returns the stringsize of a given string. 1049 * Returns the stringsize of a given NULL terminated string
1050 * stops after maxbytes or NULL (\0) whichever occurs first.
1051 * maxbytes = -1 ignores maxbytes and relies on NULL terminator (\0)
1052 * to terminate the string
1050 */ 1053 */
1051int font_getstringsize(const unsigned char *str, int *w, int *h, int fontnumber) 1054int font_getstringnsize(const unsigned char *str, size_t maxbytes, int *w, int *h, int fontnum)
1052{ 1055{
1053 struct font* pf = font_get(fontnumber); 1056 struct font* pf = font_get(fontnum);
1057 font_lock( fontnum, true );
1054 unsigned short ch; 1058 unsigned short ch;
1055 int width = 0; 1059 int width = 0;
1060 size_t b = maxbytes - 1;
1056 1061
1057 font_lock( fontnumber, true ); 1062 for (str = utf8decode(str, &ch); ch != 0 && b < maxbytes; str = utf8decode(str, &ch), b--)
1058 for (str = utf8decode(str, &ch); ch != 0 ; str = utf8decode(str, &ch))
1059 { 1063 {
1060 if (is_diacritic(ch, NULL)) 1064 if (is_diacritic(ch, NULL))
1061 continue; 1065 continue;
@@ -1067,10 +1071,18 @@ int font_getstringsize(const unsigned char *str, int *w, int *h, int fontnumber)
1067 *w = width; 1071 *w = width;
1068 if ( h ) 1072 if ( h )
1069 *h = pf->height; 1073 *h = pf->height;
1070 font_lock( fontnumber, false ); 1074 font_lock( fontnum, false );
1071 return width; 1075 return width;
1072} 1076}
1073 1077
1078/*
1079 * Returns the stringsize of a given NULL terminated string.
1080 */
1081int font_getstringsize(const unsigned char *str, int *w, int *h, int fontnumber)
1082{
1083 return font_getstringnsize(str, -1, w, h, fontnumber);
1084}
1085
1074/* ----------------------------------------------------------------- 1086/* -----------------------------------------------------------------
1075 * vim: et sw=4 ts=8 sts=4 tw=78 1087 * vim: et sw=4 ts=8 sts=4 tw=78
1076 */ 1088 */
diff --git a/firmware/include/strptokspn_r.h b/firmware/include/strptokspn_r.h
new file mode 100644
index 0000000000..d565118190
--- /dev/null
+++ b/firmware/include/strptokspn_r.h
@@ -0,0 +1,26 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2022 William Wilgus
11 *
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.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22
23#ifndef __STRPTOKSPN_R_H__
24#define __STRPTOKSPN_R_H__
25const char *strptokspn_r(const char *ptr, const char *sep, size_t *len, const char **end);
26#endif