Skip to content

Commit df2c2ab

Browse files
committed
FEAT: implemented proper ask/hide and input/hide
That was not working well on Windows (with enabled virtual terminal processing), now it successfully hides user input. As a bonus this change contain a way how to turn off read-line console input and enter use the console as a key-stroke (and mouse as well) input. Simple use example is available here: https://gist.github.com/Oldes/face8a5790df7121a78ba606a3e150f4
1 parent cb58670 commit df2c2ab

18 files changed

+310
-61
lines changed

src/boot/modes.r

+17-10
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
REBOL [
22
System: "REBOL [R3] Language Interpreter and Run-time Environment"
3-
Title: "Port modes"
3+
Title: "Port & console modes"
44
Rights: {
55
Copyright 2012 REBOL Technologies
66
REBOL is a trademark of REBOL Technologies
@@ -11,12 +11,19 @@ REBOL [
1111
}
1212
]
1313

14-
owner-read
15-
owner-write
16-
owner-execute
17-
group-read
18-
group-write
19-
group-execute
20-
world-read
21-
world-write
22-
world-execute
14+
*port-modes* [
15+
owner-read
16+
owner-write
17+
owner-execute
18+
group-read
19+
group-write
20+
group-execute
21+
world-read
22+
world-write
23+
world-execute
24+
]
25+
26+
*console-modes* [
27+
echo
28+
line
29+
]

src/boot/words.r

+2-1
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,8 @@ on-top
229229
hidden
230230
owner
231231

232-
*port-modes*
232+
*port-modes* ;@@ modes are defined in modes.r file and these
233+
*console-modes* ;@@ placeholders are replaced here by make-boot.r script
233234

234235
bits
235236
crash

src/core/n-io.c

+2
Original file line numberDiff line numberDiff line change
@@ -409,11 +409,13 @@ static REBSER *Read_All_File(char *fname)
409409

410410
val = OFV(port, STD_PORT_ACTOR);
411411
if (IS_NATIVE(val)) {
412+
// Makes the port object fully consistent with internal native structures (e.g. the actual length of data read).
412413
Do_Port_Action(port, A_UPDATE); // uses current stack frame
413414
}
414415

415416
val = OFV(port, STD_PORT_AWAKE);
416417
if (ANY_FUNC(val)) {
418+
// Calls the port's awake function with the event as an argument.
417419
val = Apply_Func(0, val, D_ARG(2), 0);
418420
if (!(IS_LOGIC(val) && VAL_LOGIC(val))) return R_FALSE;
419421
}

src/core/p-console.c

+22-3
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,9 @@
5757
arg = D_ARG(2);
5858
*D_RET = *D_ARG(1);
5959

60-
req = Use_Port_State(port, RDI_STDIO, sizeof(REBREQ));
60+
//O: known limitation: works only with default system's imput port (not for custom console ports)
61+
req = Host_Lib->std_io;
62+
req->port = port;
6163

6264
switch (action) {
6365

@@ -85,17 +87,22 @@
8587
if (req->actual == 1 && req->data[0] == '\x1B') return R_NONE; // CTRL-C
8688

8789
#ifdef TO_WINDOWS
88-
if (req->actual > 1) req->actual -= 2; // remove CRLF from tail
90+
if (req->actual > 1 && GET_FLAG(req->modes, RDM_READ_LINE)) req->actual -= 2; // remove CRLF from tail
8991
#else
9092
if (req->actual > 0) req->actual -= 1; // remove LF from tail
9193
#endif
9294

9395
Set_Binary(ds, Copy_Bytes(req->data, req->actual));
9496
break;
9597

98+
case A_UPDATE:
99+
// do nothing here, no wake-up, events should be handled by user defined port's awake function
100+
// ==>> SYSTEM/PORTS/INPUT/SCHEME/AWAKE
101+
return R_NONE;
102+
96103
case A_OPEN:
97104
// ?? why???
98-
//if (OS_DO_DEVICE(req, RDC_OPEN)) Trap_Port(RE_CANNOT_OPEN, port);
105+
if (OS_DO_DEVICE(req, RDC_OPEN)) Trap_Port(RE_CANNOT_OPEN, port, req->error);
99106
SET_OPEN(req);
100107
break;
101108

@@ -108,6 +115,18 @@
108115
if (IS_OPEN(req)) return R_TRUE;
109116
return R_FALSE;
110117

118+
case A_MODIFY:
119+
if (IS_WORD(arg)
120+
&& (VAL_WORD_CANON(arg) == SYM_ECHO || VAL_WORD_CANON(arg) == SYM_LINE)
121+
) {
122+
spec = D_ARG(3);
123+
if (!IS_LOGIC(spec)) Trap2(RE_INVALID_VALUE_FOR, spec, arg);
124+
req->modify.mode = (VAL_WORD_CANON(arg) == SYM_ECHO) ? MODE_CONSOLE_ECHO : MODE_CONSOLE_LINE;
125+
req->modify.value = VAL_LOGIC(spec);
126+
OS_DO_DEVICE(req, RDC_MODIFY);
127+
} else Trap1(RE_BAD_FILE_MODE, arg);
128+
return R_ARG3;
129+
111130
case A_QUERY:
112131
spec = Get_System(SYS_STANDARD, STD_CONSOLE_INFO);
113132
if (!IS_OBJECT(spec)) Trap_Arg(spec);

src/core/t-event.c

+3
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,9 @@
230230
else if (IS_EVENT_MODEL(value, EVM_CALLBACK)) {
231231
*val = *Get_System(SYS_PORTS, PORTS_CALLBACK);
232232
}
233+
else if (IS_EVENT_MODEL(value, EVM_CONSOLE)) {
234+
*val = *Get_System(SYS_PORTS, PORTS_INPUT);
235+
}
233236
else {
234237
// assumes EVM_DEVICE
235238
// Event holds the IO-Request, which has the PORT:

src/core/t-port.c

+1
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@
8989
case A_CREATE:
9090
case A_DELETE:
9191
case A_RENAME:
92+
case A_MODIFY:
9293
value = As_Port(value);
9394
case A_UPDATE:
9495
default:

src/include/reb-device.h

+5
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ enum {
108108

109109
enum {
110110
RDM_NULL, // Null device
111+
RDM_READ_LINE,
111112
};
112113

113114
#pragma pack(4)
@@ -191,6 +192,10 @@ struct rebol_devreq {
191192
u32 device_in; // requested device ID (1-based; 0 = none)
192193
u32 device_out;
193194
} midi;
195+
struct {
196+
u32 mode;
197+
u32 value;
198+
} modify;
194199
};
195200
};
196201
#pragma pack()

src/include/reb-event.h

+1
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ enum {
7373
EVM_GUI, // GUI event uses system/view/event/port
7474
EVM_CALLBACK, // Callback event uses system/ports/callback port
7575
EVM_MIDI, // event holds midi port pointer
76+
EVM_CONSOLE, // native console events
7677
};
7778

7879
// Special messages

src/include/reb-host.h

+2
Original file line numberDiff line numberDiff line change
@@ -41,3 +41,5 @@
4141

4242
#include "reb-gob.h"
4343
#include "reb-lib.h"
44+
45+
#include "tmp-portmodes.h"

src/include/sys-core.h

+1
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ typedef struct rebol_mold {
119119
#include "host-lib.h"
120120
#include "sys-stack.h"
121121
#include "sys-state.h"
122+
#include "tmp-portmodes.h"
122123

123124
/***********************************************************************
124125
**

src/mezz/mezz-files.r

+12-11
Original file line numberDiff line numberDiff line change
@@ -62,31 +62,32 @@ clean-path: func [
6262
reverse out
6363
]
6464

65-
input: function [
65+
input: func [
6666
{Inputs a string from the console.}
67-
; /hide "Mask input with a * character"
67+
/hide "Turns off echoing inputs"
68+
/local line port
6869
][
70+
port: system/ports/input
6971
if any [
70-
not port? system/ports/input
71-
not open? system/ports/input
72+
not port? port
73+
not open? port
7274
][
73-
system/ports/input: open [scheme: 'console]
75+
system/ports/input: port: open [scheme: 'console]
7476
]
75-
if line: read system/ports/input [ line: to string! line ]
77+
if hide [ modify port 'echo false ]
78+
if line: read port [ line: to string! line ]
79+
if hide [ modify port 'echo true ]
7680
line
7781
]
7882

7983
ask: func [
8084
"Ask the user for input."
8185
question [series!] "Prompt to user"
8286
/hide "Turns off echoing inputs"
87+
/char "Waits only on single key press and returns char as a result"
8388
][
8489
prin question
85-
either hide [
86-
prin "^[[8m" ; ANSI conceal command
87-
also input
88-
print "^[[28m" ; ANSI reveal command
89-
][ input ]
90+
also apply :input [hide] prin LF
9091
]
9192

9293
confirm: func [

src/mezz/sys-ports.r

+10-1
Original file line numberDiff line numberDiff line change
@@ -196,8 +196,12 @@ init-schemes: func [
196196
][
197197
remove event-list ;avoid event overflow caused by wake-up recursively calling into wait
198198
if wake-up port event [
199-
; Add port to wake list:
199+
;@@ `wake-up` function is natively calling UPDATE action on current port
200+
;@@ this is processed in port's actor function,
201+
;@@ for example in `Console_Actor` in p-console.c file
202+
;@@ If result of this action is truethy, port is waked up here
200203
;print ["==System-waked:" port/spec/ref]
204+
; Add port to wake list:
201205
unless find waked port [append waked port]
202206
]
203207
++ n-event
@@ -229,6 +233,11 @@ init-schemes: func [
229233
make-scheme [
230234
title: "Console Access"
231235
name: 'console
236+
;awake: func [event] [
237+
; print ["Console event:" event/type mold event/key event/offset]
238+
; ;probe event
239+
; false
240+
;]
232241
]
233242

234243
make-scheme [

src/os/host-main.c

+4-2
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ extern void Init_Ext_Test(void); // see: host-ext-test.c
9090
#endif
9191

9292
// Host bare-bones stdio functs:
93-
extern void Open_StdIO(void);
93+
extern REBREQ *Open_StdIO();
9494
extern void Close_StdIO(void);
9595
extern void Put_Str(REBYTE *buf);
9696
extern REBYTE *Get_Str(void);
@@ -268,10 +268,11 @@ int main(int argc, char **argv) {
268268
#endif
269269
REBYTE vers[8];
270270
REBINT n;
271+
REBREQ *std_io;
271272

272273
// Must be done before an console I/O can occur. Does not use reb-lib,
273274
// so this device should open even if there are other problems.
274-
Open_StdIO(); // also sets up interrupt handler
275+
std_io = Open_StdIO(); // also sets up interrupt handler
275276

276277
Host_Lib = &Host_Lib_Init;
277278

@@ -290,6 +291,7 @@ int main(int argc, char **argv) {
290291
if (!Host_Lib) Host_Crash("Missing host lib");
291292
// !!! Second part will become vers[2] < RL_REV on release!!!
292293
if (vers[1] != RL_VER || vers[2] != RL_REV) Host_Crash("Incompatible reb-lib DLL");
294+
Host_Lib->std_io = std_io;
293295
n = RL_Init(&Main_Args, Host_Lib);
294296
if (n == 1) Host_Crash("Host-lib wrong size");
295297
if (n == 2) Host_Crash("Host-lib wrong version/checksum");

src/os/host-stdio.c

+12-2
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,9 @@
4949
void Host_Crash(char *reason);
5050

5151
// Temporary globals: (either move or remove?!)
52-
REBREQ Std_IO_Req;
52+
// O: where it should be moved?
53+
// O: as the Std_IO_Req is shared with lib (DLL), I'm now storing it also in Host_Lib struct
54+
static REBREQ Std_IO_Req;
5355
static REBYTE *inbuf;
5456
static REBCNT inbuf_len = 32*1024;
5557

@@ -105,7 +107,7 @@ static int Fetch_Buf()
105107

106108
/***********************************************************************
107109
**
108-
*/ void Open_StdIO(void)
110+
*/ REBREQ *Open_StdIO()
109111
/*
110112
** Open REBOL's standard IO device. This same device is used
111113
** by both the host code and the R3 DLL itself.
@@ -125,6 +127,7 @@ static int Fetch_Buf()
125127

126128
inbuf = OS_Make(inbuf_len);
127129
inbuf[0] = 0;
130+
return &Std_IO_Req;
128131
}
129132

130133
/***********************************************************************
@@ -152,6 +155,13 @@ static int Fetch_Buf()
152155
{
153156
REBYTE *line;
154157

158+
// make sure that we are in LINE reading mode!
159+
if (!GET_FLAG(Std_IO_Req.modes, RDM_READ_LINE)) {
160+
// if not, set it back
161+
Std_IO_Req.modify.mode = RDM_READ_LINE;
162+
Std_IO_Req.modify.value = TRUE;
163+
OS_Do_Device(&Std_IO_Req, RDC_MODIFY);
164+
}
155165
if ((line = Get_Next_Line())) return line;
156166

157167
if (Fetch_Buf()) return Get_Next_Line();

src/os/posix/dev-stdio.c

+26-1
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,31 @@ static void Close_Stdio(void)
298298
return DR_DONE;
299299
}
300300

301+
/***********************************************************************
302+
**
303+
*/ DEVICE_CMD Modify_IO(REBREQ *req)
304+
/*
305+
** Change console's mode.
306+
**
307+
***********************************************************************/
308+
{
309+
long total;
310+
if (req->modify.mode == MODE_CONSOLE_ECHO) {
311+
if (Std_Out >= 0) {
312+
if(req->modify.value) {
313+
total = write(Std_Out, "\x1B[28m", 5);
314+
} else {
315+
total = write(Std_Out, "\x1B[8m", 4);
316+
}
317+
if (total < 0) {
318+
req->error = errno;
319+
return DR_ERROR;
320+
}
321+
}
322+
}
323+
return DR_DONE;
324+
}
325+
301326
/***********************************************************************
302327
**
303328
*/ DEVICE_CMD Open_Echo(REBREQ *req)
@@ -340,7 +365,7 @@ static DEVICE_CMD_FUNC Dev_Cmds[RDC_MAX] =
340365
0, // poll
341366
0, // connect
342367
Query_IO,
343-
0, // modify
368+
Modify_IO, // modify
344369
Open_Echo, // CREATE used for opening echo file
345370
};
346371

0 commit comments

Comments
 (0)