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
4b461128
Commit
4b461128
authored
Jan 31, 1999
by
Alexandre Julliard
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Added input queue to server-side console object,
read/write_console_input requests, and use them for Read/WriteConsoleInput.
parent
0b78af7c
Show whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
253 additions
and
106 deletions
+253
-106
server.h
include/server.h
+25
-0
object.h
include/server/object.h
+3
-0
request.h
include/server/request.h
+6
-0
module.c
loader/ne/module.c
+1
-2
kernel32.spec
relay32/kernel32.spec
+1
-1
console.c
server/console.c
+58
-0
request.c
server/request.c
+20
-0
trace.c
server/trace.c
+32
-0
console.c
win32/console.c
+107
-103
No files found.
include/server.h
View file @
4b461128
...
...
@@ -510,6 +510,31 @@ struct get_console_info_reply
};
/* Add input records to a console input queue */
struct
write_console_input_request
{
int
handle
;
/* handle to the console input */
int
count
;
/* number of input records */
/* INPUT_RECORD records[0]; */
/* input records */
};
struct
write_console_input_reply
{
int
written
;
/* number of records written */
};
/* Fetch input records from a console input queue */
struct
read_console_input_request
{
int
handle
;
/* handle to the console input */
int
count
;
/* max number of records to retrieve */
int
flush
;
/* flush the retrieved records from the queue? */
};
struct
read_console_input_reply
{
/* INPUT_RECORD records[0]; */
/* input records */
};
/* Create a change notification */
struct
create_change_notification_request
{
...
...
include/server/object.h
View file @
4b461128
...
...
@@ -203,6 +203,7 @@ extern int create_pipe( struct object *obj[2] );
/* console functions */
struct
tagINPUT_RECORD
;
extern
int
create_console
(
int
fd
,
struct
object
*
obj
[
2
]
);
extern
int
set_console_fd
(
int
handle
,
int
fd
,
int
pid
);
extern
int
get_console_mode
(
int
handle
,
int
*
mode
);
...
...
@@ -211,6 +212,8 @@ extern int set_console_info( int handle, struct set_console_info_request *req,
const
char
*
title
);
extern
int
get_console_info
(
int
handle
,
struct
get_console_info_reply
*
reply
,
const
char
**
title
);
extern
int
write_console_input
(
int
handle
,
int
count
,
struct
tagINPUT_RECORD
*
records
);
extern
int
read_console_input
(
int
handle
,
int
count
,
int
flush
);
/* change notification functions */
...
...
include/server/request.h
View file @
4b461128
...
...
@@ -47,6 +47,8 @@ enum request
REQ_SET_CONSOLE_MODE
,
REQ_SET_CONSOLE_INFO
,
REQ_GET_CONSOLE_INFO
,
REQ_WRITE_CONSOLE_INPUT
,
REQ_READ_CONSOLE_INPUT
,
REQ_CREATE_CHANGE_NOTIFICATION
,
REQ_CREATE_MAPPING
,
REQ_GET_MAPPING_INFO
,
...
...
@@ -101,6 +103,8 @@ DECL_HANDLER(get_console_mode);
DECL_HANDLER
(
set_console_mode
);
DECL_HANDLER
(
set_console_info
);
DECL_HANDLER
(
get_console_info
);
DECL_HANDLER
(
write_console_input
);
DECL_HANDLER
(
read_console_input
);
DECL_HANDLER
(
create_change_notification
);
DECL_HANDLER
(
create_mapping
);
DECL_HANDLER
(
get_mapping_info
);
...
...
@@ -152,6 +156,8 @@ static const struct handler {
{
(
void
(
*
)())
req_set_console_mode
,
sizeof
(
struct
set_console_mode_request
)
},
{
(
void
(
*
)())
req_set_console_info
,
sizeof
(
struct
set_console_info_request
)
},
{
(
void
(
*
)())
req_get_console_info
,
sizeof
(
struct
get_console_info_request
)
},
{
(
void
(
*
)())
req_write_console_input
,
sizeof
(
struct
write_console_input_request
)
},
{
(
void
(
*
)())
req_read_console_input
,
sizeof
(
struct
read_console_input_request
)
},
{
(
void
(
*
)())
req_create_change_notification
,
sizeof
(
struct
create_change_notification_request
)
},
{
(
void
(
*
)())
req_create_mapping
,
sizeof
(
struct
create_mapping_request
)
},
{
(
void
(
*
)())
req_get_mapping_info
,
sizeof
(
struct
get_mapping_info_request
)
},
...
...
loader/ne/module.c
View file @
4b461128
...
...
@@ -1102,8 +1102,7 @@ BOOL16 WINAPI ModuleNext( MODULEENTRY *lpme )
lpme
->
szModule
[
min
(
*
name
,
MAX_MODULE_NAME
)]
=
'\0'
;
lpme
->
hModule
=
lpme
->
wNext
;
lpme
->
wcUsage
=
pModule
->
count
;
strncpy
(
lpme
->
szExePath
,
NE_MODULE_NAME
(
pModule
),
MAX_PATH
);
lpme
->
szExePath
[
MAX_PATH
]
=
'\0'
;
lstrcpyn32A
(
lpme
->
szExePath
,
NE_MODULE_NAME
(
pModule
),
sizeof
(
lpme
->
szExePath
)
);
lpme
->
wNext
=
pModule
->
next
;
return
TRUE
;
}
...
...
relay32/kernel32.spec
View file @
4b461128
...
...
@@ -746,7 +746,7 @@ init MAIN_KernelInit
727 stdcall WideCharToMultiByte(long long wstr long ptr long ptr ptr) WideCharToMultiByte
728 stdcall WinExec(str long) WinExec32
729 stdcall WriteConsoleA(long ptr long ptr ptr) WriteConsole32A
730 st
ub WriteConsoleInput
A
730 st
dcall WriteConsoleInputA(long ptr long ptr) WriteConsoleInput32
A
731 stub WriteConsoleInputW
732 stdcall WriteConsoleOutputA(long ptr long long ptr) WriteConsoleOutput32A
733 stub WriteConsoleOutputAttribute
...
...
server/console.c
View file @
4b461128
...
...
@@ -33,6 +33,8 @@ struct console_input
int
fd
;
/* Unix file descriptor */
int
mode
;
/* input mode */
struct
screen_buffer
*
output
;
/* associated screen buffer */
int
recnum
;
/* number of input records */
INPUT_RECORD
*
records
;
/* input records */
};
struct
screen_buffer
...
...
@@ -135,6 +137,8 @@ int create_console( int fd, struct object *obj[2] )
console_input
->
mode
=
ENABLE_PROCESSED_INPUT
|
ENABLE_LINE_INPUT
|
ENABLE_ECHO_INPUT
|
ENABLE_MOUSE_INPUT
;
console_input
->
output
=
screen_buffer
;
console_input
->
recnum
=
0
;
console_input
->
records
=
NULL
;
screen_buffer
->
fd
=
write_fd
;
screen_buffer
->
mode
=
ENABLE_PROCESSED_OUTPUT
|
ENABLE_WRAP_AT_EOL_OUTPUT
;
screen_buffer
->
input
=
console_input
;
...
...
@@ -281,6 +285,60 @@ int get_console_info( int handle, struct get_console_info_reply *reply, const ch
return
1
;
}
/* add input events to a console input queue */
int
write_console_input
(
int
handle
,
int
count
,
INPUT_RECORD
*
records
)
{
INPUT_RECORD
*
new_rec
;
struct
console_input
*
console
;
if
(
!
(
console
=
(
struct
console_input
*
)
get_handle_obj
(
current
->
process
,
handle
,
GENERIC_WRITE
,
&
console_input_ops
)))
return
-
1
;
if
(
!
(
new_rec
=
realloc
(
console
->
records
,
(
console
->
recnum
+
count
)
*
sizeof
(
INPUT_RECORD
)
)))
{
SET_ERROR
(
ERROR_NOT_ENOUGH_MEMORY
);
release_object
(
console
);
return
-
1
;
}
console
->
records
=
new_rec
;
memcpy
(
new_rec
+
console
->
recnum
,
records
,
count
*
sizeof
(
INPUT_RECORD
)
);
console
->
recnum
+=
count
;
release_object
(
console
);
return
count
;
}
/* retrieve a pointer to the console input records */
int
read_console_input
(
int
handle
,
int
count
,
int
flush
)
{
struct
console_input
*
console
;
if
(
!
(
console
=
(
struct
console_input
*
)
get_handle_obj
(
current
->
process
,
handle
,
GENERIC_READ
,
&
console_input_ops
)))
return
-
1
;
if
((
count
<
0
)
||
(
count
>
console
->
recnum
))
count
=
console
->
recnum
;
send_reply
(
current
,
-
1
,
1
,
console
->
records
,
count
*
sizeof
(
INPUT_RECORD
)
);
if
(
flush
)
{
int
i
;
for
(
i
=
count
;
i
<
console
->
recnum
;
i
++
)
console
->
records
[
i
-
count
]
=
console
->
records
[
i
];
if
((
console
->
recnum
-=
count
)
>
0
)
{
INPUT_RECORD
*
new_rec
=
realloc
(
console
->
records
,
console
->
recnum
*
sizeof
(
INPUT_RECORD
)
);
if
(
new_rec
)
console
->
records
=
new_rec
;
}
else
{
free
(
console
->
records
);
console
->
records
=
NULL
;
}
}
release_object
(
console
);
return
count
;
}
static
void
console_input_dump
(
struct
object
*
obj
,
int
verbose
)
{
struct
console_input
*
console
=
(
struct
console_input
*
)
obj
;
...
...
server/request.c
View file @
4b461128
...
...
@@ -15,6 +15,7 @@
#include "winerror.h"
#include "winnt.h"
#include "winbase.h"
#include "wincon.h"
#define WANT_REQUEST_HANDLERS
#include "server.h"
#include "server/request.h"
...
...
@@ -677,6 +678,25 @@ DECL_HANDLER(set_console_mode)
send_reply
(
current
,
-
1
,
0
);
}
/* add input records to a console input queue */
DECL_HANDLER
(
write_console_input
)
{
struct
write_console_input_reply
reply
;
INPUT_RECORD
*
records
=
(
INPUT_RECORD
*
)
data
;
if
(
len
!=
req
->
count
*
sizeof
(
INPUT_RECORD
))
fatal_protocol_error
(
"write_console_input: bad length %d for %d records
\n
"
,
len
,
req
->
count
);
reply
.
written
=
write_console_input
(
req
->
handle
,
req
->
count
,
records
);
send_reply
(
current
,
-
1
,
1
,
&
reply
,
sizeof
(
reply
)
);
}
/* fetch input records from a console input queue */
DECL_HANDLER
(
read_console_input
)
{
read_console_input
(
req
->
handle
,
req
->
count
,
req
->
flush
);
}
/* create a change notification */
DECL_HANDLER
(
create_change_notification
)
{
...
...
server/trace.c
View file @
4b461128
...
...
@@ -458,6 +458,32 @@ static int dump_get_console_info_reply( struct get_console_info_reply *req, int
return
(
int
)
sizeof
(
*
req
);
}
static
int
dump_write_console_input_request
(
struct
write_console_input_request
*
req
,
int
len
)
{
fprintf
(
stderr
,
" handle=%d,"
,
req
->
handle
);
fprintf
(
stderr
,
" count=%d"
,
req
->
count
);
return
(
int
)
sizeof
(
*
req
);
}
static
int
dump_write_console_input_reply
(
struct
write_console_input_reply
*
req
,
int
len
)
{
fprintf
(
stderr
,
" written=%d"
,
req
->
written
);
return
(
int
)
sizeof
(
*
req
);
}
static
int
dump_read_console_input_request
(
struct
read_console_input_request
*
req
,
int
len
)
{
fprintf
(
stderr
,
" handle=%d,"
,
req
->
handle
);
fprintf
(
stderr
,
" count=%d,"
,
req
->
count
);
fprintf
(
stderr
,
" flush=%d"
,
req
->
flush
);
return
(
int
)
sizeof
(
*
req
);
}
static
int
dump_read_console_input_reply
(
struct
read_console_input_reply
*
req
,
int
len
)
{
return
(
int
)
sizeof
(
*
req
);
}
static
int
dump_create_change_notification_request
(
struct
create_change_notification_request
*
req
,
int
len
)
{
fprintf
(
stderr
,
" subtree=%d,"
,
req
->
subtree
);
...
...
@@ -607,6 +633,10 @@ static const struct dumper dumpers[REQ_NB_REQUESTS] =
(
void
(
*
)())
0
},
{
(
int
(
*
)(
void
*
,
int
))
dump_get_console_info_request
,
(
void
(
*
)())
dump_get_console_info_reply
},
{
(
int
(
*
)(
void
*
,
int
))
dump_write_console_input_request
,
(
void
(
*
)())
dump_write_console_input_reply
},
{
(
int
(
*
)(
void
*
,
int
))
dump_read_console_input_request
,
(
void
(
*
)())
dump_read_console_input_reply
},
{
(
int
(
*
)(
void
*
,
int
))
dump_create_change_notification_request
,
(
void
(
*
)())
dump_create_change_notification_reply
},
{
(
int
(
*
)(
void
*
,
int
))
dump_create_mapping_request
,
...
...
@@ -661,6 +691,8 @@ static const char * const req_names[REQ_NB_REQUESTS] =
"set_console_mode"
,
"set_console_info"
,
"get_console_info"
,
"write_console_input"
,
"read_console_input"
,
"create_change_notification"
,
"create_mapping"
,
"get_mapping_info"
,
...
...
win32/console.c
View file @
4b461128
...
...
@@ -1043,44 +1043,122 @@ BOOL32 WINAPI ReadConsoleInput32A(HANDLE32 hConsoleInput,
LPINPUT_RECORD
lpBuffer
,
DWORD
nLength
,
LPDWORD
lpNumberOfEventsRead
)
{
CONSOLE
*
console
=
CONSOLE_GetPtr
(
hConsoleInput
);
TRACE
(
console
,
"(%d,%p,%ld,%p)
\n
"
,
hConsoleInput
,
lpBuffer
,
nLength
,
lpNumberOfEventsRead
);
if
(
!
console
)
{
FIXME
(
console
,
"(%d,%p,%ld,%p), No console handle!
\n
"
,
hConsoleInput
,
lpBuffer
,
nLength
,
lpNumberOfEventsRead
);
struct
read_console_input_request
req
;
int
len
;
/* Indicate that nothing was read */
*
lpNumberOfEventsRead
=
0
;
if
((
req
.
handle
=
HANDLE_GetServerHandle
(
PROCESS_Current
(),
hConsoleInput
,
K32OBJ_CONSOLE
,
GENERIC_READ
))
==
-
1
)
return
FALSE
;
req
.
count
=
nLength
;
req
.
flush
=
1
;
/* loop until we get at least one event */
for
(;;)
{
CLIENT_SendRequest
(
REQ_READ_CONSOLE_INPUT
,
-
1
,
1
,
&
req
,
sizeof
(
req
)
);
if
(
CLIENT_WaitReply
(
&
len
,
NULL
,
1
,
lpBuffer
,
nLength
*
sizeof
(
*
lpBuffer
)
))
return
FALSE
;
assert
(
!
(
len
%
sizeof
(
INPUT_RECORD
))
);
if
(
len
)
break
;
WaitForSingleObject
(
hConsoleInput
,
INFINITE32
);
}
CONSOLE_get_input
(
hConsoleInput
);
/* SDK: return at least 1 input record */
while
(
!
console
->
nrofirs
)
{
DWORD
res
;
if
(
lpNumberOfEventsRead
)
*
lpNumberOfEventsRead
=
len
/
sizeof
(
INPUT_RECORD
);
return
TRUE
;
}
res
=
WaitForSingleObject
(
hConsoleInput
,
0
);
switch
(
res
)
{
case
STATUS_TIMEOUT
:
continue
;
case
0
:
break
;
/*ok*/
case
WAIT_FAILED
:
return
0
;
/*FIXME: SetLastError?*/
default:
break
;
/*hmm*/
}
CONSOLE_get_input
(
hConsoleInput
);
}
if
(
nLength
>
console
->
nrofirs
)
nLength
=
console
->
nrofirs
;
memcpy
(
lpBuffer
,
console
->
irs
,
sizeof
(
INPUT_RECORD
)
*
nLength
);
if
(
lpNumberOfEventsRead
)
*
lpNumberOfEventsRead
=
nLength
;
CONSOLE_drain_input
(
console
,
nLength
);
K32OBJ_DecCount
(
&
console
->
header
);
/***********************************************************************
* ReadConsoleInput32W (KERNEL32.570)
*/
BOOL32
WINAPI
ReadConsoleInput32W
(
HANDLE32
handle
,
LPINPUT_RECORD
buffer
,
DWORD
count
,
LPDWORD
read
)
{
/* FIXME: Fix this if we get UNICODE input. */
return
ReadConsoleInput32A
(
handle
,
buffer
,
count
,
read
);
}
/***********************************************************************
* FlushConsoleInputBuffer (KERNEL32.132)
*/
BOOL32
WINAPI
FlushConsoleInputBuffer
(
HANDLE32
handle
)
{
struct
read_console_input_request
req
;
int
len
;
if
((
req
.
handle
=
HANDLE_GetServerHandle
(
PROCESS_Current
(),
handle
,
K32OBJ_CONSOLE
,
GENERIC_READ
))
==
-
1
)
return
FALSE
;
req
.
count
=
-
1
;
/* get all records */
req
.
flush
=
1
;
CLIENT_SendRequest
(
REQ_READ_CONSOLE_INPUT
,
-
1
,
1
,
&
req
,
sizeof
(
req
)
);
return
!
CLIENT_WaitReply
(
&
len
,
NULL
,
0
);
}
/***********************************************************************
* PeekConsoleInputA (KERNEL32.550)
*
* Gets 'count' first events (or less) from input queue.
*
* Does not need a complex console.
*/
BOOL32
WINAPI
PeekConsoleInput32A
(
HANDLE32
handle
,
LPINPUT_RECORD
buffer
,
DWORD
count
,
LPDWORD
read
)
{
struct
read_console_input_request
req
;
int
len
;
if
((
req
.
handle
=
HANDLE_GetServerHandle
(
PROCESS_Current
(),
handle
,
K32OBJ_CONSOLE
,
GENERIC_READ
))
==
-
1
)
return
FALSE
;
req
.
count
=
count
;
req
.
flush
=
0
;
CLIENT_SendRequest
(
REQ_READ_CONSOLE_INPUT
,
-
1
,
1
,
&
req
,
sizeof
(
req
)
);
if
(
CLIENT_WaitReply
(
&
len
,
NULL
,
1
,
buffer
,
count
*
sizeof
(
*
buffer
)
))
return
FALSE
;
assert
(
!
(
len
%
sizeof
(
INPUT_RECORD
))
);
if
(
read
)
*
read
=
len
/
sizeof
(
INPUT_RECORD
);
return
TRUE
;
}
/***********************************************************************
* PeekConsoleInputW (KERNEL32.551)
*/
BOOL32
WINAPI
PeekConsoleInput32W
(
HANDLE32
hConsoleInput
,
LPINPUT_RECORD
pirBuffer
,
DWORD
cInRecords
,
LPDWORD
lpcRead
)
{
/* FIXME: Hmm. Fix this if we get UNICODE input. */
return
PeekConsoleInput32A
(
hConsoleInput
,
pirBuffer
,
cInRecords
,
lpcRead
);
}
/******************************************************************************
* WriteConsoleInput32A [KERNEL32.730] Write data to a console input buffer
*
*/
BOOL32
WINAPI
WriteConsoleInput32A
(
HANDLE32
handle
,
INPUT_RECORD
*
buffer
,
DWORD
count
,
LPDWORD
written
)
{
struct
write_console_input_request
req
;
struct
write_console_input_reply
reply
;
if
((
req
.
handle
=
HANDLE_GetServerHandle
(
PROCESS_Current
(),
handle
,
K32OBJ_CONSOLE
,
GENERIC_WRITE
))
==
-
1
)
return
FALSE
;
req
.
count
=
count
;
CLIENT_SendRequest
(
REQ_WRITE_CONSOLE_INPUT
,
-
1
,
2
,
&
req
,
sizeof
(
req
),
buffer
,
count
*
sizeof
(
*
buffer
)
);
if
(
CLIENT_WaitSimpleReply
(
&
reply
,
sizeof
(
reply
),
NULL
))
return
FALSE
;
if
(
written
)
*
written
=
reply
.
written
;
return
TRUE
;
}
/***********************************************************************
* SetConsoleTitle32A (KERNEL32.476)
*
...
...
@@ -1185,33 +1263,6 @@ BOOL32 WINAPI SetConsoleTitle32W( LPCWSTR title )
return
ret
;
}
/***********************************************************************
* ReadConsoleInput32W (KERNEL32.570)
*/
BOOL32
WINAPI
ReadConsoleInput32W
(
HANDLE32
hConsoleInput
,
LPINPUT_RECORD
lpBuffer
,
DWORD
nLength
,
LPDWORD
lpNumberOfEventsRead
)
{
FIXME
(
console
,
"(%d,%p,%ld,%p): stub
\n
"
,
hConsoleInput
,
lpBuffer
,
nLength
,
lpNumberOfEventsRead
);
return
0
;
}
/***********************************************************************
* FlushConsoleInputBuffer (KERNEL32.132)
*/
BOOL32
WINAPI
FlushConsoleInputBuffer
(
HANDLE32
hConsoleInput
)
{
CONSOLE
*
console
=
CONSOLE_GetPtr
(
hConsoleInput
);
if
(
!
console
)
return
FALSE
;
CONSOLE_drain_input
(
console
,
console
->
nrofirs
);
K32OBJ_DecCount
(
&
console
->
header
);
return
TRUE
;
}
/******************************************************************************
* SetConsoleCursorPosition [KERNEL32.627]
* Sets the cursor position in console
...
...
@@ -1271,53 +1322,6 @@ BOOL32 WINAPI GetNumberOfConsoleMouseButtons(LPDWORD nrofbuttons)
return
TRUE
;
}
/***********************************************************************
* PeekConsoleInputA (KERNEL32.550)
*
* Gets 'cInRecords' first events (or less) from input queue.
*
* Does not need a complex console.
*/
BOOL32
WINAPI
PeekConsoleInput32A
(
HANDLE32
hConsoleInput
,
LPINPUT_RECORD
pirBuffer
,
DWORD
cInRecords
,
LPDWORD
lpcRead
)
{
CONSOLE
*
console
=
CONSOLE_GetPtr
(
hConsoleInput
);
if
(
!
console
)
{
FIXME
(
console
,
"(%d,%p,%ld,%p), No console handle passed!
\n
"
,
hConsoleInput
,
pirBuffer
,
cInRecords
,
lpcRead
);
/* Indicate that nothing was read */
*
lpcRead
=
0
;
return
FALSE
;
}
TRACE
(
console
,
"(%d,%p,%ld,%p)
\n
"
,
hConsoleInput
,
pirBuffer
,
cInRecords
,
lpcRead
);
CONSOLE_get_input
(
hConsoleInput
);
if
(
cInRecords
>
console
->
nrofirs
)
cInRecords
=
console
->
nrofirs
;
if
(
pirBuffer
)
memcpy
(
pirBuffer
,
console
->
irs
,
cInRecords
*
sizeof
(
INPUT_RECORD
));
if
(
lpcRead
)
*
lpcRead
=
cInRecords
;
K32OBJ_DecCount
(
&
console
->
header
);
return
TRUE
;
}
/***********************************************************************
* PeekConsoleInputW (KERNEL32.551)
*/
BOOL32
WINAPI
PeekConsoleInput32W
(
HANDLE32
hConsoleInput
,
LPINPUT_RECORD
pirBuffer
,
DWORD
cInRecords
,
LPDWORD
lpcRead
)
{
/* FIXME: Hmm. Fix this if we get UNICODE input. */
return
PeekConsoleInput32A
(
hConsoleInput
,
pirBuffer
,
cInRecords
,
lpcRead
);
}
/******************************************************************************
* GetConsoleCursorInfo32 [KERNEL32.296] Gets size and visibility of console
*
...
...
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