From f5265e4cec6f46680c2c5e5c9ed3c34c2510b592 Mon Sep 17 00:00:00 2001
From: Fabrice Weinberg <Fabrice@weinberg.me>
Date: Sun, 10 Jan 2016 20:11:41 +0100
Subject: [PATCH] Support line breaks in string fix #15

---
 SSD1306.cpp | 33 ++++++++++++++++++++-------------
 SSD1306.h   |  1 +
 2 files changed, 21 insertions(+), 13 deletions(-)

diff --git a/SSD1306.cpp b/SSD1306.cpp
index d046338..2d13709 100644
--- a/SSD1306.cpp
+++ b/SSD1306.cpp
@@ -234,17 +234,13 @@ void SSD1306::drawXbm(int16_t xMove, int16_t yMove, int16_t width, int16_t heigh
   }
 }
 
-void SSD1306::drawString(int16_t xMove, int16_t yMove, String t) {
-  // char* text must be freed!
-  char* text = utf8ascii(t);
-
+void SSD1306::drawStringInternal(int16_t xMove, int16_t yMove, char* text, uint16_t textLength, uint16_t textWidth) {
   uint8_t textHeight       = pgm_read_byte(fontData + HEIGHT_POS);
   uint8_t firstChar        = pgm_read_byte(fontData + FIRST_CHAR_POS);
   uint16_t sizeOfJumpTable = pgm_read_byte(fontData + CHAR_NUM_POS)  * JUMPTABLE_BYTES;
 
-  uint8_t textWidth        = getStringWidth(text);
-
   uint8_t cursorX         = 0;
+  uint8_t cursorY         = 0;
 
   switch (textAlignment) {
     case TEXT_ALIGN_CENTER_BOTH:
@@ -259,12 +255,13 @@ void SSD1306::drawString(int16_t xMove, int16_t yMove, String t) {
   }
 
   // Don't draw anything if it is not on the screen.
-  if (xMove + textWidth  < 0 || xMove > DISPLAY_WIDTH ) {free(text); return;}
-  if (yMove + textHeight < 0 || yMove > DISPLAY_HEIGHT) {free(text); return;}
+  if (xMove + textWidth  < 0 || xMove > DISPLAY_WIDTH ) {return;}
+  if (yMove + textHeight < 0 || yMove > DISPLAY_HEIGHT) {return;}
 
-  uint16_t length = strlen(text);
+  for (uint16_t j = 0; j < textLength; j++) {
+    int16_t xPos = xMove + cursorX;
+    int16_t yPos = yMove + cursorY;
 
-  for (uint16_t j = 0; j < length; j++) {
     byte code = text[j];
     if (code >= firstChar) {
       byte charCode = code - firstChar;
@@ -279,13 +276,24 @@ void SSD1306::drawString(int16_t xMove, int16_t yMove, String t) {
       if (msbJumpToChar != 255 && lsbJumpToChar != 255) {
         // Get the position of the char data
         uint16_t charDataPosition = JUMPTABLE_START + sizeOfJumpTable + ((msbJumpToChar << 8) + lsbJumpToChar);
-        drawInternal(xMove + cursorX, yMove, currentCharWidth, textHeight, fontData, charDataPosition, charByteSize);
+        drawInternal(xPos, yPos, currentCharWidth, textHeight, fontData, charDataPosition, charByteSize);
       }
 
       cursorX += currentCharWidth;
+    } else if (code == 10) {
+      // Support line breaks (\n) in String
+      cursorY += pgm_read_byte(fontData + HEIGHT_POS);
+      cursorX = 0;
     }
   }
+}
+
 
+void SSD1306::drawString(int16_t xMove, int16_t yMove, String strUser) {
+  // char* text must be freed!
+  char* text = utf8ascii(strUser);
+  uint16_t length = strlen(text);
+  drawStringInternal(xMove, yMove, text, length, getStringWidth(text, length));
   free(text);
 }
 
@@ -314,10 +322,9 @@ void SSD1306::drawStringMaxWidth(int16_t x, int16_t y, int16_t maxLineWidth, Str
   drawString(x, y + lineNumber * lineHeight, text.substring(startsAt));
 }
 
-uint16_t SSD1306::getStringWidth(const char* text) {
+uint16_t SSD1306::getStringWidth(const char* text, uint16_t length) {
   uint16_t stringWidth = 0;
   uint16_t firstChar        = pgm_read_byte(fontData + FIRST_CHAR_POS);
-  uint16_t length           = strlen(text);
   while (length--) {
     stringWidth += pgm_read_byte(fontData + JUMPTABLE_START + (text[length] - firstChar) * JUMPTABLE_BYTES + JUMPTABLE_WIDTH);
   }
diff --git a/SSD1306.h b/SSD1306.h
index ab24c0d..1878f88 100644
--- a/SSD1306.h
+++ b/SSD1306.h
@@ -134,6 +134,7 @@ class SSD1306 {
 
     void drawInternal(int16_t xMove, int16_t yMove, int16_t width, int16_t height, const char *data, uint16_t offset, uint16_t bytesInData);
 
+    void drawStringInternal(int16_t xMove, int16_t yMove, char* text, uint16_t textLength, uint16_t textWidth);
   public:
 
     // Create the display object connected to pin sda and sdc
-- 
GitLab