From 71367fd518acdf3257250cde7a21766b707424d2 Mon Sep 17 00:00:00 2001
From: Scott Lahteine <github@thinkyhead.com>
Date: Sun, 28 May 2017 11:12:12 -0500
Subject: [PATCH] Scrolling status message option

---
 Marlin/Configuration_adv.h                    |  3 ++
 .../Cartesio/Configuration_adv.h              |  3 ++
 .../Felix/Configuration_adv.h                 |  3 ++
 .../FolgerTech-i3-2020/Configuration_adv.h    |  3 ++
 .../Hephestos/Configuration_adv.h             |  3 ++
 .../Hephestos_2/Configuration_adv.h           |  3 ++
 .../K8200/Configuration_adv.h                 |  3 ++
 .../K8400/Configuration_adv.h                 |  3 ++
 .../RigidBot/Configuration_adv.h              |  3 ++
 .../SCARA/Configuration_adv.h                 |  3 ++
 .../TAZ4/Configuration_adv.h                  |  3 ++
 .../TinyBoy2/Configuration_adv.h              |  3 ++
 .../WITBOX/Configuration_adv.h                |  3 ++
 .../FLSUN/auto_calibrate/Configuration_adv.h  |  3 ++
 .../FLSUN/kossel_mini/Configuration_adv.h     |  3 ++
 .../delta/generic/Configuration_adv.h         |  3 ++
 .../delta/kossel_mini/Configuration_adv.h     |  3 ++
 .../delta/kossel_pro/Configuration_adv.h      |  3 ++
 .../delta/kossel_xl/Configuration_adv.h       |  3 ++
 .../gCreate_gMax1.5+/Configuration_adv.h      |  3 ++
 .../makibox/Configuration_adv.h               |  3 ++
 .../tvrrug/Round2/Configuration_adv.h         |  3 ++
 .../wt150/Configuration_adv.h                 |  3 ++
 Marlin/ultralcd.cpp                           | 40 +++++++++++-----
 Marlin/ultralcd_impl_DOGM.h                   | 47 +++++++++++++------
 Marlin/ultralcd_impl_HD44780.h                | 37 ++++++++++-----
 26 files changed, 154 insertions(+), 39 deletions(-)

diff --git a/Marlin/Configuration_adv.h b/Marlin/Configuration_adv.h
index 36291de0d3..d593ed0957 100644
--- a/Marlin/Configuration_adv.h
+++ b/Marlin/Configuration_adv.h
@@ -442,6 +442,9 @@
 // Include a page of printer information in the LCD Main Menu
 //#define LCD_INFO_MENU
 
+// Scroll a longer status message into view
+//#define STATUS_MESSAGE_SCROLLING
+
 // On the Info Screen, display XY with one decimal place when possible
 //#define LCD_DECIMAL_SMALL_XY
 
diff --git a/Marlin/example_configurations/Cartesio/Configuration_adv.h b/Marlin/example_configurations/Cartesio/Configuration_adv.h
index 5a1184c930..a8f4c31665 100644
--- a/Marlin/example_configurations/Cartesio/Configuration_adv.h
+++ b/Marlin/example_configurations/Cartesio/Configuration_adv.h
@@ -442,6 +442,9 @@
 // Include a page of printer information in the LCD Main Menu
 //#define LCD_INFO_MENU
 
+// Scroll a longer status message into view
+//#define STATUS_MESSAGE_SCROLLING
+
 // On the Info Screen, display XY with one decimal place when possible
 //#define LCD_DECIMAL_SMALL_XY
 
diff --git a/Marlin/example_configurations/Felix/Configuration_adv.h b/Marlin/example_configurations/Felix/Configuration_adv.h
index a0daae4e64..3132bf9ff5 100644
--- a/Marlin/example_configurations/Felix/Configuration_adv.h
+++ b/Marlin/example_configurations/Felix/Configuration_adv.h
@@ -442,6 +442,9 @@
 // Include a page of printer information in the LCD Main Menu
 //#define LCD_INFO_MENU
 
+// Scroll a longer status message into view
+//#define STATUS_MESSAGE_SCROLLING
+
 // On the Info Screen, display XY with one decimal place when possible
 //#define LCD_DECIMAL_SMALL_XY
 
diff --git a/Marlin/example_configurations/FolgerTech-i3-2020/Configuration_adv.h b/Marlin/example_configurations/FolgerTech-i3-2020/Configuration_adv.h
index 14488300c7..142cd1d241 100644
--- a/Marlin/example_configurations/FolgerTech-i3-2020/Configuration_adv.h
+++ b/Marlin/example_configurations/FolgerTech-i3-2020/Configuration_adv.h
@@ -442,6 +442,9 @@
 // Include a page of printer information in the LCD Main Menu
 //#define LCD_INFO_MENU
 
+// Scroll a longer status message into view
+//#define STATUS_MESSAGE_SCROLLING
+
 // On the Info Screen, display XY with one decimal place when possible
 //#define LCD_DECIMAL_SMALL_XY
 
diff --git a/Marlin/example_configurations/Hephestos/Configuration_adv.h b/Marlin/example_configurations/Hephestos/Configuration_adv.h
index e165a7fc34..171ab3e4d8 100644
--- a/Marlin/example_configurations/Hephestos/Configuration_adv.h
+++ b/Marlin/example_configurations/Hephestos/Configuration_adv.h
@@ -442,6 +442,9 @@
 // Include a page of printer information in the LCD Main Menu
 //#define LCD_INFO_MENU
 
+// Scroll a longer status message into view
+//#define STATUS_MESSAGE_SCROLLING
+
 // On the Info Screen, display XY with one decimal place when possible
 //#define LCD_DECIMAL_SMALL_XY
 
diff --git a/Marlin/example_configurations/Hephestos_2/Configuration_adv.h b/Marlin/example_configurations/Hephestos_2/Configuration_adv.h
index 7fe59aa6d1..fb7869435d 100644
--- a/Marlin/example_configurations/Hephestos_2/Configuration_adv.h
+++ b/Marlin/example_configurations/Hephestos_2/Configuration_adv.h
@@ -443,6 +443,9 @@
 // Include a page of printer information in the LCD Main Menu
 #define LCD_INFO_MENU
 
+// Scroll a longer status message into view
+//#define STATUS_MESSAGE_SCROLLING
+
 // On the Info Screen, display XY with one decimal place when possible
 #define LCD_DECIMAL_SMALL_XY
 
diff --git a/Marlin/example_configurations/K8200/Configuration_adv.h b/Marlin/example_configurations/K8200/Configuration_adv.h
index 2311850eb0..44aae82fac 100644
--- a/Marlin/example_configurations/K8200/Configuration_adv.h
+++ b/Marlin/example_configurations/K8200/Configuration_adv.h
@@ -455,6 +455,9 @@
 // Include a page of printer information in the LCD Main Menu
 //#define LCD_INFO_MENU
 
+// Scroll a longer status message into view
+//#define STATUS_MESSAGE_SCROLLING
+
 // On the Info Screen, display XY with one decimal place when possible
 //#define LCD_DECIMAL_SMALL_XY
 
diff --git a/Marlin/example_configurations/K8400/Configuration_adv.h b/Marlin/example_configurations/K8400/Configuration_adv.h
index 538c121d8b..a04d83baf8 100644
--- a/Marlin/example_configurations/K8400/Configuration_adv.h
+++ b/Marlin/example_configurations/K8400/Configuration_adv.h
@@ -442,6 +442,9 @@
 // Include a page of printer information in the LCD Main Menu
 //#define LCD_INFO_MENU
 
+// Scroll a longer status message into view
+//#define STATUS_MESSAGE_SCROLLING
+
 // On the Info Screen, display XY with one decimal place when possible
 //#define LCD_DECIMAL_SMALL_XY
 
diff --git a/Marlin/example_configurations/RigidBot/Configuration_adv.h b/Marlin/example_configurations/RigidBot/Configuration_adv.h
index 0df6dfc187..3605da6a74 100644
--- a/Marlin/example_configurations/RigidBot/Configuration_adv.h
+++ b/Marlin/example_configurations/RigidBot/Configuration_adv.h
@@ -442,6 +442,9 @@
 // Include a page of printer information in the LCD Main Menu
 //#define LCD_INFO_MENU
 
