return visual_ptr - *visual_out;
}
-static grub_uint32_t
-map_code (grub_uint32_t in, struct grub_term_output *term)
-{
- if (in <= 0x7f)
- return in;
-
- switch (term->flags & GRUB_TERM_CODE_TYPE_MASK)
- {
- case GRUB_TERM_CODE_TYPE_VGA:
- switch (in)
- {
- case GRUB_TERM_DISP_LEFT:
- return 0x1b;
- case GRUB_TERM_DISP_UP:
- return 0x18;
- case GRUB_TERM_DISP_RIGHT:
- return 0x1a;
- case GRUB_TERM_DISP_DOWN:
- return 0x19;
- case GRUB_TERM_DISP_HLINE:
- return 0xc4;
- case GRUB_TERM_DISP_VLINE:
- return 0xb3;
- case GRUB_TERM_DISP_UL:
- return 0xda;
- case GRUB_TERM_DISP_UR:
- return 0xbf;
- case GRUB_TERM_DISP_LL:
- return 0xc0;
- case GRUB_TERM_DISP_LR:
- return 0xd9;
- }
- return '?';
- case GRUB_TERM_CODE_TYPE_ASCII:
- /* Better than nothing. */
- switch (in)
- {
- case GRUB_TERM_DISP_LEFT:
- return '<';
-
- case GRUB_TERM_DISP_UP:
- return '^';
-
- case GRUB_TERM_DISP_RIGHT:
- return '>';
-
- case GRUB_TERM_DISP_DOWN:
- return 'v';
-
- case GRUB_TERM_DISP_HLINE:
- return '-';
-
- case GRUB_TERM_DISP_VLINE:
- return '|';
-
- case GRUB_TERM_DISP_UL:
- case GRUB_TERM_DISP_UR:
- case GRUB_TERM_DISP_LL:
- case GRUB_TERM_DISP_LR:
- return '+';
-
- }
- return '?';
- }
- return in;
-}
-
-static grub_uint32_t
-mirror_code (grub_uint32_t in)
+grub_uint32_t
+grub_unicode_mirror_code (grub_uint32_t in)
{
int i;
for (i = 0; grub_unicode_bidi_pairs[i].key; i++)
return grub_unicode_bidi_pairs[i].replace;
return in;
}
-
-static void
-putglyph (const struct grub_unicode_glyph *c, struct grub_term_output *term)
-{
- struct grub_unicode_glyph c2 =
- {
- .variant = 0,
- .attributes = 0,
- .ncomb = 0,
- .combining = 0,
- .estimated_width = 1
- };
-
- if (c->base == '\t' && term->getxy)
- {
- int n;
-
- n = 8 - ((term->getxy () >> 8) & 7);
- c2.base = ' ';
- while (n--)
- (term->putchar) (&c2);
-
- return;
- }
-
- if ((term->flags & GRUB_TERM_CODE_TYPE_MASK)
- == GRUB_TERM_CODE_TYPE_UTF8_LOGICAL
- || (term->flags & GRUB_TERM_CODE_TYPE_MASK)
- == GRUB_TERM_CODE_TYPE_UTF8_VISUAL)
- {
- int i;
- c2.estimated_width = grub_term_getcharwidth (term, c);
- for (i = -1; i < (int) c->ncomb; i++)
- {
- grub_uint8_t u8[20], *ptr;
- grub_uint32_t code;
-
- if (i == -1)
- {
- code = c->base;
- if ((term->flags & GRUB_TERM_CODE_TYPE_MASK)
- == GRUB_TERM_CODE_TYPE_UTF8_VISUAL
- && (c->attributes & GRUB_UNICODE_GLYPH_ATTRIBUTE_MIRROR))
- code = mirror_code (code);
- }
- else
- code = c->combining[i].code;
-
- grub_ucs4_to_utf8 (&code, 1, u8, sizeof (u8));
-
- for (ptr = u8; *ptr; ptr++)
- {
- c2.base = *ptr;
- (term->putchar) (&c2);
- c2.estimated_width = 0;
- }
- }
- c2.estimated_width = 1;
- }
- else
- (term->putchar) (c);
-
- if (c->base == '\n')
- {
- c2.base = '\r';
- (term->putchar) (&c2);
- }
-}
-
-static void
-putcode_real (grub_uint32_t code, struct grub_term_output *term)
-{
- struct grub_unicode_glyph c =
- {
- .variant = 0,
- .attributes = 0,
- .ncomb = 0,
- .combining = 0,
- .estimated_width = 1
- };
-
- c.base = map_code (code, term);
- putglyph (&c, term);
-}
-
-/* Put a Unicode character. */
-void
-grub_putcode (grub_uint32_t code, struct grub_term_output *term)
-{
- /* Combining character by itself? */
- if (grub_unicode_get_comb_type (code) != GRUB_UNICODE_COMB_NONE)
- return;
-
- putcode_real (code, term);
-}
-
-void
-grub_print_ucs4 (const grub_uint32_t * str,
- const grub_uint32_t * last_position,
- int margin_left, int margin_right,
- struct grub_term_output *term)
-{
- grub_ssize_t max_width;
- grub_ssize_t startwidth;
-
- {
- struct grub_unicode_glyph space_glyph = {
- .base = ' ',
- .variant = 0,
- .attributes = 0,
- .ncomb = 0,
- .combining = 0
- };
- max_width = grub_term_width (term)
- - grub_term_getcharwidth (term, &space_glyph)
- * (margin_left + margin_right) - 1;
- }
-
- if (((term->getxy () >> 8) & 0xff) < margin_left)
- grub_print_spaces (term, margin_left - ((term->getxy () >> 8) & 0xff));
-
- startwidth = ((term->getxy () >> 8) & 0xff) - margin_left;
-
- if ((term->flags & GRUB_TERM_CODE_TYPE_MASK)
- == GRUB_TERM_CODE_TYPE_VISUAL_GLYPHS
- || (term->flags & GRUB_TERM_CODE_TYPE_MASK)
- == GRUB_TERM_CODE_TYPE_UTF8_VISUAL)
- {
- grub_ssize_t visual_len;
- struct grub_unicode_glyph *visual;
- struct grub_unicode_glyph *visual_ptr;
-
- auto grub_ssize_t getcharwidth (const struct grub_unicode_glyph *c);
- grub_ssize_t getcharwidth (const struct grub_unicode_glyph *c)
- {
- return grub_term_getcharwidth (term, c);
- }
-
- visual_len = grub_bidi_logical_to_visual (str, last_position - str,
- &visual, getcharwidth,
- max_width, startwidth);
- if (visual_len < 0)
- {
- grub_print_error ();
- return;
- }
- for (visual_ptr = visual; visual_ptr < visual + visual_len; visual_ptr++)
- {
- if (visual_ptr->base == '\n')
- grub_print_spaces (term, margin_right);
- putglyph (visual_ptr, term);
- if (visual_ptr->base == '\n')
- grub_print_spaces (term, margin_left);
- grub_free (visual_ptr->combining);
- }
- grub_free (visual);
- return;
- }
-
- {
- const grub_uint32_t *ptr;
- grub_ssize_t line_width = startwidth;
- grub_ssize_t lastspacewidth = 0;
- const grub_uint32_t *line_start = str, *last_space = str - 1;
-
- for (ptr = str; ptr < last_position; ptr++)
- {
- grub_ssize_t last_width = 0;
- if (grub_unicode_get_comb_type (*ptr) == GRUB_UNICODE_COMB_NONE)
- {
- struct grub_unicode_glyph c = {
- .variant = 0,
- .attributes = 0,
- .ncomb = 0,
- .combining = 0
- };
- c.base = *ptr;
- line_width += last_width = grub_term_getcharwidth (term, &c);
- }
-
- if (*ptr == ' ')
- {
- lastspacewidth = line_width;
- last_space = ptr;
- }
-
- if (line_width > max_width || *ptr == '\n')
- {
- const grub_uint32_t *ptr2;
-
- if (line_width > max_width && last_space > line_start)
- ptr = last_space;
- else if (line_width > max_width
- && line_start == str && startwidth != 0)
- {
- ptr = str;
- lastspacewidth = startwidth;
- }
- else
- lastspacewidth = line_width - last_width;
-
- for (ptr2 = line_start; ptr2 < ptr; ptr2++)
- {
- /* Skip combining characters on non-UTF8 terminals. */
- if ((term->flags & GRUB_TERM_CODE_TYPE_MASK)
- != GRUB_TERM_CODE_TYPE_UTF8_LOGICAL
- && grub_unicode_get_comb_type (*ptr2)
- != GRUB_UNICODE_COMB_NONE)
- continue;
- putcode_real (*ptr2, term);
- }
-
- grub_print_spaces (term, margin_right);
- grub_putcode ('\n', term);
- line_width -= lastspacewidth;
- grub_print_spaces (term, margin_left);
- if (ptr == last_space || *ptr == '\n')
- ptr++;
- line_start = ptr;
- }
- }
-
- {
- const grub_uint32_t *ptr2;
- for (ptr2 = line_start; ptr2 < last_position; ptr2++)
- {
- /* Skip combining characters on non-UTF8 terminals. */
- if ((term->flags & GRUB_TERM_CODE_TYPE_MASK)
- != GRUB_TERM_CODE_TYPE_UTF8_LOGICAL
- && grub_unicode_get_comb_type (*ptr2)
- != GRUB_UNICODE_COMB_NONE)
- continue;
- putcode_real (*ptr2, term);
- }
- }
- }
-}
-
-void
-grub_xputs_normal (const char *str)
-{
- grub_term_output_t term;
-
- FOR_ACTIVE_TERM_OUTPUTS(term)
- {
- grub_uint32_t *unicode_str, *unicode_last_position;
- grub_utf8_to_ucs4_alloc (str, &unicode_str,
- &unicode_last_position);
- grub_print_ucs4 (unicode_str, unicode_last_position, 0, 0, term);
- grub_free (unicode_str);
- }
-}
grub_newline_hook = process_newline;
}
+static grub_uint32_t
+map_code (grub_uint32_t in, struct grub_term_output *term)
+{
+ if (in <= 0x7f)
+ return in;
+
+ switch (term->flags & GRUB_TERM_CODE_TYPE_MASK)
+ {
+ case GRUB_TERM_CODE_TYPE_VGA:
+ switch (in)
+ {
+ case GRUB_TERM_DISP_LEFT:
+ return 0x1b;
+ case GRUB_TERM_DISP_UP:
+ return 0x18;
+ case GRUB_TERM_DISP_RIGHT:
+ return 0x1a;
+ case GRUB_TERM_DISP_DOWN:
+ return 0x19;
+ case GRUB_TERM_DISP_HLINE:
+ return 0xc4;
+ case GRUB_TERM_DISP_VLINE:
+ return 0xb3;
+ case GRUB_TERM_DISP_UL:
+ return 0xda;
+ case GRUB_TERM_DISP_UR:
+ return 0xbf;
+ case GRUB_TERM_DISP_LL:
+ return 0xc0;
+ case GRUB_TERM_DISP_LR:
+ return 0xd9;
+ }
+ return '?';
+ case GRUB_TERM_CODE_TYPE_ASCII:
+ /* Better than nothing. */
+ switch (in)
+ {
+ case GRUB_TERM_DISP_LEFT:
+ return '<';
+
+ case GRUB_TERM_DISP_UP:
+ return '^';
+
+ case GRUB_TERM_DISP_RIGHT:
+ return '>';
+
+ case GRUB_TERM_DISP_DOWN:
+ return 'v';
+
+ case GRUB_TERM_DISP_HLINE:
+ return '-';
+
+ case GRUB_TERM_DISP_VLINE:
+ return '|';
+
+ case GRUB_TERM_DISP_UL:
+ case GRUB_TERM_DISP_UR:
+ case GRUB_TERM_DISP_LL:
+ case GRUB_TERM_DISP_LR:
+ return '+';
+
+ }
+ return '?';
+ }
+ return in;
+}
+
void
grub_puts_terminal (const char *str, struct grub_term_output *term)
{
grub_errno = GRUB_ERR_NONE;
}
+
+static void
+putglyph (const struct grub_unicode_glyph *c, struct grub_term_output *term)
+{
+ struct grub_unicode_glyph c2 =
+ {
+ .variant = 0,
+ .attributes = 0,
+ .ncomb = 0,
+ .combining = 0,
+ .estimated_width = 1
+ };
+
+ if (c->base == '\t' && term->getxy)
+ {
+ int n;
+
+ n = 8 - ((term->getxy () >> 8) & 7);
+ c2.base = ' ';
+ while (n--)
+ (term->putchar) (&c2);
+
+ return;
+ }
+
+ if ((term->flags & GRUB_TERM_CODE_TYPE_MASK)
+ == GRUB_TERM_CODE_TYPE_UTF8_LOGICAL
+ || (term->flags & GRUB_TERM_CODE_TYPE_MASK)
+ == GRUB_TERM_CODE_TYPE_UTF8_VISUAL)
+ {
+ int i;
+ c2.estimated_width = grub_term_getcharwidth (term, c);
+ for (i = -1; i < (int) c->ncomb; i++)
+ {
+ grub_uint8_t u8[20], *ptr;
+ grub_uint32_t code;
+
+ if (i == -1)
+ {
+ code = c->base;
+ if ((term->flags & GRUB_TERM_CODE_TYPE_MASK)
+ == GRUB_TERM_CODE_TYPE_UTF8_VISUAL
+ && (c->attributes & GRUB_UNICODE_GLYPH_ATTRIBUTE_MIRROR))
+ code = grub_unicode_mirror_code (code);
+ }
+ else
+ code = c->combining[i].code;
+
+ grub_ucs4_to_utf8 (&code, 1, u8, sizeof (u8));
+
+ for (ptr = u8; *ptr; ptr++)
+ {
+ c2.base = *ptr;
+ (term->putchar) (&c2);
+ c2.estimated_width = 0;
+ }
+ }
+ c2.estimated_width = 1;
+ }
+ else
+ (term->putchar) (c);
+
+ if (c->base == '\n')
+ {
+ c2.base = '\r';
+ (term->putchar) (&c2);
+ }
+}
+
+static void
+putcode_real (grub_uint32_t code, struct grub_term_output *term)
+{
+ struct grub_unicode_glyph c =
+ {
+ .variant = 0,
+ .attributes = 0,
+ .ncomb = 0,
+ .combining = 0,
+ .estimated_width = 1
+ };
+
+ c.base = map_code (code, term);
+ putglyph (&c, term);
+}
+
+/* Put a Unicode character. */
+void
+grub_putcode (grub_uint32_t code, struct grub_term_output *term)
+{
+ /* Combining character by itself? */
+ if (grub_unicode_get_comb_type (code) != GRUB_UNICODE_COMB_NONE)
+ return;
+
+ putcode_real (code, term);
+}
+
+void
+grub_print_ucs4 (const grub_uint32_t * str,
+ const grub_uint32_t * last_position,
+ int margin_left, int margin_right,
+ struct grub_term_output *term)
+{
+ grub_ssize_t max_width;
+ grub_ssize_t startwidth;
+
+ {
+ struct grub_unicode_glyph space_glyph = {
+ .base = ' ',
+ .variant = 0,
+ .attributes = 0,
+ .ncomb = 0,
+ .combining = 0
+ };
+ max_width = grub_term_width (term)
+ - grub_term_getcharwidth (term, &space_glyph)
+ * (margin_left + margin_right) - 1;
+ }
+
+ if (((term->getxy () >> 8) & 0xff) < margin_left)
+ grub_print_spaces (term, margin_left - ((term->getxy () >> 8) & 0xff));
+
+ startwidth = ((term->getxy () >> 8) & 0xff) - margin_left;
+
+ if ((term->flags & GRUB_TERM_CODE_TYPE_MASK)
+ == GRUB_TERM_CODE_TYPE_VISUAL_GLYPHS
+ || (term->flags & GRUB_TERM_CODE_TYPE_MASK)
+ == GRUB_TERM_CODE_TYPE_UTF8_VISUAL)
+ {
+ grub_ssize_t visual_len;
+ struct grub_unicode_glyph *visual;
+ struct grub_unicode_glyph *visual_ptr;
+
+ auto grub_ssize_t getcharwidth (const struct grub_unicode_glyph *c);
+ grub_ssize_t getcharwidth (const struct grub_unicode_glyph *c)
+ {
+ return grub_term_getcharwidth (term, c);
+ }
+
+ visual_len = grub_bidi_logical_to_visual (str, last_position - str,
+ &visual, getcharwidth,
+ max_width, startwidth);
+ if (visual_len < 0)
+ {
+ grub_print_error ();
+ return;
+ }
+ for (visual_ptr = visual; visual_ptr < visual + visual_len; visual_ptr++)
+ {
+ if (visual_ptr->base == '\n')
+ grub_print_spaces (term, margin_right);
+ putglyph (visual_ptr, term);
+ if (visual_ptr->base == '\n')
+ grub_print_spaces (term, margin_left);
+ grub_free (visual_ptr->combining);
+ }
+ grub_free (visual);
+ return;
+ }
+
+ {
+ const grub_uint32_t *ptr;
+ grub_ssize_t line_width = startwidth;
+ grub_ssize_t lastspacewidth = 0;
+ const grub_uint32_t *line_start = str, *last_space = str - 1;
+
+ for (ptr = str; ptr < last_position; ptr++)
+ {
+ grub_ssize_t last_width = 0;
+ if (grub_unicode_get_comb_type (*ptr) == GRUB_UNICODE_COMB_NONE)
+ {
+ struct grub_unicode_glyph c = {
+ .variant = 0,
+ .attributes = 0,
+ .ncomb = 0,
+ .combining = 0
+ };
+ c.base = *ptr;
+ line_width += last_width = grub_term_getcharwidth (term, &c);
+ }
+
+ if (*ptr == ' ')
+ {
+ lastspacewidth = line_width;
+ last_space = ptr;
+ }
+
+ if (line_width > max_width || *ptr == '\n')
+ {
+ const grub_uint32_t *ptr2;
+
+ if (line_width > max_width && last_space > line_start)
+ ptr = last_space;
+ else if (line_width > max_width
+ && line_start == str && startwidth != 0)
+ {
+ ptr = str;
+ lastspacewidth = startwidth;
+ }
+ else
+ lastspacewidth = line_width - last_width;
+
+ for (ptr2 = line_start; ptr2 < ptr; ptr2++)
+ {
+ /* Skip combining characters on non-UTF8 terminals. */
+ if ((term->flags & GRUB_TERM_CODE_TYPE_MASK)
+ != GRUB_TERM_CODE_TYPE_UTF8_LOGICAL
+ && grub_unicode_get_comb_type (*ptr2)
+ != GRUB_UNICODE_COMB_NONE)
+ continue;
+ putcode_real (*ptr2, term);
+ }
+
+ grub_print_spaces (term, margin_right);
+ grub_putcode ('\n', term);
+ line_width -= lastspacewidth;
+ grub_print_spaces (term, margin_left);
+ if (ptr == last_space || *ptr == '\n')
+ ptr++;
+ line_start = ptr;
+ }
+ }
+
+ {
+ const grub_uint32_t *ptr2;
+ for (ptr2 = line_start; ptr2 < last_position; ptr2++)
+ {
+ /* Skip combining characters on non-UTF8 terminals. */
+ if ((term->flags & GRUB_TERM_CODE_TYPE_MASK)
+ != GRUB_TERM_CODE_TYPE_UTF8_LOGICAL
+ && grub_unicode_get_comb_type (*ptr2)
+ != GRUB_UNICODE_COMB_NONE)
+ continue;
+ putcode_real (*ptr2, term);
+ }
+ }
+ }
+}
+
+void
+grub_xputs_normal (const char *str)
+{
+ grub_term_output_t term;
+
+ FOR_ACTIVE_TERM_OUTPUTS(term)
+ {
+ grub_uint32_t *unicode_str, *unicode_last_position;
+ grub_utf8_to_ucs4_alloc (str, &unicode_str,
+ &unicode_last_position);
+ grub_print_ucs4 (unicode_str, unicode_last_position, 0, 0, term);
+ grub_free (unicode_str);
+ }
+}