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
"tests/vscode:/vscode.git/clone" did not exist on "7fa74925e74b6ae186293fbd26a411a09ba4d775"
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
Show 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