wrapping to multiple lines at word boundaries #1479
Replies: 9 comments 8 replies
-
this looks kinda messy, cleaner: // display a string on multiple lines, keeping words intact where possible
void printwords(const char *msg, int xloc, int yloc) {
int dspwidth = u8g2.getDisplayWidth(); // display width in pixels
int strwidth = 0; // string width in pixels
char glyph[2]; glyph[1] = 0;
for (const char *ptr = msg, *lastblank = NULL; *ptr; ++ptr) {
while (xloc == 0 && *msg == ' ')
if (ptr == msg++) ++ptr; // skip blanks at the left edge
glyph[0] = *ptr;
strwidth += u8g2.getStrWidth(glyph); // accumulate the pixel width
if (*ptr == ' ') lastblank = ptr; // remember where the last blank was
else ++strwidth; // non-blanks will be separated by one additional pixel
if (xloc + strwidth > dspwidth) { // if we ran past the right edge of the display
int starting_xloc = xloc;
while (msg < (lastblank ? lastblank : ptr)) { // print to the last blank, or a full line
glyph[0] = *msg++;
xloc += u8g2.drawStr(xloc, yloc, glyph);
}
strwidth -= xloc - starting_xloc; // account for what we printed
yloc += u8g2.getMaxCharHeight(); // advance to the next line
xloc = 0; lastblank = NULL;
}
}
while (*msg) { // print any characters left over
glyph[0] = *msg++;
xloc += u8g2.drawStr(xloc, yloc, glyph);
}
} by the way thanks for the code |
Beta Was this translation helpful? Give feedback.
-
You're welcome. Your version is exactly the same code, character-for-character, just formatted differently. Whether mine is "messy" and yours is "cleaner" is a matter of taste. I prefer to let indentation do the work of showing block structure, like Python does, and I treat the brackets as unfortunately necessary "syntactic sugar". I also use very few blank lines so that I can see as much code as possible on one screen. Both are valid approaches. As they said in Roman times, de gustibus non est disputandum. |
Beta Was this translation helpful? Give feedback.
-
By the way, here is a slightly extended version that allows an embedded \n character to force a new line. // display a string on multiple text lines, keeping words intact where possible,
// and accepting \n to force a new line
void printwords(const char *msg, int xloc, int yloc /*bottom*/ ) {
int dspwidth = u8g2.getDisplayWidth(); // display width in pixels
int strwidth = 0; // string width in pixels
char glyph[2]; glyph[1] = 0;
for (const char *ptr = msg, *lastblank = NULL; *ptr; ++ptr) {
while (xloc == 0 && (*msg == ' ' || *msg == '\n'))
if (ptr == msg++) ++ptr; // skip blanks and newlines at the left edge
glyph[0] = *ptr;
strwidth += u8g2.getStrWidth(glyph); // accumulate the pixel width
if (*ptr == ' ') lastblank = ptr; // remember where the last blank was
else ++strwidth; // non-blanks will be separated by one additional pixel
if (*ptr == '\n' || // if we found a newline character,
xloc + strwidth > dspwidth) { // or if we ran past the right edge of the display
int starting_xloc = xloc;
// print to just before the last blank, or to just before where we got to
while (msg < (lastblank ? lastblank : ptr)) {
glyph[0] = *msg++;
xloc += u8g2.drawStr(xloc, yloc, glyph); }
strwidth -= xloc - starting_xloc; // account for what we printed
yloc += u8g2.getMaxCharHeight(); // advance to the next line
xloc = 0; lastblank = NULL; } }
while (*msg) { // print any characters left over
glyph[0] = *msg++;
xloc += u8g2.drawStr(xloc, yloc, glyph); } } |
Beta Was this translation helpful? Give feedback.
-
Very nice. I like all the contributions :-) |
Beta Was this translation helpful? Give feedback.
-
thanks for sharing, everyone! |
Beta Was this translation helpful? Give feedback.
-
There is an example for scrolling itself without the wrapping: https://github.com/olikraus/u8g2/blob/master/sys/arduino/u8g2_page_buffer/Shennong/Shennong.ino |
Beta Was this translation helpful? Give feedback.
-
That's correct, mgagic -- my code doesn't scroll if the text overflows the bottom of the screen. That would require a design for the user interface: Does it scroll automatically to the end of the text,, and at what speed? How would the user get back to the top? Should text movement be controlled with events representing external key or button presses? |
Beta Was this translation helpful? Give feedback.
-
Just adding to the pile, this is what I ended up with for wrapping the text around. edit: changed it to correctly handle strings that include multi-byte utf8 characters
|
Beta Was this translation helpful? Give feedback.
-
Very helpful. thank you! |
Beta Was this translation helpful? Give feedback.
-
A great library! But I was disappointed that drawSTR doesn't wrap to multiple lines, so I wrote this function to print a string on multiple lines, breaking it into words at a space where possible. Maybe it can be useful to other folks.
To start at the top of the screen, call it like this: printwords("blah blah blah...", 0, u8g2.getMaxCharHeight());
Beta Was this translation helpful? Give feedback.
All reactions