diff --git a/Marlin/ultralcd.cpp b/Marlin/ultralcd.cpp
index f6ff6eb757..0e54aeb2db 100755
--- a/Marlin/ultralcd.cpp
+++ b/Marlin/ultralcd.cpp
@@ -28,6 +28,7 @@
 #include "temperature.h"
 #include "stepper.h"
 #include "configuration_store.h"
+#include "utility.h"
 
 #if ENABLED(PRINTCOUNTER)
   #include "printcounter.h"
@@ -1878,6 +1879,7 @@ void kill_screen(const char* lcd_msg) {
    *
    */
   #if ENABLED(FWRETRACT)
+
     static void lcd_control_retract_menu() {
       START_MENU();
       MENU_ITEM(back, MSG_CONTROL);
@@ -1895,6 +1897,7 @@ void kill_screen(const char* lcd_msg) {
       MENU_ITEM_EDIT(float3, MSG_CONTROL_RETRACT_RECOVERF, &retract_recover_feedrate_mm_s, 1, 999);
       END_MENU();
     }
+
   #endif // FWRETRACT
 
   #if ENABLED(SDSUPPORT)
@@ -2582,12 +2585,12 @@ void lcd_update() {
       lcd_implementation_update_indicators();
     #endif
 
-    #if ENABLED(LCD_HAS_SLOW_BUTTONS)
-      slow_buttons = lcd_implementation_read_slow_buttons(); // buttons which take too long to read in interrupt context
-    #endif
-
     #if ENABLED(ULTIPANEL)
 
+      #if ENABLED(LCD_HAS_SLOW_BUTTONS)
+        slow_buttons = lcd_implementation_read_slow_buttons(); // buttons which take too long to read in interrupt context
+      #endif
+
       #if ENABLED(REPRAPWORLD_KEYPAD)
 
         static uint8_t keypad_debounce = 0;
@@ -2936,252 +2939,4 @@ void lcd_reset_alert_level() { lcd_status_message_level = 0; }
 
 #endif // ULTIPANEL
 
-/*********************************/
-/** Number to string conversion **/
-/*********************************/
-
-#define DIGIT(n) ('0' + (n))
-#define DIGIMOD(n) DIGIT((n) % 10)
-
-char conv[8];
-
-// Convert float to rj string with 123 or -12 format
-char *ftostr3(const float& x) { return itostr3((int)x); }
-
-// Convert float to rj string with _123, -123, _-12, or __-1 format
-char *ftostr4sign(const float& x) { return itostr4sign((int)x); }
-
-// Convert unsigned int to string with 12 format
-char* itostr2(const uint8_t& x) {
-  int xx = x;
-  conv[0] = DIGIMOD(xx / 10);
-  conv[1] = DIGIMOD(xx);
-  conv[2] = '\0';
-  return conv;
-}
-
-// Convert float to string with +123.4 / -123.4 format
-char* ftostr41sign(const float& x) {
-  int xx = int(abs(x * 10)) % 10000;
-  conv[0] = x >= 0 ? '+' : '-';
-  conv[1] = DIGIMOD(xx / 1000);
-  conv[2] = DIGIMOD(xx / 100);
-  conv[3] = DIGIMOD(xx / 10);
-  conv[4] = '.';
-  conv[5] = DIGIMOD(xx);
-  conv[6] = '\0';
-  return conv;
-}
-
-// Convert signed float to string with 023.45 / -23.45 format
-char *ftostr32(const float& x) {
-  long xx = abs(x * 100);
-  conv[0] = x >= 0 ? DIGIMOD(xx / 10000) : '-';
-  conv[1] = DIGIMOD(xx / 1000);
-  conv[2] = DIGIMOD(xx / 100);
-  conv[3] = '.';
-  conv[4] = DIGIMOD(xx / 10);
-  conv[5] = DIGIMOD(xx);
-  conv[6] = '\0';
-  return conv;
-}
-
-// Convert signed float to string (6 digit) with -1.234 / _0.000 / +1.234 format
-char* ftostr43sign(const float& x, char plus/*=' '*/) {
-  long xx = x * 1000;
-  if (xx == 0)
-    conv[0] = ' ';
-  else if (xx > 0)
-    conv[0] = plus;
-  else {
-    xx = -xx;
-    conv[0] = '-';
-  }
-  conv[1] = DIGIMOD(xx / 1000);
-  conv[2] = '.';
-  conv[3] = DIGIMOD(xx / 100);
-  conv[4] = DIGIMOD(xx / 10);
-  conv[5] = DIGIMOD(xx);
-  conv[6] = '\0';
-  return conv;
-}
-
-// Convert unsigned float to string with 1.23 format
-char* ftostr12ns(const float& x) {
-  long xx = x * 100;
-  xx = abs(xx);
-  conv[0] = DIGIMOD(xx / 100);
-  conv[1] = '.';
-  conv[2] = DIGIMOD(xx / 10);
-  conv[3] = DIGIMOD(xx);
-  conv[4] = '\0';
-  return conv;
-}
-
-// Convert signed int to lj string with +012 / -012 format
-char* itostr3sign(const int& x) {
-  int xx;
-  if (x >= 0) {
-    conv[0] = '+';
-    xx = x;
-  }
-  else {
-    conv[0] = '-';
-    xx = -x;
-  }
-  conv[1] = DIGIMOD(xx / 100);
-  conv[2] = DIGIMOD(xx / 10);
-  conv[3] = DIGIMOD(xx);
-  conv[4] = '.';
-  conv[5] = '0';
-  conv[6] = '\0';
-  return conv;
-}
-
-// Convert signed int to rj string with 123 or -12 format
-char* itostr3(const int& x) {
-  int xx = x;
-  if (xx < 0) {
-    conv[0] = '-';
-    xx = -xx;
-  }
-  else
-    conv[0] = xx >= 100 ? DIGIMOD(xx / 100) : ' ';
-
-  conv[1] = xx >= 10 ? DIGIMOD(xx / 10) : ' ';
-  conv[2] = DIGIMOD(xx);
-  conv[3] = '\0';
-  return conv;
-}
-
-// Convert unsigned int to lj string with 123 format
-char* itostr3left(const int& xx) {
-  if (xx >= 100) {
-    conv[0] = DIGIMOD(xx / 100);
-    conv[1] = DIGIMOD(xx / 10);
-    conv[2] = DIGIMOD(xx);
-    conv[3] = '\0';
-  }
-  else if (xx >= 10) {
-    conv[0] = DIGIMOD(xx / 10);
-    conv[1] = DIGIMOD(xx);
-    conv[2] = '\0';
-  }
-  else {
-    conv[0] = DIGIMOD(xx);
-    conv[1] = '\0';
-  }
-  return conv;
-}
-
-// Convert signed int to rj string with _123, -123, _-12, or __-1 format
-char *itostr4sign(const int& x) {
-  int xx = abs(x);
-  int sign = 0;
-  if (xx >= 100) {
-    conv[1] = DIGIMOD(xx / 100);
-    conv[2] = DIGIMOD(xx / 10);
-  }
-  else if (xx >= 10) {
-    conv[0] = ' ';
-    sign = 1;
-    conv[2] = DIGIMOD(xx / 10);
-  }
-  else {
-    conv[0] = ' ';
-    conv[1] = ' ';
-    sign = 2;
-  }
-  conv[sign] = x < 0 ? '-' : ' ';
-  conv[3] = DIGIMOD(xx);
-  conv[4] = '\0';
-  return conv;
-}
-
-// Convert unsigned float to rj string with 12345 format
-char* ftostr5rj(const float& x) {
-  long xx = abs(x);
-  conv[0] = xx >= 10000 ? DIGIMOD(xx / 10000) : ' ';
-  conv[1] = xx >= 1000 ? DIGIMOD(xx / 1000) : ' ';
-  conv[2] = xx >= 100 ? DIGIMOD(xx / 100) : ' ';
-  conv[3] = xx >= 10 ? DIGIMOD(xx / 10) : ' ';
-  conv[4] = DIGIMOD(xx);
-  conv[5] = '\0';
-  return conv;
-}
-
-// Convert signed float to string with +1234.5 format
-char* ftostr51sign(const float& x) {
-  long xx = abs(x * 10);
-  conv[0] = (x >= 0) ? '+' : '-';
-  conv[1] = DIGIMOD(xx / 10000);
-  conv[2] = DIGIMOD(xx / 1000);
-  conv[3] = DIGIMOD(xx / 100);
-  conv[4] = DIGIMOD(xx / 10);
-  conv[5] = '.';
-  conv[6] = DIGIMOD(xx);
-  conv[7] = '\0';
-  return conv;
-}
-
-// Convert signed float to string with +123.45 format
-char* ftostr52sign(const float& x) {
-  long xx = abs(x * 100);
-  conv[0] = (x >= 0) ? '+' : '-';
-  conv[1] = DIGIMOD(xx / 10000);
-  conv[2] = DIGIMOD(xx / 1000);
-  conv[3] = DIGIMOD(xx / 100);
-  conv[4] = '.';
-  conv[5] = DIGIMOD(xx / 10);
-  conv[6] = DIGIMOD(xx);
-  conv[7] = '\0';
-  return conv;
-}
-
-// Convert signed float to space-padded string with -_23.4_ format
-char* ftostr52sp(const float& x) {
-  long xx = x * 100;
-  uint8_t dig;
-  if (xx < 0) { // negative val = -_0
-    xx = -xx;
-    conv[0] = '-';
-    dig = (xx / 1000) % 10;
-    conv[1] = dig ? DIGIT(dig) : ' ';
-  }
-  else { // positive val = __0
-    dig = (xx / 10000) % 10;
-    if (dig) {
-      conv[0] = DIGIT(dig);
-      conv[1] = DIGIMOD(xx / 1000);
-    }
-    else {
-      conv[0] = ' ';
-      dig = (xx / 1000) % 10;
-      conv[1] = dig ? DIGIT(dig) : ' ';
-    }
-  }
-
-  conv[2] = DIGIMOD(xx / 100); // lsd always
-
-  dig = xx % 10;
-  if (dig) { // 2 decimal places
-    conv[5] = DIGIT(dig);
-    conv[4] = DIGIMOD(xx / 10);
-    conv[3] = '.';
-  }
-  else { // 1 or 0 decimal place
-    dig = (xx / 10) % 10;
-    if (dig) {
-      conv[4] = DIGIT(dig);
-      conv[3] = '.';
-    }
-    else {
-      conv[3] = conv[4] = ' ';
-    }
-    conv[5] = ' ';
-  }
-  conv[6] = '\0';
-  return conv;
-}
-
 #endif // ULTRA_LCD
diff --git a/Marlin/ultralcd.h b/Marlin/ultralcd.h
index 4cc8334ec9..3652da0057 100644
--- a/Marlin/ultralcd.h
+++ b/Marlin/ultralcd.h
@@ -167,21 +167,4 @@
 
 #endif //ULTRA_LCD
 
-char* itostr2(const uint8_t& x);
-char* itostr3sign(const int& x);
-char* itostr3(const int& x);
-char* itostr3left(const int& x);
-char* itostr4sign(const int& x);
-
-char* ftostr3(const float& x);
-char* ftostr4sign(const float& x);
-char* ftostr41sign(const float& x);
-char* ftostr32(const float& x);
-char* ftostr43sign(const float& x, char plus=' ');
-char* ftostr12ns(const float& x);
-char* ftostr5rj(const float& x);
-char* ftostr51sign(const float& x);
-char* ftostr52sign(const float& x);
-char* ftostr52sp(const float& x); // remove zero-padding from ftostr32
-
 #endif //ULTRALCD_H
diff --git a/Marlin/ultralcd_impl_DOGM.h b/Marlin/ultralcd_impl_DOGM.h
index c5353a605f..8defa94801 100644
--- a/Marlin/ultralcd_impl_DOGM.h
+++ b/Marlin/ultralcd_impl_DOGM.h
@@ -45,6 +45,7 @@
 #include "ultralcd.h"
 #include "ultralcd_st7920_u8glib_rrd.h"
 #include "dogm_bitmaps.h"
+#include "utility.h"
 #include "duration_t.h"
 
 #include <U8glib.h>
@@ -200,26 +201,20 @@ char lcd_print(char c) {
 }
 
 char lcd_print(const char* str) {
-  char c;
   int i = 0;
-  char n = 0;
-  while ((c = str[i++])) {
-    n += lcd_print(c);
-  }
+  char c, n = 0;
+  while ((c = str[i++])) n += lcd_print(c);
   return n;
 }
 
-/* Arduino < 1.0.0 is missing a function to print PROGMEM strings, so we need to implement our own */
+// Needed for Arduino < 1.0.0
 char lcd_printPGM(const char* str) {
-  char c;
-  char n = 0;
-  while ((c = pgm_read_byte(str++))) {
-    n += lcd_print(c);
-  }
+  char c, n = 0;
+  while ((c = pgm_read_byte(str++))) n += lcd_print(c);
   return n;
 }
 
-/* Warning: This function is called from interrupt context */
+// Initialize or re-initializw the LCD
 static void lcd_implementation_init() {
 
   #if defined(LCD_PIN_BL) && LCD_PIN_BL > -1 // Enable LCD backlight
@@ -290,6 +285,7 @@ static void lcd_implementation_init() {
   #endif // SHOW_BOOTSCREEN
 }
 
+// The kill screen is displayed for unrecoverable conditions
 void lcd_kill_screen() {
   lcd_setFont(FONT_MENU);
   u8g.setPrintPos(0, u8g.getHeight()/4*1);
@@ -302,6 +298,10 @@ void lcd_kill_screen() {
 
 static void lcd_implementation_clear() { } // Automatically cleared by Picture Loop
 
+//
+// Status Screen
+//
+
 FORCE_INLINE void _draw_centered_temp(int temp, int x, int y) {
   int degsize = 6 * (temp >= 100 ? 3 : temp >= 10 ? 2 : 1); // number's pixel width
   u8g.setPrintPos(x - (18 - degsize) / 2, y); // move left if shorter
@@ -472,164 +472,173 @@ static void lcd_implementation_status_screen() {
   #endif
 }
 
-static void lcd_implementation_mark_as_selected(uint8_t row, bool isSelected) {
-  if (isSelected) {
-    u8g.setColorIndex(1);  // black on white
-    u8g.drawBox(0, row * (DOG_CHAR_HEIGHT) + 3 - (TALL_FONT_CORRECTION), LCD_PIXEL_WIDTH, DOG_CHAR_HEIGHT);
-    u8g.setColorIndex(0);  // following text must be white on black
-  }
-  else {
-    u8g.setColorIndex(1); // unmarked text is black on white
-  }
-  u8g.setPrintPos((START_COL) * (DOG_CHAR_WIDTH), (row + 1) * (DOG_CHAR_HEIGHT));
-}
+#if ENABLED(ULTIPANEL)
 
-#if ENABLED(LCD_INFO_MENU) || ENABLED(FILAMENT_CHANGE_FEATURE)
-
-  static void lcd_implementation_drawmenu_static(uint8_t row, const char* pstr, bool center=true, bool invert=false, const char* valstr=NULL) {
-
-    lcd_implementation_mark_as_selected(row, invert);
-
-    char c;
-    int8_t n = LCD_WIDTH - (START_COL);
-
-    if (center && !valstr) {
-      int8_t pad = (LCD_WIDTH - lcd_strlen_P(pstr)) / 2;
-      while (--pad >= 0) { lcd_print(' '); n--; }
-    }
-    while (n > 0 && (c = pgm_read_byte(pstr))) {
-      n -= lcd_print(c);
-      pstr++;
-    }
-    if (valstr) while (n > 0 && (c = *valstr)) {
-      n -= lcd_print(c);
-      valstr++;
-    }
-    while (n-- > 0) lcd_print(' ');
-  }
-
-#endif // LCD_INFO_MENU || FILAMENT_CHANGE_FEATURE
-
-static void lcd_implementation_drawmenu_generic(bool isSelected, uint8_t row, const char* pstr, char pre_char, char post_char) {
-  UNUSED(pre_char);
-
-  char c;
-  uint8_t n = LCD_WIDTH - (START_COL) - 2;
-
-  lcd_implementation_mark_as_selected(row, isSelected);
-
-  while (c = pgm_read_byte(pstr)) {
-    n -= lcd_print(c);
-    pstr++;
-  }
-  while (n--) lcd_print(' ');
-  u8g.setPrintPos(LCD_PIXEL_WIDTH - (DOG_CHAR_WIDTH), (row + 1) * (DOG_CHAR_HEIGHT));
-  lcd_print(post_char);
-  lcd_print(' ');
-}
-
-static void _drawmenu_setting_edit_generic(bool isSelected, uint8_t row, const char* pstr, const char* data, bool pgm) {
-  char c;
-  uint8_t vallen = (pgm ? lcd_strlen_P(data) : (lcd_strlen((char*)data)));
-  uint8_t n = LCD_WIDTH - (START_COL) - 2 - vallen;
-
-  lcd_implementation_mark_as_selected(row, isSelected);
-
-  while (c = pgm_read_byte(pstr)) {
-    n -= lcd_print(c);
-    pstr++;
-  }
-  lcd_print(':');
-  while (n--) lcd_print(' ');
-  u8g.setPrintPos(LCD_PIXEL_WIDTH - (DOG_CHAR_WIDTH) * vallen, (row + 1) * (DOG_CHAR_HEIGHT));
-  if (pgm)  lcd_printPGM(data);  else  lcd_print((char*)data);
-}
-
-#define lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, data) _drawmenu_setting_edit_generic(sel, row, pstr, data, false)
-#define lcd_implementation_drawmenu_setting_edit_generic_P(sel, row, pstr, data) _drawmenu_setting_edit_generic(sel, row, pstr, data, true)
-
-#define lcd_implementation_drawmenu_setting_edit_int3(sel, row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, itostr3(*(data)))
-#define lcd_implementation_drawmenu_setting_edit_float3(sel, row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, ftostr3(*(data)))
-#define lcd_implementation_drawmenu_setting_edit_float32(sel, row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, ftostr32(*(data)))
-#define lcd_implementation_drawmenu_setting_edit_float43(sel, row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, ftostr43sign(*(data)))
-#define lcd_implementation_drawmenu_setting_edit_float5(sel, row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, ftostr5rj(*(data)))
-#define lcd_implementation_drawmenu_setting_edit_float52(sel, row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, ftostr52sign(*(data)))
-#define lcd_implementation_drawmenu_setting_edit_float51(sel, row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, ftostr51sign(*(data)))
-#define lcd_implementation_drawmenu_setting_edit_long5(sel, row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, ftostr5rj(*(data)))
-#define lcd_implementation_drawmenu_setting_edit_bool(sel, row, pstr, pstr2, data) lcd_implementation_drawmenu_setting_edit_generic_P(sel, row, pstr, (*(data))?PSTR(MSG_ON):PSTR(MSG_OFF))
-
-//Add version for callback functions
-#define lcd_implementation_drawmenu_setting_edit_callback_int3(sel, row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, itostr3(*(data)))
-#define lcd_implementation_drawmenu_setting_edit_callback_float3(sel, row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, ftostr3(*(data)))
-#define lcd_implementation_drawmenu_setting_edit_callback_float32(sel, row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, ftostr32(*(data)))
-#define lcd_implementation_drawmenu_setting_edit_callback_float43(sel, row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, ftostr43sign(*(data)))
-#define lcd_implementation_drawmenu_setting_edit_callback_float5(sel, row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, ftostr5rj(*(data)))
-#define lcd_implementation_drawmenu_setting_edit_callback_float52(sel, row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, ftostr52sign(*(data)))
-#define lcd_implementation_drawmenu_setting_edit_callback_float51(sel, row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, ftostr51sign(*(data)))
-#define lcd_implementation_drawmenu_setting_edit_callback_long5(sel, row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, ftostr5rj(*(data)))
-#define lcd_implementation_drawmenu_setting_edit_callback_bool(sel, row, pstr, pstr2, data, callback) lcd_implementation_drawmenu_setting_edit_generic_P(sel, row, pstr, (*(data))?PSTR(MSG_ON):PSTR(MSG_OFF))
-
-void lcd_implementation_drawedit(const char* pstr, const char* value=NULL) {
-  uint8_t rows = 1;
-  uint8_t lcd_width = LCD_WIDTH - (START_COL), char_width = DOG_CHAR_WIDTH;
-  uint8_t vallen = lcd_strlen(value);
-
-  #if ENABLED(USE_BIG_EDIT_FONT)
-    if (lcd_strlen_P(pstr) <= LCD_WIDTH_EDIT - 1) {
-      lcd_setFont(FONT_MENU_EDIT);
-      lcd_width = LCD_WIDTH_EDIT + 1;
-      char_width = DOG_CHAR_WIDTH_EDIT;
-      if (lcd_strlen_P(pstr) >= LCD_WIDTH_EDIT - vallen) rows = 2;
+  // Set the colors for a menu item based on whether it is selected
+  static void lcd_implementation_mark_as_selected(uint8_t row, bool isSelected) {
+    if (isSelected) {
+      u8g.setColorIndex(1);  // black on white
+      u8g.drawBox(0, row * (DOG_CHAR_HEIGHT) + 3 - (TALL_FONT_CORRECTION), LCD_PIXEL_WIDTH, DOG_CHAR_HEIGHT);
+      u8g.setColorIndex(0);  // following text must be white on black
     }
     else {
-      lcd_setFont(FONT_MENU);
+      u8g.setColorIndex(1); // unmarked text is black on white
     }
-  #endif
-
-  if (lcd_strlen_P(pstr) > LCD_WIDTH - 2 - vallen) rows = 2;
-
-  const float kHalfChar = (DOG_CHAR_HEIGHT_EDIT) / 2;
-  float rowHeight = u8g.getHeight() / (rows + 1); // 1/(rows+1) = 1/2 or 1/3
-
-  u8g.setPrintPos(0, rowHeight + kHalfChar);
-  lcd_printPGM(pstr);
-  if (value != NULL) {
-    lcd_print(':');
-    u8g.setPrintPos((lcd_width - 1 - vallen) * char_width, rows * rowHeight + kHalfChar);
-    lcd_print(value);
+    u8g.setPrintPos((START_COL) * (DOG_CHAR_WIDTH), (row + 1) * (DOG_CHAR_HEIGHT));
   }
-}
 
-#if ENABLED(SDSUPPORT)
+  #if ENABLED(LCD_INFO_MENU) || ENABLED(FILAMENT_CHANGE_FEATURE)
 
-  static void _drawmenu_sd(bool isSelected, uint8_t row, const char* pstr, const char* filename, char* const longFilename, bool isDir) {
-    UNUSED(pstr);
-    char c;
-    uint8_t n = LCD_WIDTH - (START_COL) - 1;
+    // Draw a static line of text in the same idiom as a menu item
+    static void lcd_implementation_drawmenu_static(uint8_t row, const char* pstr, bool center=true, bool invert=false, const char* valstr=NULL) {
 
-    if (longFilename[0]) {
-      filename = longFilename;
-      longFilename[n] = '\0';
+      lcd_implementation_mark_as_selected(row, invert);
+
+      char c;
+      int8_t n = LCD_WIDTH - (START_COL);
+
+      if (center && !valstr) {
+        int8_t pad = (LCD_WIDTH - lcd_strlen_P(pstr)) / 2;
+        while (--pad >= 0) { lcd_print(' '); n--; }
+      }
+      while (n > 0 && (c = pgm_read_byte(pstr))) {
+        n -= lcd_print(c);
+        pstr++;
+      }
+      if (valstr) while (n > 0 && (c = *valstr)) {
+        n -= lcd_print(c);
+        valstr++;
+      }
+      while (n-- > 0) lcd_print(' ');
     }
 
+  #endif // LCD_INFO_MENU || FILAMENT_CHANGE_FEATURE
+
+  // Draw a generic menu item
+  static void lcd_implementation_drawmenu_generic(bool isSelected, uint8_t row, const char* pstr, char pre_char, char post_char) {
+    UNUSED(pre_char);
+
+    char c;
+    uint8_t n = LCD_WIDTH - (START_COL) - 2;
+
     lcd_implementation_mark_as_selected(row, isSelected);
 
-    if (isDir) lcd_print(LCD_STR_FOLDER[0]);
-    while ((c = *filename)) {
+    while (c = pgm_read_byte(pstr)) {
       n -= lcd_print(c);
-      filename++;
+      pstr++;
     }
     while (n--) lcd_print(' ');
+    u8g.setPrintPos(LCD_PIXEL_WIDTH - (DOG_CHAR_WIDTH), (row + 1) * (DOG_CHAR_HEIGHT));
+    lcd_print(post_char);
+    lcd_print(' ');
   }
 
-  #define lcd_implementation_drawmenu_sdfile(sel, row, pstr, filename, longFilename) _drawmenu_sd(sel, row, pstr, filename, longFilename, false)
-  #define lcd_implementation_drawmenu_sddirectory(sel, row, pstr, filename, longFilename) _drawmenu_sd(sel, row, pstr, filename, longFilename, true)
+  // Macros for specific types of menu items
+  #define lcd_implementation_drawmenu_back(sel, row, pstr) lcd_implementation_drawmenu_generic(sel, row, pstr, LCD_STR_UPLEVEL[0], LCD_STR_UPLEVEL[0])
+  #define lcd_implementation_drawmenu_submenu(sel, row, pstr, data) lcd_implementation_drawmenu_generic(sel, row, pstr, '>', LCD_STR_ARROW_RIGHT[0])
+  #define lcd_implementation_drawmenu_gcode(sel, row, pstr, gcode) lcd_implementation_drawmenu_generic(sel, row, pstr, '>', ' ')
+  #define lcd_implementation_drawmenu_function(sel, row, pstr, data) lcd_implementation_drawmenu_generic(sel, row, pstr, '>', ' ')
 
-#endif //SDSUPPORT
+  // Draw a menu item with an editable value
+  static void _drawmenu_setting_edit_generic(bool isSelected, uint8_t row, const char* pstr, const char* data, bool pgm) {
+    char c;
+    uint8_t vallen = (pgm ? lcd_strlen_P(data) : (lcd_strlen((char*)data)));
+    uint8_t n = LCD_WIDTH - (START_COL) - 2 - vallen;
 
-#define lcd_implementation_drawmenu_back(sel, row, pstr) lcd_implementation_drawmenu_generic(sel, row, pstr, LCD_STR_UPLEVEL[0], LCD_STR_UPLEVEL[0])
-#define lcd_implementation_drawmenu_submenu(sel, row, pstr, data) lcd_implementation_drawmenu_generic(sel, row, pstr, '>', LCD_STR_ARROW_RIGHT[0])
-#define lcd_implementation_drawmenu_gcode(sel, row, pstr, gcode) lcd_implementation_drawmenu_generic(sel, row, pstr, '>', ' ')
-#define lcd_implementation_drawmenu_function(sel, row, pstr, data) lcd_implementation_drawmenu_generic(sel, row, pstr, '>', ' ')
+    lcd_implementation_mark_as_selected(row, isSelected);
+
+    while (c = pgm_read_byte(pstr)) {
+      n -= lcd_print(c);
+      pstr++;
+    }
+    lcd_print(':');
+    while (n--) lcd_print(' ');
+    u8g.setPrintPos(LCD_PIXEL_WIDTH - (DOG_CHAR_WIDTH) * vallen, (row + 1) * (DOG_CHAR_HEIGHT));
+    if (pgm)  lcd_printPGM(data);  else  lcd_print((char*)data);
+  }
+
+  // Macros for edit items
+  #define lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, data) _drawmenu_setting_edit_generic(sel, row, pstr, data, false)
+  #define lcd_implementation_drawmenu_setting_edit_generic_P(sel, row, pstr, data) _drawmenu_setting_edit_generic(sel, row, pstr, data, true)
+
+  #define lcd_implementation_drawmenu_setting_edit_int3(sel, row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, itostr3(*(data)))
+  #define lcd_implementation_drawmenu_setting_edit_float3(sel, row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, ftostr3(*(data)))
+  #define lcd_implementation_drawmenu_setting_edit_float32(sel, row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, ftostr32(*(data)))
+  #define lcd_implementation_drawmenu_setting_edit_float43(sel, row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, ftostr43sign(*(data)))
+  #define lcd_implementation_drawmenu_setting_edit_float5(sel, row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, ftostr5rj(*(data)))
+  #define lcd_implementation_drawmenu_setting_edit_float52(sel, row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, ftostr52sign(*(data)))
+  #define lcd_implementation_drawmenu_setting_edit_float51(sel, row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, ftostr51sign(*(data)))
+  #define lcd_implementation_drawmenu_setting_edit_long5(sel, row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, ftostr5rj(*(data)))
+  #define lcd_implementation_drawmenu_setting_edit_bool(sel, row, pstr, pstr2, data) lcd_implementation_drawmenu_setting_edit_generic_P(sel, row, pstr, (*(data))?PSTR(MSG_ON):PSTR(MSG_OFF))
+
+  #define lcd_implementation_drawmenu_setting_edit_callback_int3(sel, row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, itostr3(*(data)))
+  #define lcd_implementation_drawmenu_setting_edit_callback_float3(sel, row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, ftostr3(*(data)))
+  #define lcd_implementation_drawmenu_setting_edit_callback_float32(sel, row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, ftostr32(*(data)))
+  #define lcd_implementation_drawmenu_setting_edit_callback_float43(sel, row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, ftostr43sign(*(data)))
+  #define lcd_implementation_drawmenu_setting_edit_callback_float5(sel, row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, ftostr5rj(*(data)))
+  #define lcd_implementation_drawmenu_setting_edit_callback_float52(sel, row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, ftostr52sign(*(data)))
+  #define lcd_implementation_drawmenu_setting_edit_callback_float51(sel, row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, ftostr51sign(*(data)))
+  #define lcd_implementation_drawmenu_setting_edit_callback_long5(sel, row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, ftostr5rj(*(data)))
+  #define lcd_implementation_drawmenu_setting_edit_callback_bool(sel, row, pstr, pstr2, data, callback) lcd_implementation_drawmenu_setting_edit_generic_P(sel, row, pstr, (*(data))?PSTR(MSG_ON):PSTR(MSG_OFF))
+
+  void lcd_implementation_drawedit(const char* pstr, const char* value=NULL) {
+    uint8_t rows = 1;
+    uint8_t lcd_width = LCD_WIDTH - (START_COL), char_width = DOG_CHAR_WIDTH;
+    uint8_t vallen = lcd_strlen(value);
+
+    #if ENABLED(USE_BIG_EDIT_FONT)
+      if (lcd_strlen_P(pstr) <= LCD_WIDTH_EDIT - 1) {
+        lcd_setFont(FONT_MENU_EDIT);
+        lcd_width = LCD_WIDTH_EDIT + 1;
+        char_width = DOG_CHAR_WIDTH_EDIT;
+        if (lcd_strlen_P(pstr) >= LCD_WIDTH_EDIT - vallen) rows = 2;
+      }
+      else {
+        lcd_setFont(FONT_MENU);
+      }
+    #endif
+
+    if (lcd_strlen_P(pstr) > LCD_WIDTH - 2 - vallen) rows = 2;
+
+    const float kHalfChar = (DOG_CHAR_HEIGHT_EDIT) / 2;
+    float rowHeight = u8g.getHeight() / (rows + 1); // 1/(rows+1) = 1/2 or 1/3
+
+    u8g.setPrintPos(0, rowHeight + kHalfChar);
+    lcd_printPGM(pstr);
+    if (value != NULL) {
+      lcd_print(':');
+      u8g.setPrintPos((lcd_width - 1 - vallen) * char_width, rows * rowHeight + kHalfChar);
+      lcd_print(value);
+    }
+  }
+
+  #if ENABLED(SDSUPPORT)
+
+    static void _drawmenu_sd(bool isSelected, uint8_t row, const char* pstr, const char* filename, char* const longFilename, bool isDir) {
+      UNUSED(pstr);
+      char c;
+      uint8_t n = LCD_WIDTH - (START_COL) - 1;
+
+      if (longFilename[0]) {
+        filename = longFilename;
+        longFilename[n] = '\0';
+      }
+
+      lcd_implementation_mark_as_selected(row, isSelected);
+
+      if (isDir) lcd_print(LCD_STR_FOLDER[0]);
+      while ((c = *filename)) {
+        n -= lcd_print(c);
+        filename++;
+      }
+      while (n--) lcd_print(' ');
+    }
+
+    #define lcd_implementation_drawmenu_sdfile(sel, row, pstr, filename, longFilename) _drawmenu_sd(sel, row, pstr, filename, longFilename, false)
+    #define lcd_implementation_drawmenu_sddirectory(sel, row, pstr, filename, longFilename) _drawmenu_sd(sel, row, pstr, filename, longFilename, true)
+
+  #endif // SDSUPPORT
+
+#endif // ULTIPANEL
 
 #endif //__ULTRALCD_IMPL_DOGM_H
diff --git a/Marlin/ultralcd_impl_HD44780.h b/Marlin/ultralcd_impl_HD44780.h
index 05a892be72..44d0bb977f 100644
--- a/Marlin/ultralcd_impl_HD44780.h
+++ b/Marlin/ultralcd_impl_HD44780.h
@@ -24,9 +24,11 @@
 #define ULTRALCD_IMPL_HD44780_H
 
 /**
-* Implementation of the LCD display routines for a Hitachi HD44780 display. These are common LCD character displays.
-**/
+ * Implementation of the LCD display routines for a Hitachi HD44780 display.
+ * These are the most common LCD character displays.
+ */
 
+#include "utility.h"
 #include "duration_t.h"
 
 extern volatile uint8_t buttons;  //an extended version of the last checked buttons in a bit array.
@@ -787,135 +789,158 @@ static void lcd_implementation_status_screen() {
   lcd_print(lcd_status_message);
 }
 
-#if ENABLED(LCD_INFO_MENU) || ENABLED(FILAMENT_CHANGE_FEATURE)
+#if ENABLED(ULTIPANEL)
 
-  static void lcd_implementation_drawmenu_static(uint8_t row, const char* pstr, bool center=true, bool invert=false, const char *valstr=NULL) {
-    UNUSED(invert);
-    char c;
-    int8_t n = LCD_WIDTH;
-    lcd.setCursor(0, row);
-    if (center && !valstr) {
-      int8_t pad = (LCD_WIDTH - lcd_strlen_P(pstr)) / 2;
-      while (--pad >= 0) { lcd.print(' '); n--; }
+  #if ENABLED(LCD_INFO_MENU) || ENABLED(FILAMENT_CHANGE_FEATURE)
+
+    static void lcd_implementation_drawmenu_static(uint8_t row, const char* pstr, bool center=true, bool invert=false, const char *valstr=NULL) {
+      UNUSED(invert);
+      char c;
+      int8_t n = LCD_WIDTH;
+      lcd.setCursor(0, row);
+      if (center && !valstr) {
+        int8_t pad = (LCD_WIDTH - lcd_strlen_P(pstr)) / 2;
+        while (--pad >= 0) { lcd.print(' '); n--; }
+      }
+      while (n > 0 && (c = pgm_read_byte(pstr))) {
+        n -= lcd_print(c);
+        pstr++;
+      }
+      if (valstr) while (n > 0 && (c = *valstr)) {
+        n -= lcd_print(c);
+        valstr++;
+      }
+      while (n-- > 0) lcd.print(' ');
     }
-    while (n > 0 && (c = pgm_read_byte(pstr))) {
+
+  #endif // LCD_INFO_MENU || FILAMENT_CHANGE_FEATURE
+
+  static void lcd_implementation_drawmenu_generic(bool sel, uint8_t row, const char* pstr, char pre_char, char post_char) {
+    char c;
+    uint8_t n = LCD_WIDTH - 2;
+    lcd.setCursor(0, row);
+    lcd.print(sel ? pre_char : ' ');
+    while ((c = pgm_read_byte(pstr)) && n > 0) {
       n -= lcd_print(c);
       pstr++;
     }
-    if (valstr) while (n > 0 && (c = *valstr)) {
-      n -= lcd_print(c);
-      valstr++;
-    }
-    while (n-- > 0) lcd.print(' ');
-  }
-
-#endif // LCD_INFO_MENU || FILAMENT_CHANGE_FEATURE
-
-static void lcd_implementation_drawmenu_generic(bool sel, uint8_t row, const char* pstr, char pre_char, char post_char) {
-  char c;
-  uint8_t n = LCD_WIDTH - 2;
-  lcd.setCursor(0, row);
-  lcd.print(sel ? pre_char : ' ');
-  while ((c = pgm_read_byte(pstr)) && n > 0) {
-    n -= lcd_print(c);
-    pstr++;
-  }
-  while (n--) lcd.print(' ');
-  lcd.print(post_char);
-}
-
-static void lcd_implementation_drawmenu_setting_edit_generic(bool sel, uint8_t row, const char* pstr, char pre_char, char* data) {
-  char c;
-  uint8_t n = LCD_WIDTH - 2 - lcd_strlen(data);
-  lcd.setCursor(0, row);
-  lcd.print(sel ? pre_char : ' ');
-  while ((c = pgm_read_byte(pstr)) && n > 0) {
-    n -= lcd_print(c);
-    pstr++;
-  }
-  lcd.print(':');
-  while (n--) lcd.print(' ');
-  lcd_print(data);
-}
-static void lcd_implementation_drawmenu_setting_edit_generic_P(bool sel, uint8_t row, const char* pstr, char pre_char, const char* data) {
-  char c;
-  uint8_t n = LCD_WIDTH - 2 - lcd_strlen_P(data);
-  lcd.setCursor(0, row);
-  lcd.print(sel ? pre_char : ' ');
-  while ((c = pgm_read_byte(pstr)) && n > 0) {
-    n -= lcd_print(c);
-    pstr++;
-  }
-  lcd.print(':');
-  while (n--) lcd.print(' ');
-  lcd_printPGM(data);
-}
-
-#define lcd_implementation_drawmenu_setting_edit_int3(sel, row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, '>', itostr3(*(data)))
-#define lcd_implementation_drawmenu_setting_edit_float3(sel, row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, '>', ftostr3(*(data)))
-#define lcd_implementation_drawmenu_setting_edit_float32(sel, row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, '>', ftostr32(*(data)))
-#define lcd_implementation_drawmenu_setting_edit_float43(sel, row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, '>', ftostr43sign(*(data)))
-#define lcd_implementation_drawmenu_setting_edit_float5(sel, row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, '>', ftostr5rj(*(data)))
-#define lcd_implementation_drawmenu_setting_edit_float52(sel, row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, '>', ftostr52sign(*(data)))
-#define lcd_implementation_drawmenu_setting_edit_float51(sel, row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, '>', ftostr51sign(*(data)))
-#define lcd_implementation_drawmenu_setting_edit_long5(sel, row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, '>', ftostr5rj(*(data)))
-#define lcd_implementation_drawmenu_setting_edit_bool(sel, row, pstr, pstr2, data) lcd_implementation_drawmenu_setting_edit_generic_P(sel, row, pstr, '>', (*(data))?PSTR(MSG_ON):PSTR(MSG_OFF))
-
-//Add version for callback functions
-#define lcd_implementation_drawmenu_setting_edit_callback_int3(sel, row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, '>', itostr3(*(data)))
-#define lcd_implementation_drawmenu_setting_edit_callback_float3(sel, row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, '>', ftostr3(*(data)))
-#define lcd_implementation_drawmenu_setting_edit_callback_float32(sel, row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, '>', ftostr32(*(data)))
-#define lcd_implementation_drawmenu_setting_edit_callback_float43(sel, row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, '>', ftostr43sign(*(data)))
-#define lcd_implementation_drawmenu_setting_edit_callback_float5(sel, row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, '>', ftostr5rj(*(data)))
-#define lcd_implementation_drawmenu_setting_edit_callback_float52(sel, row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, '>', ftostr52sign(*(data)))
-#define lcd_implementation_drawmenu_setting_edit_callback_float51(sel, row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, '>', ftostr51sign(*(data)))
-#define lcd_implementation_drawmenu_setting_edit_callback_long5(sel, row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, '>', ftostr5rj(*(data)))
-#define lcd_implementation_drawmenu_setting_edit_callback_bool(sel, row, pstr, pstr2, data, callback) lcd_implementation_drawmenu_setting_edit_generic_P(sel, row, pstr, '>', (*(data))?PSTR(MSG_ON):PSTR(MSG_OFF))
-
-void lcd_implementation_drawedit(const char* pstr, const char* value=NULL) {
-  lcd.setCursor(1, 1);
-  lcd_printPGM(pstr);
-  if (value != NULL) {
-    lcd.print(':');
-    lcd.setCursor(LCD_WIDTH - lcd_strlen(value), 1);
-    lcd_print(value);
-  }
-}
-
-#if ENABLED(SDSUPPORT)
-
-  static void lcd_implementation_drawmenu_sd(bool sel, uint8_t row, const char* pstr, const char* filename, char* longFilename, uint8_t concat, char post_char) {
-    UNUSED(pstr);
-    char c;
-    uint8_t n = LCD_WIDTH - concat;
-    lcd.setCursor(0, row);
-    lcd.print(sel ? '>' : ' ');
-    if (longFilename[0]) {
-      filename = longFilename;
-      longFilename[n] = '\0';
-    }
-    while ((c = *filename) && n > 0) {
-      n -= lcd_print(c);
-      filename++;
-    }
     while (n--) lcd.print(' ');
     lcd.print(post_char);
   }
 
-  static void lcd_implementation_drawmenu_sdfile(bool sel, uint8_t row, const char* pstr, const char* filename, char* longFilename) {
-    lcd_implementation_drawmenu_sd(sel, row, pstr, filename, longFilename, 2, ' ');
+  static void lcd_implementation_drawmenu_setting_edit_generic(bool sel, uint8_t row, const char* pstr, char pre_char, char* data) {
+    char c;
+    uint8_t n = LCD_WIDTH - 2 - lcd_strlen(data);
+    lcd.setCursor(0, row);
+    lcd.print(sel ? pre_char : ' ');
+    while ((c = pgm_read_byte(pstr)) && n > 0) {
+      n -= lcd_print(c);
+      pstr++;
+    }
+    lcd.print(':');
+    while (n--) lcd.print(' ');
+    lcd_print(data);
+  }
+  static void lcd_implementation_drawmenu_setting_edit_generic_P(bool sel, uint8_t row, const char* pstr, char pre_char, const char* data) {
+    char c;
+    uint8_t n = LCD_WIDTH - 2 - lcd_strlen_P(data);
+    lcd.setCursor(0, row);
+    lcd.print(sel ? pre_char : ' ');
+    while ((c = pgm_read_byte(pstr)) && n > 0) {
+      n -= lcd_print(c);
+      pstr++;
+    }
+    lcd.print(':');
+    while (n--) lcd.print(' ');
+    lcd_printPGM(data);
   }
 
-  static void lcd_implementation_drawmenu_sddirectory(bool sel, uint8_t row, const char* pstr, const char* filename, char* longFilename) {
-    lcd_implementation_drawmenu_sd(sel, row, pstr, filename, longFilename, 2, LCD_STR_FOLDER[0]);
+  #define lcd_implementation_drawmenu_setting_edit_int3(sel, row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, '>', itostr3(*(data)))
+  #define lcd_implementation_drawmenu_setting_edit_float3(sel, row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, '>', ftostr3(*(data)))
+  #define lcd_implementation_drawmenu_setting_edit_float32(sel, row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, '>', ftostr32(*(data)))
+  #define lcd_implementation_drawmenu_setting_edit_float43(sel, row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, '>', ftostr43sign(*(data)))
+  #define lcd_implementation_drawmenu_setting_edit_float5(sel, row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, '>', ftostr5rj(*(data)))
+  #define lcd_implementation_drawmenu_setting_edit_float52(sel, row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, '>', ftostr52sign(*(data)))
+  #define lcd_implementation_drawmenu_setting_edit_float51(sel, row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, '>', ftostr51sign(*(data)))
+  #define lcd_implementation_drawmenu_setting_edit_long5(sel, row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, '>', ftostr5rj(*(data)))
+  #define lcd_implementation_drawmenu_setting_edit_bool(sel, row, pstr, pstr2, data) lcd_implementation_drawmenu_setting_edit_generic_P(sel, row, pstr, '>', (*(data))?PSTR(MSG_ON):PSTR(MSG_OFF))
+
+  //Add version for callback functions
+  #define lcd_implementation_drawmenu_setting_edit_callback_int3(sel, row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, '>', itostr3(*(data)))
+  #define lcd_implementation_drawmenu_setting_edit_callback_float3(sel, row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, '>', ftostr3(*(data)))
+  #define lcd_implementation_drawmenu_setting_edit_callback_float32(sel, row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, '>', ftostr32(*(data)))
+  #define lcd_implementation_drawmenu_setting_edit_callback_float43(sel, row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, '>', ftostr43sign(*(data)))
+  #define lcd_implementation_drawmenu_setting_edit_callback_float5(sel, row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, '>', ftostr5rj(*(data)))
+  #define lcd_implementation_drawmenu_setting_edit_callback_float52(sel, row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, '>', ftostr52sign(*(data)))
+  #define lcd_implementation_drawmenu_setting_edit_callback_float51(sel, row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, '>', ftostr51sign(*(data)))
+  #define lcd_implementation_drawmenu_setting_edit_callback_long5(sel, row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(sel, row, pstr, '>', ftostr5rj(*(data)))
+  #define lcd_implementation_drawmenu_setting_edit_callback_bool(sel, row, pstr, pstr2, data, callback) lcd_implementation_drawmenu_setting_edit_generic_P(sel, row, pstr, '>', (*(data))?PSTR(MSG_ON):PSTR(MSG_OFF))
+
+  void lcd_implementation_drawedit(const char* pstr, const char* value=NULL) {
+    lcd.setCursor(1, 1);
+    lcd_printPGM(pstr);
+    if (value != NULL) {
+      lcd.print(':');
+      lcd.setCursor(LCD_WIDTH - lcd_strlen(value), 1);
+      lcd_print(value);
+    }
   }
 
-#endif //SDSUPPORT
+  #if ENABLED(SDSUPPORT)
 
-#define lcd_implementation_drawmenu_back(sel, row, pstr) lcd_implementation_drawmenu_generic(sel, row, pstr, LCD_STR_UPLEVEL[0], LCD_STR_UPLEVEL[0])
-#define lcd_implementation_drawmenu_submenu(sel, row, pstr, data) lcd_implementation_drawmenu_generic(sel, row, pstr, '>', LCD_STR_ARROW_RIGHT[0])
-#define lcd_implementation_drawmenu_gcode(sel, row, pstr, gcode) lcd_implementation_drawmenu_generic(sel, row, pstr, '>', ' ')
-#define lcd_implementation_drawmenu_function(sel, row, pstr, data) lcd_implementation_drawmenu_generic(sel, row, pstr, '>', ' ')
+    static void lcd_implementation_drawmenu_sd(bool sel, uint8_t row, const char* pstr, const char* filename, char* longFilename, uint8_t concat, char post_char) {
+      UNUSED(pstr);
+      char c;
+      uint8_t n = LCD_WIDTH - concat;
+      lcd.setCursor(0, row);
+      lcd.print(sel ? '>' : ' ');
+      if (longFilename[0]) {
+        filename = longFilename;
+        longFilename[n] = '\0';
+      }
+      while ((c = *filename) && n > 0) {
+        n -= lcd_print(c);
+        filename++;
+      }
+      while (n--) lcd.print(' ');
+      lcd.print(post_char);
+    }
+
+    static void lcd_implementation_drawmenu_sdfile(bool sel, uint8_t row, const char* pstr, const char* filename, char* longFilename) {
+      lcd_implementation_drawmenu_sd(sel, row, pstr, filename, longFilename, 2, ' ');
+    }
+
+    static void lcd_implementation_drawmenu_sddirectory(bool sel, uint8_t row, const char* pstr, const char* filename, char* longFilename) {
+      lcd_implementation_drawmenu_sd(sel, row, pstr, filename, longFilename, 2, LCD_STR_FOLDER[0]);
+    }
+
+  #endif // SDSUPPORT
+
+  #define lcd_implementation_drawmenu_back(sel, row, pstr) lcd_implementation_drawmenu_generic(sel, row, pstr, LCD_STR_UPLEVEL[0], LCD_STR_UPLEVEL[0])
+  #define lcd_implementation_drawmenu_submenu(sel, row, pstr, data) lcd_implementation_drawmenu_generic(sel, row, pstr, '>', LCD_STR_ARROW_RIGHT[0])
+  #define lcd_implementation_drawmenu_gcode(sel, row, pstr, gcode) lcd_implementation_drawmenu_generic(sel, row, pstr, '>', ' ')
+  #define lcd_implementation_drawmenu_function(sel, row, pstr, data) lcd_implementation_drawmenu_generic(sel, row, pstr, '>', ' ')
+
+  #if ENABLED(LCD_HAS_SLOW_BUTTONS)
+
+    extern millis_t next_button_update_ms;
+
+    static uint8_t lcd_implementation_read_slow_buttons() {
+      #if ENABLED(LCD_I2C_TYPE_MCP23017)
+        // Reading these buttons this is likely to be too slow to call inside interrupt context
+        // so they are called during normal lcd_update
+        uint8_t slow_bits = lcd.readButtons() << B_I2C_BTN_OFFSET;
+        #if ENABLED(LCD_I2C_VIKI)
+          if ((slow_bits & (B_MI | B_RI)) && PENDING(millis(), next_button_update_ms)) // LCD clicked
+            slow_bits &= ~(B_MI | B_RI); // Disable LCD clicked buttons if screen is updated
+        #endif // LCD_I2C_VIKI
+        return slow_bits;
+      #endif // LCD_I2C_TYPE_MCP23017
+    }
+
+  #endif // LCD_HAS_SLOW_BUTTONS
+
+#endif // ULTIPANEL
 
 #if ENABLED(LCD_HAS_STATUS_INDICATORS)
 
@@ -955,23 +980,4 @@ void lcd_implementation_drawedit(const char* pstr, const char* value=NULL) {
 
 #endif // LCD_HAS_STATUS_INDICATORS
 
-#if ENABLED(LCD_HAS_SLOW_BUTTONS)
-
-  extern millis_t next_button_update_ms;
-
-  static uint8_t lcd_implementation_read_slow_buttons() {
-    #if ENABLED(LCD_I2C_TYPE_MCP23017)
-      // Reading these buttons this is likely to be too slow to call inside interrupt context
-      // so they are called during normal lcd_update
-      uint8_t slow_bits = lcd.readButtons() << B_I2C_BTN_OFFSET;
-      #if ENABLED(LCD_I2C_VIKI)
-        if ((slow_bits & (B_MI | B_RI)) && PENDING(millis(), next_button_update_ms)) // LCD clicked
-          slow_bits &= ~(B_MI | B_RI); // Disable LCD clicked buttons if screen is updated
-      #endif // LCD_I2C_VIKI
-      return slow_bits;
-    #endif // LCD_I2C_TYPE_MCP23017
-  }
-
-#endif // LCD_HAS_SLOW_BUTTONS
-
 #endif // ULTRALCD_IMPL_HD44780_H
diff --git a/Marlin/utility.cpp b/Marlin/utility.cpp
index 0285219c40..b2d09004c9 100644
--- a/Marlin/utility.cpp
+++ b/Marlin/utility.cpp
@@ -32,3 +32,186 @@ void safe_delay(millis_t ms) {
   }
   delay(ms);
 }
+
+#if ENABLED(ULTRA_LCD)
+
+  char conv[8];
+
+  #define DIGIT(n) ('0' + (n))
+  #define DIGIMOD(n, f) DIGIT((n)/(f) % 10)
+  #define RJDIGIT(n, f) ((n) >= (f) ? DIGIMOD(n, f) : ' ')
+  #define MINUSOR(n, alt) (n >= 0 ? (alt) : (n = -n, '-'))
+
+  // Convert unsigned int to string with 12 format
+  char* itostr2(const uint8_t& x) {
+    int xx = x;
+    conv[0] = DIGIMOD(xx, 10);
+    conv[1] = DIGIMOD(xx, 1);
+    conv[2] = '\0';
+    return conv;
+  }
+
+  // Convert signed int to rj string with 123 or -12 format
+  char* itostr3(const int& x) {
+    int xx = x;
+    conv[0] = MINUSOR(xx, RJDIGIT(xx, 100));
+    conv[1] = RJDIGIT(xx, 10);
+    conv[2] = DIGIMOD(xx, 1);
+    conv[3] = '\0';
+    return conv;
+  }
+
+  // Convert unsigned int to lj string with 123 format
+  char* itostr3left(const int& xx) {
+    char *str = &conv[3];
+    *str = '\0';
+    *(--str) = DIGIMOD(xx, 1);
+    if (xx >= 10) {
+      *(--str) = DIGIMOD(xx, 10);
+      if (xx >= 100)
+        *(--str) = DIGIMOD(xx, 100);
+    }
+    return str;
+  }
+
+  // Convert signed int to rj string with _123, -123, _-12, or __-1 format
+  char *itostr4sign(const int& x) {
+    int xx = abs(x), sign = 0;
+    if (xx >= 100) {
+      conv[1] = DIGIMOD(xx, 100);
+      conv[2] = DIGIMOD(xx, 10);
+    }
+    else {
+      conv[0] = ' ';
+      if (xx >= 10) {
+        sign = 1;
+        conv[2] = DIGIMOD(xx, 10);
+      }
+      else {
+        conv[1] = ' ';
+        sign = 2;
+      }
+    }
+    conv[sign] = x < 0 ? '-' : ' ';
+    conv[3] = DIGIMOD(xx, 1);
+    conv[4] = '\0';
+    return conv;
+  }
+
+  // Convert unsigned float to string with 1.23 format
+  char* ftostr12ns(const float& x) {
+    long xx = abs(x * 100);
+    conv[0] = DIGIMOD(xx, 100);
+    conv[1] = '.';
+    conv[2] = DIGIMOD(xx, 10);
+    conv[3] = DIGIMOD(xx, 1);
+    conv[4] = '\0';
+    return conv;
+  }
+
+  // Convert signed float to fixed-length string with 023.45 / -23.45 format
+  char *ftostr32(const float& x) {
+    long xx = x * 100;
+    conv[0] = MINUSOR(xx, DIGIMOD(xx, 10000));
+    conv[1] = DIGIMOD(xx, 1000);
+    conv[2] = DIGIMOD(xx, 100);
+    conv[3] = '.';
+    conv[4] = DIGIMOD(xx, 10);
+    conv[5] = DIGIMOD(xx, 1);
+    conv[6] = '\0';
+    return conv;
+  }
+
+  // Convert float to fixed-length string with +123.4 / -123.4 format
+  char* ftostr41sign(const float& x) {
+    int xx = x * 10;
+    conv[0] = MINUSOR(xx, '+');
+    conv[1] = DIGIMOD(xx, 1000);
+    conv[2] = DIGIMOD(xx, 100);
+    conv[3] = DIGIMOD(xx, 10);
+    conv[4] = '.';
+    conv[5] = DIGIMOD(xx, 1);
+    conv[6] = '\0';
+    return conv;
+  }
+
+  // Convert signed float to string (6 digit) with -1.234 / _0.000 / +1.234 format
+  char* ftostr43sign(const float& x, char plus/*=' '*/) {
+    long xx = x * 1000;
+    conv[0] = xx ? MINUSOR(xx, plus) : ' ';
+    conv[1] = DIGIMOD(xx, 1000);
+    conv[2] = '.';
+    conv[3] = DIGIMOD(xx, 100);
+    conv[4] = DIGIMOD(xx, 10);
+    conv[5] = DIGIMOD(xx, 1);
+    conv[6] = '\0';
+    return conv;
+  }
+
+  // Convert unsigned float to rj string with 12345 format
+  char* ftostr5rj(const float& x) {
+    long xx = abs(x);
+    conv[0] = RJDIGIT(xx, 10000);
+    conv[1] = RJDIGIT(xx, 1000);
+    conv[2] = RJDIGIT(xx, 100);
+    conv[3] = RJDIGIT(xx, 10);
+    conv[4] = DIGIMOD(xx, 1);
+    conv[5] = '\0';
+    return conv;
+  }
+
+  // Convert signed float to string with +1234.5 format
+  char* ftostr51sign(const float& x) {
+    long xx = x * 10;
+    conv[0] = MINUSOR(xx, '+');
+    conv[1] = DIGIMOD(xx, 10000);
+    conv[2] = DIGIMOD(xx, 1000);
+    conv[3] = DIGIMOD(xx, 100);
+    conv[4] = DIGIMOD(xx, 10);
+    conv[5] = '.';
+    conv[6] = DIGIMOD(xx, 1);
+    conv[7] = '\0';
+    return conv;
+  }
+
+  // Convert signed float to string with +123.45 format
+  char* ftostr52sign(const float& x) {
+    long xx = x * 100;
+    conv[0] = MINUSOR(xx, '+');
+    conv[1] = DIGIMOD(xx, 10000);
+    conv[2] = DIGIMOD(xx, 1000);
+    conv[3] = DIGIMOD(xx, 100);
+    conv[4] = '.';
+    conv[5] = DIGIMOD(xx, 10);
+    conv[6] = DIGIMOD(xx, 1);
+    conv[7] = '\0';
+    return conv;
+  }
+
+  // Convert signed float to space-padded string with -_23.4_ format
+  char* ftostr52sp(const float& x) {
+    long xx = x * 100;
+    uint8_t dig;
+    conv[0] = MINUSOR(xx, RJDIGIT(xx, 10000));
+    conv[1] = RJDIGIT(xx, 1000);
+    conv[2] = DIGIMOD(xx, 100);
+
+    if ((dig = xx % 10)) {          // second digit after decimal point?
+      conv[3] = '.';
+      conv[4] = DIGIMOD(xx, 10);
+      conv[5] = DIGIT(dig);
+    }
+    else {
+      if ((dig = (xx / 10) % 10)) { // first digit after decimal point?
+        conv[3] = '.';
+        conv[4] = DIGIT(dig);
+      }
+      else                          // nothing after decimal point
+        conv[3] = conv[4] = ' ';
+      conv[5] = ' ';
+    }
+    conv[6] = '\0';
+    return conv;
+  }
+
+#endif // ULTRA_LCD
diff --git a/Marlin/utility.h b/Marlin/utility.h
index 8ca70dbf83..8b107e7fd3 100644
--- a/Marlin/utility.h
+++ b/Marlin/utility.h
@@ -25,4 +25,50 @@
 
 void safe_delay(millis_t ms);
 
-#endif
+#if ENABLED(ULTRA_LCD)
+
+  // Convert unsigned int to string with 12 format
+  char* itostr2(const uint8_t& x);
+
+  // Convert signed int to rj string with 123 or -12 format
+  char* itostr3(const int& x);
+
+  // Convert unsigned int to lj string with 123 format
+  char* itostr3left(const int& xx);
+
+  // Convert signed int to rj string with _123, -123, _-12, or __-1 format
+  char *itostr4sign(const int& x);
+
+  // Convert unsigned float to string with 1.23 format
+  char* ftostr12ns(const float& x);
+
+  // Convert signed float to fixed-length string with 023.45 / -23.45 format
+  char *ftostr32(const float& x);
+
+  // Convert float to fixed-length string with +123.4 / -123.4 format
+  char* ftostr41sign(const float& x);
+
+  // Convert signed float to string (6 digit) with -1.234 / _0.000 / +1.234 format
+  char* ftostr43sign(const float& x, char plus=' ');
+
+  // Convert unsigned float to rj string with 12345 format
+  char* ftostr5rj(const float& x);
+
+  // Convert signed float to string with +1234.5 format
+  char* ftostr51sign(const float& x);
+
+  // Convert signed float to space-padded string with -_23.4_ format
+  char* ftostr52sp(const float& x);
+
+  // Convert signed float to string with +123.45 format
+  char* ftostr52sign(const float& x);
+
+  // Convert float to rj string with 123 or -12 format
+  FORCE_INLINE char *ftostr3(const float& x) { return itostr3((int)x); }
+
+  // Convert float to rj string with _123, -123, _-12, or __-1 format
+  FORCE_INLINE char *ftostr4sign(const float& x) { return itostr4sign((int)x); }
+
+#endif // ULTRA_LCD
+
+#endif // __UTILITY_H__