Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-winehq
Commits
151b4295
Commit
151b4295
authored
Aug 28, 2020
by
Jacek Caban
Committed by
Alexandre Julliard
Aug 28, 2020
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
conhost: Implement IOCTL_CONDRV_SET_OUTPUT_INFO.
Signed-off-by:
Jacek Caban
<
jacek@codeweavers.com
>
Signed-off-by:
Alexandre Julliard
<
julliard@winehq.org
>
parent
df8578da
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
199 additions
and
0 deletions
+199
-0
conhost.c
programs/conhost/conhost.c
+199
-0
No files found.
programs/conhost/conhost.c
View file @
151b4295
...
...
@@ -88,12 +88,15 @@ struct screen_buffer
unsigned
short
popup_attr
;
/* pop-up color attributes */
unsigned
int
max_width
;
/* size (w-h) of the window given font size */
unsigned
int
max_height
;
char_info_t
*
data
;
/* the data for each cell - a width x height matrix */
unsigned
int
color_map
[
16
];
/* color table */
RECT
win
;
/* current visible window on the screen buffer */
struct
font_info
font
;
/* console font information */
struct
wine_rb_entry
entry
;
/* map entry */
};
static
const
char_info_t
empty_char_info
=
{
' '
,
0x0007
};
/* white on black space */
static
void
*
ioctl_buffer
;
static
size_t
ioctl_buffer_size
;
...
...
@@ -120,6 +123,7 @@ static struct wine_rb_tree screen_buffer_map = { screen_buffer_compare_id };
static
struct
screen_buffer
*
create_screen_buffer
(
struct
console
*
console
,
int
id
,
int
width
,
int
height
)
{
struct
screen_buffer
*
screen_buffer
;
unsigned
int
i
;
if
(
!
(
screen_buffer
=
malloc
(
sizeof
(
*
screen_buffer
)
)))
return
NULL
;
screen_buffer
->
console
=
console
;
...
...
@@ -147,6 +151,20 @@ static struct screen_buffer *create_screen_buffer( struct console *console, int
screen_buffer
->
font
.
face_len
=
0
;
memset
(
screen_buffer
->
color_map
,
0
,
sizeof
(
screen_buffer
->
color_map
)
);
if
(
!
(
screen_buffer
->
data
=
malloc
(
screen_buffer
->
width
*
screen_buffer
->
height
*
sizeof
(
*
screen_buffer
->
data
)
)))
{
free
(
screen_buffer
);
return
NULL
;
}
/* clear the first row */
for
(
i
=
0
;
i
<
screen_buffer
->
width
;
i
++
)
screen_buffer
->
data
[
i
]
=
empty_char_info
;
/* and copy it to all other rows */
for
(
i
=
1
;
i
<
screen_buffer
->
height
;
i
++
)
memcpy
(
&
screen_buffer
->
data
[
i
*
screen_buffer
->
width
],
screen_buffer
->
data
,
screen_buffer
->
width
*
sizeof
(
char_info_t
)
);
if
(
wine_rb_put
(
&
screen_buffer_map
,
(
const
void
*
)
id
,
&
screen_buffer
->
entry
))
{
ERR
(
"id %x already exists
\n
"
,
id
);
...
...
@@ -164,6 +182,11 @@ static void destroy_screen_buffer( struct screen_buffer *screen_buffer )
free
(
screen_buffer
);
}
static
BOOL
is_active
(
struct
screen_buffer
*
screen_buffer
)
{
return
screen_buffer
==
screen_buffer
->
console
->
active
;
}
static
NTSTATUS
read_console_input
(
struct
console
*
console
,
size_t
out_size
)
{
size_t
count
=
min
(
out_size
/
sizeof
(
INPUT_RECORD
),
console
->
record_count
);
...
...
@@ -274,6 +297,178 @@ static NTSTATUS get_output_info( struct screen_buffer *screen_buffer, size_t *ou
return
STATUS_SUCCESS
;
}
static
NTSTATUS
change_screen_buffer_size
(
struct
screen_buffer
*
screen_buffer
,
int
new_width
,
int
new_height
)
{
int
i
,
old_width
,
old_height
,
copy_width
,
copy_height
;
char_info_t
*
new_data
;
if
(
!
(
new_data
=
malloc
(
new_width
*
new_height
*
sizeof
(
*
new_data
)
)))
return
STATUS_NO_MEMORY
;
old_width
=
screen_buffer
->
width
;
old_height
=
screen_buffer
->
height
;
copy_width
=
min
(
old_width
,
new_width
);
copy_height
=
min
(
old_height
,
new_height
);
/* copy all the rows */
for
(
i
=
0
;
i
<
copy_height
;
i
++
)
{
memcpy
(
&
new_data
[
i
*
new_width
],
&
screen_buffer
->
data
[
i
*
old_width
],
copy_width
*
sizeof
(
char_info_t
)
);
}
/* clear the end of each row */
if
(
new_width
>
old_width
)
{
/* fill first row */
for
(
i
=
old_width
;
i
<
new_width
;
i
++
)
new_data
[
i
]
=
empty_char_info
;
/* and blast it to the other rows */
for
(
i
=
1
;
i
<
copy_height
;
i
++
)
memcpy
(
&
new_data
[
i
*
new_width
+
old_width
],
&
new_data
[
old_width
],
(
new_width
-
old_width
)
*
sizeof
(
char_info_t
)
);
}
/* clear remaining rows */
if
(
new_height
>
old_height
)
{
/* fill first row */
for
(
i
=
0
;
i
<
new_width
;
i
++
)
new_data
[
old_height
*
new_width
+
i
]
=
empty_char_info
;
/* and blast it to the other rows */
for
(
i
=
old_height
+
1
;
i
<
new_height
;
i
++
)
memcpy
(
&
new_data
[
i
*
new_width
],
&
new_data
[
old_height
*
new_width
],
new_width
*
sizeof
(
char_info_t
)
);
}
free
(
screen_buffer
->
data
);
screen_buffer
->
data
=
new_data
;
screen_buffer
->
width
=
new_width
;
screen_buffer
->
height
=
new_height
;
return
STATUS_SUCCESS
;
}
static
NTSTATUS
set_output_info
(
struct
screen_buffer
*
screen_buffer
,
const
struct
condrv_output_info_params
*
params
,
size_t
extra_size
)
{
const
struct
condrv_output_info
*
info
=
&
params
->
info
;
WCHAR
*
font_name
;
NTSTATUS
status
;
TRACE
(
"%p
\n
"
,
screen_buffer
);
extra_size
-=
sizeof
(
*
params
);
if
(
params
->
mask
&
SET_CONSOLE_OUTPUT_INFO_CURSOR_GEOM
)
{
if
(
info
->
cursor_size
<
1
||
info
->
cursor_size
>
100
)
return
STATUS_INVALID_PARAMETER
;
screen_buffer
->
cursor_size
=
info
->
cursor_size
;
screen_buffer
->
cursor_visible
=
!!
info
->
cursor_visible
;
}
if
(
params
->
mask
&
SET_CONSOLE_OUTPUT_INFO_CURSOR_POS
)
{
if
(
info
->
cursor_x
<
0
||
info
->
cursor_x
>=
screen_buffer
->
width
||
info
->
cursor_y
<
0
||
info
->
cursor_y
>=
screen_buffer
->
height
)
{
return
STATUS_INVALID_PARAMETER
;
}
if
(
screen_buffer
->
cursor_x
!=
info
->
cursor_x
||
screen_buffer
->
cursor_y
!=
info
->
cursor_y
)
{
screen_buffer
->
cursor_x
=
info
->
cursor_x
;
screen_buffer
->
cursor_y
=
info
->
cursor_y
;
}
}
if
(
params
->
mask
&
SET_CONSOLE_OUTPUT_INFO_SIZE
)
{
/* new screen-buffer cannot be smaller than actual window */
if
(
info
->
width
<
screen_buffer
->
win
.
right
-
screen_buffer
->
win
.
left
+
1
||
info
->
height
<
screen_buffer
->
win
.
bottom
-
screen_buffer
->
win
.
top
+
1
)
{
return
STATUS_INVALID_PARAMETER
;
}
/* FIXME: there are also some basic minimum and max size to deal with */
if
((
status
=
change_screen_buffer_size
(
screen_buffer
,
info
->
width
,
info
->
height
)))
return
status
;
/* scroll window to display sb */
if
(
screen_buffer
->
win
.
right
>=
info
->
width
)
{
screen_buffer
->
win
.
right
-=
screen_buffer
->
win
.
left
;
screen_buffer
->
win
.
left
=
0
;
}
if
(
screen_buffer
->
win
.
bottom
>=
info
->
height
)
{
screen_buffer
->
win
.
bottom
-=
screen_buffer
->
win
.
top
;
screen_buffer
->
win
.
top
=
0
;
}
if
(
screen_buffer
->
cursor_x
>=
info
->
width
)
screen_buffer
->
cursor_x
=
info
->
width
-
1
;
if
(
screen_buffer
->
cursor_y
>=
info
->
height
)
screen_buffer
->
cursor_y
=
info
->
height
-
1
;
if
(
is_active
(
screen_buffer
)
&&
screen_buffer
->
console
->
mode
&
ENABLE_WINDOW_INPUT
)
{
INPUT_RECORD
ir
;
ir
.
EventType
=
WINDOW_BUFFER_SIZE_EVENT
;
ir
.
Event
.
WindowBufferSizeEvent
.
dwSize
.
X
=
info
->
width
;
ir
.
Event
.
WindowBufferSizeEvent
.
dwSize
.
Y
=
info
->
height
;
write_console_input
(
screen_buffer
->
console
,
&
ir
,
1
);
}
}
if
(
params
->
mask
&
SET_CONSOLE_OUTPUT_INFO_ATTR
)
{
screen_buffer
->
attr
=
info
->
attr
;
}
if
(
params
->
mask
&
SET_CONSOLE_OUTPUT_INFO_POPUP_ATTR
)
{
screen_buffer
->
popup_attr
=
info
->
popup_attr
;
}
if
(
params
->
mask
&
SET_CONSOLE_OUTPUT_INFO_DISPLAY_WINDOW
)
{
if
(
info
->
win_left
<
0
||
info
->
win_left
>
info
->
win_right
||
info
->
win_right
>=
screen_buffer
->
width
||
info
->
win_top
<
0
||
info
->
win_top
>
info
->
win_bottom
||
info
->
win_bottom
>=
screen_buffer
->
height
)
{
return
STATUS_INVALID_PARAMETER
;
}
if
(
screen_buffer
->
win
.
left
!=
info
->
win_left
||
screen_buffer
->
win
.
top
!=
info
->
win_top
||
screen_buffer
->
win
.
right
!=
info
->
win_right
||
screen_buffer
->
win
.
bottom
!=
info
->
win_bottom
)
{
screen_buffer
->
win
.
left
=
info
->
win_left
;
screen_buffer
->
win
.
top
=
info
->
win_top
;
screen_buffer
->
win
.
right
=
info
->
win_right
;
screen_buffer
->
win
.
bottom
=
info
->
win_bottom
;
}
}
if
(
params
->
mask
&
SET_CONSOLE_OUTPUT_INFO_MAX_SIZE
)
{
screen_buffer
->
max_width
=
info
->
max_width
;
screen_buffer
->
max_height
=
info
->
max_height
;
}
if
(
params
->
mask
&
SET_CONSOLE_OUTPUT_INFO_COLORTABLE
)
{
memcpy
(
screen_buffer
->
color_map
,
info
->
color_map
,
sizeof
(
screen_buffer
->
color_map
)
);
}
if
(
params
->
mask
&
SET_CONSOLE_OUTPUT_INFO_FONT
)
{
screen_buffer
->
font
.
width
=
info
->
font_width
;
screen_buffer
->
font
.
height
=
info
->
font_height
;
screen_buffer
->
font
.
weight
=
info
->
font_weight
;
screen_buffer
->
font
.
pitch_family
=
info
->
font_pitch_family
;
if
(
extra_size
)
{
const
WCHAR
*
params_font
=
(
const
WCHAR
*
)(
params
+
1
);
extra_size
=
extra_size
/
sizeof
(
WCHAR
)
*
sizeof
(
WCHAR
);
font_name
=
malloc
(
extra_size
);
if
(
font_name
)
{
memcpy
(
font_name
,
params_font
,
extra_size
);
free
(
screen_buffer
->
font
.
face_name
);
screen_buffer
->
font
.
face_name
=
font_name
;
screen_buffer
->
font
.
face_len
=
extra_size
;
}
}
}
return
STATUS_SUCCESS
;
}
static
NTSTATUS
set_console_title
(
struct
console
*
console
,
const
WCHAR
*
in_title
,
size_t
size
)
{
WCHAR
*
title
=
NULL
;
...
...
@@ -326,6 +521,10 @@ static NTSTATUS screen_buffer_ioctl( struct screen_buffer *screen_buffer, unsign
if
(
in_size
||
*
out_size
<
sizeof
(
struct
condrv_output_info
))
return
STATUS_INVALID_PARAMETER
;
return
get_output_info
(
screen_buffer
,
out_size
);
case
IOCTL_CONDRV_SET_OUTPUT_INFO
:
if
(
in_size
<
sizeof
(
struct
condrv_output_info
)
||
*
out_size
)
return
STATUS_INVALID_PARAMETER
;
return
set_output_info
(
screen_buffer
,
in_data
,
in_size
);
default:
FIXME
(
"unsupported ioctl %x
\n
"
,
code
);
return
STATUS_NOT_SUPPORTED
;
...
...
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