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
633b244b
Commit
633b244b
authored
Oct 13, 2020
by
Jacek Caban
Committed by
Alexandre Julliard
Oct 13, 2020
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
kernel32: Always use conhost for ReadConsoleW.
Signed-off-by:
Jacek Caban
<
jacek@codeweavers.com
>
Signed-off-by:
Alexandre Julliard
<
julliard@winehq.org
>
parent
143c2103
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
9 additions
and
1249 deletions
+9
-1249
Makefile.in
dlls/kernel32/Makefile.in
+0
-1
console.c
dlls/kernel32/console.c
+9
-169
console_private.h
dlls/kernel32/console_private.h
+0
-34
editline.c
dlls/kernel32/editline.c
+0
-1044
kernel_main.c
dlls/kernel32/kernel_main.c
+0
-1
No files found.
dlls/kernel32/Makefile.in
View file @
633b244b
...
@@ -10,7 +10,6 @@ C_SRCS = \
...
@@ -10,7 +10,6 @@ C_SRCS = \
computername.c
\
computername.c
\
console.c
\
console.c
\
debugger.c
\
debugger.c
\
editline.c
\
file.c
\
file.c
\
heap.c
\
heap.c
\
kernel_main.c
\
kernel_main.c
\
...
...
dlls/kernel32/console.c
View file @
633b244b
...
@@ -41,7 +41,6 @@
...
@@ -41,7 +41,6 @@
#include "wine/exception.h"
#include "wine/exception.h"
#include "wine/debug.h"
#include "wine/debug.h"
#include "excpt.h"
#include "excpt.h"
#include "console_private.h"
#include "kernel_private.h"
#include "kernel_private.h"
WINE_DEFAULT_DEBUG_CHANNEL
(
console
);
WINE_DEFAULT_DEBUG_CHANNEL
(
console
);
...
@@ -243,10 +242,6 @@ DWORD WINAPI GetConsoleTitleA(LPSTR title, DWORD size)
...
@@ -243,10 +242,6 @@ DWORD WINAPI GetConsoleTitleA(LPSTR title, DWORD size)
}
}
static
WCHAR
*
S_EditString
/* = NULL */
;
static
unsigned
S_EditStrPos
/* = 0 */
;
/***********************************************************************
/***********************************************************************
* ReadConsoleA (KERNEL32.@)
* ReadConsoleA (KERNEL32.@)
*/
*/
...
@@ -274,76 +269,23 @@ BOOL WINAPI ReadConsoleA( HANDLE handle, LPVOID buffer, DWORD length, DWORD *ret
...
@@ -274,76 +269,23 @@ BOOL WINAPI ReadConsoleA( HANDLE handle, LPVOID buffer, DWORD length, DWORD *ret
/***********************************************************************
/***********************************************************************
* ReadConsoleW (KERNEL32.@)
* ReadConsoleW (KERNEL32.@)
*/
*/
BOOL
WINAPI
ReadConsoleW
(
HANDLE
hConsoleInput
,
LPVOID
lpBuffer
,
BOOL
WINAPI
ReadConsoleW
(
HANDLE
handle
,
void
*
buffer
,
DWORD
length
,
DWORD
*
count
,
void
*
reserved
)
DWORD
nNumberOfCharsToRead
,
LPDWORD
lpNumberOfCharsRead
,
LPVOID
lpReserved
)
{
{
IO_STATUS_BLOCK
io
;
BOOL
ret
;
DWORD
charsread
;
LPWSTR
xbuf
=
lpBuffer
;
DWORD
mode
;
TRACE
(
"(%p,%p,%d,%p,%p)
\n
"
,
TRACE
(
"(%p,%p,%d,%p,%p)
\n
"
,
handle
,
buffer
,
length
,
count
,
reserved
);
hConsoleInput
,
lpBuffer
,
nNumberOfCharsToRead
,
lpNumberOfCharsRead
,
lpReserved
);
if
(
nNumberOfCharsToRead
>
INT_MAX
)
if
(
length
>
INT_MAX
)
{
{
SetLastError
(
ERROR_NOT_ENOUGH_MEMORY
);
SetLastError
(
ERROR_NOT_ENOUGH_MEMORY
);
return
FALSE
;
return
FALSE
;
}
}
if
(
!
NtDeviceIoControlFile
(
hConsoleInput
,
NULL
,
NULL
,
NULL
,
&
io
,
IOCTL_CONDRV_READ_CONSOLE
,
NULL
,
0
,
lpBuffer
,
ret
=
DeviceIoControl
(
handle
,
IOCTL_CONDRV_READ_CONSOLE
,
NULL
,
0
,
buffer
,
nNumberOfCharsToRead
*
sizeof
(
WCHAR
)))
length
*
sizeof
(
WCHAR
),
count
,
NULL
);
{
if
(
ret
)
*
count
/=
sizeof
(
WCHAR
);
if
(
lpNumberOfCharsRead
)
*
lpNumberOfCharsRead
=
io
.
Information
/
sizeof
(
WCHAR
);
else
SetLastError
(
ERROR_INVALID_HANDLE
);
return
TRUE
;
return
ret
;
}
if
(
!
GetConsoleMode
(
hConsoleInput
,
&
mode
))
return
FALSE
;
if
(
mode
&
ENABLE_LINE_INPUT
)
{
if
(
!
S_EditString
||
S_EditString
[
S_EditStrPos
]
==
0
)
{
HeapFree
(
GetProcessHeap
(),
0
,
S_EditString
);
if
(
!
(
S_EditString
=
CONSOLE_Readline
(
hConsoleInput
,
TRUE
)))
return
FALSE
;
S_EditStrPos
=
0
;
}
charsread
=
lstrlenW
(
&
S_EditString
[
S_EditStrPos
]);
if
(
charsread
>
nNumberOfCharsToRead
)
charsread
=
nNumberOfCharsToRead
;
memcpy
(
xbuf
,
&
S_EditString
[
S_EditStrPos
],
charsread
*
sizeof
(
WCHAR
));
S_EditStrPos
+=
charsread
;
}
else
{
INPUT_RECORD
ir
;
DWORD
timeout
=
INFINITE
;
/* FIXME: should we read at least 1 char? The SDK does not say */
/* wait for at least one available input record (it doesn't mean we'll have
* chars stored in xbuf...)
*
* Although SDK doc keeps silence about 1 char, SDK examples assume
* that we should wait for at least one character (not key). --KS
*/
charsread
=
0
;
do
{
if
(
read_console_input
(
hConsoleInput
,
&
ir
,
timeout
)
!=
rci_gotone
)
break
;
if
(
ir
.
EventType
==
KEY_EVENT
&&
ir
.
Event
.
KeyEvent
.
bKeyDown
&&
ir
.
Event
.
KeyEvent
.
uChar
.
UnicodeChar
)
{
xbuf
[
charsread
++
]
=
ir
.
Event
.
KeyEvent
.
uChar
.
UnicodeChar
;
timeout
=
0
;
}
}
while
(
charsread
<
nNumberOfCharsToRead
);
/* nothing has been read */
if
(
timeout
==
INFINITE
)
return
FALSE
;
}
if
(
lpNumberOfCharsRead
)
*
lpNumberOfCharsRead
=
charsread
;
return
TRUE
;
}
}
...
@@ -398,26 +340,6 @@ BOOL WINAPI DECLSPEC_HOTPATCH WriteConsoleW( HANDLE handle, const void *buffer,
...
@@ -398,26 +340,6 @@ BOOL WINAPI DECLSPEC_HOTPATCH WriteConsoleW( HANDLE handle, const void *buffer,
/******************************************************************
/******************************************************************
* CONSOLE_FillLineUniform
*
* Helper function for ScrollConsoleScreenBufferW
* Fills a part of a line with a constant character info
*/
void
CONSOLE_FillLineUniform
(
HANDLE
hConsoleOutput
,
int
i
,
int
j
,
int
len
,
LPCHAR_INFO
lpFill
)
{
struct
condrv_fill_output_params
params
;
params
.
mode
=
CHAR_INFO_MODE_TEXTATTR
;
params
.
x
=
i
;
params
.
y
=
j
;
params
.
count
=
len
;
params
.
wrap
=
FALSE
;
params
.
ch
=
lpFill
->
Char
.
UnicodeChar
;
params
.
attr
=
lpFill
->
Attributes
;
DeviceIoControl
(
hConsoleOutput
,
IOCTL_CONDRV_FILL_OUTPUT
,
&
params
,
sizeof
(
params
),
NULL
,
0
,
NULL
,
NULL
);
}
/******************************************************************
* GetConsoleDisplayMode (KERNEL32.@)
* GetConsoleDisplayMode (KERNEL32.@)
*/
*/
BOOL
WINAPI
GetConsoleDisplayMode
(
LPDWORD
lpModeFlags
)
BOOL
WINAPI
GetConsoleDisplayMode
(
LPDWORD
lpModeFlags
)
...
@@ -444,88 +366,6 @@ BOOL WINAPI SetConsoleDisplayMode(HANDLE hConsoleOutput, DWORD dwFlags,
...
@@ -444,88 +366,6 @@ BOOL WINAPI SetConsoleDisplayMode(HANDLE hConsoleOutput, DWORD dwFlags,
return
TRUE
;
return
TRUE
;
}
}
/* ====================================================================
*
* Console manipulation functions
*
* ====================================================================*/
/* some missing functions...
* FIXME: those are likely to be defined as undocumented function in kernel32 (or part of them)
* should get the right API and implement them
* SetConsoleCommandHistoryMode
* SetConsoleNumberOfCommands[AW]
*/
int
CONSOLE_GetHistory
(
int
idx
,
WCHAR
*
buf
,
int
buf_len
)
{
int
len
=
0
;
SERVER_START_REQ
(
get_console_input_history
)
{
req
->
handle
=
0
;
req
->
index
=
idx
;
if
(
buf
&&
buf_len
>
1
)
{
wine_server_set_reply
(
req
,
buf
,
(
buf_len
-
1
)
*
sizeof
(
WCHAR
)
);
}
if
(
!
wine_server_call_err
(
req
))
{
if
(
buf
)
buf
[
wine_server_reply_size
(
reply
)
/
sizeof
(
WCHAR
)]
=
0
;
len
=
reply
->
total
/
sizeof
(
WCHAR
)
+
1
;
}
}
SERVER_END_REQ
;
return
len
;
}
/******************************************************************
* CONSOLE_AppendHistory
*
*
*/
BOOL
CONSOLE_AppendHistory
(
const
WCHAR
*
ptr
)
{
size_t
len
=
lstrlenW
(
ptr
);
BOOL
ret
;
while
(
len
&&
(
ptr
[
len
-
1
]
==
'\n'
||
ptr
[
len
-
1
]
==
'\r'
))
len
--
;
if
(
!
len
)
return
FALSE
;
SERVER_START_REQ
(
append_console_input_history
)
{
req
->
handle
=
0
;
wine_server_add_data
(
req
,
ptr
,
len
*
sizeof
(
WCHAR
)
);
ret
=
!
wine_server_call_err
(
req
);
}
SERVER_END_REQ
;
return
ret
;
}
/******************************************************************
* CONSOLE_GetNumHistoryEntries
*
*
*/
unsigned
CONSOLE_GetNumHistoryEntries
(
HANDLE
console
)
{
struct
condrv_input_info
info
;
BOOL
ret
=
DeviceIoControl
(
console
,
IOCTL_CONDRV_GET_INPUT_INFO
,
NULL
,
0
,
&
info
,
sizeof
(
info
),
NULL
,
NULL
);
return
ret
?
info
.
history_index
:
~
0
;
}
/******************************************************************
* CONSOLE_GetEditionMode
*
*
*/
BOOL
CONSOLE_GetEditionMode
(
HANDLE
hConIn
,
int
*
mode
)
{
struct
condrv_input_info
info
;
return
DeviceIoControl
(
hConIn
,
IOCTL_CONDRV_GET_INPUT_INFO
,
NULL
,
0
,
&
info
,
sizeof
(
info
),
NULL
,
NULL
)
?
info
.
edition_mode
:
0
;
}
/******************************************************************
/******************************************************************
* GetConsoleAliasW
* GetConsoleAliasW
*
*
...
...
dlls/kernel32/console_private.h
deleted
100644 → 0
View file @
143c2103
/*
* Console private definitions
*
* Copyright 2002 Eric Pouech
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef __WINE_CONSOLE_PRIVATE_H
#define __WINE_CONSOLE_PRIVATE_H
/* console.c */
extern
int
CONSOLE_GetHistory
(
int
idx
,
WCHAR
*
buf
,
int
buf_len
)
DECLSPEC_HIDDEN
;
extern
BOOL
CONSOLE_AppendHistory
(
const
WCHAR
*
p
)
DECLSPEC_HIDDEN
;
extern
unsigned
CONSOLE_GetNumHistoryEntries
(
HANDLE
)
DECLSPEC_HIDDEN
;
extern
void
CONSOLE_FillLineUniform
(
HANDLE
hConsoleOutput
,
int
i
,
int
j
,
int
len
,
LPCHAR_INFO
lpFill
)
DECLSPEC_HIDDEN
;
extern
BOOL
CONSOLE_GetEditionMode
(
HANDLE
,
int
*
)
DECLSPEC_HIDDEN
;
/* editline.c */
extern
WCHAR
*
CONSOLE_Readline
(
HANDLE
,
BOOL
)
DECLSPEC_HIDDEN
;
#endif
/* __WINE_CONSOLE_PRIVATE_H */
dlls/kernel32/editline.c
deleted
100644 → 0
View file @
143c2103
/*
* line edition function for Win32 console
*
* Copyright 2001 Eric Pouech
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <stdarg.h>
#include <string.h>
#include "windef.h"
#include "winbase.h"
#include "wincon.h"
#include "winuser.h"
#include "winnls.h"
#include "wine/debug.h"
#include "console_private.h"
WINE_DEFAULT_DEBUG_CHANNEL
(
console
);
struct
WCEL_Context
;
typedef
struct
{
WCHAR
val
;
/* vk or unicode char */
void
(
*
func
)(
struct
WCEL_Context
*
ctx
);
}
KeyEntry
;
typedef
struct
{
DWORD
keyState
;
/* keyState (from INPUT_RECORD) to match */
BOOL
chkChar
;
/* check vk or char */
const
KeyEntry
*
entries
;
/* array of entries */
}
KeyMap
;
typedef
struct
WCEL_Context
{
WCHAR
*
line
;
/* the line being edited */
size_t
alloc
;
/* number of WCHAR in line */
unsigned
len
;
/* number of chars in line */
unsigned
last_rub
;
/* number of chars to rub to get to start
(for consoles that can't change cursor pos) */
unsigned
last_max
;
/* max number of chars written
(for consoles that can't change cursor pos) */
unsigned
ofs
;
/* offset for cursor in current line */
WCHAR
*
yanked
;
/* yanked line */
unsigned
mark
;
/* marked point (emacs mode only) */
CONSOLE_SCREEN_BUFFER_INFO
csbi
;
/* current state (initial cursor, window size, attribute) */
CONSOLE_CURSOR_INFO
cinfo
;
/* original cursor state (size, visibility) */
HANDLE
hConIn
;
HANDLE
hConOut
;
unsigned
done
:
1
,
/* to 1 when we're done with editing */
error
:
1
,
/* to 1 when an error occurred in the editing */
can_wrap
:
1
,
/* to 1 when multi-line edition can take place */
shall_echo
:
1
,
/* to 1 when characters should be echo:ed when keyed-in */
insert
:
1
,
/* to 1 when new characters are inserted (otherwise overwrite) */
insertkey
:
1
,
/* to 1 when the Insert key toggle is active */
can_pos_cursor
:
1
;
/* to 1 when console can (re)position cursor */
unsigned
histSize
;
unsigned
histPos
;
WCHAR
*
histCurr
;
}
WCEL_Context
;
#if 0
static void WCEL_Dump(WCEL_Context* ctx, const char* pfx)
{
MESSAGE("%s: [line=%s[alloc=%u] ofs=%u len=%u start=(%d,%d) mask=%c%c%c]\n"
"\t\thist=(size=%u pos=%u curr=%s)\n"
"\t\tyanked=%s\n",
pfx, debugstr_w(ctx->line), ctx->alloc, ctx->ofs, ctx->len,
ctx->csbi.dwCursorPosition.X, ctx->csbi.dwCursorPosition.Y,
ctx->done ? 'D' : 'd', ctx->error ? 'E' : 'e', ctx->can_wrap ? 'W' : 'w',
ctx->histSize, ctx->histPos, debugstr_w(ctx->histCurr),
debugstr_w(ctx->yanked));
}
#endif
/* ====================================================================
*
* Console helper functions
*
* ====================================================================*/
static
BOOL
WCEL_Get
(
WCEL_Context
*
ctx
,
INPUT_RECORD
*
ir
)
{
DWORD
num_read
;
if
(
ReadConsoleInputW
(
ctx
->
hConIn
,
ir
,
1
,
&
num_read
))
return
TRUE
;
ctx
->
error
=
1
;
return
FALSE
;
}
static
inline
void
WCEL_Beep
(
WCEL_Context
*
ctx
)
{
Beep
(
400
,
300
);
}
static
inline
BOOL
WCEL_IsSingleLine
(
WCEL_Context
*
ctx
,
size_t
len
)
{
return
ctx
->
csbi
.
dwCursorPosition
.
X
+
ctx
->
len
+
len
<=
ctx
->
csbi
.
dwSize
.
X
;
}
static
inline
int
WCEL_CharWidth
(
WCHAR
wch
)
{
return
wch
<
' '
?
2
:
1
;
}
static
inline
int
WCEL_StringWidth
(
const
WCHAR
*
str
,
int
beg
,
int
len
)
{
int
i
,
ofs
;
for
(
i
=
0
,
ofs
=
0
;
i
<
len
;
i
++
)
ofs
+=
WCEL_CharWidth
(
str
[
beg
+
i
]);
return
ofs
;
}
static
inline
COORD
WCEL_GetCoord
(
WCEL_Context
*
ctx
,
int
strofs
)
{
COORD
c
;
int
len
=
ctx
->
csbi
.
dwSize
.
X
-
ctx
->
csbi
.
dwCursorPosition
.
X
;
int
ofs
;
ofs
=
WCEL_StringWidth
(
ctx
->
line
,
0
,
strofs
);
c
.
Y
=
ctx
->
csbi
.
dwCursorPosition
.
Y
;
if
(
ofs
>=
len
)
{
ofs
-=
len
;
c
.
X
=
ofs
%
ctx
->
csbi
.
dwSize
.
X
;
c
.
Y
+=
1
+
ofs
/
ctx
->
csbi
.
dwSize
.
X
;
}
else
c
.
X
=
ctx
->
csbi
.
dwCursorPosition
.
X
+
ofs
;
return
c
;
}
static
DWORD
WCEL_WriteConsole
(
WCEL_Context
*
ctx
,
DWORD
beg
,
DWORD
len
)
{
DWORD
i
,
last
,
dw
,
ret
=
0
;
WCHAR
tmp
[
2
];
for
(
i
=
last
=
0
;
i
<
len
;
i
++
)
{
if
(
ctx
->
line
[
beg
+
i
]
<
' '
)
{
if
(
last
!=
i
)
{
WriteConsoleW
(
ctx
->
hConOut
,
&
ctx
->
line
[
beg
+
last
],
i
-
last
,
&
dw
,
NULL
);
ret
+=
dw
;
}
tmp
[
0
]
=
'^'
;
tmp
[
1
]
=
'@'
+
ctx
->
line
[
beg
+
i
];
WriteConsoleW
(
ctx
->
hConOut
,
tmp
,
2
,
&
dw
,
NULL
);
last
=
i
+
1
;
ret
+=
dw
;
}
}
if
(
last
!=
len
)
{
WriteConsoleW
(
ctx
->
hConOut
,
&
ctx
->
line
[
beg
+
last
],
len
-
last
,
&
dw
,
NULL
);
ret
+=
dw
;
}
return
ret
;
}
static
inline
void
WCEL_WriteNChars
(
WCEL_Context
*
ctx
,
char
ch
,
int
count
)
{
DWORD
dw
;
if
(
count
>
0
)
{
while
(
count
--
)
WriteFile
(
ctx
->
hConOut
,
&
ch
,
1
,
&
dw
,
NULL
);
}
}
static
inline
void
WCEL_Update
(
WCEL_Context
*
ctx
,
int
beg
,
int
len
)
{
int
i
,
last
;
DWORD
count
;
WCHAR
tmp
[
2
];
/* bare console case is handled in CONSOLE_ReadLine (we always reprint the whole string) */
if
(
!
ctx
->
shall_echo
||
!
ctx
->
can_pos_cursor
)
return
;
for
(
i
=
last
=
beg
;
i
<
beg
+
len
;
i
++
)
{
if
(
ctx
->
line
[
i
]
<
' '
)
{
if
(
last
!=
i
)
{
WriteConsoleOutputCharacterW
(
ctx
->
hConOut
,
&
ctx
->
line
[
last
],
i
-
last
,
WCEL_GetCoord
(
ctx
,
last
),
&
count
);
FillConsoleOutputAttribute
(
ctx
->
hConOut
,
ctx
->
csbi
.
wAttributes
,
i
-
last
,
WCEL_GetCoord
(
ctx
,
last
),
&
count
);
}
tmp
[
0
]
=
'^'
;
tmp
[
1
]
=
'@'
+
ctx
->
line
[
i
];
WriteConsoleOutputCharacterW
(
ctx
->
hConOut
,
tmp
,
2
,
WCEL_GetCoord
(
ctx
,
i
),
&
count
);
FillConsoleOutputAttribute
(
ctx
->
hConOut
,
ctx
->
csbi
.
wAttributes
,
2
,
WCEL_GetCoord
(
ctx
,
i
),
&
count
);
last
=
i
+
1
;
}
}
if
(
last
!=
beg
+
len
)
{
WriteConsoleOutputCharacterW
(
ctx
->
hConOut
,
&
ctx
->
line
[
last
],
i
-
last
,
WCEL_GetCoord
(
ctx
,
last
),
&
count
);
FillConsoleOutputAttribute
(
ctx
->
hConOut
,
ctx
->
csbi
.
wAttributes
,
i
-
last
,
WCEL_GetCoord
(
ctx
,
last
),
&
count
);
}
}
/* ====================================================================
*
* context manipulation functions
*
* ====================================================================*/
static
BOOL
WCEL_Grow
(
WCEL_Context
*
ctx
,
size_t
len
)
{
if
(
!
WCEL_IsSingleLine
(
ctx
,
len
)
&&
!
ctx
->
can_wrap
)
{
FIXME
(
"Mode doesn't allow wrapping. However, we should allow overwriting the current string
\n
"
);
return
FALSE
;
}
if
(
ctx
->
len
+
len
>=
ctx
->
alloc
)
{
WCHAR
*
newline
;
size_t
newsize
;
/* round up size to 32 byte-WCHAR boundary */
newsize
=
(
ctx
->
len
+
len
+
1
+
31
)
&
~
31
;
if
(
ctx
->
line
)
newline
=
HeapReAlloc
(
GetProcessHeap
(),
0
,
ctx
->
line
,
sizeof
(
WCHAR
)
*
newsize
);
else
newline
=
HeapAlloc
(
GetProcessHeap
(),
0
,
sizeof
(
WCHAR
)
*
newsize
);
if
(
!
newline
)
return
FALSE
;
ctx
->
line
=
newline
;
ctx
->
alloc
=
newsize
;
}
return
TRUE
;
}
static
void
WCEL_DeleteString
(
WCEL_Context
*
ctx
,
int
beg
,
int
end
)
{
unsigned
str_len
=
end
-
beg
;
if
(
end
<
ctx
->
len
)
memmove
(
&
ctx
->
line
[
beg
],
&
ctx
->
line
[
end
],
(
ctx
->
len
-
end
)
*
sizeof
(
WCHAR
));
/* we need to clean from ctx->len - str_len to ctx->len */
if
(
ctx
->
shall_echo
)
{
COORD
cbeg
=
WCEL_GetCoord
(
ctx
,
ctx
->
len
-
str_len
);
COORD
cend
=
WCEL_GetCoord
(
ctx
,
ctx
->
len
);
CHAR_INFO
ci
;
ci
.
Char
.
UnicodeChar
=
' '
;
ci
.
Attributes
=
ctx
->
csbi
.
wAttributes
;
if
(
cbeg
.
Y
==
cend
.
Y
)
{
/* partial erase of sole line */
CONSOLE_FillLineUniform
(
ctx
->
hConOut
,
cbeg
.
X
,
cbeg
.
Y
,
cend
.
X
-
cbeg
.
X
,
&
ci
);
}
else
{
int
i
;
/* erase til eol on first line */
CONSOLE_FillLineUniform
(
ctx
->
hConOut
,
cbeg
.
X
,
cbeg
.
Y
,
ctx
->
csbi
.
dwSize
.
X
-
cbeg
.
X
,
&
ci
);
/* completely erase all the others (full lines) */
for
(
i
=
cbeg
.
Y
+
1
;
i
<
cend
.
Y
;
i
++
)
CONSOLE_FillLineUniform
(
ctx
->
hConOut
,
0
,
i
,
ctx
->
csbi
.
dwSize
.
X
,
&
ci
);
/* erase from beginning of line until last pos on last line */
CONSOLE_FillLineUniform
(
ctx
->
hConOut
,
0
,
cend
.
Y
,
cend
.
X
,
&
ci
);
}
}
ctx
->
len
-=
str_len
;
WCEL_Update
(
ctx
,
0
,
ctx
->
len
);
ctx
->
line
[
ctx
->
len
]
=
0
;
}
static
void
WCEL_InsertString
(
WCEL_Context
*
ctx
,
const
WCHAR
*
str
)
{
size_t
len
=
lstrlenW
(
str
),
updtlen
;
if
(
!
len
)
return
;
if
(
ctx
->
insert
)
{
if
(
!
WCEL_Grow
(
ctx
,
len
))
return
;
if
(
ctx
->
len
>
ctx
->
ofs
)
memmove
(
&
ctx
->
line
[
ctx
->
ofs
+
len
],
&
ctx
->
line
[
ctx
->
ofs
],
(
ctx
->
len
-
ctx
->
ofs
)
*
sizeof
(
WCHAR
));
ctx
->
len
+=
len
;
updtlen
=
ctx
->
len
-
ctx
->
ofs
;
}
else
{
if
(
ctx
->
ofs
+
len
>
ctx
->
len
)
{
if
(
!
WCEL_Grow
(
ctx
,
(
ctx
->
ofs
+
len
)
-
ctx
->
len
))
return
;
ctx
->
len
=
ctx
->
ofs
+
len
;
}
updtlen
=
len
;
}
memcpy
(
&
ctx
->
line
[
ctx
->
ofs
],
str
,
len
*
sizeof
(
WCHAR
));
ctx
->
line
[
ctx
->
len
]
=
0
;
WCEL_Update
(
ctx
,
ctx
->
ofs
,
updtlen
);
ctx
->
ofs
+=
len
;
}
static
void
WCEL_InsertChar
(
WCEL_Context
*
ctx
,
WCHAR
c
)
{
WCHAR
buffer
[
2
];
buffer
[
0
]
=
c
;
buffer
[
1
]
=
0
;
WCEL_InsertString
(
ctx
,
buffer
);
}
static
void
WCEL_FreeYank
(
WCEL_Context
*
ctx
)
{
HeapFree
(
GetProcessHeap
(),
0
,
ctx
->
yanked
);
ctx
->
yanked
=
NULL
;
}
static
void
WCEL_SaveYank
(
WCEL_Context
*
ctx
,
int
beg
,
int
end
)
{
int
len
=
end
-
beg
;
if
(
len
<=
0
)
return
;
WCEL_FreeYank
(
ctx
);
/* After WCEL_FreeYank ctx->yanked is empty */
ctx
->
yanked
=
HeapAlloc
(
GetProcessHeap
(),
0
,
(
len
+
1
)
*
sizeof
(
WCHAR
));
if
(
!
ctx
->
yanked
)
return
;
memcpy
(
ctx
->
yanked
,
&
ctx
->
line
[
beg
],
len
*
sizeof
(
WCHAR
));
ctx
->
yanked
[
len
]
=
0
;
}
/* FIXME NTDLL doesn't export iswalnum, and I don't want to link in msvcrt when most
* of the data lay in unicode lib
*/
static
inline
BOOL
WCEL_iswalnum
(
WCHAR
wc
)
{
WORD
type
;
GetStringTypeW
(
CT_CTYPE1
,
&
wc
,
1
,
&
type
);
return
type
&
(
C1_ALPHA
|
C1_DIGIT
|
C1_LOWER
|
C1_UPPER
);
}
static
int
WCEL_GetLeftWordTransition
(
WCEL_Context
*
ctx
,
int
ofs
)
{
ofs
--
;
while
(
ofs
>=
0
&&
!
WCEL_iswalnum
(
ctx
->
line
[
ofs
]))
ofs
--
;
while
(
ofs
>=
0
&&
WCEL_iswalnum
(
ctx
->
line
[
ofs
]))
ofs
--
;
if
(
ofs
>=
0
)
ofs
++
;
return
max
(
ofs
,
0
);
}
static
int
WCEL_GetRightWordTransition
(
WCEL_Context
*
ctx
,
int
ofs
)
{
ofs
++
;
while
(
ofs
<=
ctx
->
len
&&
WCEL_iswalnum
(
ctx
->
line
[
ofs
]))
ofs
++
;
while
(
ofs
<=
ctx
->
len
&&
!
WCEL_iswalnum
(
ctx
->
line
[
ofs
]))
ofs
++
;
return
min
(
ofs
,
ctx
->
len
);
}
static
WCHAR
*
WCEL_GetHistory
(
WCEL_Context
*
ctx
,
int
idx
)
{
WCHAR
*
ptr
;
if
(
idx
==
ctx
->
histSize
-
1
)
{
ptr
=
HeapAlloc
(
GetProcessHeap
(),
0
,
(
lstrlenW
(
ctx
->
histCurr
)
+
1
)
*
sizeof
(
WCHAR
));
lstrcpyW
(
ptr
,
ctx
->
histCurr
);
}
else
{
int
len
=
CONSOLE_GetHistory
(
idx
,
NULL
,
0
);
if
((
ptr
=
HeapAlloc
(
GetProcessHeap
(),
0
,
len
*
sizeof
(
WCHAR
))))
{
CONSOLE_GetHistory
(
idx
,
ptr
,
len
);
}
}
return
ptr
;
}
static
void
WCEL_HistoryInit
(
WCEL_Context
*
ctx
)
{
ctx
->
histPos
=
CONSOLE_GetNumHistoryEntries
(
ctx
->
hConIn
);
ctx
->
histSize
=
ctx
->
histPos
+
1
;
ctx
->
histCurr
=
HeapAlloc
(
GetProcessHeap
(),
HEAP_ZERO_MEMORY
,
sizeof
(
WCHAR
));
}
static
void
WCEL_MoveToHist
(
WCEL_Context
*
ctx
,
int
idx
)
{
WCHAR
*
data
=
WCEL_GetHistory
(
ctx
,
idx
);
int
len
=
lstrlenW
(
data
)
+
1
;
/* save current line edition for recall when needed (FIXME seems broken to me) */
if
(
ctx
->
histPos
==
ctx
->
histSize
-
1
)
{
HeapFree
(
GetProcessHeap
(),
0
,
ctx
->
histCurr
);
ctx
->
histCurr
=
HeapAlloc
(
GetProcessHeap
(),
0
,
(
ctx
->
len
+
1
)
*
sizeof
(
WCHAR
));
memcpy
(
ctx
->
histCurr
,
ctx
->
line
,
(
ctx
->
len
+
1
)
*
sizeof
(
WCHAR
));
}
/* need to clean also the screen if new string is shorter than old one */
WCEL_DeleteString
(
ctx
,
0
,
ctx
->
len
);
ctx
->
ofs
=
0
;
/* insert new string */
if
(
WCEL_Grow
(
ctx
,
len
))
{
WCEL_InsertString
(
ctx
,
data
);
ctx
->
histPos
=
idx
;
}
HeapFree
(
GetProcessHeap
(),
0
,
data
);
}
static
void
WCEL_FindPrevInHist
(
WCEL_Context
*
ctx
)
{
int
startPos
=
ctx
->
histPos
;
WCHAR
*
data
;
unsigned
int
len
,
oldofs
;
if
(
ctx
->
histPos
&&
ctx
->
histPos
==
ctx
->
histSize
)
{
startPos
--
;
ctx
->
histPos
--
;
}
do
{
data
=
WCEL_GetHistory
(
ctx
,
ctx
->
histPos
);
if
(
ctx
->
histPos
)
ctx
->
histPos
--
;
else
ctx
->
histPos
=
(
ctx
->
histSize
-
1
);
len
=
lstrlenW
(
data
)
+
1
;
if
((
len
>=
ctx
->
ofs
)
&&
(
memcmp
(
ctx
->
line
,
data
,
ctx
->
ofs
*
sizeof
(
WCHAR
))
==
0
))
{
/* need to clean also the screen if new string is shorter than old one */
WCEL_DeleteString
(
ctx
,
0
,
ctx
->
len
);
if
(
WCEL_Grow
(
ctx
,
len
))
{
oldofs
=
ctx
->
ofs
;
ctx
->
ofs
=
0
;
WCEL_InsertString
(
ctx
,
data
);
ctx
->
ofs
=
oldofs
;
if
(
ctx
->
shall_echo
)
SetConsoleCursorPosition
(
ctx
->
hConOut
,
WCEL_GetCoord
(
ctx
,
ctx
->
ofs
));
HeapFree
(
GetProcessHeap
(),
0
,
data
);
return
;
}
}
HeapFree
(
GetProcessHeap
(),
0
,
data
);
}
while
(
ctx
->
histPos
!=
startPos
);
return
;
}
/* ====================================================================
*
* basic edition functions
*
* ====================================================================*/
static
void
WCEL_Done
(
WCEL_Context
*
ctx
)
{
WCHAR
nl
=
'\n'
;
if
(
!
WCEL_Grow
(
ctx
,
2
))
return
;
ctx
->
line
[
ctx
->
len
++
]
=
'\r'
;
ctx
->
line
[
ctx
->
len
++
]
=
'\n'
;
ctx
->
line
[
ctx
->
len
]
=
0
;
WriteConsoleW
(
ctx
->
hConOut
,
&
nl
,
1
,
NULL
,
NULL
);
if
(
ctx
->
insertkey
)
SetConsoleCursorInfo
(
ctx
->
hConOut
,
&
ctx
->
cinfo
);
ctx
->
done
=
1
;
}
static
void
WCEL_MoveLeft
(
WCEL_Context
*
ctx
)
{
if
(
ctx
->
ofs
>
0
)
ctx
->
ofs
--
;
}
static
void
WCEL_MoveRight
(
WCEL_Context
*
ctx
)
{
if
(
ctx
->
ofs
<
ctx
->
len
)
ctx
->
ofs
++
;
}
static
void
WCEL_MoveToLeftWord
(
WCEL_Context
*
ctx
)
{
unsigned
int
new_ofs
=
WCEL_GetLeftWordTransition
(
ctx
,
ctx
->
ofs
);
if
(
new_ofs
!=
ctx
->
ofs
)
ctx
->
ofs
=
new_ofs
;
}
static
void
WCEL_MoveToRightWord
(
WCEL_Context
*
ctx
)
{
unsigned
int
new_ofs
=
WCEL_GetRightWordTransition
(
ctx
,
ctx
->
ofs
);
if
(
new_ofs
!=
ctx
->
ofs
)
ctx
->
ofs
=
new_ofs
;
}
static
void
WCEL_MoveToBeg
(
WCEL_Context
*
ctx
)
{
ctx
->
ofs
=
0
;
}
static
void
WCEL_MoveToEnd
(
WCEL_Context
*
ctx
)
{
ctx
->
ofs
=
ctx
->
len
;
}
static
void
WCEL_SetMark
(
WCEL_Context
*
ctx
)
{
ctx
->
mark
=
ctx
->
ofs
;
}
static
void
WCEL_ExchangeMark
(
WCEL_Context
*
ctx
)
{
unsigned
tmp
;
if
(
ctx
->
mark
>
ctx
->
len
)
return
;
tmp
=
ctx
->
ofs
;
ctx
->
ofs
=
ctx
->
mark
;
ctx
->
mark
=
tmp
;
}
static
void
WCEL_CopyMarkedZone
(
WCEL_Context
*
ctx
)
{
unsigned
beg
,
end
;
if
(
ctx
->
mark
>
ctx
->
len
||
ctx
->
mark
==
ctx
->
ofs
)
return
;
if
(
ctx
->
mark
>
ctx
->
ofs
)
{
beg
=
ctx
->
ofs
;
end
=
ctx
->
mark
;
}
else
{
beg
=
ctx
->
mark
;
end
=
ctx
->
ofs
;
}
WCEL_SaveYank
(
ctx
,
beg
,
end
);
}
static
void
WCEL_TransposeChar
(
WCEL_Context
*
ctx
)
{
WCHAR
c
;
if
(
!
ctx
->
ofs
||
ctx
->
ofs
==
ctx
->
len
)
return
;
c
=
ctx
->
line
[
ctx
->
ofs
];
ctx
->
line
[
ctx
->
ofs
]
=
ctx
->
line
[
ctx
->
ofs
-
1
];
ctx
->
line
[
ctx
->
ofs
-
1
]
=
c
;
WCEL_Update
(
ctx
,
ctx
->
ofs
-
1
,
2
);
ctx
->
ofs
++
;
}
static
void
WCEL_TransposeWords
(
WCEL_Context
*
ctx
)
{
unsigned
int
left_ofs
=
WCEL_GetLeftWordTransition
(
ctx
,
ctx
->
ofs
),
right_ofs
=
WCEL_GetRightWordTransition
(
ctx
,
ctx
->
ofs
);
if
(
left_ofs
<
ctx
->
ofs
&&
right_ofs
>
ctx
->
ofs
)
{
unsigned
len_r
=
right_ofs
-
ctx
->
ofs
;
unsigned
len_l
=
ctx
->
ofs
-
left_ofs
;
char
*
tmp
=
HeapAlloc
(
GetProcessHeap
(),
0
,
len_r
*
sizeof
(
WCHAR
));
if
(
!
tmp
)
return
;
memcpy
(
tmp
,
&
ctx
->
line
[
ctx
->
ofs
],
len_r
*
sizeof
(
WCHAR
));
memmove
(
&
ctx
->
line
[
left_ofs
+
len_r
],
&
ctx
->
line
[
left_ofs
],
len_l
*
sizeof
(
WCHAR
));
memcpy
(
&
ctx
->
line
[
left_ofs
],
tmp
,
len_r
*
sizeof
(
WCHAR
));
HeapFree
(
GetProcessHeap
(),
0
,
tmp
);
WCEL_Update
(
ctx
,
left_ofs
,
len_l
+
len_r
);
ctx
->
ofs
=
right_ofs
;
}
}
static
void
WCEL_LowerCaseWord
(
WCEL_Context
*
ctx
)
{
unsigned
int
new_ofs
=
WCEL_GetRightWordTransition
(
ctx
,
ctx
->
ofs
);
if
(
new_ofs
!=
ctx
->
ofs
)
{
CharLowerBuffW
(
ctx
->
line
+
ctx
->
ofs
,
new_ofs
-
ctx
->
ofs
+
1
);
WCEL_Update
(
ctx
,
ctx
->
ofs
,
new_ofs
-
ctx
->
ofs
+
1
);
ctx
->
ofs
=
new_ofs
;
}
}
static
void
WCEL_UpperCaseWord
(
WCEL_Context
*
ctx
)
{
unsigned
int
new_ofs
=
WCEL_GetRightWordTransition
(
ctx
,
ctx
->
ofs
);
if
(
new_ofs
!=
ctx
->
ofs
)
{
CharUpperBuffW
(
ctx
->
line
+
ctx
->
ofs
,
new_ofs
-
ctx
->
ofs
+
1
);
WCEL_Update
(
ctx
,
ctx
->
ofs
,
new_ofs
-
ctx
->
ofs
+
1
);
ctx
->
ofs
=
new_ofs
;
}
}
static
void
WCEL_CapitalizeWord
(
WCEL_Context
*
ctx
)
{
unsigned
int
new_ofs
=
WCEL_GetRightWordTransition
(
ctx
,
ctx
->
ofs
);
if
(
new_ofs
!=
ctx
->
ofs
)
{
CharUpperBuffW
(
ctx
->
line
+
ctx
->
ofs
,
1
);
CharLowerBuffW
(
ctx
->
line
+
ctx
->
ofs
+
1
,
new_ofs
-
ctx
->
ofs
);
WCEL_Update
(
ctx
,
ctx
->
ofs
,
new_ofs
-
ctx
->
ofs
+
1
);
ctx
->
ofs
=
new_ofs
;
}
}
static
void
WCEL_Yank
(
WCEL_Context
*
ctx
)
{
if
(
ctx
->
yanked
)
WCEL_InsertString
(
ctx
,
ctx
->
yanked
);
}
static
void
WCEL_KillToEndOfLine
(
WCEL_Context
*
ctx
)
{
WCEL_SaveYank
(
ctx
,
ctx
->
ofs
,
ctx
->
len
);
WCEL_DeleteString
(
ctx
,
ctx
->
ofs
,
ctx
->
len
);
}
static
void
WCEL_KillFromBegOfLine
(
WCEL_Context
*
ctx
)
{
if
(
ctx
->
ofs
)
{
WCEL_SaveYank
(
ctx
,
0
,
ctx
->
ofs
);
WCEL_DeleteString
(
ctx
,
0
,
ctx
->
ofs
);
ctx
->
ofs
=
0
;
}
}
static
void
WCEL_KillMarkedZone
(
WCEL_Context
*
ctx
)
{
unsigned
beg
,
end
;
if
(
ctx
->
mark
>
ctx
->
len
||
ctx
->
mark
==
ctx
->
ofs
)
return
;
if
(
ctx
->
mark
>
ctx
->
ofs
)
{
beg
=
ctx
->
ofs
;
end
=
ctx
->
mark
;
}
else
{
beg
=
ctx
->
mark
;
end
=
ctx
->
ofs
;
}
WCEL_SaveYank
(
ctx
,
beg
,
end
);
WCEL_DeleteString
(
ctx
,
beg
,
end
);
ctx
->
ofs
=
beg
;
}
static
void
WCEL_DeletePrevChar
(
WCEL_Context
*
ctx
)
{
if
(
ctx
->
ofs
)
{
WCEL_DeleteString
(
ctx
,
ctx
->
ofs
-
1
,
ctx
->
ofs
);
ctx
->
ofs
--
;
}
}
static
void
WCEL_DeleteCurrChar
(
WCEL_Context
*
ctx
)
{
if
(
ctx
->
ofs
<
ctx
->
len
)
WCEL_DeleteString
(
ctx
,
ctx
->
ofs
,
ctx
->
ofs
+
1
);
}
static
void
WCEL_DeleteLeftWord
(
WCEL_Context
*
ctx
)
{
unsigned
int
new_ofs
=
WCEL_GetLeftWordTransition
(
ctx
,
ctx
->
ofs
);
if
(
new_ofs
!=
ctx
->
ofs
)
{
WCEL_DeleteString
(
ctx
,
new_ofs
,
ctx
->
ofs
);
ctx
->
ofs
=
new_ofs
;
}
}
static
void
WCEL_DeleteRightWord
(
WCEL_Context
*
ctx
)
{
unsigned
int
new_ofs
=
WCEL_GetRightWordTransition
(
ctx
,
ctx
->
ofs
);
if
(
new_ofs
!=
ctx
->
ofs
)
{
WCEL_DeleteString
(
ctx
,
ctx
->
ofs
,
new_ofs
);
}
}
static
void
WCEL_MoveToPrevHist
(
WCEL_Context
*
ctx
)
{
if
(
ctx
->
histPos
)
WCEL_MoveToHist
(
ctx
,
ctx
->
histPos
-
1
);
}
static
void
WCEL_MoveToNextHist
(
WCEL_Context
*
ctx
)
{
if
(
ctx
->
histPos
<
ctx
->
histSize
-
1
)
WCEL_MoveToHist
(
ctx
,
ctx
->
histPos
+
1
);
}
static
void
WCEL_MoveToFirstHist
(
WCEL_Context
*
ctx
)
{
if
(
ctx
->
histPos
!=
0
)
WCEL_MoveToHist
(
ctx
,
0
);
}
static
void
WCEL_MoveToLastHist
(
WCEL_Context
*
ctx
)
{
if
(
ctx
->
histPos
!=
ctx
->
histSize
-
1
)
WCEL_MoveToHist
(
ctx
,
ctx
->
histSize
-
1
);
}
static
void
WCEL_Redraw
(
WCEL_Context
*
ctx
)
{
if
(
ctx
->
shall_echo
)
{
COORD
c
=
WCEL_GetCoord
(
ctx
,
ctx
->
len
);
CHAR_INFO
ci
;
WCEL_Update
(
ctx
,
0
,
ctx
->
len
);
ci
.
Char
.
UnicodeChar
=
' '
;
ci
.
Attributes
=
ctx
->
csbi
.
wAttributes
;
CONSOLE_FillLineUniform
(
ctx
->
hConOut
,
c
.
X
,
c
.
Y
,
ctx
->
csbi
.
dwSize
.
X
-
c
.
X
,
&
ci
);
}
}
static
void
WCEL_RepeatCount
(
WCEL_Context
*
ctx
)
{
#if 0
/* FIXME: wait until all console code is in kernel32 */
INPUT_RECORD ir;
unsigned repeat = 0;
while (WCEL_Get(ctx, &ir, FALSE))
{
if (ir.EventType != KEY_EVENT) break;
if (ir.Event.KeyEvent.bKeyDown)
{
if ((ir.Event.KeyEvent.dwControlKeyState & ~(NUMLOCK_ON|SCROLLLOCK_ON|CAPSLOCK_ON)) != 0)
break;
if (ir.Event.KeyEvent.uChar.UnicodeChar < '0' ||
ir.Event.KeyEvent.uChar.UnicodeChar > '9')
break;
repeat = repeat * 10 + ir.Event.KeyEvent.uChar.UnicodeChar - '0';
}
WCEL_Get(ctx, &ir, TRUE);
}
FIXME("=> %u\n", repeat);
#endif
}
static
void
WCEL_ToggleInsert
(
WCEL_Context
*
ctx
)
{
CONSOLE_CURSOR_INFO
cinfo
;
ctx
->
insertkey
=
!
ctx
->
insertkey
;
if
(
GetConsoleCursorInfo
(
ctx
->
hConOut
,
&
cinfo
))
{
cinfo
.
dwSize
=
ctx
->
insertkey
?
100
:
25
;
SetConsoleCursorInfo
(
ctx
->
hConOut
,
&
cinfo
);
}
}
/* ====================================================================
*
* Key Maps
*
* ====================================================================*/
#define CTRL(x) ((x) - '@')
static
const
KeyEntry
StdKeyMap
[]
=
{
{
/*VK_BACK*/
0x08
,
WCEL_DeletePrevChar
},
{
/*VK_RETURN*/
0x0d
,
WCEL_Done
},
{
/*VK_DELETE*/
0x2e
,
WCEL_DeleteCurrChar
},
{
0
,
NULL
}
};
static
const
KeyEntry
EmacsKeyMapCtrl
[]
=
{
{
CTRL
(
'@'
),
WCEL_SetMark
},
{
CTRL
(
'A'
),
WCEL_MoveToBeg
},
{
CTRL
(
'B'
),
WCEL_MoveLeft
},
/* C: done in server */
{
CTRL
(
'D'
),
WCEL_DeleteCurrChar
},
{
CTRL
(
'E'
),
WCEL_MoveToEnd
},
{
CTRL
(
'F'
),
WCEL_MoveRight
},
{
CTRL
(
'G'
),
WCEL_Beep
},
{
CTRL
(
'H'
),
WCEL_DeletePrevChar
},
/* I: meaningless (or tab ???) */
{
CTRL
(
'J'
),
WCEL_Done
},
{
CTRL
(
'K'
),
WCEL_KillToEndOfLine
},
{
CTRL
(
'L'
),
WCEL_Redraw
},
{
CTRL
(
'M'
),
WCEL_Done
},
{
CTRL
(
'N'
),
WCEL_MoveToNextHist
},
/* O; insert line... meaningless */
{
CTRL
(
'P'
),
WCEL_MoveToPrevHist
},
/* Q: [NIY] quoting... */
/* R: [NIY] search backwards... */
/* S: [NIY] search forwards... */
{
CTRL
(
'T'
),
WCEL_TransposeChar
},
{
CTRL
(
'U'
),
WCEL_RepeatCount
},
/* V: paragraph down... meaningless */
{
CTRL
(
'W'
),
WCEL_KillMarkedZone
},
{
CTRL
(
'X'
),
WCEL_ExchangeMark
},
{
CTRL
(
'Y'
),
WCEL_Yank
},
/* Z: meaningless */
{
0
,
NULL
}
};
static
const
KeyEntry
EmacsKeyMapAlt
[]
=
{
{
/*DEL*/
127
,
WCEL_DeleteLeftWord
},
{
'<'
,
WCEL_MoveToFirstHist
},
{
'>'
,
WCEL_MoveToLastHist
},
{
'?'
,
WCEL_Beep
},
{
'b'
,
WCEL_MoveToLeftWord
},
{
'c'
,
WCEL_CapitalizeWord
},
{
'd'
,
WCEL_DeleteRightWord
},
{
'f'
,
WCEL_MoveToRightWord
},
{
'l'
,
WCEL_LowerCaseWord
},
{
't'
,
WCEL_TransposeWords
},
{
'u'
,
WCEL_UpperCaseWord
},
{
'w'
,
WCEL_CopyMarkedZone
},
{
0
,
NULL
}
};
static
const
KeyEntry
EmacsStdKeyMap
[]
=
{
{
/*VK_PRIOR*/
0x21
,
WCEL_MoveToPrevHist
},
{
/*VK_NEXT*/
0x22
,
WCEL_MoveToNextHist
},
{
/*VK_END*/
0x23
,
WCEL_MoveToEnd
},
{
/*VK_HOME*/
0x24
,
WCEL_MoveToBeg
},
{
/*VK_RIGHT*/
0x27
,
WCEL_MoveRight
},
{
/*VK_LEFT*/
0x25
,
WCEL_MoveLeft
},
{
/*VK_INSERT*/
0x2d
,
WCEL_ToggleInsert
},
{
0
,
NULL
}
};
static
const
KeyMap
EmacsKeyMap
[]
=
{
{
0
,
0
,
StdKeyMap
},
{
0
,
0
,
EmacsStdKeyMap
},
{
RIGHT_ALT_PRESSED
,
1
,
EmacsKeyMapAlt
},
/* right alt */
{
LEFT_ALT_PRESSED
,
1
,
EmacsKeyMapAlt
},
/* left alt */
{
RIGHT_CTRL_PRESSED
,
1
,
EmacsKeyMapCtrl
},
/* right ctrl */
{
LEFT_CTRL_PRESSED
,
1
,
EmacsKeyMapCtrl
},
/* left ctrl */
{
0
,
0
,
NULL
}
};
static
const
KeyEntry
Win32StdKeyMap
[]
=
{
{
/*VK_LEFT*/
0x25
,
WCEL_MoveLeft
},
{
/*VK_RIGHT*/
0x27
,
WCEL_MoveRight
},
{
/*VK_HOME*/
0x24
,
WCEL_MoveToBeg
},
{
/*VK_END*/
0x23
,
WCEL_MoveToEnd
},
{
/*VK_UP*/
0x26
,
WCEL_MoveToPrevHist
},
{
/*VK_DOWN*/
0x28
,
WCEL_MoveToNextHist
},
{
/*VK_INSERT*/
0x2d
,
WCEL_ToggleInsert
},
{
/*VK_F8*/
0x77
,
WCEL_FindPrevInHist
},
{
0
,
NULL
}
};
static
const
KeyEntry
Win32KeyMapCtrl
[]
=
{
{
/*VK_LEFT*/
0x25
,
WCEL_MoveToLeftWord
},
{
/*VK_RIGHT*/
0x27
,
WCEL_MoveToRightWord
},
{
/*VK_END*/
0x23
,
WCEL_KillToEndOfLine
},
{
/*VK_HOME*/
0x24
,
WCEL_KillFromBegOfLine
},
{
0
,
NULL
}
};
static
const
KeyMap
Win32KeyMap
[]
=
{
{
0
,
0
,
StdKeyMap
},
{
SHIFT_PRESSED
,
0
,
StdKeyMap
},
{
0
,
0
,
Win32StdKeyMap
},
{
RIGHT_CTRL_PRESSED
,
0
,
Win32KeyMapCtrl
},
{
LEFT_CTRL_PRESSED
,
0
,
Win32KeyMapCtrl
},
{
0
,
0
,
NULL
}
};
#undef CTRL
/* ====================================================================
*
* Read line master function
*
* ====================================================================*/
WCHAR
*
CONSOLE_Readline
(
HANDLE
hConsoleIn
,
BOOL
can_pos_cursor
)
{
WCEL_Context
ctx
;
INPUT_RECORD
ir
;
const
KeyMap
*
km
;
const
KeyEntry
*
ke
;
unsigned
ofs
;
void
(
*
func
)(
struct
WCEL_Context
*
ctx
);
DWORD
mode
,
input_mode
,
ks
;
int
use_emacs
;
CONSOLE_SCREEN_BUFFER_INFO
csbi
;
memset
(
&
ctx
,
0
,
sizeof
(
ctx
));
ctx
.
hConIn
=
hConsoleIn
;
WCEL_HistoryInit
(
&
ctx
);
if
(
!
CONSOLE_GetEditionMode
(
hConsoleIn
,
&
use_emacs
))
use_emacs
=
0
;
if
((
ctx
.
hConOut
=
CreateFileA
(
"CONOUT$"
,
GENERIC_READ
|
GENERIC_WRITE
,
0
,
NULL
,
OPEN_EXISTING
,
0
,
0
))
==
INVALID_HANDLE_VALUE
||
!
GetConsoleScreenBufferInfo
(
ctx
.
hConOut
,
&
ctx
.
csbi
))
return
NULL
;
if
(
!
GetConsoleMode
(
hConsoleIn
,
&
mode
))
mode
=
0
;
input_mode
=
mode
;
ctx
.
shall_echo
=
(
mode
&
ENABLE_ECHO_INPUT
)
?
1
:
0
;
ctx
.
insert
=
(
mode
&
(
ENABLE_INSERT_MODE
|
ENABLE_EXTENDED_FLAGS
))
==
(
ENABLE_INSERT_MODE
|
ENABLE_EXTENDED_FLAGS
)
?
1
:
0
;
if
(
!
GetConsoleMode
(
ctx
.
hConOut
,
&
mode
))
mode
=
0
;
ctx
.
can_wrap
=
(
mode
&
ENABLE_WRAP_AT_EOL_OUTPUT
)
?
1
:
0
;
ctx
.
can_pos_cursor
=
can_pos_cursor
;
GetConsoleCursorInfo
(
ctx
.
hConOut
,
&
ctx
.
cinfo
);
if
(
!
WCEL_Grow
(
&
ctx
,
1
))
{
CloseHandle
(
ctx
.
hConOut
);
return
NULL
;
}
ctx
.
line
[
0
]
=
0
;
/* EPP WCEL_Dump(&ctx, "init"); */
while
(
!
ctx
.
done
&&
!
ctx
.
error
&&
WCEL_Get
(
&
ctx
,
&
ir
))
{
if
(
ir
.
EventType
!=
KEY_EVENT
)
continue
;
TRACE
(
"key%s repeatCount=%u, keyCode=%02x scanCode=%02x char=%02x keyState=%08x
\n
"
,
ir
.
Event
.
KeyEvent
.
bKeyDown
?
"Down"
:
"Up "
,
ir
.
Event
.
KeyEvent
.
wRepeatCount
,
ir
.
Event
.
KeyEvent
.
wVirtualKeyCode
,
ir
.
Event
.
KeyEvent
.
wVirtualScanCode
,
ir
.
Event
.
KeyEvent
.
uChar
.
UnicodeChar
,
ir
.
Event
.
KeyEvent
.
dwControlKeyState
);
if
(
!
ir
.
Event
.
KeyEvent
.
bKeyDown
)
continue
;
/* EPP WCEL_Dump(&ctx, "before func"); */
ofs
=
ctx
.
ofs
;
/* mask out some bits which don't interest us */
ks
=
ir
.
Event
.
KeyEvent
.
dwControlKeyState
&
~
(
NUMLOCK_ON
|
SCROLLLOCK_ON
|
CAPSLOCK_ON
|
ENHANCED_KEY
);
func
=
NULL
;
for
(
km
=
(
use_emacs
)
?
EmacsKeyMap
:
Win32KeyMap
;
km
->
entries
!=
NULL
;
km
++
)
{
if
(
km
->
keyState
!=
ks
)
continue
;
if
(
km
->
chkChar
)
{
for
(
ke
=
&
km
->
entries
[
0
];
ke
->
func
!=
0
;
ke
++
)
if
(
ke
->
val
==
ir
.
Event
.
KeyEvent
.
uChar
.
UnicodeChar
)
break
;
}
else
{
for
(
ke
=
&
km
->
entries
[
0
];
ke
->
func
!=
0
;
ke
++
)
if
(
ke
->
val
==
ir
.
Event
.
KeyEvent
.
wVirtualKeyCode
)
break
;
}
if
(
ke
->
func
)
{
func
=
ke
->
func
;
break
;
}
}
CONSOLE_GetEditionMode
(
hConsoleIn
,
&
use_emacs
);
GetConsoleMode
(
hConsoleIn
,
&
mode
);
if
(
input_mode
!=
mode
)
{
input_mode
=
mode
;
ctx
.
insertkey
=
0
;
}
ctx
.
insert
=
(
mode
&
(
ENABLE_INSERT_MODE
|
ENABLE_EXTENDED_FLAGS
))
==
(
ENABLE_INSERT_MODE
|
ENABLE_EXTENDED_FLAGS
);
if
(
ctx
.
insertkey
)
ctx
.
insert
=
!
ctx
.
insert
;
GetConsoleScreenBufferInfo
(
ctx
.
hConOut
,
&
csbi
);
ctx
.
csbi
.
wAttributes
=
csbi
.
wAttributes
;
if
(
func
)
(
func
)(
&
ctx
);
else
if
(
!
(
ir
.
Event
.
KeyEvent
.
dwControlKeyState
&
LEFT_ALT_PRESSED
))
WCEL_InsertChar
(
&
ctx
,
ir
.
Event
.
KeyEvent
.
uChar
.
UnicodeChar
);
else
TRACE
(
"Dropped event
\n
"
);
/* EPP WCEL_Dump(&ctx, "after func"); */
if
(
!
ctx
.
shall_echo
)
continue
;
if
(
ctx
.
can_pos_cursor
)
{
if
(
ctx
.
ofs
!=
ofs
)
SetConsoleCursorPosition
(
ctx
.
hConOut
,
WCEL_GetCoord
(
&
ctx
,
ctx
.
ofs
));
}
else
if
(
!
ctx
.
done
&&
!
ctx
.
error
)
{
DWORD
last
;
/* erase previous chars */
WCEL_WriteNChars
(
&
ctx
,
'\b'
,
ctx
.
last_rub
);
/* write chars up to cursor */
ctx
.
last_rub
=
WCEL_WriteConsole
(
&
ctx
,
0
,
ctx
.
ofs
);
/* write chars past cursor */
last
=
ctx
.
last_rub
+
WCEL_WriteConsole
(
&
ctx
,
ctx
.
ofs
,
ctx
.
len
-
ctx
.
ofs
);
if
(
last
<
ctx
.
last_max
)
/* ctx.line has been shortened, erase */
{
WCEL_WriteNChars
(
&
ctx
,
' '
,
ctx
.
last_max
-
last
);
WCEL_WriteNChars
(
&
ctx
,
'\b'
,
ctx
.
last_max
-
last
);
ctx
.
last_max
=
last
;
}
else
ctx
.
last_max
=
last
;
/* reposition at cursor */
WCEL_WriteNChars
(
&
ctx
,
'\b'
,
last
-
ctx
.
last_rub
);
}
}
if
(
ctx
.
error
)
{
HeapFree
(
GetProcessHeap
(),
0
,
ctx
.
line
);
ctx
.
line
=
NULL
;
}
WCEL_FreeYank
(
&
ctx
);
if
(
ctx
.
line
)
CONSOLE_AppendHistory
(
ctx
.
line
);
CloseHandle
(
ctx
.
hConOut
);
HeapFree
(
GetProcessHeap
(),
0
,
ctx
.
histCurr
);
return
ctx
.
line
;
}
dlls/kernel32/kernel_main.c
View file @
633b244b
...
@@ -30,7 +30,6 @@
...
@@ -30,7 +30,6 @@
#include "winternl.h"
#include "winternl.h"
#include "kernel_private.h"
#include "kernel_private.h"
#include "console_private.h"
#include "wine/debug.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL
(
process
);
WINE_DEFAULT_DEBUG_CHANNEL
(
process
);
...
...
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