* grub-core/commands/cat.c: Show UTF-8 characters.

This commit is contained in:
Vladimir 'phcoder' Serbinenko 2013-05-08 11:09:08 +02:00
parent 3e912fda81
commit 16f7c8f6d3
3 changed files with 94 additions and 11 deletions

View file

@ -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.

View 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')
{
grub_printf ("\n");
i++;
}
else
if (is_0d && buf[i] != '\n')
{
grub_setcolorstate (GRUB_TERM_COLOR_HIGHLIGHT);
grub_printf ("<%x>", (int) c);
grub_printf ("<%x>", (int) '\r');
grub_setcolorstate (GRUB_TERM_COLOR_STANDARD);
}
is_0d = 0;
if (!grub_utf8_process (buf[i], &code, &count))
{
grub_setcolorstate (GRUB_TERM_COLOR_HIGHLIGHT);
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);

View 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)