+// Scroll a longer status message into view
+//#define STATUS_MESSAGE_SCROLLING
+
 // On the Info Screen, display XY with one decimal place when possible
 //#define LCD_DECIMAL_SMALL_XY
 
diff --git a/Marlin/example_configurations/SCARA/Configuration_adv.h b/Marlin/example_configurations/SCARA/Configuration_adv.h
index 60b47073cb..6bfee737dd 100644
--- a/Marlin/example_configurations/SCARA/Configuration_adv.h
+++ b/Marlin/example_configurations/SCARA/Configuration_adv.h
@@ -442,6 +442,9 @@
 // Include a page of printer information in the LCD Main Menu
 //#define LCD_INFO_MENU
 
+// Scroll a longer status message into view
+//#define STATUS_MESSAGE_SCROLLING
+
 // On the Info Screen, display XY with one decimal place when possible
 //#define LCD_DECIMAL_SMALL_XY
 
diff --git a/Marlin/example_configurations/TAZ4/Configuration_adv.h b/Marlin/example_configurations/TAZ4/Configuration_adv.h
index 7bc66c6d4d..05caf958ef 100644
--- a/Marlin/example_configurations/TAZ4/Configuration_adv.h
+++ b/Marlin/example_configurations/TAZ4/Configuration_adv.h
@@ -442,6 +442,9 @@
 // Include a page of printer information in the LCD Main Menu
 //#define LCD_INFO_MENU
 
+// Scroll a longer status message into view
+//#define STATUS_MESSAGE_SCROLLING
+
 // On the Info Screen, display XY with one decimal place when possible
 //#define LCD_DECIMAL_SMALL_XY
 
diff --git a/Marlin/example_configurations/TinyBoy2/Configuration_adv.h b/Marlin/example_configurations/TinyBoy2/Configuration_adv.h
index 36623187da..488da0e2b2 100644
--- a/Marlin/example_configurations/TinyBoy2/Configuration_adv.h
+++ b/Marlin/example_configurations/TinyBoy2/Configuration_adv.h
@@ -442,6 +442,9 @@
 // Include a page of printer information in the LCD Main Menu
 #define LCD_INFO_MENU
 
+// Scroll a longer status message into view
+//#define STATUS_MESSAGE_SCROLLING
+
 // On the Info Screen, display XY with one decimal place when possible
 //#define LCD_DECIMAL_SMALL_XY
 
diff --git a/Marlin/example_configurations/WITBOX/Configuration_adv.h b/Marlin/example_configurations/WITBOX/Configuration_adv.h
index e165a7fc34..171ab3e4d8 100644
--- a/Marlin/example_configurations/WITBOX/Configuration_adv.h
+++ b/Marlin/example_configurations/WITBOX/Configuration_adv.h
@@ -442,6 +442,9 @@
 // Include a page of printer information in the LCD Main Menu
 //#define LCD_INFO_MENU
 
+// Scroll a longer status message into view
+//#define STATUS_MESSAGE_SCROLLING
+
 // On the Info Screen, display XY with one decimal place when possible
 //#define LCD_DECIMAL_SMALL_XY
 
diff --git a/Marlin/example_configurations/delta/FLSUN/auto_calibrate/Configuration_adv.h b/Marlin/example_configurations/delta/FLSUN/auto_calibrate/Configuration_adv.h
index 62eaf358bb..eb44f9e09f 100644
--- a/Marlin/example_configurations/delta/FLSUN/auto_calibrate/Configuration_adv.h
+++ b/Marlin/example_configurations/delta/FLSUN/auto_calibrate/Configuration_adv.h
@@ -444,6 +444,9 @@
 // Include a page of printer information in the LCD Main Menu
 //#define LCD_INFO_MENU
 
+// Scroll a longer status message into view
+//#define STATUS_MESSAGE_SCROLLING
+
 // On the Info Screen, display XY with one decimal place when possible
 //#define LCD_DECIMAL_SMALL_XY
 
diff --git a/Marlin/example_configurations/delta/FLSUN/kossel_mini/Configuration_adv.h b/Marlin/example_configurations/delta/FLSUN/kossel_mini/Configuration_adv.h
index 6ad9e985fa..6eed64c6fa 100644
--- a/Marlin/example_configurations/delta/FLSUN/kossel_mini/Configuration_adv.h
+++ b/Marlin/example_configurations/delta/FLSUN/kossel_mini/Configuration_adv.h
@@ -444,6 +444,9 @@
 // Include a page of printer information in the LCD Main Menu
 //#define LCD_INFO_MENU
 
