Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
dadigang
Ventoy
Commits
15b8b1f3
Unverified
Commit
15b8b1f3
authored
Mar 29, 2022
by
A1ive
Committed by
GitHub
Mar 29, 2022
Browse files
support scrolling menu entry's text (#1539)
parent
a20592ec
Changes
9
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
2902 additions
and
0 deletions
+2902
-0
GRUB2/MOD_SRC/grub-2.04/grub-core/gfxmenu/gfxmenu.c
GRUB2/MOD_SRC/grub-2.04/grub-core/gfxmenu/gfxmenu.c
+4
-0
GRUB2/MOD_SRC/grub-2.04/grub-core/gfxmenu/gui_list.c
GRUB2/MOD_SRC/grub-2.04/grub-core/gfxmenu/gui_list.c
+961
-0
GRUB2/MOD_SRC/grub-2.04/grub-core/gfxmenu/view.c
GRUB2/MOD_SRC/grub-2.04/grub-core/gfxmenu/view.c
+24
-0
GRUB2/MOD_SRC/grub-2.04/grub-core/normal/charset.c
GRUB2/MOD_SRC/grub-2.04/grub-core/normal/charset.c
+1352
-0
GRUB2/MOD_SRC/grub-2.04/grub-core/normal/menu.c
GRUB2/MOD_SRC/grub-2.04/grub-core/normal/menu.c
+16
-0
GRUB2/MOD_SRC/grub-2.04/grub-core/normal/menu_text.c
GRUB2/MOD_SRC/grub-2.04/grub-core/normal/menu_text.c
+39
-0
GRUB2/MOD_SRC/grub-2.04/include/grub/charset.h
GRUB2/MOD_SRC/grub-2.04/include/grub/charset.h
+329
-0
GRUB2/MOD_SRC/grub-2.04/include/grub/gfxmenu_view.h
GRUB2/MOD_SRC/grub-2.04/include/grub/gfxmenu_view.h
+128
-0
GRUB2/MOD_SRC/grub-2.04/include/grub/menu_viewer.h
GRUB2/MOD_SRC/grub-2.04/include/grub/menu_viewer.h
+49
-0
No files found.
GRUB2/MOD_SRC/grub-2.04/grub-core/gfxmenu/gfxmenu.c
View file @
15b8b1f3
...
@@ -119,6 +119,8 @@ grub_gfxmenu_try (int entry, grub_menu_t menu, int nested)
...
@@ -119,6 +119,8 @@ grub_gfxmenu_try (int entry, grub_menu_t menu, int nested)
view
->
menu
=
menu
;
view
->
menu
=
menu
;
view
->
nested
=
nested
;
view
->
nested
=
nested
;
view
->
first_timeout
=
-
1
;
view
->
first_timeout
=
-
1
;
if
(
menu
->
size
)
view
->
menu_title_offset
=
grub_zalloc
(
sizeof
(
*
view
->
menu_title_offset
)
*
menu
->
size
);
grub_video_set_viewport
(
0
,
0
,
mode_info
.
width
,
mode_info
.
height
);
grub_video_set_viewport
(
0
,
0
,
mode_info
.
width
,
mode_info
.
height
);
if
(
view
->
double_repaint
)
if
(
view
->
double_repaint
)
...
@@ -134,6 +136,8 @@ grub_gfxmenu_try (int entry, grub_menu_t menu, int nested)
...
@@ -134,6 +136,8 @@ grub_gfxmenu_try (int entry, grub_menu_t menu, int nested)
instance
->
fini
=
grub_gfxmenu_viewer_fini
;
instance
->
fini
=
grub_gfxmenu_viewer_fini
;
instance
->
print_timeout
=
grub_gfxmenu_print_timeout
;
instance
->
print_timeout
=
grub_gfxmenu_print_timeout
;
instance
->
clear_timeout
=
grub_gfxmenu_clear_timeout
;
instance
->
clear_timeout
=
grub_gfxmenu_clear_timeout
;
if
(
view
->
menu_title_offset
)
instance
->
scroll_chosen_entry
=
grub_gfxmenu_scroll_chosen_entry
;
grub_menu_register_viewer
(
instance
);
grub_menu_register_viewer
(
instance
);
...
...
GRUB2/MOD_SRC/grub-2.04/grub-core/gfxmenu/gui_list.c
0 → 100644
View file @
15b8b1f3
/* gui_list.c - GUI component to display a selectable list of items. */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2008,2009 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#include <grub/mm.h>
#include <grub/misc.h>
#include <grub/gui.h>
#include <grub/gui_string_util.h>
#include <grub/gfxmenu_view.h>
#include <grub/gfxwidgets.h>
#include <grub/color.h>
#include <grub/charset.h>
enum
scrollbar_slice_mode
{
SCROLLBAR_SLICE_WEST
,
SCROLLBAR_SLICE_CENTER
,
SCROLLBAR_SLICE_EAST
};
struct
grub_gui_list_impl
{
struct
grub_gui_list
list
;
grub_gui_container_t
parent
;
grub_video_rect_t
bounds
;
char
*
id
;
int
visible
;
int
icon_width
;
int
icon_height
;
int
item_height
;
int
item_padding
;
int
item_icon_space
;
int
item_spacing
;
grub_font_t
item_font
;
int
selected_item_font_inherit
;
grub_font_t
selected_item_font
;
grub_video_rgba_color_t
item_color
;
int
selected_item_color_inherit
;
grub_video_rgba_color_t
selected_item_color
;
int
draw_scrollbar
;
int
need_to_recreate_scrollbar
;
char
*
scrollbar_frame_pattern
;
char
*
scrollbar_thumb_pattern
;
grub_gfxmenu_box_t
scrollbar_frame
;
grub_gfxmenu_box_t
scrollbar_thumb
;
int
scrollbar_thumb_overlay
;
int
scrollbar_width
;
enum
scrollbar_slice_mode
scrollbar_slice
;
int
scrollbar_left_pad
;
int
scrollbar_right_pad
;
int
scrollbar_top_pad
;
int
scrollbar_bottom_pad
;
int
first_shown_index
;
int
need_to_recreate_boxes
;
char
*
theme_dir
;
char
*
menu_box_pattern
;
char
*
item_box_pattern
;
int
selected_item_box_pattern_inherit
;
char
*
selected_item_box_pattern
;
grub_gfxmenu_box_t
menu_box
;
grub_gfxmenu_box_t
selected_item_box
;
grub_gfxmenu_box_t
item_box
;
grub_gfxmenu_icon_manager_t
icon_manager
;
grub_gfxmenu_view_t
view
;
};
typedef
struct
grub_gui_list_impl
*
list_impl_t
;
static
void
list_destroy
(
void
*
vself
)
{
list_impl_t
self
=
vself
;
grub_free
(
self
->
theme_dir
);
grub_free
(
self
->
menu_box_pattern
);
grub_free
(
self
->
item_box_pattern
);
grub_free
(
self
->
selected_item_box_pattern
);
if
(
self
->
menu_box
)
self
->
menu_box
->
destroy
(
self
->
menu_box
);
if
(
self
->
item_box
)
self
->
item_box
->
destroy
(
self
->
item_box
);
if
(
self
->
selected_item_box
)
self
->
selected_item_box
->
destroy
(
self
->
selected_item_box
);
if
(
self
->
icon_manager
)
grub_gfxmenu_icon_manager_destroy
(
self
->
icon_manager
);
if
(
self
->
scrollbar_thumb
)
self
->
scrollbar_thumb
->
destroy
(
self
->
scrollbar_thumb
);
if
(
self
->
scrollbar_frame
)
self
->
scrollbar_frame
->
destroy
(
self
->
scrollbar_frame
);
grub_free
(
self
->
scrollbar_thumb_pattern
);
grub_free
(
self
->
scrollbar_frame_pattern
);
grub_free
(
self
);
}
static
int
get_num_shown_items
(
list_impl_t
self
)
{
int
boxpad
=
self
->
item_padding
;
int
item_vspace
=
self
->
item_spacing
;
int
item_height
=
self
->
item_height
;
grub_gfxmenu_box_t
box
=
self
->
menu_box
;
int
box_top_pad
=
box
->
get_top_pad
(
box
);
int
box_bottom_pad
=
box
->
get_bottom_pad
(
box
);
grub_gfxmenu_box_t
itembox
=
self
->
item_box
;
grub_gfxmenu_box_t
selbox
=
self
->
selected_item_box
;
int
item_top_pad
=
itembox
->
get_top_pad
(
itembox
);
int
item_bottom_pad
=
itembox
->
get_bottom_pad
(
itembox
);
int
sel_top_pad
=
selbox
->
get_top_pad
(
selbox
);
int
sel_bottom_pad
=
selbox
->
get_bottom_pad
(
selbox
);
int
max_top_pad
=
grub_max
(
item_top_pad
,
sel_top_pad
);
int
max_bottom_pad
=
grub_max
(
item_bottom_pad
,
sel_bottom_pad
);
if
(
item_height
+
item_vspace
<=
0
)
return
1
;
return
(
self
->
bounds
.
height
+
item_vspace
-
2
*
boxpad
-
max_top_pad
-
max_bottom_pad
-
box_top_pad
-
box_bottom_pad
)
/
(
item_height
+
item_vspace
);
}
static
int
check_boxes
(
list_impl_t
self
)
{
if
(
self
->
need_to_recreate_boxes
)
{
grub_gui_recreate_box
(
&
self
->
menu_box
,
self
->
menu_box_pattern
,
self
->
theme_dir
);
grub_gui_recreate_box
(
&
self
->
item_box
,
self
->
item_box_pattern
,
self
->
theme_dir
);
grub_gui_recreate_box
(
&
self
->
selected_item_box
,
self
->
selected_item_box_pattern
,
self
->
theme_dir
);
self
->
need_to_recreate_boxes
=
0
;
}
return
(
self
->
menu_box
!=
0
&&
self
->
selected_item_box
!=
0
&&
self
->
item_box
!=
0
);
}
static
int
check_scrollbar
(
list_impl_t
self
)
{
if
(
self
->
need_to_recreate_scrollbar
)
{
grub_gui_recreate_box
(
&
self
->
scrollbar_frame
,
self
->
scrollbar_frame_pattern
,
self
->
theme_dir
);
grub_gui_recreate_box
(
&
self
->
scrollbar_thumb
,
self
->
scrollbar_thumb_pattern
,
self
->
theme_dir
);
self
->
need_to_recreate_scrollbar
=
0
;
}
if
(
self
->
scrollbar_frame
==
0
||
self
->
scrollbar_thumb
==
0
)
return
0
;
/* Sanity checks. */
grub_gfxmenu_box_t
frame
=
self
->
scrollbar_frame
;
grub_gfxmenu_box_t
thumb
=
self
->
scrollbar_thumb
;
grub_gfxmenu_box_t
menu
=
self
->
menu_box
;
int
min_width
=
frame
->
get_left_pad
(
frame
)
+
frame
->
get_right_pad
(
frame
);
int
min_height
=
frame
->
get_top_pad
(
frame
)
+
frame
->
get_bottom_pad
(
frame
)
+
self
->
scrollbar_top_pad
+
self
->
scrollbar_bottom_pad
+
menu
->
get_top_pad
(
menu
)
+
menu
->
get_bottom_pad
(
menu
);
if
(
!
self
->
scrollbar_thumb_overlay
)
{
min_width
+=
thumb
->
get_left_pad
(
thumb
)
+
thumb
->
get_right_pad
(
thumb
);
min_height
+=
thumb
->
get_top_pad
(
thumb
)
+
thumb
->
get_bottom_pad
(
thumb
);
}
if
(
min_width
<=
self
->
scrollbar_width
&&
min_height
<=
(
int
)
self
->
bounds
.
height
)
return
1
;
/* Unprintable dimenstions. */
self
->
draw_scrollbar
=
0
;
return
0
;
}
static
const
char
*
list_get_id
(
void
*
vself
)
{
list_impl_t
self
=
vself
;
return
self
->
id
;
}
static
int
list_is_instance
(
void
*
vself
__attribute__
((
unused
)),
const
char
*
type
)
{
return
(
grub_strcmp
(
type
,
"component"
)
==
0
||
grub_strcmp
(
type
,
"list"
)
==
0
);
}
static
struct
grub_video_bitmap
*
get_item_icon
(
list_impl_t
self
,
int
item_index
)
{
grub_menu_entry_t
entry
;
entry
=
grub_menu_get_entry
(
self
->
view
->
menu
,
item_index
);
if
(
!
entry
)
return
0
;
return
grub_gfxmenu_icon_manager_get_icon
(
self
->
icon_manager
,
entry
);
}
static
void
make_selected_item_visible
(
list_impl_t
self
)
{
int
selected_index
=
self
->
view
->
selected
;
if
(
selected_index
<
0
)
return
;
/* No item is selected. */
int
num_shown_items
=
get_num_shown_items
(
self
);
int
last_shown_index
=
self
->
first_shown_index
+
(
num_shown_items
-
1
);
if
(
selected_index
<
self
->
first_shown_index
)
self
->
first_shown_index
=
selected_index
;
else
if
(
selected_index
>
last_shown_index
)
self
->
first_shown_index
=
selected_index
-
(
num_shown_items
-
1
);
}
/* Draw a scrollbar on the menu. */
static
void
draw_scrollbar
(
list_impl_t
self
,
int
value
,
int
extent
,
int
min
,
int
max
,
int
scrollbar_width
,
int
scrollbar_height
)
{
unsigned
thumby
,
thumbheight
;
grub_gfxmenu_box_t
frame
=
self
->
scrollbar_frame
;
grub_gfxmenu_box_t
thumb
=
self
->
scrollbar_thumb
;
int
frame_vertical_pad
=
(
frame
->
get_top_pad
(
frame
)
+
frame
->
get_bottom_pad
(
frame
));
int
frame_horizontal_pad
=
(
frame
->
get_left_pad
(
frame
)
+
frame
->
get_right_pad
(
frame
));
unsigned
thumb_vertical_pad
=
(
thumb
->
get_top_pad
(
thumb
)
+
thumb
->
get_bottom_pad
(
thumb
));
int
thumb_horizontal_pad
=
(
thumb
->
get_left_pad
(
thumb
)
+
thumb
->
get_right_pad
(
thumb
));
int
tracktop
=
frame
->
get_top_pad
(
frame
);
unsigned
tracklen
;
if
(
scrollbar_height
<=
frame_vertical_pad
)
tracklen
=
0
;
else
tracklen
=
scrollbar_height
-
frame_vertical_pad
;
frame
->
set_content_size
(
frame
,
scrollbar_width
-
frame_horizontal_pad
,
tracklen
);
if
(
self
->
scrollbar_thumb_overlay
)
{
tracklen
+=
thumb_vertical_pad
;
tracktop
-=
thumb
->
get_top_pad
(
thumb
);
}
if
(
value
<=
min
||
max
<=
min
)
thumby
=
0
;
else
thumby
=
((
unsigned
)
tracklen
*
(
value
-
min
))
/
((
unsigned
)
(
max
-
min
));
if
(
max
<=
min
)
thumbheight
=
1
;
else
thumbheight
=
((
unsigned
)
(
tracklen
*
extent
)
/
((
unsigned
)
(
max
-
min
)))
+
1
;
/* Rare occasion: too many entries or too low height. */
if
(
thumbheight
<
thumb_vertical_pad
)
{
thumbheight
=
thumb_vertical_pad
;
if
(
value
<=
min
||
max
<=
extent
||
tracklen
<=
thumb_vertical_pad
)
thumby
=
0
;
else
thumby
=
((
unsigned
)
((
tracklen
-
thumb_vertical_pad
)
*
(
value
-
min
))
/
((
unsigned
)(
max
-
extent
)));
}
thumby
+=
tracktop
;
int
thumbx
=
frame
->
get_left_pad
(
frame
);
int
thumbwidth
=
scrollbar_width
-
frame_horizontal_pad
;
if
(
!
self
->
scrollbar_thumb_overlay
)
thumbwidth
-=
thumb_horizontal_pad
;
else
thumbx
-=
thumb
->
get_left_pad
(
thumb
);
thumb
->
set_content_size
(
thumb
,
thumbwidth
,
thumbheight
-
thumb_vertical_pad
);
frame
->
draw
(
frame
,
0
,
0
);
thumb
->
draw
(
thumb
,
thumbx
,
thumby
);
}
/* Draw the list of items. */
static
void
draw_menu
(
list_impl_t
self
,
int
num_shown_items
)
{
if
(
!
self
->
menu_box
||
!
self
->
selected_item_box
||
!
self
->
item_box
)
return
;
int
boxpad
=
self
->
item_padding
;
int
icon_text_space
=
self
->
item_icon_space
;
int
item_vspace
=
self
->
item_spacing
;
int
ascent
=
grub_font_get_ascent
(
self
->
item_font
);
int
descent
=
grub_font_get_descent
(
self
->
item_font
);
int
selected_ascent
=
grub_font_get_ascent
(
self
->
selected_item_font
);
int
selected_descent
=
grub_font_get_descent
(
self
->
selected_item_font
);
int
text_box_height
=
self
->
item_height
;
make_selected_item_visible
(
self
);
grub_gfxmenu_box_t
itembox
=
self
->
item_box
;
grub_gfxmenu_box_t
selbox
=
self
->
selected_item_box
;
int
item_leftpad
=
itembox
->
get_left_pad
(
itembox
);
int
item_rightpad
=
itembox
->
get_right_pad
(
itembox
);
int
item_border_width
=
item_leftpad
+
item_rightpad
;
int
item_toppad
=
itembox
->
get_top_pad
(
itembox
);
int
sel_leftpad
=
selbox
->
get_left_pad
(
selbox
);
int
sel_rightpad
=
selbox
->
get_right_pad
(
selbox
);
int
sel_border_width
=
sel_leftpad
+
sel_rightpad
;
int
sel_toppad
=
selbox
->
get_top_pad
(
selbox
);
int
max_leftpad
=
grub_max
(
item_leftpad
,
sel_leftpad
);
int
max_toppad
=
grub_max
(
item_toppad
,
sel_toppad
);
int
item_top
=
0
;
int
menu_index
;
int
visible_index
;
struct
grub_video_rect
oviewport
;
grub_video_get_viewport
(
&
oviewport
.
x
,
&
oviewport
.
y
,
&
oviewport
.
width
,
&
oviewport
.
height
);
grub_video_set_viewport
(
oviewport
.
x
+
boxpad
,
oviewport
.
y
+
boxpad
,
oviewport
.
width
-
2
*
boxpad
,
oviewport
.
height
-
2
*
boxpad
);
int
cwidth
=
oviewport
.
width
-
2
*
boxpad
;
itembox
->
set_content_size
(
itembox
,
cwidth
-
item_border_width
,
text_box_height
);
selbox
->
set_content_size
(
selbox
,
cwidth
-
sel_border_width
,
text_box_height
);
int
text_left_offset
=
self
->
icon_width
+
icon_text_space
;
int
item_text_top_offset
=
(
text_box_height
-
(
ascent
+
descent
))
/
2
+
ascent
;
int
sel_text_top_offset
=
(
text_box_height
-
(
selected_ascent
+
selected_descent
))
/
2
+
selected_ascent
;
grub_video_rect_t
svpsave
,
sviewport
;
sviewport
.
x
=
max_leftpad
+
text_left_offset
;
int
text_viewport_width
=
cwidth
-
sviewport
.
x
;
sviewport
.
height
=
text_box_height
;
grub_video_color_t
item_color
;
grub_video_color_t
sel_color
;
item_color
=
grub_video_map_rgba_color
(
self
->
item_color
);
sel_color
=
grub_video_map_rgba_color
(
self
->
selected_item_color
);
int
item_box_top_offset
=
max_toppad
-
item_toppad
;
int
sel_box_top_offset
=
max_toppad
-
sel_toppad
;
int
item_viewport_width
=
text_viewport_width
-
item_rightpad
;
int
sel_viewport_width
=
text_viewport_width
-
sel_rightpad
;
int
tmp_icon_top_offset
=
(
text_box_height
-
self
->
icon_height
)
/
2
;
int
item_icon_top_offset
=
item_toppad
+
tmp_icon_top_offset
;
int
sel_icon_top_offset
=
sel_toppad
+
tmp_icon_top_offset
;
for
(
visible_index
=
0
,
menu_index
=
self
->
first_shown_index
;
visible_index
<
num_shown_items
&&
menu_index
<
self
->
view
->
menu
->
size
;
visible_index
++
,
menu_index
++
)
{
int
is_selected
=
(
menu_index
==
self
->
view
->
selected
);
struct
grub_video_bitmap
*
icon
;
grub_font_t
font
;
grub_video_color_t
color
;
int
text_top_offset
;
int
top_pad
;
int
icon_top_offset
;
int
viewport_width
;
if
(
is_selected
)
{
selbox
->
draw
(
selbox
,
0
,
item_top
+
sel_box_top_offset
);
font
=
self
->
selected_item_font
;
color
=
sel_color
;
text_top_offset
=
sel_text_top_offset
;
top_pad
=
sel_toppad
;
icon_top_offset
=
sel_icon_top_offset
;
viewport_width
=
sel_viewport_width
;
}
else
{
itembox
->
draw
(
itembox
,
0
,
item_top
+
item_box_top_offset
);
font
=
self
->
item_font
;
color
=
item_color
;
text_top_offset
=
item_text_top_offset
;
top_pad
=
item_toppad
;
icon_top_offset
=
item_icon_top_offset
;
viewport_width
=
item_viewport_width
;
}
icon
=
get_item_icon
(
self
,
menu_index
);
if
(
icon
!=
0
)
grub_video_blit_bitmap
(
icon
,
GRUB_VIDEO_BLIT_BLEND
,
max_leftpad
,
item_top
+
icon_top_offset
,
0
,
0
,
self
->
icon_width
,
self
->
icon_height
);
const
char
*
item_title
=
grub_menu_get_entry
(
self
->
view
->
menu
,
menu_index
)
->
title
;
int
off
=
self
->
view
->
menu_title_offset
[
menu_index
];
const
char
*
scrolled_title
=
grub_utf8_offset_code
(
item_title
,
grub_strlen
(
item_title
),
off
);
if
(
scrolled_title
)
item_title
=
scrolled_title
;
sviewport
.
y
=
item_top
+
top_pad
;
sviewport
.
width
=
viewport_width
;
grub_gui_set_viewport
(
&
sviewport
,
&
svpsave
);
grub_font_draw_string
(
item_title
,
font
,
color
,
0
,
text_top_offset
);
grub_gui_restore_viewport
(
&
svpsave
);
item_top
+=
text_box_height
+
item_vspace
;
}
grub_video_set_viewport
(
oviewport
.
x
,
oviewport
.
y
,
oviewport
.
width
,
oviewport
.
height
);
}
static
void
list_paint
(
void
*
vself
,
const
grub_video_rect_t
*
region
)
{
list_impl_t
self
=
vself
;
grub_video_rect_t
vpsave
;
if
(
!
self
->
visible
)
return
;
if
(
!
grub_video_have_common_points
(
region
,
&
self
->
bounds
))
return
;
check_boxes
(
self
);
if
(
!
self
->
menu_box
||
!
self
->
selected_item_box
||
!
self
->
item_box
)
return
;
grub_gui_set_viewport
(
&
self
->
bounds
,
&
vpsave
);
{
grub_gfxmenu_box_t
box
=
self
->
menu_box
;
int
box_left_pad
=
box
->
get_left_pad
(
box
);
int
box_top_pad
=
box
->
get_top_pad
(
box
);
int
box_right_pad
=
box
->
get_right_pad
(
box
);
int
box_bottom_pad
=
box
->
get_bottom_pad
(
box
);
grub_video_rect_t
vpsave2
,
content_rect
;
int
num_shown_items
=
get_num_shown_items
(
self
);
int
drawing_scrollbar
=
(
self
->
draw_scrollbar
&&
(
num_shown_items
<
self
->
view
->
menu
->
size
)
&&
check_scrollbar
(
self
));
int
scrollbar_width
=
self
->
scrollbar_width
;
content_rect
.
x
=
box_left_pad
;
content_rect
.
y
=
box_top_pad
;
content_rect
.
width
=
self
->
bounds
.
width
-
box_left_pad
-
box_right_pad
;
content_rect
.
height
=
self
->
bounds
.
height
-
box_top_pad
-
box_bottom_pad
;
box
->
set_content_size
(
box
,
content_rect
.
width
,
content_rect
.
height
);
box
->
draw
(
box
,
0
,
0
);
switch
(
self
->
scrollbar_slice
)
{
case
SCROLLBAR_SLICE_WEST
:
content_rect
.
x
+=
self
->
scrollbar_right_pad
;
content_rect
.
width
-=
self
->
scrollbar_right_pad
;
break
;
case
SCROLLBAR_SLICE_CENTER
:
if
(
drawing_scrollbar
)
content_rect
.
width
-=
scrollbar_width
+
self
->
scrollbar_left_pad
+
self
->
scrollbar_right_pad
;
break
;
case
SCROLLBAR_SLICE_EAST
:
content_rect
.
width
-=
self
->
scrollbar_left_pad
;
break
;
}
grub_gui_set_viewport
(
&
content_rect
,
&
vpsave2
);
draw_menu
(
self
,
num_shown_items
);
grub_gui_restore_viewport
(
&
vpsave2
);
if
(
drawing_scrollbar
)
{
content_rect
.
y
+=
self
->
scrollbar_top_pad
;
content_rect
.
height
-=
self
->
scrollbar_top_pad
+
self
->
scrollbar_bottom_pad
;
content_rect
.
width
=
scrollbar_width
;
switch
(
self
->
scrollbar_slice
)
{
case
SCROLLBAR_SLICE_WEST
:
if
(
box_left_pad
>
scrollbar_width
)
{
content_rect
.
x
=
box_left_pad
-
scrollbar_width
;
content_rect
.
width
=
scrollbar_width
;
}
else
{
content_rect
.
x
=
0
;
content_rect
.
width
=
box_left_pad
;
}
break
;
case
SCROLLBAR_SLICE_CENTER
:
content_rect
.
x
=
self
->
bounds
.
width
-
box_right_pad
-
scrollbar_width
-
self
->
scrollbar_right_pad
;
content_rect
.
width
=
scrollbar_width
;
break
;
case
SCROLLBAR_SLICE_EAST
:
content_rect
.
x
=
self
->
bounds
.
width
-
box_right_pad
;
content_rect
.
width
=
box_right_pad
;
break
;
}
grub_gui_set_viewport
(
&
content_rect
,
&
vpsave2
);
draw_scrollbar
(
self
,
self
->
first_shown_index
,
num_shown_items
,
0
,
self
->
view
->
menu
->
size
,
scrollbar_width
,
content_rect
.
height
);
grub_gui_restore_viewport
(
&
vpsave2
);
}
}
grub_gui_restore_viewport
(
&
vpsave
);
}
static
void
list_set_parent
(
void
*
vself
,
grub_gui_container_t
parent
)
{
list_impl_t
self
=
vself
;
self
->
parent
=
parent
;
}
static
grub_gui_container_t
list_get_parent
(
void
*
vself
)
{
list_impl_t
self
=
vself
;
return
self
->
parent
;
}
static
void
list_set_bounds
(
void
*
vself
,
const
grub_video_rect_t
*
bounds
)
{
list_impl_t
self
=
vself
;
self
->
bounds
=
*
bounds
;
}
static
void
list_get_bounds
(
void
*
vself
,
grub_video_rect_t
*
bounds
)
{
list_impl_t
self
=
vself
;
*
bounds
=
self
->
bounds
;
}
static
void
list_get_minimal_size
(
void
*
vself
,
unsigned
*
width
,
unsigned
*
height
)
{
list_impl_t
self
=
vself
;
if
(
check_boxes
(
self
))
{
int
boxpad
=
self
->
item_padding
;
int
item_vspace
=
self
->
item_spacing
;
int
item_height
=
self
->
item_height
;
int
num_items
=
3
;
grub_gfxmenu_box_t
box
=
self
->
menu_box
;
int
box_left_pad
=
box
->
get_left_pad
(
box
);
int
box_top_pad
=
box
->
get_top_pad
(
box
);
int
box_right_pad
=
box
->
get_right_pad
(
box
);
int
box_bottom_pad
=
box
->
get_bottom_pad
(
box
);
unsigned
width_s
;
grub_gfxmenu_box_t
selbox
=
self
->
selected_item_box
;
int
sel_top_pad
=
selbox
->
get_top_pad
(
selbox
);
int
sel_bottom_pad
=
selbox
->
get_bottom_pad
(
selbox
);
int
sel_left_pad
=
selbox
->
get_left_pad
(
selbox
);
int
sel_right_pad
=
selbox
->
get_right_pad
(
selbox
);
grub_gfxmenu_box_t
itembox
=
self
->
item_box
;
int
item_top_pad
=
itembox
->
get_top_pad
(
itembox
);
int
item_bottom_pad
=
itembox
->
get_bottom_pad
(
itembox
);
int
item_left_pad
=
itembox
->
get_left_pad
(
itembox
);
int
item_right_pad
=
itembox
->
get_right_pad
(
itembox
);
int
max_left_pad
=
grub_max
(
item_left_pad
,
sel_left_pad
);
int
max_right_pad
=
grub_max
(
item_right_pad
,
sel_right_pad
);
int
max_top_pad
=
grub_max
(
item_top_pad
,
sel_top_pad
);
int
max_bottom_pad
=
grub_max
(
item_bottom_pad
,
sel_bottom_pad
);
*
width
=
grub_font_get_string_width
(
self
->
item_font
,
"Typical OS"
);
width_s
=
grub_font_get_string_width
(
self
->
selected_item_font
,
"Typical OS"
);
if
(
*
width
<
width_s
)
*
width
=
width_s
;
*
width
+=
2
*
boxpad
+
box_left_pad
+
box_right_pad
+
max_left_pad
+
max_right_pad
+
self
->
item_icon_space
+
self
->
icon_width
;
switch
(
self
->
scrollbar_slice
)
{
case
SCROLLBAR_SLICE_WEST
:
*
width
+=
self
->
scrollbar_right_pad
;
break
;
case
SCROLLBAR_SLICE_CENTER
:
*
width
+=
self
->
scrollbar_width
+
self
->
scrollbar_left_pad
+
self
->
scrollbar_right_pad
;
break
;
case
SCROLLBAR_SLICE_EAST
:
*
width
+=
self
->
scrollbar_left_pad
;
break
;
}
/* Set the menu box height to fit the items. */
*
height
=
(
item_height
*
num_items
+
item_vspace
*
(
num_items
-
1
)
+
2
*
boxpad
+
box_top_pad
+
box_bottom_pad
+
max_top_pad
+
max_bottom_pad
);
}
else
{
*
width
=
0
;
*
height
=
0
;
}
}
static
grub_err_t
list_set_property
(
void
*
vself
,
const
char
*
name
,
const
char
*
value
)
{
list_impl_t
self
=
vself
;
if
(
grub_strcmp
(
name
,
"item_font"
)
==
0
)
{
self
->
item_font
=
grub_font_get
(
value
);
if
(
self
->
selected_item_font_inherit
)
self
->
selected_item_font
=
self
->
item_font
;
}
else
if
(
grub_strcmp
(
name
,
"selected_item_font"
)
==
0
)
{
if
(
!
value
||
grub_strcmp
(
value
,
"inherit"
)
==
0
)
{
self
->
selected_item_font
=
self
->
item_font
;
self
->
selected_item_font_inherit
=
1
;
}
else
{
self
->
selected_item_font
=
grub_font_get
(
value
);
self
->
selected_item_font_inherit
=
0
;
}
}
else
if
(
grub_strcmp
(
name
,
"item_color"
)
==
0
)
{
grub_video_rgba_color_t
color
;
if
(
grub_video_parse_color
(
value
,
&
color
)
==
GRUB_ERR_NONE
)
{
self
->
item_color
=
color
;
if
(
self
->
selected_item_color_inherit
)
self
->
selected_item_color
=
self
->
item_color
;
}
}
else
if
(
grub_strcmp
(
name
,
"selected_item_color"
)
==
0
)
{
if
(
!
value
||
grub_strcmp
(
value
,
"inherit"
)
==
0
)
{
self
->
selected_item_color
=
self
->
item_color
;
self
->
selected_item_color_inherit
=
1
;
}
else
{
grub_video_rgba_color_t
color
;
if
(
grub_video_parse_color
(
value
,
&
color
)
==
GRUB_ERR_NONE
)
{
self
->
selected_item_color
=
color
;
self
->
selected_item_color_inherit
=
0
;
}
}
}
else
if
(
grub_strcmp
(
name
,
"icon_width"
)
==
0
)
{
self
->
icon_width
=
grub_strtol
(
value
,
0
,
10
);
grub_gfxmenu_icon_manager_set_icon_size
(
self
->
icon_manager
,
self
->
icon_width
,
self
->
icon_height
);
}
else
if
(
grub_strcmp
(
name
,
"icon_height"
)
==
0
)
{
self
->
icon_height
=
grub_strtol
(
value
,
0
,
10
);
grub_gfxmenu_icon_manager_set_icon_size
(
self
->
icon_manager
,
self
->
icon_width
,
self
->
icon_height
);
}
else
if
(
grub_strcmp
(
name
,
"item_height"
)
==
0
)
{
self
->
item_height
=
grub_strtol
(
value
,
0
,
10
);
}
else
if
(
grub_strcmp
(
name
,
"item_padding"
)
==
0
)
{
self
->
item_padding
=
grub_strtol
(
value
,
0
,
10
);
}
else
if
(
grub_strcmp
(
name
,
"item_icon_space"
)
==
0
)
{
self
->
item_icon_space
=
grub_strtol
(
value
,
0
,
10
);
}
else
if
(
grub_strcmp
(
name
,
"item_spacing"
)
==
0
)
{
self
->
item_spacing
=
grub_strtol
(
value
,
0
,
10
);
}
else
if
(
grub_strcmp
(
name
,
"visible"
)
==
0
)
{
self
->
visible
=
grub_strcmp
(
value
,
"false"
)
!=
0
;
}
else
if
(
grub_strcmp
(
name
,
"menu_pixmap_style"
)
==
0
)
{
self
->
need_to_recreate_boxes
=
1
;
grub_free
(
self
->
menu_box_pattern
);
self
->
menu_box_pattern
=
value
?
grub_strdup
(
value
)
:
0
;
}
else
if
(
grub_strcmp
(
name
,
"item_pixmap_style"
)
==
0
)
{
self
->
need_to_recreate_boxes
=
1
;
grub_free
(
self
->
item_box_pattern
);
self
->
item_box_pattern
=
value
?
grub_strdup
(
value
)
:
0
;
if
(
self
->
selected_item_box_pattern_inherit
)
{
grub_free
(
self
->
selected_item_box_pattern
);
self
->
selected_item_box_pattern
=
value
?
grub_strdup
(
value
)
:
0
;
}
}
else
if
(
grub_strcmp
(
name
,
"selected_item_pixmap_style"
)
==
0
)
{
if
(
!
value
||
grub_strcmp
(
value
,
"inherit"
)
==
0
)
{
grub_free
(
self
->
selected_item_box_pattern
);
char
*
tmp
=
self
->
item_box_pattern
;
self
->
selected_item_box_pattern
=
tmp
?
grub_strdup
(
tmp
)
:
0
;
self
->
selected_item_box_pattern_inherit
=
1
;
}
else
{
self
->
need_to_recreate_boxes
=
1
;
grub_free
(
self
->
selected_item_box_pattern
);
self
->
selected_item_box_pattern
=
value
?
grub_strdup
(
value
)
:
0
;
self
->
selected_item_box_pattern_inherit
=
0
;
}
}
else
if
(
grub_strcmp
(
name
,
"scrollbar_frame"
)
==
0
)
{
self
->
need_to_recreate_scrollbar
=
1
;
grub_free
(
self
->
scrollbar_frame_pattern
);
self
->
scrollbar_frame_pattern
=
value
?
grub_strdup
(
value
)
:
0
;
}
else
if
(
grub_strcmp
(
name
,
"scrollbar_thumb"
)
==
0
)
{
self
->
need_to_recreate_scrollbar
=
1
;
grub_free
(
self
->
scrollbar_thumb_pattern
);
self
->
scrollbar_thumb_pattern
=
value
?
grub_strdup
(
value
)
:
0
;
}
else
if
(
grub_strcmp
(
name
,
"scrollbar_thumb_overlay"
)
==
0
)
{
self
->
scrollbar_thumb_overlay
=
grub_strcmp
(
value
,
"true"
)
==
0
;
}
else
if
(
grub_strcmp
(
name
,
"scrollbar_width"
)
==
0
)
{
self
->
scrollbar_width
=
grub_strtol
(
value
,
0
,
10
);
}
else
if
(
grub_strcmp
(
name
,
"scrollbar_slice"
)
==
0
)
{
if
(
grub_strcmp
(
value
,
"west"
)
==
0
)
self
->
scrollbar_slice
=
SCROLLBAR_SLICE_WEST
;
else
if
(
grub_strcmp
(
value
,
"center"
)
==
0
)
self
->
scrollbar_slice
=
SCROLLBAR_SLICE_CENTER
;
else
if
(
grub_strcmp
(
value
,
"east"
)
==
0
)
self
->
scrollbar_slice
=
SCROLLBAR_SLICE_EAST
;
}
else
if
(
grub_strcmp
(
name
,
"scrollbar_left_pad"
)
==
0
)
{
self
->
scrollbar_left_pad
=
grub_strtol
(
value
,
0
,
10
);
}
else
if
(
grub_strcmp
(
name
,
"scrollbar_right_pad"
)
==
0
)
{
self
->
scrollbar_right_pad
=
grub_strtol
(
value
,
0
,
10
);
}
else
if
(
grub_strcmp
(
name
,
"scrollbar_top_pad"
)
==
0
)
{
self
->
scrollbar_top_pad
=
grub_strtol
(
value
,
0
,
10
);
}
else
if
(
grub_strcmp
(
name
,
"scrollbar_bottom_pad"
)
==
0
)
{
self
->
scrollbar_bottom_pad
=
grub_strtol
(
value
,
0
,
10
);
}
else
if
(
grub_strcmp
(
name
,
"scrollbar"
)
==
0
)
{
self
->
draw_scrollbar
=
grub_strcmp
(
value
,
"false"
)
!=
0
;
}
else
if
(
grub_strcmp
(
name
,
"theme_dir"
)
==
0
)
{
self
->
need_to_recreate_boxes
=
1
;
grub_free
(
self
->
theme_dir
);
self
->
theme_dir
=
value
?
grub_strdup
(
value
)
:
0
;
}
else
if
(
grub_strcmp
(
name
,
"id"
)
==
0
)
{
grub_free
(
self
->
id
);
if
(
value
)
self
->
id
=
grub_strdup
(
value
);
else
self
->
id
=
0
;
}
return
grub_errno
;
}
/* Set necessary information that the gfxmenu view provides. */
static
void
list_set_view_info
(
void
*
vself
,
grub_gfxmenu_view_t
view
)
{
list_impl_t
self
=
vself
;
grub_gfxmenu_icon_manager_set_theme_path
(
self
->
icon_manager
,
view
->
theme_path
);
self
->
view
=
view
;
}
/* Refresh list variables */
static
void
list_refresh_info
(
void
*
vself
,
grub_gfxmenu_view_t
view
)
{
list_impl_t
self
=
vself
;
if
(
view
->
nested
)
self
->
first_shown_index
=
0
;
}
static
struct
grub_gui_component_ops
list_comp_ops
=
{
.
destroy
=
list_destroy
,
.
get_id
=
list_get_id
,
.
is_instance
=
list_is_instance
,
.
paint
=
list_paint
,
.
set_parent
=
list_set_parent
,
.
get_parent
=
list_get_parent
,
.
set_bounds
=
list_set_bounds
,
.
get_bounds
=
list_get_bounds
,
.
get_minimal_size
=
list_get_minimal_size
,
.
set_property
=
list_set_property
};
static
struct
grub_gui_list_ops
list_ops
=
{
.
set_view_info
=
list_set_view_info
,
.
refresh_list
=
list_refresh_info
};
grub_gui_component_t
grub_gui_list_new
(
void
)
{
list_impl_t
self
;
grub_font_t
default_font
;
grub_video_rgba_color_t
default_fg_color
;
self
=
grub_zalloc
(
sizeof
(
*
self
));
if
(
!
self
)
return
0
;
self
->
list
.
ops
=
&
list_ops
;
self
->
list
.
component
.
ops
=
&
list_comp_ops
;
self
->
visible
=
1
;
default_font
=
grub_font_get
(
"Unknown Regular 16"
);
default_fg_color
=
grub_video_rgba_color_rgb
(
0
,
0
,
0
);
self
->
icon_width
=
32
;
self
->
icon_height
=
32
;
self
->
item_height
=
42
;
self
->
item_padding
=
14
;
self
->
item_icon_space
=
4
;
self
->
item_spacing
=
16
;
self
->
item_font
=
default_font
;
self
->
selected_item_font_inherit
=
1
;
/* Default to using the item_font. */
self
->
selected_item_font
=
default_font
;
self
->
item_color
=
default_fg_color
;
self
->
selected_item_color_inherit
=
1
;
/* Default to using the item_color. */
self
->
selected_item_color
=
default_fg_color
;
self
->
draw_scrollbar
=
1
;
self
->
need_to_recreate_scrollbar
=
1
;
self
->
scrollbar_frame
=
0
;
self
->
scrollbar_thumb
=
0
;
self
->
scrollbar_frame_pattern
=
0
;
self
->
scrollbar_thumb_pattern
=
0
;
self
->
scrollbar_thumb_overlay
=
0
;
self
->
scrollbar_width
=
16
;
self
->
scrollbar_slice
=
SCROLLBAR_SLICE_EAST
;
self
->
scrollbar_left_pad
=
2
;
self
->
scrollbar_right_pad
=
0
;
self
->
scrollbar_top_pad
=
0
;
self
->
scrollbar_bottom_pad
=
0
;
self
->
first_shown_index
=
0
;
self
->
need_to_recreate_boxes
=
0
;
self
->
theme_dir
=
0
;
self
->
menu_box_pattern
=
0
;
self
->
item_box_pattern
=
0
;
self
->
selected_item_box_pattern_inherit
=
1
;
/*Default to using the item_box.*/
self
->
selected_item_box_pattern
=
0
;
self
->
menu_box
=
grub_gfxmenu_create_box
(
0
,
0
);
self
->
item_box
=
grub_gfxmenu_create_box
(
0
,
0
);
self
->
selected_item_box
=
grub_gfxmenu_create_box
(
0
,
0
);
self
->
icon_manager
=
grub_gfxmenu_icon_manager_new
();
if
(
!
self
->
icon_manager
)
{
self
->
list
.
component
.
ops
->
destroy
(
self
);
return
0
;
}
grub_gfxmenu_icon_manager_set_icon_size
(
self
->
icon_manager
,
self
->
icon_width
,
self
->
icon_height
);
return
(
grub_gui_component_t
)
self
;
}
GRUB2/MOD_SRC/grub-2.04/grub-core/gfxmenu/view.c
View file @
15b8b1f3
...
@@ -37,6 +37,7 @@
...
@@ -37,6 +37,7 @@
#include <grub/gui_string_util.h>
#include <grub/gui_string_util.h>
#include <grub/icon_manager.h>
#include <grub/icon_manager.h>
#include <grub/i18n.h>
#include <grub/i18n.h>
#include <grub/charset.h>
static
void
static
void
init_terminal
(
grub_gfxmenu_view_t
view
);
init_terminal
(
grub_gfxmenu_view_t
view
);
...
@@ -142,6 +143,8 @@ grub_gfxmenu_view_destroy (grub_gfxmenu_view_t view)
...
@@ -142,6 +143,8 @@ grub_gfxmenu_view_destroy (grub_gfxmenu_view_t view)
grub_free
(
view
->
title_text
);
grub_free
(
view
->
title_text
);
grub_free
(
view
->
progress_message_text
);
grub_free
(
view
->
progress_message_text
);
grub_free
(
view
->
theme_path
);
grub_free
(
view
->
theme_path
);
if
(
view
->
menu_title_offset
)
grub_free
(
view
->
menu_title_offset
);
if
(
view
->
canvas
)
if
(
view
->
canvas
)
view
->
canvas
->
component
.
ops
->
destroy
(
view
->
canvas
);
view
->
canvas
->
component
.
ops
->
destroy
(
view
->
canvas
);
grub_free
(
view
);
grub_free
(
view
);
...
@@ -428,6 +431,27 @@ grub_gfxmenu_set_chosen_entry (int entry, void *data)
...
@@ -428,6 +431,27 @@ grub_gfxmenu_set_chosen_entry (int entry, void *data)
}
}
void
grub_gfxmenu_scroll_chosen_entry
(
void
*
data
,
int
diren
)
{
grub_gfxmenu_view_t
view
=
data
;
const
char
*
item_title
;
int
off
;
if
(
!
view
->
menu
->
size
)
return
;
item_title
=
grub_menu_get_entry
(
view
->
menu
,
view
->
selected
)
->
title
;
off
=
view
->
menu_title_offset
[
view
->
selected
]
+
diren
;
if
(
off
<
0
||
off
>
grub_utf8_get_num_code
(
item_title
,
grub_strlen
(
item_title
)))
return
;
view
->
menu_title_offset
[
view
->
selected
]
=
off
;
grub_gfxmenu_redraw_menu
(
view
);
}
static
void
static
void
grub_gfxmenu_draw_terminal_box
(
void
)
grub_gfxmenu_draw_terminal_box
(
void
)
{
{
...
...
GRUB2/MOD_SRC/grub-2.04/grub-core/normal/charset.c
0 → 100644
View file @
15b8b1f3
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
/*
Current problems with Unicode rendering:
- B and BN bidi type characters (ignored)
- Mc type characters with combining class 0 (poorly combined)
- Mn type characters with combining class 0 (poorly combined)
- Me type characters with combining class 0 (poorly combined)
- Cf type characters (ignored)
- Cc type characters (ignored)
- Line-breaking rules (e.g. Zs type characters)
- Indic languages
- non-Semitic shaping (rarely used)
- Zl and Zp characters
- Combining characters of types 7, 8, 9, 21, 35, 36, 84, 91, 103, 107,
118, 122, 129, 130, 132, 218, 224, 226, 233, 234
- Private use characters (not really a problem)
- Variations (no font support)
- Vertical text
- Ligatures
Font information ignored:
- Kerning
- Justification data
- Glyph posititioning
- Baseline data
Most underline diacritics aren't displayed in gfxterm
*/
#include <grub/charset.h>
#include <grub/mm.h>
#include <grub/misc.h>
#include <grub/unicode.h>
#include <grub/term.h>
#include <grub/normal.h>
#if HAVE_FONT_SOURCE
#include "widthspec.h"
#endif
/* Returns -2 if not enough space, -1 on invalid character. */
grub_ssize_t
grub_encode_utf8_character
(
grub_uint8_t
*
dest
,
grub_uint8_t
*
destend
,
grub_uint32_t
code
)
{
if
(
dest
>=
destend
)
return
-
2
;
if
(
code
<=
0x007F
)
{
*
dest
++
=
code
;
return
1
;
}
if
(
code
<=
0x07FF
)
{
if
(
dest
+
1
>=
destend
)
return
-
2
;
*
dest
++
=
(
code
>>
6
)
|
0xC0
;
*
dest
++
=
(
code
&
0x3F
)
|
0x80
;
return
2
;
}
if
((
code
>=
0xDC00
&&
code
<=
0xDFFF
)
||
(
code
>=
0xD800
&&
code
<=
0xDBFF
))
{
/* No surrogates in UCS-4... */
return
-
1
;
}
if
(
code
<
0x10000
)
{
if
(
dest
+
2
>=
destend
)
return
-
2
;
*
dest
++
=
(
code
>>
12
)
|
0xE0
;
*
dest
++
=
((
code
>>
6
)
&
0x3F
)
|
0x80
;
*
dest
++
=
(
code
&
0x3F
)
|
0x80
;
return
3
;
}
{
if
(
dest
+
3
>=
destend
)
return
-
2
;
*
dest
++
=
(
code
>>
18
)
|
0xF0
;
*
dest
++
=
((
code
>>
12
)
&
0x3F
)
|
0x80
;
*
dest
++
=
((
code
>>
6
)
&
0x3F
)
|
0x80
;
*
dest
++
=
(
code
&
0x3F
)
|
0x80
;
return
4
;
}
}
/* Convert UCS-4 to UTF-8. */
grub_size_t
grub_ucs4_to_utf8
(
const
grub_uint32_t
*
src
,
grub_size_t
size
,
grub_uint8_t
*
dest
,
grub_size_t
destsize
)
{
/* Keep last char for \0. */
grub_uint8_t
*
destend
=
dest
+
destsize
-
1
;
grub_uint8_t
*
dest0
=
dest
;
while
(
size
--
&&
dest
<
destend
)
{
grub_uint32_t
code
=
*
src
++
;
grub_ssize_t
s
;
s
=
grub_encode_utf8_character
(
dest
,
destend
,
code
);
if
(
s
==
-
2
)
break
;
if
(
s
==
-
1
)
{
*
dest
++
=
'?'
;
continue
;
}
dest
+=
s
;
}
*
dest
=
0
;
return
dest
-
dest0
;
}
/* Returns the number of bytes the string src would occupy is converted
to UTF-8, excluding trailing \0. */
grub_size_t
grub_get_num_of_utf8_bytes
(
const
grub_uint32_t
*
src
,
grub_size_t
size
)
{
grub_size_t
remaining
;
const
grub_uint32_t
*
ptr
;
grub_size_t
cnt
=
0
;
remaining
=
size
;
ptr
=
src
;
while
(
remaining
--
)
{
grub_uint32_t
code
=
*
ptr
++
;
if
(
code
<=
0x007F
)
cnt
++
;
else
if
(
code
<=
0x07FF
)
cnt
+=
2
;
else
if
((
code
>=
0xDC00
&&
code
<=
0xDFFF
)
||
(
code
>=
0xD800
&&
code
<=
0xDBFF
))
/* No surrogates in UCS-4... */
cnt
++
;
else
if
(
code
<
0x10000
)
cnt
+=
3
;
else
cnt
+=
4
;
}
return
cnt
;
}
/* Convert UCS-4 to UTF-8. */
char
*
grub_ucs4_to_utf8_alloc
(
const
grub_uint32_t
*
src
,
grub_size_t
size
)
{
grub_uint8_t
*
ret
;
grub_size_t
cnt
=
grub_get_num_of_utf8_bytes
(
src
,
size
)
+
1
;
ret
=
grub_malloc
(
cnt
);
if
(
!
ret
)
return
0
;
grub_ucs4_to_utf8
(
src
,
size
,
ret
,
cnt
);
return
(
char
*
)
ret
;
}
int
grub_is_valid_utf8
(
const
grub_uint8_t
*
src
,
grub_size_t
srcsize
)
{
int
count
=
0
;
grub_uint32_t
code
=
0
;
while
(
srcsize
)
{
if
(
srcsize
!=
(
grub_size_t
)
-
1
)
srcsize
--
;
if
(
!
grub_utf8_process
(
*
src
++
,
&
code
,
&
count
))
return
0
;
if
(
count
!=
0
)
continue
;
if
(
code
==
0
)
return
1
;
if
(
code
>
GRUB_UNICODE_LAST_VALID
)
return
0
;
}
return
1
;
}
grub_ssize_t
grub_utf8_to_ucs4_alloc
(
const
char
*
msg
,
grub_uint32_t
**
unicode_msg
,
grub_uint32_t
**
last_position
)
{
grub_size_t
msg_len
=
grub_strlen
(
msg
);
*
unicode_msg
=
grub_malloc
(
msg_len
*
sizeof
(
grub_uint32_t
));
if
(
!*
unicode_msg
)
return
-
1
;
msg_len
=
grub_utf8_to_ucs4
(
*
unicode_msg
,
msg_len
,
(
grub_uint8_t
*
)
msg
,
-
1
,
0
);
if
(
last_position
)
*
last_position
=
*
unicode_msg
+
msg_len
;
return
msg_len
;
}
/* Convert a (possibly null-terminated) UTF-8 string of at most SRCSIZE
bytes (if SRCSIZE is -1, it is ignored) in length to a UCS-4 string.
Return the number of characters converted. DEST must be able to hold
at least DESTSIZE characters.
If SRCEND is not NULL, then *SRCEND is set to the next byte after the
last byte used in SRC. */
grub_size_t
grub_utf8_to_ucs4
(
grub_uint32_t
*
dest
,
grub_size_t
destsize
,
const
grub_uint8_t
*
src
,
grub_size_t
srcsize
,
const
grub_uint8_t
**
srcend
)
{
grub_uint32_t
*
p
=
dest
;
int
count
=
0
;
grub_uint32_t
code
=
0
;
if
(
srcend
)
*
srcend
=
src
;
while
(
srcsize
&&
destsize
)
{
int
was_count
=
count
;
if
(
srcsize
!=
(
grub_size_t
)
-
1
)
srcsize
--
;
if
(
!
grub_utf8_process
(
*
src
++
,
&
code
,
&
count
))
{
code
=
'?'
;
count
=
0
;
/* Character c may be valid, don't eat it. */
if
(
was_count
)
src
--
;
}
if
(
count
!=
0
)
continue
;
if
(
code
==
0
)
break
;
*
p
++
=
code
;
destsize
--
;
}
if
(
srcend
)
*
srcend
=
src
;
return
p
-
dest
;
}
static
grub_uint8_t
*
join_types
=
NULL
;
static
void
unpack_join
(
void
)
{
unsigned
i
;
struct
grub_unicode_compact_range
*
cur
;
join_types
=
grub_zalloc
(
GRUB_UNICODE_MAX_CACHED_CHAR
);
if
(
!
join_types
)
{
grub_errno
=
GRUB_ERR_NONE
;
return
;
}
for
(
cur
=
grub_unicode_compact
;
cur
->
len
;
cur
++
)
for
(
i
=
cur
->
start
;
i
<
cur
->
start
+
(
unsigned
)
cur
->
len
&&
i
<
GRUB_UNICODE_MAX_CACHED_CHAR
;
i
++
)
join_types
[
i
]
=
cur
->
join_type
;
}
static
grub_uint8_t
*
bidi_types
=
NULL
;
static
void
unpack_bidi
(
void
)
{
unsigned
i
;
struct
grub_unicode_compact_range
*
cur
;
bidi_types
=
grub_zalloc
(
GRUB_UNICODE_MAX_CACHED_CHAR
);
if
(
!
bidi_types
)
{
grub_errno
=
GRUB_ERR_NONE
;
return
;
}
for
(
cur
=
grub_unicode_compact
;
cur
->
len
;
cur
++
)
for
(
i
=
cur
->
start
;
i
<
cur
->
start
+
(
unsigned
)
cur
->
len
&&
i
<
GRUB_UNICODE_MAX_CACHED_CHAR
;
i
++
)
if
(
cur
->
bidi_mirror
)
bidi_types
[
i
]
=
cur
->
bidi_type
|
0x80
;
else
bidi_types
[
i
]
=
cur
->
bidi_type
|
0x00
;
}
static
inline
enum
grub_bidi_type
get_bidi_type
(
grub_uint32_t
c
)
{
struct
grub_unicode_compact_range
*
cur
;
if
(
!
bidi_types
)
unpack_bidi
();
if
(
bidi_types
&&
c
<
GRUB_UNICODE_MAX_CACHED_CHAR
)
return
bidi_types
[
c
]
&
0x7f
;
for
(
cur
=
grub_unicode_compact
;
cur
->
len
;
cur
++
)
if
(
cur
->
start
<=
c
&&
c
<
cur
->
start
+
(
unsigned
)
cur
->
len
)
return
cur
->
bidi_type
;
return
GRUB_BIDI_TYPE_L
;
}
static
inline
enum
grub_join_type
get_join_type
(
grub_uint32_t
c
)
{
struct
grub_unicode_compact_range
*
cur
;
if
(
!
join_types
)
unpack_join
();
if
(
join_types
&&
c
<
GRUB_UNICODE_MAX_CACHED_CHAR
)
return
join_types
[
c
];
for
(
cur
=
grub_unicode_compact
;
cur
->
len
;
cur
++
)
if
(
cur
->
start
<=
c
&&
c
<
cur
->
start
+
(
unsigned
)
cur
->
len
)
return
cur
->
join_type
;
return
GRUB_JOIN_TYPE_NONJOINING
;
}
static
inline
int
is_mirrored
(
grub_uint32_t
c
)
{
struct
grub_unicode_compact_range
*
cur
;
if
(
!
bidi_types
)
unpack_bidi
();
if
(
bidi_types
&&
c
<
GRUB_UNICODE_MAX_CACHED_CHAR
)
return
!!
(
bidi_types
[
c
]
&
0x80
);
for
(
cur
=
grub_unicode_compact
;
cur
->
len
;
cur
++
)
if
(
cur
->
start
<=
c
&&
c
<
cur
->
start
+
(
unsigned
)
cur
->
len
)
return
cur
->
bidi_mirror
;
return
0
;
}
enum
grub_comb_type
grub_unicode_get_comb_type
(
grub_uint32_t
c
)
{
static
grub_uint8_t
*
comb_types
=
NULL
;
struct
grub_unicode_compact_range
*
cur
;
if
(
!
comb_types
)
{
unsigned
i
;
comb_types
=
grub_zalloc
(
GRUB_UNICODE_MAX_CACHED_CHAR
);
if
(
comb_types
)
for
(
cur
=
grub_unicode_compact
;
cur
->
len
;
cur
++
)
for
(
i
=
cur
->
start
;
i
<
cur
->
start
+
(
unsigned
)
cur
->
len
&&
i
<
GRUB_UNICODE_MAX_CACHED_CHAR
;
i
++
)
comb_types
[
i
]
=
cur
->
comb_type
;
else
grub_errno
=
GRUB_ERR_NONE
;
}
if
(
comb_types
&&
c
<
GRUB_UNICODE_MAX_CACHED_CHAR
)
return
comb_types
[
c
];
for
(
cur
=
grub_unicode_compact
;
cur
->
len
;
cur
++
)
if
(
cur
->
start
<=
c
&&
c
<
cur
->
start
+
(
unsigned
)
cur
->
len
)
return
cur
->
comb_type
;
return
GRUB_UNICODE_COMB_NONE
;
}
#if HAVE_FONT_SOURCE
grub_size_t
grub_unicode_estimate_width
(
const
struct
grub_unicode_glyph
*
c
)
{
if
(
grub_unicode_get_comb_type
(
c
->
base
))
return
0
;
if
(
widthspec
[
c
->
base
>>
3
]
&
(
1
<<
(
c
->
base
&
7
)))
return
2
;
else
return
1
;
}
#endif
static
inline
int
is_type_after
(
enum
grub_comb_type
a
,
enum
grub_comb_type
b
)
{
/* Shadda is numerically higher than most of Arabic diacritics but has
to be rendered before them. */
if
(
a
==
GRUB_UNICODE_COMB_ARABIC_SHADDA
&&
b
<=
GRUB_UNICODE_COMB_ARABIC_KASRA
&&
b
>=
GRUB_UNICODE_COMB_ARABIC_FATHATAN
)
return
0
;
if
(
b
==
GRUB_UNICODE_COMB_ARABIC_SHADDA
&&
a
<=
GRUB_UNICODE_COMB_ARABIC_KASRA
&&
a
>=
GRUB_UNICODE_COMB_ARABIC_FATHATAN
)
return
1
;
return
a
>
b
;
}
grub_size_t
grub_unicode_aglomerate_comb
(
const
grub_uint32_t
*
in
,
grub_size_t
inlen
,
struct
grub_unicode_glyph
*
out
)
{
int
haveout
=
0
;
const
grub_uint32_t
*
ptr
;
unsigned
last_comb_pointer
=
0
;
grub_memset
(
out
,
0
,
sizeof
(
*
out
));
if
(
inlen
&&
grub_iscntrl
(
*
in
))
{
out
->
base
=
*
in
;
out
->
variant
=
0
;
out
->
attributes
=
0
;
out
->
ncomb
=
0
;
out
->
estimated_width
=
1
;
return
1
;
}
for
(
ptr
=
in
;
ptr
<
in
+
inlen
;
ptr
++
)
{
/* Variation selectors >= 17 are outside of BMP and SMP.
Handle variation selectors first to avoid potentially costly lookups.
*/
if
(
*
ptr
>=
GRUB_UNICODE_VARIATION_SELECTOR_1
&&
*
ptr
<=
GRUB_UNICODE_VARIATION_SELECTOR_16
)
{
if
(
haveout
)
out
->
variant
=
*
ptr
-
GRUB_UNICODE_VARIATION_SELECTOR_1
+
1
;
continue
;
}
if
(
*
ptr
>=
GRUB_UNICODE_VARIATION_SELECTOR_17
&&
*
ptr
<=
GRUB_UNICODE_VARIATION_SELECTOR_256
)
{
if
(
haveout
)
out
->
variant
=
*
ptr
-
GRUB_UNICODE_VARIATION_SELECTOR_17
+
17
;
continue
;
}
enum
grub_comb_type
comb_type
;
comb_type
=
grub_unicode_get_comb_type
(
*
ptr
);
if
(
comb_type
)
{
struct
grub_unicode_combining
*
n
;
unsigned
j
;
if
(
!
haveout
)
continue
;
if
(
comb_type
==
GRUB_UNICODE_COMB_MC
||
comb_type
==
GRUB_UNICODE_COMB_ME
||
comb_type
==
GRUB_UNICODE_COMB_MN
)
last_comb_pointer
=
out
->
ncomb
;
if
(
out
->
ncomb
+
1
<=
(
int
)
ARRAY_SIZE
(
out
->
combining_inline
))
n
=
out
->
combining_inline
;
else
if
(
out
->
ncomb
>
(
int
)
ARRAY_SIZE
(
out
->
combining_inline
))
{
n
=
grub_realloc
(
out
->
combining_ptr
,
sizeof
(
n
[
0
])
*
(
out
->
ncomb
+
1
));
if
(
!
n
)
{
grub_errno
=
GRUB_ERR_NONE
;
continue
;
}
out
->
combining_ptr
=
n
;
}
else
{
n
=
grub_malloc
(
sizeof
(
n
[
0
])
*
(
out
->
ncomb
+
1
));
if
(
!
n
)
{
grub_errno
=
GRUB_ERR_NONE
;
continue
;
}
grub_memcpy
(
n
,
out
->
combining_inline
,
sizeof
(
out
->
combining_inline
));
out
->
combining_ptr
=
n
;
}
for
(
j
=
last_comb_pointer
;
j
<
out
->
ncomb
;
j
++
)
if
(
is_type_after
(
n
[
j
].
type
,
comb_type
))
break
;
grub_memmove
(
n
+
j
+
1
,
n
+
j
,
(
out
->
ncomb
-
j
)
*
sizeof
(
n
[
0
]));
n
[
j
].
code
=
*
ptr
;
n
[
j
].
type
=
comb_type
;
out
->
ncomb
++
;
continue
;
}
if
(
haveout
)
return
ptr
-
in
;
haveout
=
1
;
out
->
base
=
*
ptr
;
out
->
variant
=
0
;
out
->
attributes
=
0
;
out
->
ncomb
=
0
;
out
->
estimated_width
=
1
;
}
return
ptr
-
in
;
}
static
void
revert
(
struct
grub_unicode_glyph
*
visual
,
struct
grub_term_pos
*
pos
,
unsigned
start
,
unsigned
end
)
{
struct
grub_unicode_glyph
t
;
unsigned
i
;
int
a
=
0
,
b
=
0
;
if
(
pos
)
{
a
=
pos
[
visual
[
start
].
orig_pos
].
x
;
b
=
pos
[
visual
[
end
].
orig_pos
].
x
;
}
for
(
i
=
0
;
i
<
(
end
-
start
)
/
2
+
1
;
i
++
)
{
t
=
visual
[
start
+
i
];
visual
[
start
+
i
]
=
visual
[
end
-
i
];
visual
[
end
-
i
]
=
t
;
if
(
pos
)
{
pos
[
visual
[
start
+
i
].
orig_pos
].
x
=
a
+
b
-
pos
[
visual
[
start
+
i
].
orig_pos
].
x
;
pos
[
visual
[
end
-
i
].
orig_pos
].
x
=
a
+
b
-
pos
[
visual
[
end
-
i
].
orig_pos
].
x
;
}
}
}
static
grub_ssize_t
bidi_line_wrap
(
struct
grub_unicode_glyph
*
visual_out
,
struct
grub_unicode_glyph
*
visual
,
grub_size_t
visual_len
,
grub_size_t
(
*
getcharwidth
)
(
const
struct
grub_unicode_glyph
*
visual
,
void
*
getcharwidth_arg
),
void
*
getcharwidth_arg
,
grub_size_t
maxwidth
,
grub_size_t
startwidth
,
grub_uint32_t
contchar
,
struct
grub_term_pos
*
pos
,
int
primitive_wrap
,
grub_size_t
log_end
)
{
struct
grub_unicode_glyph
*
outptr
=
visual_out
;
unsigned
line_start
=
0
;
grub_ssize_t
line_width
;
unsigned
k
;
grub_ssize_t
last_space
=
-
1
;
grub_ssize_t
last_space_width
=
0
;
int
lines
=
0
;
if
(
!
visual_len
)
return
0
;
if
(
startwidth
>=
maxwidth
&&
(
grub_ssize_t
)
maxwidth
>
0
)
{
if
(
contchar
)
{
grub_memset
(
outptr
,
0
,
sizeof
(
visual
[
0
]));
outptr
->
base
=
contchar
;
outptr
++
;
}
grub_memset
(
outptr
,
0
,
sizeof
(
visual
[
0
]));
outptr
->
base
=
'\n'
;
outptr
++
;
startwidth
=
0
;
}
line_width
=
startwidth
;
for
(
k
=
0
;
k
<=
visual_len
;
k
++
)
{
grub_ssize_t
last_width
=
0
;
if
(
pos
&&
k
!=
visual_len
)
{
pos
[
visual
[
k
].
orig_pos
].
x
=
line_width
;
pos
[
visual
[
k
].
orig_pos
].
y
=
lines
;
pos
[
visual
[
k
].
orig_pos
].
valid
=
1
;
}
if
(
k
==
visual_len
&&
pos
)
{
pos
[
log_end
].
x
=
line_width
;
pos
[
log_end
].
y
=
lines
;
pos
[
log_end
].
valid
=
1
;
}
if
(
getcharwidth
&&
k
!=
visual_len
)
line_width
+=
last_width
=
getcharwidth
(
&
visual
[
k
],
getcharwidth_arg
);
if
(
k
!=
visual_len
&&
(
visual
[
k
].
base
==
' '
||
visual
[
k
].
base
==
'\t'
)
&&
!
primitive_wrap
)
{
last_space
=
k
;
last_space_width
=
line_width
;
}
if
(((
grub_ssize_t
)
maxwidth
>
0
&&
line_width
>
(
grub_ssize_t
)
maxwidth
)
||
k
==
visual_len
)
{
unsigned
min_odd_level
=
0xffffffff
;
unsigned
max_level
=
0
;
unsigned
kk
=
k
;
lines
++
;
if
(
k
!=
visual_len
&&
last_space
>
(
signed
)
line_start
)
{
kk
=
last_space
;
line_width
-=
last_space_width
;
}
else
if
(
k
!=
visual_len
&&
line_start
==
0
&&
startwidth
!=
0
&&
!
primitive_wrap
&&
lines
==
1
&&
line_width
-
startwidth
<
maxwidth
)
{
kk
=
0
;
line_width
-=
startwidth
;
}
else
line_width
=
last_width
;
{
unsigned
i
;
for
(
i
=
line_start
;
i
<
kk
;
i
++
)
{
if
(
visual
[
i
].
bidi_level
>
max_level
)
max_level
=
visual
[
i
].
bidi_level
;
if
(
visual
[
i
].
bidi_level
<
min_odd_level
&&
(
visual
[
i
].
bidi_level
&
1
))
min_odd_level
=
visual
[
i
].
bidi_level
;
}
}
{
unsigned
j
;
/* FIXME: can be optimized. */
for
(
j
=
max_level
;
j
>
min_odd_level
-
1
;
j
--
)
{
unsigned
in
=
line_start
;
unsigned
i
;
for
(
i
=
line_start
;
i
<
kk
;
i
++
)
{
if
(
i
!=
line_start
&&
visual
[
i
].
bidi_level
>=
j
&&
visual
[
i
-
1
].
bidi_level
<
j
)
in
=
i
;
if
(
visual
[
i
].
bidi_level
>=
j
&&
(
i
+
1
==
kk
||
visual
[
i
+
1
].
bidi_level
<
j
))
revert
(
visual
,
pos
,
in
,
i
);
}
}
}
{
unsigned
i
;
for
(
i
=
line_start
;
i
<
kk
;
i
++
)
{
if
(
is_mirrored
(
visual
[
i
].
base
)
&&
visual
[
i
].
bidi_level
)
visual
[
i
].
attributes
|=
GRUB_UNICODE_GLYPH_ATTRIBUTE_MIRROR
;
if
((
visual
[
i
].
attributes
&
GRUB_UNICODE_GLYPH_ATTRIBUTES_JOIN
)
&&
visual
[
i
].
bidi_level
)
{
int
left
,
right
;
left
=
visual
[
i
].
attributes
&
(
GRUB_UNICODE_GLYPH_ATTRIBUTE_LEFT_JOINED
|
GRUB_UNICODE_GLYPH_ATTRIBUTE_LEFT_JOINED_EXPLICIT
);
right
=
visual
[
i
].
attributes
&
(
GRUB_UNICODE_GLYPH_ATTRIBUTE_RIGHT_JOINED
|
GRUB_UNICODE_GLYPH_ATTRIBUTE_RIGHT_JOINED_EXPLICIT
);
visual
[
i
].
attributes
&=
~
GRUB_UNICODE_GLYPH_ATTRIBUTES_JOIN
;
left
<<=
GRUB_UNICODE_GLYPH_ATTRIBUTES_JOIN_LEFT_TO_RIGHT_SHIFT
;
right
>>=
GRUB_UNICODE_GLYPH_ATTRIBUTES_JOIN_LEFT_TO_RIGHT_SHIFT
;
visual
[
i
].
attributes
|=
(
left
|
right
);
}
}
}
{
int
left_join
=
0
;
unsigned
i
;
for
(
i
=
line_start
;
i
<
kk
;
i
++
)
{
enum
grub_join_type
join_type
=
get_join_type
(
visual
[
i
].
base
);
if
(
!
(
visual
[
i
].
attributes
&
GRUB_UNICODE_GLYPH_ATTRIBUTE_LEFT_JOINED_EXPLICIT
)
&&
(
join_type
==
GRUB_JOIN_TYPE_LEFT
||
join_type
==
GRUB_JOIN_TYPE_DUAL
))
{
if
(
left_join
)
visual
[
i
].
attributes
|=
GRUB_UNICODE_GLYPH_ATTRIBUTE_LEFT_JOINED
;
else
visual
[
i
].
attributes
&=
~
GRUB_UNICODE_GLYPH_ATTRIBUTE_LEFT_JOINED
;
}
if
(
join_type
==
GRUB_JOIN_TYPE_NONJOINING
||
join_type
==
GRUB_JOIN_TYPE_LEFT
)
left_join
=
0
;
if
(
join_type
==
GRUB_JOIN_TYPE_RIGHT
||
join_type
==
GRUB_JOIN_TYPE_DUAL
||
join_type
==
GRUB_JOIN_TYPE_CAUSING
)
left_join
=
1
;
}
}
{
int
right_join
=
0
;
signed
i
;
for
(
i
=
kk
-
1
;
i
>=
0
&&
(
unsigned
)
i
+
1
>
line_start
;
i
--
)
{
enum
grub_join_type
join_type
=
get_join_type
(
visual
[
i
].
base
);
if
(
!
(
visual
[
i
].
attributes
&
GRUB_UNICODE_GLYPH_ATTRIBUTE_RIGHT_JOINED_EXPLICIT
)
&&
(
join_type
==
GRUB_JOIN_TYPE_RIGHT
||
join_type
==
GRUB_JOIN_TYPE_DUAL
))
{
if
(
right_join
)
visual
[
i
].
attributes
|=
GRUB_UNICODE_GLYPH_ATTRIBUTE_RIGHT_JOINED
;
else
visual
[
i
].
attributes
&=
~
GRUB_UNICODE_GLYPH_ATTRIBUTE_RIGHT_JOINED
;
}
if
(
join_type
==
GRUB_JOIN_TYPE_NONJOINING
||
join_type
==
GRUB_JOIN_TYPE_RIGHT
)
right_join
=
0
;
if
(
join_type
==
GRUB_JOIN_TYPE_LEFT
||
join_type
==
GRUB_JOIN_TYPE_DUAL
||
join_type
==
GRUB_JOIN_TYPE_CAUSING
)
right_join
=
1
;
}
}
grub_memcpy
(
outptr
,
&
visual
[
line_start
],
(
kk
-
line_start
)
*
sizeof
(
visual
[
0
]));
outptr
+=
kk
-
line_start
;
if
(
kk
!=
visual_len
)
{
if
(
contchar
)
{
grub_memset
(
outptr
,
0
,
sizeof
(
visual
[
0
]));
outptr
->
base
=
contchar
;
outptr
++
;
}
grub_memset
(
outptr
,
0
,
sizeof
(
visual
[
0
]));
outptr
->
base
=
'\n'
;
outptr
++
;
}
if
((
signed
)
kk
==
last_space
)
kk
++
;
line_start
=
kk
;
if
(
pos
&&
kk
!=
visual_len
)
{
pos
[
visual
[
kk
].
orig_pos
].
x
=
0
;
pos
[
visual
[
kk
].
orig_pos
].
y
=
lines
;
}
}
}
return
outptr
-
visual_out
;
}
static
grub_ssize_t
grub_bidi_line_logical_to_visual
(
const
grub_uint32_t
*
logical
,
grub_size_t
logical_len
,
struct
grub_unicode_glyph
*
visual_out
,
grub_size_t
(
*
getcharwidth
)
(
const
struct
grub_unicode_glyph
*
visual
,
void
*
getcharwidth_arg
),
void
*
getcharwidth_arg
,
grub_size_t
maxwidth
,
grub_size_t
startwidth
,
grub_uint32_t
contchar
,
struct
grub_term_pos
*
pos
,
int
primitive_wrap
,
grub_size_t
log_end
)
{
enum
grub_bidi_type
type
=
GRUB_BIDI_TYPE_L
;
enum
override_status
{
OVERRIDE_NEUTRAL
=
0
,
OVERRIDE_R
,
OVERRIDE_L
};
unsigned
base_level
;
enum
override_status
cur_override
;
unsigned
i
;
unsigned
stack_level
[
GRUB_BIDI_MAX_EXPLICIT_LEVEL
+
3
];
enum
override_status
stack_override
[
GRUB_BIDI_MAX_EXPLICIT_LEVEL
+
3
];
unsigned
stack_depth
=
0
;
unsigned
invalid_pushes
=
0
;
unsigned
visual_len
=
0
;
unsigned
run_start
,
run_end
;
struct
grub_unicode_glyph
*
visual
;
unsigned
cur_level
;
int
bidi_needed
=
0
;
#define push_stack(new_override, new_level) \
{ \
if (new_level > GRUB_BIDI_MAX_EXPLICIT_LEVEL) \
{ \
invalid_pushes++; \
} \
else \
{ \
stack_level[stack_depth] = cur_level; \
stack_override[stack_depth] = cur_override; \
stack_depth++; \
cur_level = new_level; \
cur_override = new_override; \
} \
}
#define pop_stack() \
{ \
if (invalid_pushes) \
{ \
invalid_pushes--; \
} \
else if (stack_depth) \
{ \
stack_depth--; \
cur_level = stack_level[stack_depth]; \
cur_override = stack_override[stack_depth]; \
} \
}
visual
=
grub_malloc
(
sizeof
(
visual
[
0
])
*
logical_len
);
if
(
!
visual
)
return
-
1
;
for
(
i
=
0
;
i
<
logical_len
;
i
++
)
{
type
=
get_bidi_type
(
logical
[
i
]);
if
(
type
==
GRUB_BIDI_TYPE_L
||
type
==
GRUB_BIDI_TYPE_AL
||
type
==
GRUB_BIDI_TYPE_R
)
break
;
}
if
(
type
==
GRUB_BIDI_TYPE_R
||
type
==
GRUB_BIDI_TYPE_AL
)
base_level
=
1
;
else
base_level
=
0
;
cur_level
=
base_level
;
cur_override
=
OVERRIDE_NEUTRAL
;
{
const
grub_uint32_t
*
lptr
;
enum
{
JOIN_DEFAULT
,
NOJOIN
,
JOIN_FORCE
}
join_state
=
JOIN_DEFAULT
;
int
zwj_propagate_to_previous
=
0
;
for
(
lptr
=
logical
;
lptr
<
logical
+
logical_len
;)
{
grub_size_t
p
;
if
(
*
lptr
==
GRUB_UNICODE_ZWJ
)
{
if
(
zwj_propagate_to_previous
)
{
visual
[
visual_len
-
1
].
attributes
|=
GRUB_UNICODE_GLYPH_ATTRIBUTE_RIGHT_JOINED_EXPLICIT
|
GRUB_UNICODE_GLYPH_ATTRIBUTE_RIGHT_JOINED
;
}
zwj_propagate_to_previous
=
0
;
join_state
=
JOIN_FORCE
;
lptr
++
;
continue
;
}
if
(
*
lptr
==
GRUB_UNICODE_ZWNJ
)
{
if
(
zwj_propagate_to_previous
)
{
visual
[
visual_len
-
1
].
attributes
|=
GRUB_UNICODE_GLYPH_ATTRIBUTE_RIGHT_JOINED_EXPLICIT
;
visual
[
visual_len
-
1
].
attributes
&=
~
GRUB_UNICODE_GLYPH_ATTRIBUTE_RIGHT_JOINED
;
}
zwj_propagate_to_previous
=
0
;
join_state
=
NOJOIN
;
lptr
++
;
continue
;
}
/* The tags: deprecated, never used. */
if
(
*
lptr
>=
GRUB_UNICODE_TAG_START
&&
*
lptr
<=
GRUB_UNICODE_TAG_END
)
continue
;
p
=
grub_unicode_aglomerate_comb
(
lptr
,
logical
+
logical_len
-
lptr
,
&
visual
[
visual_len
]);
visual
[
visual_len
].
orig_pos
=
lptr
-
logical
;
type
=
get_bidi_type
(
visual
[
visual_len
].
base
);
switch
(
type
)
{
case
GRUB_BIDI_TYPE_RLE
:
bidi_needed
=
1
;
push_stack
(
cur_override
,
(
cur_level
|
1
)
+
1
);
break
;
case
GRUB_BIDI_TYPE_RLO
:
bidi_needed
=
1
;
push_stack
(
OVERRIDE_R
,
(
cur_level
|
1
)
+
1
);
break
;
case
GRUB_BIDI_TYPE_LRE
:
push_stack
(
cur_override
,
(
cur_level
&
~
1
)
+
2
);
break
;
case
GRUB_BIDI_TYPE_LRO
:
push_stack
(
OVERRIDE_L
,
(
cur_level
&
~
1
)
+
2
);
break
;
case
GRUB_BIDI_TYPE_PDF
:
pop_stack
();
break
;
case
GRUB_BIDI_TYPE_BN
:
break
;
case
GRUB_BIDI_TYPE_R
:
case
GRUB_BIDI_TYPE_AL
:
bidi_needed
=
1
;
/* Fallthrough. */
default:
{
if
(
join_state
==
JOIN_FORCE
)
{
visual
[
visual_len
].
attributes
|=
GRUB_UNICODE_GLYPH_ATTRIBUTE_LEFT_JOINED_EXPLICIT
|
GRUB_UNICODE_GLYPH_ATTRIBUTE_LEFT_JOINED
;
}
if
(
join_state
==
NOJOIN
)
{
visual
[
visual_len
].
attributes
|=
GRUB_UNICODE_GLYPH_ATTRIBUTE_LEFT_JOINED_EXPLICIT
;
visual
[
visual_len
].
attributes
&=
~
GRUB_UNICODE_GLYPH_ATTRIBUTE_LEFT_JOINED
;
}
join_state
=
JOIN_DEFAULT
;
zwj_propagate_to_previous
=
1
;
visual
[
visual_len
].
bidi_level
=
cur_level
;
if
(
cur_override
!=
OVERRIDE_NEUTRAL
)
visual
[
visual_len
].
bidi_type
=
(
cur_override
==
OVERRIDE_L
)
?
GRUB_BIDI_TYPE_L
:
GRUB_BIDI_TYPE_R
;
else
visual
[
visual_len
].
bidi_type
=
type
;
visual_len
++
;
}
}
lptr
+=
p
;
}
}
if
(
bidi_needed
)
{
for
(
run_start
=
0
;
run_start
<
visual_len
;
run_start
=
run_end
)
{
unsigned
prev_level
,
next_level
,
cur_run_level
;
unsigned
last_type
,
last_strong_type
;
for
(
run_end
=
run_start
;
run_end
<
visual_len
&&
visual
[
run_end
].
bidi_level
==
visual
[
run_start
].
bidi_level
;
run_end
++
);
if
(
run_start
==
0
)
prev_level
=
base_level
;
else
prev_level
=
visual
[
run_start
-
1
].
bidi_level
;
if
(
run_end
==
visual_len
)
next_level
=
base_level
;
else
next_level
=
visual
[
run_end
].
bidi_level
;
cur_run_level
=
visual
[
run_start
].
bidi_level
;
if
(
prev_level
&
1
)
last_type
=
GRUB_BIDI_TYPE_R
;
else
last_type
=
GRUB_BIDI_TYPE_L
;
last_strong_type
=
last_type
;
for
(
i
=
run_start
;
i
<
run_end
;
i
++
)
{
switch
(
visual
[
i
].
bidi_type
)
{
case
GRUB_BIDI_TYPE_NSM
:
visual
[
i
].
bidi_type
=
last_type
;
break
;
case
GRUB_BIDI_TYPE_EN
:
if
(
last_strong_type
==
GRUB_BIDI_TYPE_AL
)
visual
[
i
].
bidi_type
=
GRUB_BIDI_TYPE_AN
;
break
;
case
GRUB_BIDI_TYPE_L
:
case
GRUB_BIDI_TYPE_R
:
last_strong_type
=
visual
[
i
].
bidi_type
;
break
;
case
GRUB_BIDI_TYPE_ES
:
if
(
last_type
==
GRUB_BIDI_TYPE_EN
&&
i
+
1
<
run_end
&&
visual
[
i
+
1
].
bidi_type
==
GRUB_BIDI_TYPE_EN
)
visual
[
i
].
bidi_type
=
GRUB_BIDI_TYPE_EN
;
else
visual
[
i
].
bidi_type
=
GRUB_BIDI_TYPE_ON
;
break
;
case
GRUB_BIDI_TYPE_ET
:
{
unsigned
j
;
if
(
last_type
==
GRUB_BIDI_TYPE_EN
)
{
visual
[
i
].
bidi_type
=
GRUB_BIDI_TYPE_EN
;
break
;
}
for
(
j
=
i
;
j
<
run_end
&&
visual
[
j
].
bidi_type
==
GRUB_BIDI_TYPE_ET
;
j
++
);
if
(
j
!=
run_end
&&
visual
[
j
].
bidi_type
==
GRUB_BIDI_TYPE_EN
)
{
for
(;
i
<
run_end
&&
visual
[
i
].
bidi_type
==
GRUB_BIDI_TYPE_ET
;
i
++
)
visual
[
i
].
bidi_type
=
GRUB_BIDI_TYPE_EN
;
i
--
;
break
;
}
for
(;
i
<
run_end
&&
visual
[
i
].
bidi_type
==
GRUB_BIDI_TYPE_ET
;
i
++
)
visual
[
i
].
bidi_type
=
GRUB_BIDI_TYPE_ON
;
i
--
;
break
;
}
break
;
case
GRUB_BIDI_TYPE_CS
:
if
(
last_type
==
GRUB_BIDI_TYPE_EN
&&
i
+
1
<
run_end
&&
visual
[
i
+
1
].
bidi_type
==
GRUB_BIDI_TYPE_EN
)
{
visual
[
i
].
bidi_type
=
GRUB_BIDI_TYPE_EN
;
break
;
}
if
(
last_type
==
GRUB_BIDI_TYPE_AN
&&
i
+
1
<
run_end
&&
(
visual
[
i
+
1
].
bidi_type
==
GRUB_BIDI_TYPE_AN
||
(
visual
[
i
+
1
].
bidi_type
==
GRUB_BIDI_TYPE_EN
&&
last_strong_type
==
GRUB_BIDI_TYPE_AL
)))
{
visual
[
i
].
bidi_type
=
GRUB_BIDI_TYPE_EN
;
break
;
}
visual
[
i
].
bidi_type
=
GRUB_BIDI_TYPE_ON
;
break
;
case
GRUB_BIDI_TYPE_AL
:
last_strong_type
=
visual
[
i
].
bidi_type
;
visual
[
i
].
bidi_type
=
GRUB_BIDI_TYPE_R
;
break
;
default:
/* Make GCC happy. */
break
;
}
last_type
=
visual
[
i
].
bidi_type
;
if
(
visual
[
i
].
bidi_type
==
GRUB_BIDI_TYPE_EN
&&
last_strong_type
==
GRUB_BIDI_TYPE_L
)
visual
[
i
].
bidi_type
=
GRUB_BIDI_TYPE_L
;
}
if
(
prev_level
&
1
)
last_type
=
GRUB_BIDI_TYPE_R
;
else
last_type
=
GRUB_BIDI_TYPE_L
;
for
(
i
=
run_start
;
i
<
run_end
;
)
{
unsigned
j
;
unsigned
next_type
;
for
(
j
=
i
;
j
<
run_end
&&
(
visual
[
j
].
bidi_type
==
GRUB_BIDI_TYPE_B
||
visual
[
j
].
bidi_type
==
GRUB_BIDI_TYPE_S
||
visual
[
j
].
bidi_type
==
GRUB_BIDI_TYPE_WS
||
visual
[
j
].
bidi_type
==
GRUB_BIDI_TYPE_ON
);
j
++
);
if
(
j
==
i
)
{
if
(
visual
[
i
].
bidi_type
==
GRUB_BIDI_TYPE_L
)
last_type
=
GRUB_BIDI_TYPE_L
;
else
last_type
=
GRUB_BIDI_TYPE_R
;
i
++
;
continue
;
}
if
(
j
==
run_end
)
next_type
=
(
next_level
&
1
)
?
GRUB_BIDI_TYPE_R
:
GRUB_BIDI_TYPE_L
;
else
{
if
(
visual
[
j
].
bidi_type
==
GRUB_BIDI_TYPE_L
)
next_type
=
GRUB_BIDI_TYPE_L
;
else
next_type
=
GRUB_BIDI_TYPE_R
;
}
if
(
next_type
==
last_type
)
for
(;
i
<
j
;
i
++
)
visual
[
i
].
bidi_type
=
last_type
;
else
for
(;
i
<
j
;
i
++
)
visual
[
i
].
bidi_type
=
(
cur_run_level
&
1
)
?
GRUB_BIDI_TYPE_R
:
GRUB_BIDI_TYPE_L
;
}
}
for
(
i
=
0
;
i
<
visual_len
;
i
++
)
{
if
(
!
(
visual
[
i
].
bidi_level
&
1
)
&&
visual
[
i
].
bidi_type
==
GRUB_BIDI_TYPE_R
)
{
visual
[
i
].
bidi_level
++
;
continue
;
}
if
(
!
(
visual
[
i
].
bidi_level
&
1
)
&&
(
visual
[
i
].
bidi_type
==
GRUB_BIDI_TYPE_AN
||
visual
[
i
].
bidi_type
==
GRUB_BIDI_TYPE_EN
))
{
visual
[
i
].
bidi_level
+=
2
;
continue
;
}
if
((
visual
[
i
].
bidi_level
&
1
)
&&
(
visual
[
i
].
bidi_type
==
GRUB_BIDI_TYPE_L
||
visual
[
i
].
bidi_type
==
GRUB_BIDI_TYPE_AN
||
visual
[
i
].
bidi_type
==
GRUB_BIDI_TYPE_EN
))
{
visual
[
i
].
bidi_level
++
;
continue
;
}
}
}
else
{
for
(
i
=
0
;
i
<
visual_len
;
i
++
)
visual
[
i
].
bidi_level
=
0
;
}
{
grub_ssize_t
ret
;
ret
=
bidi_line_wrap
(
visual_out
,
visual
,
visual_len
,
getcharwidth
,
getcharwidth_arg
,
maxwidth
,
startwidth
,
contchar
,
pos
,
primitive_wrap
,
log_end
);
grub_free
(
visual
);
return
ret
;
}
}
static
int
is_visible
(
const
struct
grub_unicode_glyph
*
gl
)
{
if
(
gl
->
ncomb
)
return
1
;
if
(
gl
->
base
==
GRUB_UNICODE_LRM
||
gl
->
base
==
GRUB_UNICODE_RLM
)
return
0
;
return
1
;
}
grub_ssize_t
grub_bidi_logical_to_visual
(
const
grub_uint32_t
*
logical
,
grub_size_t
logical_len
,
struct
grub_unicode_glyph
**
visual_out
,
grub_size_t
(
*
getcharwidth
)
(
const
struct
grub_unicode_glyph
*
visual
,
void
*
getcharwidth_arg
),
void
*
getcharwidth_arg
,
grub_size_t
max_length
,
grub_size_t
startwidth
,
grub_uint32_t
contchar
,
struct
grub_term_pos
*
pos
,
int
primitive_wrap
)
{
const
grub_uint32_t
*
line_start
=
logical
,
*
ptr
;
struct
grub_unicode_glyph
*
visual_ptr
;
*
visual_out
=
visual_ptr
=
grub_malloc
(
3
*
sizeof
(
visual_ptr
[
0
])
*
(
logical_len
+
2
));
if
(
!
visual_ptr
)
return
-
1
;
for
(
ptr
=
logical
;
ptr
<=
logical
+
logical_len
;
ptr
++
)
{
if
(
ptr
==
logical
+
logical_len
||
*
ptr
==
'\n'
)
{
grub_ssize_t
ret
;
grub_ssize_t
i
,
j
;
ret
=
grub_bidi_line_logical_to_visual
(
line_start
,
ptr
-
line_start
,
visual_ptr
,
getcharwidth
,
getcharwidth_arg
,
max_length
,
startwidth
,
contchar
,
pos
,
primitive_wrap
,
logical_len
);
startwidth
=
0
;
if
(
ret
<
0
)
{
grub_free
(
*
visual_out
);
return
ret
;
}
for
(
i
=
0
,
j
=
0
;
i
<
ret
;
i
++
)
if
(
is_visible
(
&
visual_ptr
[
i
]))
visual_ptr
[
j
++
]
=
visual_ptr
[
i
];
visual_ptr
+=
j
;
line_start
=
ptr
;
if
(
ptr
!=
logical
+
logical_len
)
{
grub_memset
(
visual_ptr
,
0
,
sizeof
(
visual_ptr
[
0
]));
visual_ptr
->
base
=
'\n'
;
visual_ptr
++
;
line_start
++
;
}
}
}
return
visual_ptr
-
*
visual_out
;
}
grub_uint32_t
grub_unicode_mirror_code
(
grub_uint32_t
in
)
{
int
i
;
for
(
i
=
0
;
grub_unicode_bidi_pairs
[
i
].
key
;
i
++
)
if
(
grub_unicode_bidi_pairs
[
i
].
key
==
in
)
return
grub_unicode_bidi_pairs
[
i
].
replace
;
return
in
;
}
grub_uint32_t
grub_unicode_shape_code
(
grub_uint32_t
in
,
grub_uint8_t
attr
)
{
int
i
;
if
(
!
(
in
>=
GRUB_UNICODE_ARABIC_START
&&
in
<
GRUB_UNICODE_ARABIC_END
))
return
in
;
for
(
i
=
0
;
grub_unicode_arabic_shapes
[
i
].
code
;
i
++
)
if
(
grub_unicode_arabic_shapes
[
i
].
code
==
in
)
{
grub_uint32_t
out
=
0
;
switch
(
attr
&
(
GRUB_UNICODE_GLYPH_ATTRIBUTE_RIGHT_JOINED
|
GRUB_UNICODE_GLYPH_ATTRIBUTE_LEFT_JOINED
))
{
case
0
:
out
=
grub_unicode_arabic_shapes
[
i
].
isolated
;
break
;
case
GRUB_UNICODE_GLYPH_ATTRIBUTE_RIGHT_JOINED
:
out
=
grub_unicode_arabic_shapes
[
i
].
right_linked
;
break
;
case
GRUB_UNICODE_GLYPH_ATTRIBUTE_LEFT_JOINED
:
out
=
grub_unicode_arabic_shapes
[
i
].
left_linked
;
break
;
case
GRUB_UNICODE_GLYPH_ATTRIBUTE_RIGHT_JOINED
|
GRUB_UNICODE_GLYPH_ATTRIBUTE_LEFT_JOINED
:
out
=
grub_unicode_arabic_shapes
[
i
].
both_linked
;
break
;
}
if
(
out
)
return
out
;
}
return
in
;
}
const
grub_uint32_t
*
grub_unicode_get_comb_start
(
const
grub_uint32_t
*
str
,
const
grub_uint32_t
*
cur
)
{
const
grub_uint32_t
*
ptr
;
for
(
ptr
=
cur
;
ptr
>=
str
;
ptr
--
)
{
if
(
*
ptr
>=
GRUB_UNICODE_VARIATION_SELECTOR_1
&&
*
ptr
<=
GRUB_UNICODE_VARIATION_SELECTOR_16
)
continue
;
if
(
*
ptr
>=
GRUB_UNICODE_VARIATION_SELECTOR_17
&&
*
ptr
<=
GRUB_UNICODE_VARIATION_SELECTOR_256
)
continue
;
enum
grub_comb_type
comb_type
;
comb_type
=
grub_unicode_get_comb_type
(
*
ptr
);
if
(
comb_type
)
continue
;
return
ptr
;
}
return
str
;
}
const
grub_uint32_t
*
grub_unicode_get_comb_end
(
const
grub_uint32_t
*
end
,
const
grub_uint32_t
*
cur
)
{
const
grub_uint32_t
*
ptr
;
for
(
ptr
=
cur
;
ptr
<
end
;
ptr
++
)
{
if
(
*
ptr
>=
GRUB_UNICODE_VARIATION_SELECTOR_1
&&
*
ptr
<=
GRUB_UNICODE_VARIATION_SELECTOR_16
)
continue
;
if
(
*
ptr
>=
GRUB_UNICODE_VARIATION_SELECTOR_17
&&
*
ptr
<=
GRUB_UNICODE_VARIATION_SELECTOR_256
)
continue
;
enum
grub_comb_type
comb_type
;
comb_type
=
grub_unicode_get_comb_type
(
*
ptr
);
if
(
comb_type
)
continue
;
return
ptr
;
}
return
end
;
}
int
grub_utf8_get_num_code
(
const
char
*
src
,
grub_size_t
srcsize
)
{
int
count
=
0
;
grub_uint32_t
code
=
0
;
int
num
=
0
;
while
(
srcsize
)
{
if
(
srcsize
!=
(
grub_size_t
)
-
1
)
srcsize
--
;
if
(
!
grub_utf8_process
((
grub_uint8_t
)
*
src
++
,
&
code
,
&
count
))
return
0
;
if
(
count
!=
0
)
continue
;
if
(
code
==
0
||
code
>
GRUB_UNICODE_LAST_VALID
)
return
num
;
++
num
;
}
return
num
;
}
const
char
*
grub_utf8_offset_code
(
const
char
*
src
,
grub_size_t
srcsize
,
int
num
)
{
int
count
=
0
;
grub_uint32_t
code
=
0
;
while
(
srcsize
&&
num
)
{
if
(
srcsize
!=
(
grub_size_t
)
-
1
)
srcsize
--
;
if
(
!
grub_utf8_process
((
grub_uint8_t
)
*
src
++
,
&
code
,
&
count
))
return
0
;
if
(
count
!=
0
)
continue
;
if
(
code
==
0
||
code
>
GRUB_UNICODE_LAST_VALID
)
return
0
;
--
num
;
}
if
(
!
num
)
return
src
;
return
0
;
}
GRUB2/MOD_SRC/grub-2.04/grub-core/normal/menu.c
View file @
15b8b1f3
...
@@ -461,6 +461,15 @@ menu_set_chosen_entry (grub_menu_t menu, int entry)
...
@@ -461,6 +461,15 @@ menu_set_chosen_entry (grub_menu_t menu, int entry)
cur
->
set_chosen_entry
(
entry
,
cur
->
data
);
cur
->
set_chosen_entry
(
entry
,
cur
->
data
);
}
}
static
void
menu_scroll_chosen_entry
(
int
diren
)
{
struct
grub_menu_viewer
*
cur
;
for
(
cur
=
viewers
;
cur
;
cur
=
cur
->
next
)
if
(
cur
->
scroll_chosen_entry
)
cur
->
scroll_chosen_entry
(
cur
->
data
,
diren
);
}
static
void
static
void
menu_print_timeout
(
int
timeout
)
menu_print_timeout
(
int
timeout
)
{
{
...
@@ -846,6 +855,13 @@ run_menu (grub_menu_t menu, int nested, int *auto_boot)
...
@@ -846,6 +855,13 @@ run_menu (grub_menu_t menu, int nested, int *auto_boot)
menu_set_chosen_entry
(
menu
,
current_entry
);
menu_set_chosen_entry
(
menu
,
current_entry
);
break
;
break
;
case
GRUB_TERM_KEY_RIGHT
:
menu_scroll_chosen_entry
(
1
);
break
;
case
GRUB_TERM_KEY_LEFT
:
menu_scroll_chosen_entry
(
-
1
);
break
;
case
'\n'
:
case
'\n'
:
case
'\r'
:
case
'\r'
:
// case GRUB_TERM_KEY_RIGHT:
// case GRUB_TERM_KEY_RIGHT:
...
...
GRUB2/MOD_SRC/grub-2.04/grub-core/normal/menu_text.c
View file @
15b8b1f3
...
@@ -42,6 +42,7 @@ struct menu_viewer_data
...
@@ -42,6 +42,7 @@ struct menu_viewer_data
TIMEOUT_TERSE_NO_MARGIN
TIMEOUT_TERSE_NO_MARGIN
}
timeout_msg
;
}
timeout_msg
;
grub_menu_t
menu
;
grub_menu_t
menu
;
int
*
menu_title_offset
;
struct
grub_term_output
*
term
;
struct
grub_term_output
*
term
;
};
};
...
@@ -524,6 +525,37 @@ menu_text_set_chosen_entry (int entry, void *dataptr)
...
@@ -524,6 +525,37 @@ menu_text_set_chosen_entry (int entry, void *dataptr)
grub_term_refresh
(
data
->
term
);
grub_term_refresh
(
data
->
term
);
}
}
static
void
menu_text_scroll_chosen_entry
(
void
*
dataptr
,
int
diren
)
{
struct
menu_viewer_data
*
data
=
dataptr
;
const
char
*
orig_title
,
*
scrolled_title
;
int
off
;
int
selected
;
grub_menu_entry_t
entry
;
if
(
!
data
->
menu
->
size
)
return
;
selected
=
data
->
first
+
data
->
offset
;
entry
=
grub_menu_get_entry
(
data
->
menu
,
selected
);
orig_title
=
entry
->
title
;
off
=
data
->
menu_title_offset
[
selected
]
+
diren
;
if
(
off
<
0
||
off
>
grub_utf8_get_num_code
(
orig_title
,
grub_strlen
(
orig_title
)))
return
;
scrolled_title
=
grub_utf8_offset_code
(
orig_title
,
grub_strlen
(
orig_title
),
off
);
if
(
scrolled_title
)
entry
->
title
=
scrolled_title
;
print_entry
(
data
->
geo
.
first_entry_y
+
data
->
offset
,
1
,
entry
,
data
);
entry
->
title
=
orig_title
;
data
->
menu_title_offset
[
selected
]
=
off
;
grub_term_refresh
(
data
->
term
);
}
static
void
static
void
menu_text_fini
(
void
*
dataptr
)
menu_text_fini
(
void
*
dataptr
)
{
{
...
@@ -531,6 +563,8 @@ menu_text_fini (void *dataptr)
...
@@ -531,6 +563,8 @@ menu_text_fini (void *dataptr)
grub_term_setcursor
(
data
->
term
,
1
);
grub_term_setcursor
(
data
->
term
,
1
);
grub_term_cls
(
data
->
term
);
grub_term_cls
(
data
->
term
);
if
(
data
->
menu_title_offset
)
grub_free
(
data
->
menu_title_offset
);
grub_free
(
data
);
grub_free
(
data
);
}
}
...
@@ -585,9 +619,14 @@ grub_menu_try_text (struct grub_term_output *term,
...
@@ -585,9 +619,14 @@ grub_menu_try_text (struct grub_term_output *term,
return
grub_errno
;
return
grub_errno
;
}
}
if
(
menu
->
size
)
data
->
menu_title_offset
=
grub_zalloc
(
sizeof
(
*
data
->
menu_title_offset
)
*
menu
->
size
);
data
->
term
=
term
;
data
->
term
=
term
;
instance
->
data
=
data
;
instance
->
data
=
data
;
instance
->
set_chosen_entry
=
menu_text_set_chosen_entry
;
instance
->
set_chosen_entry
=
menu_text_set_chosen_entry
;
if
(
data
->
menu_title_offset
)
instance
->
scroll_chosen_entry
=
menu_text_scroll_chosen_entry
;
instance
->
print_timeout
=
menu_text_print_timeout
;
instance
->
print_timeout
=
menu_text_print_timeout
;
instance
->
clear_timeout
=
menu_text_clear_timeout
;
instance
->
clear_timeout
=
menu_text_clear_timeout
;
instance
->
fini
=
menu_text_fini
;
instance
->
fini
=
menu_text_fini
;
...
...
GRUB2/MOD_SRC/grub-2.04/include/grub/charset.h
0 → 100644
View file @
15b8b1f3
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef GRUB_CHARSET_HEADER
#define GRUB_CHARSET_HEADER 1
#include <grub/types.h>
#define GRUB_UINT8_1_LEADINGBIT 0x80
#define GRUB_UINT8_2_LEADINGBITS 0xc0
#define GRUB_UINT8_3_LEADINGBITS 0xe0
#define GRUB_UINT8_4_LEADINGBITS 0xf0
#define GRUB_UINT8_5_LEADINGBITS 0xf8
#define GRUB_UINT8_6_LEADINGBITS 0xfc
#define GRUB_UINT8_7_LEADINGBITS 0xfe
#define GRUB_UINT8_1_TRAILINGBIT 0x01
#define GRUB_UINT8_2_TRAILINGBITS 0x03
#define GRUB_UINT8_3_TRAILINGBITS 0x07
#define GRUB_UINT8_4_TRAILINGBITS 0x0f
#define GRUB_UINT8_5_TRAILINGBITS 0x1f
#define GRUB_UINT8_6_TRAILINGBITS 0x3f
#define GRUB_MAX_UTF8_PER_UTF16 4
/* You need at least one UTF-8 byte to have one UTF-16 word.
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) \
(0xD800 | ((((code) - GRUB_UCS2_LIMIT) >> 10) & 0x3ff))
#define GRUB_UTF16_LOWER_SURROGATE(code) \
(0xDC00 | (((code) - GRUB_UCS2_LIMIT) & 0x3ff))
/* Process one character from UTF8 sequence.
At beginning set *code = 0, *count = 0. Returns 0 on failure and
1 on success. *count holds the number of trailing bytes. */
static
inline
int
grub_utf8_process
(
grub_uint8_t
c
,
grub_uint32_t
*
code
,
int
*
count
)
{
if
(
*
count
)
{
if
((
c
&
GRUB_UINT8_2_LEADINGBITS
)
!=
GRUB_UINT8_1_LEADINGBIT
)
{
*
count
=
0
;
/* invalid */
return
0
;
}
else
{
*
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
;
}
}
if
((
c
&
GRUB_UINT8_1_LEADINGBIT
)
==
0
)
{
*
code
=
c
;
return
1
;
}
if
((
c
&
GRUB_UINT8_3_LEADINGBITS
)
==
GRUB_UINT8_2_LEADINGBITS
)
{
*
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
)
{
*
count
=
2
;
*
code
=
c
&
GRUB_UINT8_4_TRAILINGBITS
;
return
1
;
}
if
((
c
&
GRUB_UINT8_5_LEADINGBITS
)
==
GRUB_UINT8_4_LEADINGBITS
)
{
*
count
=
3
;
*
code
=
c
&
GRUB_UINT8_3_TRAILINGBITS
;
return
1
;
}
return
0
;
}
/* Convert a (possibly null-terminated) UTF-8 string of at most SRCSIZE
bytes (if SRCSIZE is -1, it is ignored) in length to a UTF-16 string.
Return the number of characters converted. DEST must be able to hold
at least DESTSIZE characters. If an invalid sequence is found, return -1.
If SRCEND is not NULL, then *SRCEND is set to the next byte after the
last byte used in SRC. */
static
inline
grub_size_t
grub_utf8_to_utf16
(
grub_uint16_t
*
dest
,
grub_size_t
destsize
,
const
grub_uint8_t
*
src
,
grub_size_t
srcsize
,
const
grub_uint8_t
**
srcend
)
{
grub_uint16_t
*
p
=
dest
;
int
count
=
0
;
grub_uint32_t
code
=
0
;
if
(
srcend
)
*
srcend
=
src
;
while
(
srcsize
&&
destsize
)
{
int
was_count
=
count
;
if
(
srcsize
!=
(
grub_size_t
)
-
1
)
srcsize
--
;
if
(
!
grub_utf8_process
(
*
src
++
,
&
code
,
&
count
))
{
code
=
'?'
;
count
=
0
;
/* Character c may be valid, don't eat it. */
if
(
was_count
)
src
--
;
}
if
(
count
!=
0
)
continue
;
if
(
code
==
0
)
break
;
if
(
destsize
<
2
&&
code
>=
GRUB_UCS2_LIMIT
)
break
;
if
(
code
>=
GRUB_UCS2_LIMIT
)
{
*
p
++
=
GRUB_UTF16_UPPER_SURROGATE
(
code
);
*
p
++
=
GRUB_UTF16_LOWER_SURROGATE
(
code
);
destsize
-=
2
;
}
else
{
*
p
++
=
code
;
destsize
--
;
}
}
if
(
srcend
)
*
srcend
=
src
;
return
p
-
dest
;
}
/* Determine the last position where the UTF-8 string [beg, end) can
be safely cut. */
static
inline
grub_size_t
grub_getend
(
const
char
*
beg
,
const
char
*
end
)
{
const
char
*
ptr
;
for
(
ptr
=
end
-
1
;
ptr
>=
beg
;
ptr
--
)
if
((
*
ptr
&
GRUB_UINT8_2_LEADINGBITS
)
!=
GRUB_UINT8_1_LEADINGBIT
)
break
;
if
(
ptr
<
beg
)
return
0
;
if
((
*
ptr
&
GRUB_UINT8_1_LEADINGBIT
)
==
0
)
return
ptr
+
1
-
beg
;
if
((
*
ptr
&
GRUB_UINT8_3_LEADINGBITS
)
==
GRUB_UINT8_2_LEADINGBITS
&&
ptr
+
2
<=
end
)
return
ptr
+
2
-
beg
;
if
((
*
ptr
&
GRUB_UINT8_4_LEADINGBITS
)
==
GRUB_UINT8_3_LEADINGBITS
&&
ptr
+
3
<=
end
)
return
ptr
+
3
-
beg
;
if
((
*
ptr
&
GRUB_UINT8_5_LEADINGBITS
)
==
GRUB_UINT8_4_LEADINGBITS
&&
ptr
+
4
<=
end
)
return
ptr
+
4
-
beg
;
/* Invalid character or incomplete. Cut before it. */
return
ptr
-
beg
;
}
/* Convert UTF-16 to UTF-8. */
static
inline
grub_uint8_t
*
grub_utf16_to_utf8
(
grub_uint8_t
*
dest
,
const
grub_uint16_t
*
src
,
grub_size_t
size
)
{
grub_uint32_t
code_high
=
0
;
while
(
size
--
)
{
grub_uint32_t
code
=
*
src
++
;
if
(
code_high
)
{
if
(
code
>=
0xDC00
&&
code
<=
0xDFFF
)
{
/* Surrogate pair. */
code
=
((
code_high
-
0xD800
)
<<
10
)
+
(
code
-
0xDC00
)
+
0x10000
;
*
dest
++
=
(
code
>>
18
)
|
0xF0
;
*
dest
++
=
((
code
>>
12
)
&
0x3F
)
|
0x80
;
*
dest
++
=
((
code
>>
6
)
&
0x3F
)
|
0x80
;
*
dest
++
=
(
code
&
0x3F
)
|
0x80
;
}
else
{
/* Error... */
*
dest
++
=
'?'
;
/* *src may be valid. Don't eat it. */
src
--
;
}
code_high
=
0
;
}
else
{
if
(
code
<=
0x007F
)
*
dest
++
=
code
;
else
if
(
code
<=
0x07FF
)
{
*
dest
++
=
(
code
>>
6
)
|
0xC0
;
*
dest
++
=
(
code
&
0x3F
)
|
0x80
;
}
else
if
(
code
>=
0xD800
&&
code
<=
0xDBFF
)
{
code_high
=
code
;
continue
;
}
else
if
(
code
>=
0xDC00
&&
code
<=
0xDFFF
)
{
/* Error... */
*
dest
++
=
'?'
;
}
else
if
(
code
<
0x10000
)
{
*
dest
++
=
(
code
>>
12
)
|
0xE0
;
*
dest
++
=
((
code
>>
6
)
&
0x3F
)
|
0x80
;
*
dest
++
=
(
code
&
0x3F
)
|
0x80
;
}
else
{
*
dest
++
=
(
code
>>
18
)
|
0xF0
;
*
dest
++
=
((
code
>>
12
)
&
0x3F
)
|
0x80
;
*
dest
++
=
((
code
>>
6
)
&
0x3F
)
|
0x80
;
*
dest
++
=
(
code
&
0x3F
)
|
0x80
;
}
}
}
return
dest
;
}
#define GRUB_MAX_UTF8_PER_LATIN1 2
/* Convert Latin1 to UTF-8. */
static
inline
grub_uint8_t
*
grub_latin1_to_utf8
(
grub_uint8_t
*
dest
,
const
grub_uint8_t
*
src
,
grub_size_t
size
)
{
while
(
size
--
)
{
if
(
!
(
*
src
&
0x80
))
*
dest
++
=
*
src
;
else
{
*
dest
++
=
(
*
src
>>
6
)
|
0xC0
;
*
dest
++
=
(
*
src
&
0x3F
)
|
0x80
;
}
src
++
;
}
return
dest
;
}
/* Convert UCS-4 to UTF-8. */
char
*
grub_ucs4_to_utf8_alloc
(
const
grub_uint32_t
*
src
,
grub_size_t
size
);
int
grub_is_valid_utf8
(
const
grub_uint8_t
*
src
,
grub_size_t
srcsize
);
grub_ssize_t
grub_utf8_to_ucs4_alloc
(
const
char
*
msg
,
grub_uint32_t
**
unicode_msg
,
grub_uint32_t
**
last_position
);
/* Returns the number of bytes the string src would occupy is converted
to UTF-8, excluding \0. */
grub_size_t
grub_get_num_of_utf8_bytes
(
const
grub_uint32_t
*
src
,
grub_size_t
size
);
/* Converts UCS-4 to UTF-8. Returns the number of bytes effectively written
excluding the trailing \0. */
grub_size_t
grub_ucs4_to_utf8
(
const
grub_uint32_t
*
src
,
grub_size_t
size
,
grub_uint8_t
*
dest
,
grub_size_t
destsize
);
grub_size_t
grub_utf8_to_ucs4
(
grub_uint32_t
*
dest
,
grub_size_t
destsize
,
const
grub_uint8_t
*
src
,
grub_size_t
srcsize
,
const
grub_uint8_t
**
srcend
);
/* Returns -2 if not enough space, -1 on invalid character. */
grub_ssize_t
grub_encode_utf8_character
(
grub_uint8_t
*
dest
,
grub_uint8_t
*
destend
,
grub_uint32_t
code
);
const
grub_uint32_t
*
grub_unicode_get_comb_start
(
const
grub_uint32_t
*
str
,
const
grub_uint32_t
*
cur
);
int
grub_utf8_get_num_code
(
const
char
*
src
,
grub_size_t
srcsize
);
const
char
*
grub_utf8_offset_code
(
const
char
*
src
,
grub_size_t
srcsize
,
int
num
);
#endif
GRUB2/MOD_SRC/grub-2.04/include/grub/gfxmenu_view.h
0 → 100644
View file @
15b8b1f3
/* gfxmenu_view.h - gfxmenu view interface. */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2008,2009 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef GRUB_GFXMENU_VIEW_HEADER
#define GRUB_GFXMENU_VIEW_HEADER 1
#include <grub/types.h>
#include <grub/err.h>
#include <grub/menu.h>
#include <grub/font.h>
#include <grub/gfxwidgets.h>
struct
grub_gfxmenu_view
;
/* Forward declaration of opaque type. */
typedef
struct
grub_gfxmenu_view
*
grub_gfxmenu_view_t
;
grub_gfxmenu_view_t
grub_gfxmenu_view_new
(
const
char
*
theme_path
,
int
width
,
int
height
);
void
grub_gfxmenu_view_destroy
(
grub_gfxmenu_view_t
view
);
/* Set properties on the view based on settings from the specified
theme file. */
grub_err_t
grub_gfxmenu_view_load_theme
(
grub_gfxmenu_view_t
view
,
const
char
*
theme_path
);
grub_err_t
grub_gui_recreate_box
(
grub_gfxmenu_box_t
*
boxptr
,
const
char
*
pattern
,
const
char
*
theme_dir
);
void
grub_gfxmenu_view_draw
(
grub_gfxmenu_view_t
view
);
void
grub_gfxmenu_redraw_menu
(
grub_gfxmenu_view_t
view
);
void
grub_gfxmenu_redraw_timeout
(
grub_gfxmenu_view_t
view
);
void
grub_gfxmenu_view_redraw
(
grub_gfxmenu_view_t
view
,
const
grub_video_rect_t
*
region
);
void
grub_gfxmenu_clear_timeout
(
void
*
data
);
void
grub_gfxmenu_print_timeout
(
int
timeout
,
void
*
data
);
void
grub_gfxmenu_set_chosen_entry
(
int
entry
,
void
*
data
);
void
grub_gfxmenu_scroll_chosen_entry
(
void
*
data
,
int
diren
);
grub_err_t
grub_font_draw_string
(
const
char
*
str
,
grub_font_t
font
,
grub_video_color_t
color
,
int
left_x
,
int
baseline_y
);
int
grub_font_get_string_width
(
grub_font_t
font
,
const
char
*
str
);
/* Implementation details -- this should not be used outside of the
view itself. */
#include <grub/video.h>
#include <grub/bitmap.h>
#include <grub/bitmap_scale.h>
#include <grub/gui.h>
#include <grub/gfxwidgets.h>
#include <grub/icon_manager.h>
/* Definition of the private representation of the view. */
struct
grub_gfxmenu_view
{
grub_video_rect_t
screen
;
int
need_to_check_sanity
;
grub_video_rect_t
terminal_rect
;
int
terminal_border
;
grub_font_t
title_font
;
grub_font_t
message_font
;
char
*
terminal_font_name
;
grub_video_rgba_color_t
title_color
;
grub_video_rgba_color_t
message_color
;
grub_video_rgba_color_t
message_bg_color
;
struct
grub_video_bitmap
*
raw_desktop_image
;
struct
grub_video_bitmap
*
scaled_desktop_image
;
grub_video_bitmap_selection_method_t
desktop_image_scale_method
;
grub_video_bitmap_h_align_t
desktop_image_h_align
;
grub_video_bitmap_v_align_t
desktop_image_v_align
;
grub_video_rgba_color_t
desktop_color
;
grub_gfxmenu_box_t
terminal_box
;
char
*
title_text
;
char
*
progress_message_text
;
char
*
theme_path
;
grub_gui_container_t
canvas
;
int
double_repaint
;
int
selected
;
grub_video_rect_t
progress_message_frame
;
grub_menu_t
menu
;
int
nested
;
int
first_timeout
;
int
*
menu_title_offset
;
};
#endif
/* ! GRUB_GFXMENU_VIEW_HEADER */
GRUB2/MOD_SRC/grub-2.04/include/grub/menu_viewer.h
0 → 100644
View file @
15b8b1f3
/* menu_viewer.h - Interface to menu viewer implementations. */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2009 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef GRUB_MENU_VIEWER_HEADER
#define GRUB_MENU_VIEWER_HEADER 1
#include <grub/err.h>
#include <grub/symbol.h>
#include <grub/types.h>
#include <grub/menu.h>
#include <grub/term.h>
struct
grub_menu_viewer
{
struct
grub_menu_viewer
*
next
;
void
*
data
;
void
(
*
set_chosen_entry
)
(
int
entry
,
void
*
data
);
void
(
*
scroll_chosen_entry
)
(
void
*
data
,
int
diren
);
void
(
*
print_timeout
)
(
int
timeout
,
void
*
data
);
void
(
*
clear_timeout
)
(
void
*
data
);
void
(
*
fini
)
(
void
*
fini
);
};
void
grub_menu_register_viewer
(
struct
grub_menu_viewer
*
viewer
);
grub_err_t
grub_menu_try_text
(
struct
grub_term_output
*
term
,
int
entry
,
grub_menu_t
menu
,
int
nested
);
extern
grub_err_t
(
*
grub_gfxmenu_try_hook
)
(
int
entry
,
grub_menu_t
menu
,
int
nested
);
#endif
/* GRUB_MENU_VIEWER_HEADER */
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment