From 6cdcd6c6d164882af0cba47b2da5d6a60d80bf25 Mon Sep 17 00:00:00 2001
From: AnHardt <github@kitelab.de>
Date: Mon, 16 Feb 2015 13:53:58 +0100
Subject: [PATCH] Fix iss#1492

Introduced lcd_strlen() and lcd_strlen_P().
Replaced the old functions where necessary.
Reworked language_ru.h.

Speeded up test for zero length string in cardreader.cpp
---
 Marlin/LiquidCrystalRus.cpp                   | 12 +++++---
 Marlin/cardreader.cpp                         |  2 +-
 Marlin/dogm_lcd_implementation.h              | 10 +++----
 Marlin/language_ru.h                          | 30 +++++++++----------
 Marlin/ultralcd.cpp                           | 22 +++++++++++++-
 Marlin/ultralcd.h                             |  3 +-
 .../ultralcd_implementation_hitachi_HD44780.h | 18 +++++------
 7 files changed, 61 insertions(+), 36 deletions(-)

diff --git a/Marlin/LiquidCrystalRus.cpp b/Marlin/LiquidCrystalRus.cpp
index 6ee2c112e9c..c74146236e8 100644
--- a/Marlin/LiquidCrystalRus.cpp
+++ b/Marlin/LiquidCrystalRus.cpp
@@ -14,10 +14,14 @@
 // it is a Russian alphabet translation
 // except 0401 --> 0xa2 = ╗, 0451 --> 0xb5
 const PROGMEM uint8_t utf_recode[] = 
