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
This commit is contained in:
parent
dd1fbd51fc
commit
c756a8a89d
8 changed files with 202 additions and 62 deletions
|
@ -29,8 +29,9 @@
|
||||||
#include "talk.h"
|
#include "talk.h"
|
||||||
#include "splash.h"
|
#include "splash.h"
|
||||||
#include "viewport.h"
|
#include "viewport.h"
|
||||||
#include "strtok_r.h"
|
#include "strptokspn_r.h"
|
||||||
#include "scrollbar.h"
|
#include "scrollbar.h"
|
||||||
|
#include "font.h"
|
||||||
|
|
||||||
static long progress_next_tick = 0;
|
static long progress_next_tick = 0;
|
||||||
|
|
||||||
|
@ -43,57 +44,68 @@ static bool splash_internal(struct screen * screen, const char *fmt, va_list ap,
|
||||||
struct viewport *vp, int addl_lines)
|
struct viewport *vp, int addl_lines)
|
||||||
{
|
{
|
||||||
char splash_buf[MAXBUFFER];
|
char splash_buf[MAXBUFFER];
|
||||||
char *lines[MAXLINES];
|
struct splash_lines {
|
||||||
|
const char *str;
|
||||||
|
size_t len;
|
||||||
|
} lines[MAXLINES];
|
||||||
char *next;
|
char *next;
|
||||||
char *lastbreak = NULL;
|
char *lastbreak = NULL;
|
||||||
char *store = NULL;
|
char *store = NULL;
|
||||||
int line = 0;
|
int line = 0;
|
||||||
int x = 0;
|
int x = 0;
|
||||||
int y, i;
|
int y, i;
|
||||||
int space_w, w, h;
|
int space_w, w, chr_h;
|
||||||
int width, height;
|
int width, height;
|
||||||
int maxw = 0;
|
int maxw = 0;
|
||||||
|
int fontnum = vp->font;
|
||||||
|
|
||||||
screen->getstringsize(" ", &space_w, &h);
|
char lastbrkchr;
|
||||||
y = h + (addl_lines * h);
|
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);
|
||||||
|
|
||||||
vsnprintf(splash_buf, sizeof(splash_buf), fmt, ap);
|
vsnprintf(splash_buf, sizeof(splash_buf), fmt, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
/* break splash string into display lines, doing proper word wrap */
|
/* break splash string into display lines, doing proper word wrap */
|
||||||
|
next = strptokspn_r(splash_buf, matchstr, &next_len, &store);
|
||||||
next = strtok_r(splash_buf, " ", &store);
|
|
||||||
if (!next)
|
if (!next)
|
||||||
return false; /* nothing to display */
|
return false; /* nothing to display */
|
||||||
|
|
||||||
lines[0] = next;
|
lines[line].len = next_len + 1;
|
||||||
|
lines[line].str = next;
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
screen->getstringsize(next, &w, NULL);
|
w = font_getstringnsize(next, next_len + 1, NULL, NULL, fontnum);
|
||||||
if (lastbreak)
|
if (lastbreak)
|
||||||
{
|
{
|
||||||
int next_w = (next - lastbreak) * space_w;
|
len = next - lastbreak;
|
||||||
|
int next_w = len * space_w;
|
||||||
if (x + next_w + w > vp->width - RECT_SPACING*2)
|
if (x + next_w + w > vp->width - RECT_SPACING*2 || lastbrkchr != ' ')
|
||||||
{ /* too wide, wrap */
|
{ /* too wide, or control character wrap */
|
||||||
if (x > maxw)
|
if (x > maxw)
|
||||||
maxw = x;
|
maxw = x;
|
||||||
if ((y + h > vp->height) || (line >= (MAXLINES-1)))
|
if ((y + chr_h * 2 > vp->height) || (line >= (MAXLINES-1)))
|
||||||
break; /* screen full or out of lines */
|
break; /* screen full or out of lines */
|
||||||
x = 0;
|
x = 0;
|
||||||
y += h;
|
y += chr_h;
|
||||||
lines[++line] = next;
|
lines[++line].len = next_len + len;
|
||||||
|
lines[line].str = next;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* restore & calculate spacing */
|
/* restore & calculate spacing */
|
||||||
*lastbreak = ' ';
|
lines[line].len += next_len + len + 1;
|
||||||
x += next_w;
|
x += next_w;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
x += w;
|
x += w;
|
||||||
lastbreak = next + strlen(next);
|
lastbreak = next + next_len + 1;
|
||||||
next = strtok_r(NULL, " ", &store);
|
lastbrkchr = *lastbreak;
|
||||||
|
|
||||||
|
next = strptokspn_r(NULL, matchstr, &next_len, &store);
|
||||||
|
|
||||||
if (!next)
|
if (!next)
|
||||||
{ /* no more words */
|
{ /* no more words */
|
||||||
if (x > maxw)
|
if (x > maxw)
|
||||||
|
@ -147,13 +159,10 @@ static bool splash_internal(struct screen * screen, const char *fmt, va_list ap,
|
||||||
|
|
||||||
screen->draw_border_viewport();
|
screen->draw_border_viewport();
|
||||||
|
|
||||||
/* prepare putting the text */
|
|
||||||
y = RECT_SPACING;
|
|
||||||
|
|
||||||
/* print the message to screen */
|
/* print the message to screen */
|
||||||
for (i = 0; i <= line; i++, y+=h)
|
for(i = 0, y = RECT_SPACING; i <= line; i++, y+= chr_h)
|
||||||
{
|
{
|
||||||
screen->putsxy(0, y, lines[i]);
|
screen->putsxyf(0, y, "%.*s", lines[i].len, lines[i].str);
|
||||||
}
|
}
|
||||||
return true; /* needs update */
|
return true; /* needs update */
|
||||||
}
|
}
|
||||||
|
|
|
@ -217,6 +217,7 @@ struct screen screens[NB_SCREENS] =
|
||||||
.putsxy=&lcd_putsxy,
|
.putsxy=&lcd_putsxy,
|
||||||
.puts=&lcd_puts,
|
.puts=&lcd_puts,
|
||||||
.putsf=&lcd_putsf,
|
.putsf=&lcd_putsf,
|
||||||
|
.putsxyf=&lcd_putsxyf,
|
||||||
.puts_scroll=&lcd_puts_scroll,
|
.puts_scroll=&lcd_puts_scroll,
|
||||||
.putsxy_scroll_func=&lcd_putsxy_scroll_func,
|
.putsxy_scroll_func=&lcd_putsxy_scroll_func,
|
||||||
.scroll_speed=&lcd_scroll_speed,
|
.scroll_speed=&lcd_scroll_speed,
|
||||||
|
@ -305,6 +306,7 @@ struct screen screens[NB_SCREENS] =
|
||||||
.putsxy=&lcd_remote_putsxy,
|
.putsxy=&lcd_remote_putsxy,
|
||||||
.puts=&lcd_remote_puts,
|
.puts=&lcd_remote_puts,
|
||||||
.putsf=&lcd_remote_putsf,
|
.putsf=&lcd_remote_putsf,
|
||||||
|
.putsxyf=&lcd_remote_putsxyf,
|
||||||
.puts_scroll=&lcd_remote_puts_scroll,
|
.puts_scroll=&lcd_remote_puts_scroll,
|
||||||
.putsxy_scroll_func=&lcd_remote_putsxy_scroll_func,
|
.putsxy_scroll_func=&lcd_remote_putsxy_scroll_func,
|
||||||
.scroll_speed=&lcd_remote_scroll_speed,
|
.scroll_speed=&lcd_remote_scroll_speed,
|
||||||
|
|
|
@ -109,6 +109,7 @@ struct screen
|
||||||
void (*putsxy)(int x, int y, const unsigned char *str);
|
void (*putsxy)(int x, int y, const unsigned char *str);
|
||||||
void (*puts)(int x, int y, const unsigned char *str);
|
void (*puts)(int x, int y, const unsigned char *str);
|
||||||
void (*putsf)(int x, int y, const unsigned char *str, ...);
|
void (*putsf)(int x, int y, const unsigned char *str, ...);
|
||||||
|
void (*putsxyf)(int x, int y, const unsigned char *fmt, ...);
|
||||||
bool (*puts_scroll)(int x, int y, const unsigned char *string);
|
bool (*puts_scroll)(int x, int y, const unsigned char *string);
|
||||||
bool (*putsxy_scroll_func)(int x, int y, const unsigned char *string,
|
bool (*putsxy_scroll_func)(int x, int y, const unsigned char *string,
|
||||||
void (*scroll_func)(struct scrollinfo *),
|
void (*scroll_func)(struct scrollinfo *),
|
||||||
|
|
|
@ -205,39 +205,10 @@ target/hosted/samsungypr/ypr1/wmcodec-ypr1.c
|
||||||
target/hosted/maemo/maemo-thread.c
|
target/hosted/maemo/maemo-thread.c
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Standard library */
|
|
||||||
#if (CONFIG_PLATFORM & PLATFORM_NATIVE) || defined(__MINGW32__) || defined(__CYGWIN__)
|
|
||||||
libc/strtok.c
|
|
||||||
#endif /* PLATFORM_NATIVE || __MINGW32__ || __CYGWIN__ */
|
|
||||||
#if (CONFIG_PLATFORM & PLATFORM_NATIVE) || defined(HAVE_ROCKBOX_C_LIBRARY)
|
|
||||||
libc/atoi.c
|
|
||||||
libc/errno.c
|
|
||||||
#if (CONFIG_PLATFORM & PLATFORM_NATIVE)
|
|
||||||
/* our ctype.[ch] comes from newlib and is incompitble with most desktop's ctype */
|
|
||||||
libc/ctype.c
|
|
||||||
/* alsa on linux requires a more advanced sprintf, i.e. not ours */
|
|
||||||
libc/sprintf.c
|
|
||||||
#endif
|
|
||||||
|
|
||||||
libc/memchr.c
|
|
||||||
libc/memcmp.c
|
|
||||||
|
|
||||||
libc/qsort.c
|
|
||||||
libc/random.c
|
|
||||||
libc/strcat.c
|
|
||||||
libc/strchr.c
|
|
||||||
libc/strcmp.c
|
|
||||||
libc/strcpy.c
|
|
||||||
|
|
||||||
libc/strncmp.c
|
|
||||||
libc/strrchr.c
|
|
||||||
libc/strstr.c
|
|
||||||
libc/mktime.c
|
|
||||||
libc/gmtime.c
|
|
||||||
#endif /* CONFIG_PLATFORM || HAVE_ROCKBOX_C_LIBRARY */
|
|
||||||
|
|
||||||
/* Common */
|
/* Common */
|
||||||
#ifndef BOOTLOADER
|
#ifndef BOOTLOADER
|
||||||
|
common/strptokspn.c
|
||||||
|
#define HAVE_STRTOK_R
|
||||||
common/ap_int.c
|
common/ap_int.c
|
||||||
#endif
|
#endif
|
||||||
common/version.c
|
common/version.c
|
||||||
|
@ -277,6 +248,37 @@ common/zip.c
|
||||||
common/adler32.c
|
common/adler32.c
|
||||||
common/inflate.c
|
common/inflate.c
|
||||||
|
|
||||||
|
/* Standard library */
|
||||||
|
#if (CONFIG_PLATFORM & PLATFORM_NATIVE) || defined(__MINGW32__) || defined(__CYGWIN__)
|
||||||
|
libc/strtok.c
|
||||||
|
#endif /* PLATFORM_NATIVE || __MINGW32__ || __CYGWIN__ */
|
||||||
|
#if (CONFIG_PLATFORM & PLATFORM_NATIVE) || defined(HAVE_ROCKBOX_C_LIBRARY)
|
||||||
|
libc/atoi.c
|
||||||
|
libc/errno.c
|
||||||
|
#if (CONFIG_PLATFORM & PLATFORM_NATIVE)
|
||||||
|
/* our ctype.[ch] comes from newlib and is incompitble with most desktop's ctype */
|
||||||
|
libc/ctype.c
|
||||||
|
/* alsa on linux requires a more advanced sprintf, i.e. not ours */
|
||||||
|
libc/sprintf.c
|
||||||
|
#endif
|
||||||
|
|
||||||
|
libc/memchr.c
|
||||||
|
libc/memcmp.c
|
||||||
|
|
||||||
|
libc/qsort.c
|
||||||
|
libc/random.c
|
||||||
|
libc/strcat.c
|
||||||
|
libc/strchr.c
|
||||||
|
libc/strcmp.c
|
||||||
|
libc/strcpy.c
|
||||||
|
|
||||||
|
libc/strncmp.c
|
||||||
|
libc/strrchr.c
|
||||||
|
libc/strstr.c
|
||||||
|
libc/mktime.c
|
||||||
|
libc/gmtime.c
|
||||||
|
#endif /* CONFIG_PLATFORM || HAVE_ROCKBOX_C_LIBRARY */
|
||||||
|
|
||||||
/* Display */
|
/* Display */
|
||||||
scroll_engine.c
|
scroll_engine.c
|
||||||
|
|
||||||
|
|
88
firmware/common/strptokspn.c
Normal file
88
firmware/common/strptokspn.c
Normal file
|
@ -0,0 +1,88 @@
|
||||||
|
/***************************************************************************
|
||||||
|
* __________ __ ___.
|
||||||
|
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||||
|
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||||
|
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||||
|
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||||
|
* \/ \/ \/ \/ \/
|
||||||
|
* $Id$
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 by William WIlgus
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||||
|
* KIND, either express or implied. *
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "strtok_r.h"
|
||||||
|
/* strptokspn_r is a custom implementation of strtok_r that does NOT modify
|
||||||
|
* the source string.
|
||||||
|
*
|
||||||
|
* strptokspn_r reads ptr as a series of zero or more tokens,
|
||||||
|
* and sep as delimiters of the tokens
|
||||||
|
* The tokens can be separated by one or more of the delimiters
|
||||||
|
* first call searches for the first token skipping over any leading delimiters.
|
||||||
|
* Returns pointer to first token
|
||||||
|
* Pointer *len contains the span to the first delimeter
|
||||||
|
* (this would be the resulting strlen had token actually been NULL terminated)
|
||||||
|
* Pointer **end contains pointer to first character after the last delimeter
|
||||||
|
*
|
||||||
|
* When strptokspn_r is called with a ptr == NULL, the next token is read from
|
||||||
|
* Pointer **end
|
||||||
|
*
|
||||||
|
* Note the returned token is NOT NULL terminated by the function as in strtok_r
|
||||||
|
* However the caller can use ret[len+1] = '\0'; to emulate a call to strtok_r
|
||||||
|
*/
|
||||||
|
|
||||||
|
const char *strptokspn_r(const char *ptr, const char *sep, size_t *len, const char **end)
|
||||||
|
{
|
||||||
|
*len = 0;
|
||||||
|
if (!ptr)
|
||||||
|
/* we got NULL input so then we get our last position instead */
|
||||||
|
ptr = *end;
|
||||||
|
|
||||||
|
/* pass all letters that are including in the separator string */
|
||||||
|
while (*ptr && strchr(sep, *ptr))
|
||||||
|
++ptr;
|
||||||
|
|
||||||
|
if (*ptr) {
|
||||||
|
/* so this is where the next piece of string starts */
|
||||||
|
const char *start = ptr;
|
||||||
|
|
||||||
|
/* set the end pointer to the first byte after the start */
|
||||||
|
*end = start + 1;
|
||||||
|
|
||||||
|
/* scan through the string to find where it ends, it ends on a
|
||||||
|
null byte or a character that exists in the separator string */
|
||||||
|
while (**end && !strchr(sep, **end))
|
||||||
|
++*end;
|
||||||
|
*len = (*end - start) - 1; /* this would be the string len if there actually was a NULL */
|
||||||
|
if (**end) { /* the end is not a null byte */
|
||||||
|
++*end; /* advance last pointer to beyond the match */
|
||||||
|
}
|
||||||
|
|
||||||
|
return start; /* return the position where the string starts */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* we ended up on a null byte, there are no more strings to find! */
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if !defined(HAVE_STRTOK_R)
|
||||||
|
char * strtok_r(char *ptr, const char *sep, char **end)
|
||||||
|
{
|
||||||
|
size_t len;
|
||||||
|
char * ret = (char*) strptokspn_r((const char*)ptr, sep, &len, (const char**) end);
|
||||||
|
if (ret)
|
||||||
|
ret[len + 1] = '\0';
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
#endif
|
|
@ -132,7 +132,7 @@ void font_disable_all(void);
|
||||||
void font_enable_all(void);
|
void font_enable_all(void);
|
||||||
|
|
||||||
struct font* font_get(int font);
|
struct font* font_get(int font);
|
||||||
|
int font_getstringnsize(const unsigned char *str, size_t maxbytes, int *w, int *h, int fontnumber);
|
||||||
int font_getstringsize(const unsigned char *str, int *w, int *h, int fontnumber);
|
int font_getstringsize(const unsigned char *str, int *w, int *h, int fontnumber);
|
||||||
int font_get_width(struct font* ft, unsigned short ch);
|
int font_get_width(struct font* ft, unsigned short ch);
|
||||||
const unsigned char * font_get_bits(struct font* ft, unsigned short ch);
|
const unsigned char * font_get_bits(struct font* ft, unsigned short ch);
|
||||||
|
|
|
@ -1046,16 +1046,20 @@ const unsigned char* font_get_bits(struct font* pf, unsigned short char_code)
|
||||||
#endif /* BOOTLOADER */
|
#endif /* BOOTLOADER */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Returns the stringsize of a given string.
|
* Returns the stringsize of a given NULL terminated string
|
||||||
|
* stops after maxbytes or NULL (\0) whichever occurs first.
|
||||||
|
* maxbytes = -1 ignores maxbytes and relies on NULL terminator (\0)
|
||||||
|
* to terminate the string
|
||||||
*/
|
*/
|
||||||
int font_getstringsize(const unsigned char *str, int *w, int *h, int fontnumber)
|
int font_getstringnsize(const unsigned char *str, size_t maxbytes, int *w, int *h, int fontnum)
|
||||||
{
|
{
|
||||||
struct font* pf = font_get(fontnumber);
|
struct font* pf = font_get(fontnum);
|
||||||
|
font_lock( fontnum, true );
|
||||||
unsigned short ch;
|
unsigned short ch;
|
||||||
int width = 0;
|
int width = 0;
|
||||||
|
size_t b = maxbytes - 1;
|
||||||
|
|
||||||
font_lock( fontnumber, true );
|
for (str = utf8decode(str, &ch); ch != 0 && b < maxbytes; str = utf8decode(str, &ch), b--)
|
||||||
for (str = utf8decode(str, &ch); ch != 0 ; str = utf8decode(str, &ch))
|
|
||||||
{
|
{
|
||||||
if (is_diacritic(ch, NULL))
|
if (is_diacritic(ch, NULL))
|
||||||
continue;
|
continue;
|
||||||
|
@ -1067,10 +1071,18 @@ int font_getstringsize(const unsigned char *str, int *w, int *h, int fontnumber)
|
||||||
*w = width;
|
*w = width;
|
||||||
if ( h )
|
if ( h )
|
||||||
*h = pf->height;
|
*h = pf->height;
|
||||||
font_lock( fontnumber, false );
|
font_lock( fontnum, false );
|
||||||
return width;
|
return width;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns the stringsize of a given NULL terminated string.
|
||||||
|
*/
|
||||||
|
int font_getstringsize(const unsigned char *str, int *w, int *h, int fontnumber)
|
||||||
|
{
|
||||||
|
return font_getstringnsize(str, -1, w, h, fontnumber);
|
||||||
|
}
|
||||||
|
|
||||||
/* -----------------------------------------------------------------
|
/* -----------------------------------------------------------------
|
||||||
* vim: et sw=4 ts=8 sts=4 tw=78
|
* vim: et sw=4 ts=8 sts=4 tw=78
|
||||||
*/
|
*/
|
||||||
|
|
26
firmware/include/strptokspn_r.h
Normal file
26
firmware/include/strptokspn_r.h
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
/***************************************************************************
|
||||||
|
* __________ __ ___.
|
||||||
|
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||||
|
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||||
|
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||||
|
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||||
|
* \/ \/ \/ \/ \/
|
||||||
|
* $Id$
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 William Wilgus
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||||
|
* KIND, either express or implied.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef __STRPTOKSPN_R_H__
|
||||||
|
#define __STRPTOKSPN_R_H__
|
||||||
|
const char *strptokspn_r(const char *ptr, const char *sep, size_t *len, const char **end);
|
||||||
|
#endif
|
Loading…
Reference in a new issue