+// Scroll a longer status message into view
+//#define STATUS_MESSAGE_SCROLLING
+
 // On the Info Screen, display XY with one decimal place when possible
 //#define LCD_DECIMAL_SMALL_XY
 
diff --git a/Marlin/example_configurations/delta/generic/Configuration_adv.h b/Marlin/example_configurations/delta/generic/Configuration_adv.h
index 2664b31be0..6f45736b65 100644
--- a/Marlin/example_configurations/delta/generic/Configuration_adv.h
+++ b/Marlin/example_configurations/delta/generic/Configuration_adv.h
@@ -444,6 +444,9 @@
 // Include a page of printer information in the LCD Main Menu
 //#define LCD_INFO_MENU
 
+// Scroll a longer status message into view
+//#define STATUS_MESSAGE_SCROLLING
+
 // On the Info Screen, display XY with one decimal place when possible
 //#define LCD_DECIMAL_SMALL_XY
 
diff --git a/Marlin/example_configurations/delta/kossel_mini/Configuration_adv.h b/Marlin/example_configurations/delta/kossel_mini/Configuration_adv.h
index 2664b31be0..6f45736b65 100644
--- a/Marlin/example_configurations/delta/kossel_mini/Configuration_adv.h
+++ b/Marlin/example_configurations/delta/kossel_mini/Configuration_adv.h
@@ -444,6 +444,9 @@
 // Include a page of printer information in the LCD Main Menu
 //#define LCD_INFO_MENU
 
+// Scroll a longer status message into view
+//#define STATUS_MESSAGE_SCROLLING
+
 // On the Info Screen, display XY with one decimal place when possible
 //#define LCD_DECIMAL_SMALL_XY
 
diff --git a/Marlin/example_configurations/delta/kossel_pro/Configuration_adv.h b/Marlin/example_configurations/delta/kossel_pro/Configuration_adv.h
index e7142cf161..8f7ae5496c 100644
--- a/Marlin/example_configurations/delta/kossel_pro/Configuration_adv.h
+++ b/Marlin/example_configurations/delta/kossel_pro/Configuration_adv.h
@@ -449,6 +449,9 @@
 // Include a page of printer information in the LCD Main Menu
 //#define LCD_INFO_MENU
 
+// Scroll a longer status message into view
+//#define STATUS_MESSAGE_SCROLLING
+
 // On the Info Screen, display XY with one decimal place when possible
 //#define LCD_DECIMAL_SMALL_XY
 
diff --git a/Marlin/example_configurations/delta/kossel_xl/Configuration_adv.h b/Marlin/example_configurations/delta/kossel_xl/Configuration_adv.h
index e1fe86a0ed..779dbe9a91 100644
--- a/Marlin/example_configurations/delta/kossel_xl/Configuration_adv.h
+++ b/Marlin/example_configurations/delta/kossel_xl/Configuration_adv.h
@@ -444,6 +444,9 @@
 // Include a page of printer information in the LCD Main Menu
 //#define LCD_INFO_MENU
 
+// Scroll a longer status message into view
+//#define STATUS_MESSAGE_SCROLLING
+
 // On the Info Screen, display XY with one decimal place when possible
 //#define LCD_DECIMAL_SMALL_XY
 
diff --git a/Marlin/example_configurations/gCreate_gMax1.5+/Configuration_adv.h b/Marlin/example_configurations/gCreate_gMax1.5+/Configuration_adv.h
index 59b43ccb6f..71a3d90e04 100644
--- a/Marlin/example_configurations/gCreate_gMax1.5+/Configuration_adv.h
+++ b/Marlin/example_configurations/gCreate_gMax1.5+/Configuration_adv.h
@@ -442,6 +442,9 @@
 // Include a page of printer information in the LCD Main Menu
 //#define LCD_INFO_MENU
 
+// Scroll a longer status message into view
+//#define STATUS_MESSAGE_SCROLLING
+
 // On the Info Screen, display XY with one decimal place when possible
 //#define LCD_DECIMAL_SMALL_XY
 