-       { 0x41,0xa0,0x42,0xa1,0xe0,0x45,0xa3,0xa4,0xa5,0xa6,0x4b,0xa7,0x4d,0x48,0x4f,
-         0xa8,0x50,0x43,0x54,0xa9,0xaa,0x58,0xe1,0xab,0xac,0xe2,0xad,0xae,0x62,0xaf,0xb0,0xb1,
-         0x61,0xb2,0xb3,0xb4,0xe3,0x65,0xb6,0xb7,0xb8,0xb9,0xba,0xbb,0xbc,0xbd,0x6f,
-         0xbe,0x70,0x63,0xbf,0x79,0xe4,0x78,0xe5,0xc0,0xc1,0xe6,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7
+       { 0x41,0xa0,0x42,0xa1,0xe0,0x45,0xa3,0xa4,
+         0xa5,0xa6,0x4b,0xa7,0x4d,0x48,0x4f,0xa8,
+         0x50,0x43,0x54,0xa9,0xaa,0x58,0xe1,0xab,
+         0xac,0xe2,0xad,0xae,0x62,0xaf,0xb0,0xb1,
+         0x61,0xb2,0xb3,0xb4,0xe3,0x65,0xb6,0xb7,
+         0xb8,0xb9,0xba,0xbb,0xbc,0xbd,0x6f,0xbe,
+         0x70,0x63,0xbf,0x79,0xe4,0x78,0xe5,0xc0,
+         0xc1,0xe6,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7
         };     
 
 // When the display powers up, it is configured as follows:
diff --git a/Marlin/cardreader.cpp b/Marlin/cardreader.cpp
index 498a654c510..a2dd67831be 100644
--- a/Marlin/cardreader.cpp
+++ b/Marlin/cardreader.cpp
@@ -65,7 +65,7 @@ void CardReader::lsDive(const char *prepend, SdFile parent, const char * const m
       createFilename(lfilename,p);
       
       path[0]=0;
-      if(strlen(prepend)==0) //avoid leading / if already in prepend
+      if(prepend[0]==0) //avoid leading / if already in prepend
       {
        strcat(path,"/");
       }
diff --git a/Marlin/dogm_lcd_implementation.h b/Marlin/dogm_lcd_implementation.h
index f512d329564..c7df306b32e 100644
--- a/Marlin/dogm_lcd_implementation.h
+++ b/Marlin/dogm_lcd_implementation.h
@@ -315,7 +315,7 @@ static void lcd_implementation_drawmenu_generic(uint8_t row, const char* pstr, c
 
 static void _drawmenu_setting_edit_generic(uint8_t row, const char* pstr, char pre_char, const char* data, bool pgm) {
   char c;
-  uint8_t n = LCD_WIDTH - 2 - (pgm ? strlen_P(data) : (strlen(data)));
+  uint8_t n = LCD_WIDTH - 2 - (pgm ? lcd_strlen_P(data) : (lcd_strlen((char*)data)));
 
   lcd_implementation_mark_as_selected(row, pre_char);
 
@@ -377,18 +377,18 @@ void lcd_implementation_drawedit(const char* pstr, char* value) {
   uint8_t char_width = DOG_CHAR_WIDTH;
 
   #ifdef USE_BIG_EDIT_FONT
-    if (strlen_P(pstr) <= LCD_WIDTH_EDIT - 1) {
+    if (lcd_strlen_P(pstr) <= LCD_WIDTH_EDIT - 1) {
       u8g.setFont(FONT_MENU_EDIT);
       lcd_width = LCD_WIDTH_EDIT + 1;
       char_width = DOG_CHAR_WIDTH_EDIT;
-      if (strlen_P(pstr) >= LCD_WIDTH_EDIT - strlen(value)) rows = 2;
+      if (lcd_strlen_P(pstr) >= LCD_WIDTH_EDIT - lcd_strlen(value)) rows = 2;
     }
     else {
       u8g.setFont(FONT_MENU);
     }
   #endif
 
-  if (strlen_P(pstr) > LCD_WIDTH - 2 - strlen(value)) rows = 2;
+  if (lcd_strlen_P(pstr) > LCD_WIDTH - 2 - lcd_strlen(value)) rows = 2;
 
   const float kHalfChar = DOG_CHAR_HEIGHT_EDIT / 2;
   float rowHeight = u8g.getHeight() / (rows + 1); // 1/(rows+1) = 1/2 or 1/3
@@ -396,7 +396,7 @@ void lcd_implementation_drawedit(const char* pstr, char* value) {
   u8g.setPrintPos(0, rowHeight + kHalfChar);
   lcd_printPGM(pstr);
   u8g.print(':');
-  u8g.setPrintPos((lcd_width-1-strlen(value)) * char_width, rows * rowHeight + kHalfChar);
+  u8g.setPrintPos((lcd_width-1-lcd_strlen(value)) * char_width, rows * rowHeight + kHalfChar);
   u8g.print(value);
 }
 
diff --git a/Marlin/language_ru.h b/Marlin/language_ru.h
index 03ea77851dc..bcab50b7968 100644
--- a/Marlin/language_ru.h
+++ b/Marlin/language_ru.h
@@ -13,7 +13,7 @@
 #define WELCOME_MSG                         MACHINE_NAME " Готов."
 #define MSG_SD_INSERTED                     "Карта вставлена"
 #define MSG_SD_REMOVED                      "Карта извлечена"
-#define MSG_MAIN                            "Меню \003"
+#define MSG_MAIN                            "Меню"
 #define MSG_AUTOSTART                       "Автостарт"
 #define MSG_DISABLE_STEPPERS                "Выкл. двигатели"
 #define MSG_AUTO_HOME                       "Парковка"
@@ -43,14 +43,14 @@
 #define MSG_MOVE_1MM                        "Move 1mm"
 #define MSG_MOVE_10MM                       "Move 10mm"
 #define MSG_SPEED                           "Скорость"
-#define MSG_NOZZLE                          "\002 Фильера"
-#define MSG_BED                             "\002 Кровать"
+#define MSG_NOZZLE                          LCD_STR_THERMOMETER " Фильера"
+#define MSG_BED                             LCD_STR_THERMOMETER " Кровать"
 #define MSG_FAN_SPEED                       "Куллер"
 #define MSG_FLOW                            "Поток"
-#define MSG_CONTROL                         "Настройки \003"
-#define MSG_MIN                             "\002 Минимум"
-#define MSG_MAX                             "\002 Максимум"
-#define MSG_FACTOR                          "\002 Фактор"
+#define MSG_CONTROL                         "Настройки"
+#define MSG_MIN                             LCD_STR_THERMOMETER " Минимум"
+#define MSG_MAX                             LCD_STR_THERMOMETER " Максимум"
+#define MSG_FACTOR                          LCD_STR_THERMOMETER " Фактор"
 #define MSG_AUTOTEMP                        "Autotemp"
 #define MSG_ON                              "Вкл. "
 #define MSG_OFF                             "Выкл. "
@@ -75,10 +75,10 @@
 #define MSG_YSTEPS                          "Y шаг/mm"
 #define MSG_ZSTEPS                          "Z шаг/mm"
 #define MSG_ESTEPS                          "E шаг/mm"
-#define MSG_TEMPERATURE                     "Температура     \x7E"
-#define MSG_MOTION                          "Скорости        \x7E"
+#define MSG_TEMPERATURE                     "Температура"
+#define MSG_MOTION                          "Скорости"
 #define MSG_VOLUMETRIC                      "Filament"
-#define MSG_VOLUMETRIC_ENABLED		        "E in mm3"
+#define MSG_VOLUMETRIC_ENABLED		          "E in mm3"
 #define MSG_FILAMENT_SIZE_EXTRUDER_0        "Fil. Dia. 1"
 #define MSG_FILAMENT_SIZE_EXTRUDER_1        "Fil. Dia. 2"
 #define MSG_FILAMENT_SIZE_EXTRUDER_2        "Fil. Dia. 3"
@@ -86,14 +86,14 @@
 #define MSG_STORE_EPROM                     "Сохранить в EPROM"
 #define MSG_LOAD_EPROM                      "Загруз. из EPROM"
 #define MSG_RESTORE_FAILSAFE                "Сброс настроек"
-#define MSG_REFRESH                         "\004Обновить"
-#define MSG_WATCH                           "Обзор           \003"
-#define MSG_PREPARE                         "Действия        \x7E"
-#define MSG_TUNE                            "Настройки       \x7E"
+#define MSG_REFRESH                         LCD_STR_REFRESH "Обновить"
+#define MSG_WATCH                           "Обзор"
+#define MSG_PREPARE                         "Действия"
+#define MSG_TUNE                            "Настройки"
 #define MSG_PAUSE_PRINT                     "Продолжить печать"
 #define MSG_RESUME_PRINT                    "возобн. печать"
 #define MSG_STOP_PRINT                      "Остановить печать"
-#define MSG_CARD_MENU                       "Меню карты      \x7E"
+#define MSG_CARD_MENU                       "Меню карты"
 #define MSG_NO_CARD                         "Нет карты"
 #define MSG_DWELL                           "Сон..."
 #define MSG_USERWAIT                        "Ожиданиие"
diff --git a/Marlin/ultralcd.cpp b/Marlin/ultralcd.cpp
index 3773ad32406..c9cd3388324 100644
--- a/Marlin/ultralcd.cpp
+++ b/Marlin/ultralcd.cpp
@@ -1260,6 +1260,26 @@ void lcd_init()
 #endif
 }
 
+int lcd_strlen(char *s) {
+     int i = 0, j = 0;
+   while (s[i]) {
+     if ((s[i] & 0xc0) != 0x80) j++;
+     i++;
+   }
+   return j;
+}
+
+int lcd_strlen_P(const char *s) {
+     int j = 0;
+   while (pgm_read_byte(s)) {
+     if ((pgm_read_byte(s) & 0xc0) != 0x80) j++;
+     s++;
+   }
+   return j;
+}
+
+
+
 void lcd_update()
 {
     static unsigned long timeoutToStatus = 0;
@@ -1372,7 +1392,7 @@ void lcd_ignore_click(bool b)
 }
 
 void lcd_finishstatus() {
-  int len = strlen(lcd_status_message);
+  int len = lcd_strlen(lcd_status_message);
   if (len > 0) {
     while (len < LCD_WIDTH) {
       lcd_status_message[len++] = ' ';
diff --git a/Marlin/ultralcd.h b/Marlin/ultralcd.h
index 30175be39d7..d861e9d732f 100644
--- a/Marlin/ultralcd.h
+++ b/Marlin/ultralcd.h
@@ -4,7 +4,8 @@
 #include "Marlin.h"
 
 #ifdef ULTRA_LCD
-
+  int lcd_strlen(char *s);
+  int lcd_strlen_P(const char *s);
   void lcd_update();
   void lcd_init();
   void lcd_setstatus(const char* message);
diff --git a/Marlin/ultralcd_implementation_hitachi_HD44780.h b/Marlin/ultralcd_implementation_hitachi_HD44780.h
index 9eeee1e15dc..1628bf8f4e6 100644
--- a/Marlin/ultralcd_implementation_hitachi_HD44780.h
+++ b/Marlin/ultralcd_implementation_hitachi_HD44780.h
@@ -636,7 +636,7 @@ static void lcd_implementation_drawmenu_generic(uint8_t row, const char* pstr, c
     {
         lcd.print(c);
         pstr++;
-        n--;
+        if ((pgm_read_byte(pstr) & 0xc0) != 0x80) n--;
     }
     while(n--)
         lcd.print(' ');
@@ -648,9 +648,9 @@ static void lcd_implementation_drawmenu_setting_edit_generic(uint8_t row, const
     char c;
     //Use all characters in narrow LCDs
   #if LCD_WIDTH < 20
-      uint8_t n = LCD_WIDTH - 1 - 1 - strlen(data);
+      uint8_t n = LCD_WIDTH - 1 - 1 - lcd_strlen(data);
     #else
-      uint8_t n = LCD_WIDTH - 1 - 2 - strlen(data);
+      uint8_t n = LCD_WIDTH - 1 - 2 - lcd_strlen(data);
   #endif
     lcd.setCursor(0, row);
     lcd.print(pre_char);
@@ -658,7 +658,7 @@ static void lcd_implementation_drawmenu_setting_edit_generic(uint8_t row, const
     {
         lcd.print(c);
         pstr++;
-        n--;
+        if ((pgm_read_byte(pstr) & 0xc0) != 0x80) n--;
     }
     lcd.print(':');
     while(n--)
@@ -670,9 +670,9 @@ static void lcd_implementation_drawmenu_setting_edit_generic_P(uint8_t row, cons
     char c;
     //Use all characters in narrow LCDs
   #if LCD_WIDTH < 20
-      uint8_t n = LCD_WIDTH - 1 - 1 - strlen_P(data);
+      uint8_t n = LCD_WIDTH - 1 - 1 - lcd_strlen_P(data);
     #else
-      uint8_t n = LCD_WIDTH - 1 - 2 - strlen_P(data);
+      uint8_t n = LCD_WIDTH - 1 - 2 - lcd_strlen_P(data);
   #endif
     lcd.setCursor(0, row);
     lcd.print(pre_char);
@@ -680,7 +680,7 @@ static void lcd_implementation_drawmenu_setting_edit_generic_P(uint8_t row, cons
     {
         lcd.print(c);
         pstr++;
-        n--;
+        if ((pgm_read_byte(pstr) & 0xc0) != 0x80) n--;
     }
     lcd.print(':');
     while(n--)
@@ -733,9 +733,9 @@ void lcd_implementation_drawedit(const char* pstr, char* value)
     lcd_printPGM(pstr);
     lcd.print(':');
    #if LCD_WIDTH < 20
-      lcd.setCursor(LCD_WIDTH - strlen(value), 1);
+      lcd.setCursor(LCD_WIDTH - lcd_strlen(value), 1);
     #else
-      lcd.setCursor(LCD_WIDTH -1 - strlen(value), 1);
+      lcd.setCursor(LCD_WIDTH -1 - lcd_strlen(value), 1);
    #endif
     lcd.print(value);
 }