]> git.ipfire.org Git - thirdparty/grub.git/commitdiff
* grub-core/commands/cat.c: Show UTF-8 characters.
authorVladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Wed, 8 May 2013 09:09:08 +0000 (11:09 +0200)
committerVladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Wed, 8 May 2013 09:09:08 +0000 (11:09 +0200)
ChangeLog
grub-core/commands/cat.c
include/grub/charset.h

index 0da7177af41bd823e57340216b6cdbbcaacb9514..a57d103b033efa92fc141274ab7bf481995a803c 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+2013-05-08  Vladimir Serbinenko  <phcoder@gmail.com>
+
+       * grub-core/commands/cat.c: Show UTF-8 characters.
+
 2013-05-08  Vladimir Serbinenko  <phcoder@gmail.com>
 
        * conf/Makefile.common: Poison float and double on non-emu.
index cd2d760998e97da809296fe025296c3ad9ce9b73..8a7f1af78444bd830fa912ea34bee53dd79d082f 100644 (file)
@@ -24,6 +24,7 @@
 #include <grub/misc.h>
 #include <grub/extcmd.h>
 #include <grub/i18n.h>
+#include <grub/charset.h>
 
 GRUB_MOD_LICENSE ("GPLv3+");
 
@@ -39,9 +40,15 @@ grub_cmd_cat (grub_extcmd_context_t ctxt, int argc, char **args)
   struct grub_arg_list *state = ctxt->state;
   int dos = 0;
   grub_file_t file;
-  char buf[GRUB_DISK_SECTOR_SIZE];
+  unsigned char buf[GRUB_DISK_SECTOR_SIZE];
   grub_ssize_t size;
   int key = GRUB_TERM_NO_KEY;
+  grub_uint32_t code = 0;
+  int count = 0;
+  unsigned char utbuf[GRUB_MAX_UTF8_PER_CODEPOINT + 1];
+  int utcount = 0;
+  int is_0d = 0;
+  int j;
 
   if (state[0].set)
     dos = 1;
@@ -60,21 +67,65 @@ grub_cmd_cat (grub_extcmd_context_t ctxt, int argc, char **args)
 
       for (i = 0; i < size; i++)
        {
-         unsigned char c = buf[i];
+         utbuf[utcount++] = buf[i];
 
-         if ((grub_isprint (c) || grub_isspace (c)) && c != '\r')
-           grub_printf ("%c", c);
-         else if (dos && c == '\r' && i + 1 < size && buf[i + 1] == '\n')
+         if (is_0d && buf[i] != '\n')
            {
-             grub_printf ("\n");
-             i++;
+             grub_setcolorstate (GRUB_TERM_COLOR_HIGHLIGHT);
+             grub_printf ("<%x>", (int) '\r');
+             grub_setcolorstate (GRUB_TERM_COLOR_STANDARD);
            }
-         else
+
+         is_0d = 0;
+
+         if (!grub_utf8_process (buf[i], &code, &count))
            {
              grub_setcolorstate (GRUB_TERM_COLOR_HIGHLIGHT);
-             grub_printf ("<%x>", (int) c);
+             for (j = 0; j < utcount - 1; j++)
+               grub_printf ("<%x>", (unsigned int) utbuf[j]);
+             code = 0;
+             count = 0;
+             if (utcount == 1 || !grub_utf8_process (buf[i], &code, &count))
+               {
+                 grub_printf ("<%x>", (unsigned int) buf[i]);
+                 code = 0;
+                 count = 0;
+                 utcount = 0;
+                 grub_setcolorstate (GRUB_TERM_COLOR_STANDARD);
+                 continue;
+               }
              grub_setcolorstate (GRUB_TERM_COLOR_STANDARD);
+             utcount = 1;
            }
+         if (count)
+           continue;
+
+         if ((code >= 0xa1 || grub_isprint (code)
+              || grub_isspace (code)) && code != '\r')
+           {
+             grub_printf ("%C", code);
+             count = 0; 
+             code = 0;
+             utcount = 0;
+             continue;
+           }
+
+         if (dos && code == '\r')
+           {
+             is_0d = 1;
+             count = 0; 
+             code = 0;
+             utcount = 0;
+             continue;
+           }
+
+         grub_setcolorstate (GRUB_TERM_COLOR_HIGHLIGHT);
+         for (j = 0; j < utcount; j++)
+           grub_printf ("<%x>", (unsigned int) utbuf[j]);
+         grub_setcolorstate (GRUB_TERM_COLOR_STANDARD);
+         count = 0; 
+         code = 0;
+         utcount = 0;
        }
 
       do
@@ -82,6 +133,18 @@ grub_cmd_cat (grub_extcmd_context_t ctxt, int argc, char **args)
       while (key != GRUB_TERM_ESC && key != GRUB_TERM_NO_KEY);
     }
 
+  if (is_0d)
+    {
+      grub_setcolorstate (GRUB_TERM_COLOR_HIGHLIGHT);
+      grub_printf ("<%x>", (unsigned int) '\r');
+      grub_setcolorstate (GRUB_TERM_COLOR_STANDARD);
+    }
+
+  grub_setcolorstate (GRUB_TERM_COLOR_HIGHLIGHT);
+  for (j = 0; j < utcount; j++)
+    grub_printf ("<%x>", (unsigned int) utbuf[j]);
+  grub_setcolorstate (GRUB_TERM_COLOR_STANDARD);
+
   grub_xputs ("\n");
   grub_refresh ();
   grub_file_close (file);
index ab9202884419326449f1f27851c66a31728750a7..d14faea3271386c300d6ae301197a30b8a191c35 100644 (file)
@@ -41,6 +41,7 @@
    You need at least three UTF-8 bytes to have 2 UTF-16 words (surrogate pairs).
  */
 #define GRUB_MAX_UTF16_PER_UTF8 1
+#define GRUB_MAX_UTF8_PER_CODEPOINT 4
 
 #define GRUB_UCS2_LIMIT 0x10000
 #define GRUB_UTF16_UPPER_SURROGATE(code) \
@@ -67,6 +68,14 @@ grub_utf8_process (grub_uint8_t c, grub_uint32_t *code, int *count)
          *code <<= 6;
          *code |= (c & GRUB_UINT8_6_TRAILINGBITS);
          (*count)--;
+         /* Overlong.  */
+         if ((*count == 1 && *code <= 0x1f)
+             || (*count == 2 && *code <= 0xf))
+           {
+             *code = 0;
+             *count = 0;
+             return 0;
+           }
          return 1;
        }
     }
@@ -80,6 +89,13 @@ grub_utf8_process (grub_uint8_t c, grub_uint32_t *code, int *count)
     {
       *count = 1;
       *code = c & GRUB_UINT8_5_TRAILINGBITS;
+      /* Overlong */
+      if (*code <= 1)
+       {
+         *count = 0;
+         *code = 0;
+         return 0;
+       }
       return 1;
     }
   if ((c & GRUB_UINT8_4_LEADINGBITS) == GRUB_UINT8_3_LEADINGBITS)