diff --git a/Marlin/example_configurations/makibox/Configuration_adv.h b/Marlin/example_configurations/makibox/Configuration_adv.h
index 5483576d97..9aa5607940 100644
--- a/Marlin/example_configurations/makibox/Configuration_adv.h
+++ b/Marlin/example_configurations/makibox/Configuration_adv.h
@@ -442,6 +442,9 @@
 // Include a page of printer information in the LCD Main Menu
 //#define LCD_INFO_MENU
 
+// Scroll a longer status message into view
+//#define STATUS_MESSAGE_SCROLLING
+
 // On the Info Screen, display XY with one decimal place when possible
 //#define LCD_DECIMAL_SMALL_XY
 
diff --git a/Marlin/example_configurations/tvrrug/Round2/Configuration_adv.h b/Marlin/example_configurations/tvrrug/Round2/Configuration_adv.h
index 8dcc348ab2..660d479b52 100644
--- a/Marlin/example_configurations/tvrrug/Round2/Configuration_adv.h
+++ b/Marlin/example_configurations/tvrrug/Round2/Configuration_adv.h
@@ -442,6 +442,9 @@
 // Include a page of printer information in the LCD Main Menu
 //#define LCD_INFO_MENU
 
+// Scroll a longer status message into view
+//#define STATUS_MESSAGE_SCROLLING
+
 // On the Info Screen, display XY with one decimal place when possible
 //#define LCD_DECIMAL_SMALL_XY
 
diff --git a/Marlin/example_configurations/wt150/Configuration_adv.h b/Marlin/example_configurations/wt150/Configuration_adv.h
index 700c5227fd..bf586bdba0 100644
--- a/Marlin/example_configurations/wt150/Configuration_adv.h
+++ b/Marlin/example_configurations/wt150/Configuration_adv.h
@@ -442,6 +442,9 @@
 // Include a page of printer information in the LCD Main Menu
 #define LCD_INFO_MENU
 
+// Scroll a longer status message into view
+//#define STATUS_MESSAGE_SCROLLING
+
 // On the Info Screen, display XY with one decimal place when possible
 //#define LCD_DECIMAL_SMALL_XY
 
diff --git a/Marlin/ultralcd.cpp b/Marlin/ultralcd.cpp
index 32d47419db..6cacb3ae6c 100755
--- a/Marlin/ultralcd.cpp
+++ b/Marlin/ultralcd.cpp
@@ -60,6 +60,9 @@ int lcd_preheat_hotend_temp[2], lcd_preheat_bed_temp[2], lcd_preheat_fan_speed[2
 
 uint8_t lcd_status_message_level;
 char lcd_status_message[3 * (LCD_WIDTH) + 1] = WELCOME_MSG; // worst case is kana with up to 3*LCD_WIDTH+1
+#if ENABLED(STATUS_MESSAGE_SCROLLING)
+  uint8_t status_scroll_pos = 0;
+#endif
 
 #if ENABLED(DOGLCD)
   #include "ultralcd_impl_DOGM.h"
@@ -3961,22 +3964,29 @@ void lcd_update() {
   } // ELAPSED(ms, next_lcd_update_ms)
 }
 
-void set_utf_strlen(char* s, uint8_t n) {
-  uint8_t i = 0, j = 0;
-  while (s[i] && (j < n)) {
-    #if ENABLED(MAPPER_NON)
-      j++;
-    #else
-      if ((s[i] & 0xC0u) != 0x80u) j++;
-    #endif
-    i++;
+#if DISABLED(STATUS_MESSAGE_SCROLLING)
+
+  void set_utf_strlen(char* s, uint8_t n) {
+    uint8_t i = 0, j = 0;
+    while (s[i] && (j < n)) {
+      #if ENABLED(MAPPER_NON)
+        j++;
+      #else
+        if ((s[i] & 0xC0u) != 0x80u) j++;
+      #endif
+      i++;
+    }
+    while (j++ < n) s[i++] = ' ';
+    s[i] = '\0';
   }
-  while (j++ < n) s[i++] = ' ';
-  s[i] = '\0';
-}
+
+#endif // !STATUS_MESSAGE_SCROLLING
 
 void lcd_finishstatus(bool persist=false) {
-  set_utf_strlen(lcd_status_message, LCD_WIDTH);
+  #if DISABLED(STATUS_MESSAGE_SCROLLING)
+    set_utf_strlen(lcd_status_message, LCD_WIDTH);
+  #endif
+
   #if !(ENABLED(LCD_PROGRESS_BAR) && (PROGRESS_MSG_EXPIRE > 0))
     UNUSED(persist);
   #endif
@@ -3992,6 +4002,10 @@ void lcd_finishstatus(bool persist=false) {
   #if ENABLED(FILAMENT_LCD_DISPLAY) && ENABLED(SDSUPPORT)
     previous_lcd_status_ms = millis();  //get status message to show up for a while
   #endif
+
+  #if ENABLED(STATUS_MESSAGE_SCROLLING)
+    status_scroll_pos = 0;
+  #endif
 }
 
 #if ENABLED(LCD_PROGRESS_BAR) && PROGRESS_MSG_EXPIRE > 0
diff --git a/Marlin/ultralcd_impl_DOGM.h b/Marlin/ultralcd_impl_DOGM.h
index c0049a4c75..ac6fedabba 100644
--- a/Marlin/ultralcd_impl_DOGM.h
+++ b/Marlin/ultralcd_impl_DOGM.h
@@ -234,13 +234,24 @@ char lcd_print_and_count(const char c) {
   else return charset_mapper(c);
 }
 
-void lcd_print(const char* const str) {
-  for (uint8_t i = 0; char c = str[i]; ++i) lcd_print(c);
+/**
+ * Core LCD printing functions
+ * On DOGM all strings go through a filter for utf
+ * But only use lcd_print_utf and lcd_printPGM_utf for translated text
+ */
+void lcd_print(const char* const str) { for (uint8_t i = 0; char c = str[i]; ++i) lcd_print(c); }
+void lcd_printPGM(const char* str) { for (; char c = pgm_read_byte(str); ++str) lcd_print(c); }
+
+void lcd_print_utf(const char* const str, const uint8_t maxLength=LCD_WIDTH) {
+  char c;
+  for (uint8_t i = 0, n = maxLength; n && (c = str[i]); ++i)
+    n -= charset_mapper(c);
 }
 
-/* Arduino < 1.0.0 is missing a function to print PROGMEM strings, so we need to implement our own */
-void lcd_printPGM(const char* str) {
-  for (; char c = pgm_read_byte(str); ++str) lcd_print(c);
+void lcd_printPGM_utf(const char* str, const uint8_t maxLength=LCD_WIDTH) {
+  char c;
+  for (uint8_t i = 0, n = maxLength; n && (c = str[i]); ++i)
+    n -= charset_mapper(c);
 }
 
 // Initialize or re-initialize the LCD
@@ -320,7 +331,7 @@ static void lcd_implementation_init() {
 void lcd_kill_screen() {
   lcd_setFont(FONT_MENU);
   u8g.setPrintPos(0, u8g.getHeight()/4*1);
-  lcd_print(lcd_status_message);
+  lcd_print_utf(lcd_status_message);
   u8g.setPrintPos(0, u8g.getHeight()/4*2);
   lcd_printPGM(PSTR(MSG_HALTED));
   u8g.setPrintPos(0, u8g.getHeight()/4*3);
@@ -395,6 +406,20 @@ FORCE_INLINE void _draw_axis_label(const AxisEnum axis, const char* const pstr,
   }
 }
 
+inline void lcd_implementation_status_message() {
+  #if ENABLED(STATUS_MESSAGE_SCROLLING)
+    lcd_print_utf(lcd_status_message + status_scroll_pos);
+    const uint8_t slen = lcd_strlen(lcd_status_message);
+    if (slen > LCD_WIDTH) {
+      // Skip any non-printing bytes
+      while (!charset_mapper(lcd_status_message[status_scroll_pos])) ++status_scroll_pos;
+      if (++status_scroll_pos > slen - LCD_WIDTH) status_scroll_pos = 0;
+    }
+  #else
+    lcd_print_utf(lcd_status_message);
+  #endif
+}
+
 //#define DOGM_SD_PERCENT
 
 static void lcd_implementation_status_screen() {
@@ -645,10 +670,7 @@ static void lcd_implementation_status_screen() {
 
     #if ENABLED(FILAMENT_LCD_DISPLAY) && ENABLED(SDSUPPORT)
       if (PENDING(millis(), previous_lcd_status_ms + 5000UL)) {  //Display both Status message line and Filament display on the last line
-        const char *str = lcd_status_message;
-        uint8_t i = LCD_WIDTH;
-        char c;
-        while (i-- && (c = *str++)) lcd_print(c);
+        lcd_implementation_status_message();
       }
       else {
         lcd_printPGM(PSTR(LCD_STR_FILAM_DIA));
@@ -660,10 +682,7 @@ static void lcd_implementation_status_screen() {
         u8g.print('%');
       }
     #else
-      const char *str = lcd_status_message;
-      uint8_t i = LCD_WIDTH;
-      char c;
-      while (i-- && (c = *str++)) lcd_print(c);
+      lcd_implementation_status_message();
     #endif
   }
 }
diff --git a/Marlin/ultralcd_impl_HD44780.h b/Marlin/ultralcd_impl_HD44780.h
index 1f7683387e..b735baa8fc 100644
--- a/Marlin/ultralcd_impl_HD44780.h
+++ b/Marlin/ultralcd_impl_HD44780.h
@@ -380,16 +380,22 @@ static void lcd_implementation_init(
 
 void lcd_implementation_clear() { lcd.clear(); }
 
-/* Arduino < 1.0.0 is missing a function to print PROGMEM strings, so we need to implement our own */
-void lcd_printPGM(const char *str) {
-  for (; char c = pgm_read_byte(str); ++str) charset_mapper(c);
-}
+void lcd_print(const char c) { charset_mapper(c); }
+
+void lcd_print(const char * const str) { for (uint8_t i = 0; char c = str[i]; ++i) lcd.print(c); }
+void lcd_printPGM(const char* str) { for (; char c = pgm_read_byte(str); ++str) lcd.print(c); }
 
-void lcd_print(const char* const str) {
-  for (uint8_t i = 0; const char c = str[i]; ++i) charset_mapper(c);
+void lcd_print_utf(const char * const str, const uint8_t maxLength=LCD_WIDTH) {
+  char c;
+  for (uint8_t i = 0, n = maxLength; n && (c = str[i]); ++i)
+    n -= charset_mapper(c);
 }
 
-void lcd_print(const char c) { charset_mapper(c); }
+void lcd_printPGM_utf(const char* str, const uint8_t maxLength=LCD_WIDTH) {
+  char c;
+  for (uint8_t i = 0, n = maxLength; n && (c = str[i]); ++i)
+    n -= charset_mapper(c);
+}
 
 #if ENABLED(SHOW_BOOTSCREEN)
 
@@ -545,7 +551,7 @@ void lcd_print(const char c) { charset_mapper(c); }
 
 void lcd_kill_screen() {
   lcd.setCursor(0, 0);
-  lcd_print(lcd_status_message);
+  lcd_print_utf(lcd_status_message);
   #if LCD_HEIGHT < 4
     lcd.setCursor(0, 2);
   #else
@@ -818,10 +824,17 @@ static void lcd_implementation_status_screen() {
 
   #endif // FILAMENT_LCD_DISPLAY && SDSUPPORT
 
-  const char *str = lcd_status_message;
-  uint8_t i = LCD_WIDTH;
-  char c;
-  while (i-- && (c = *str++)) lcd_print(c);
+  #if ENABLED(STATUS_MESSAGE_SCROLLING)
+    lcd_print_utf(lcd_status_message + status_scroll_pos);
+    const uint8_t slen = lcd_strlen(lcd_status_message);
+    if (slen > LCD_WIDTH) {
+      // Skip any non-printing bytes
+      while (!charset_mapper(lcd_status_message[status_scroll_pos])) ++status_scroll_pos;
+      if (++status_scroll_pos > slen - LCD_WIDTH) status_scroll_pos = 0;
+    }
+  #else
+    lcd_print_utf(lcd_status_message);
+  #endif
 }
 
 #if ENABLED(ULTIPANEL)
-- 
GitLab