Is there a way to limit input in the console to a maximum of keys?
.386
.model flat,stdcall
option casemap:none
include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
includelib \masm32\lib\kernel32.lib
.data?
hconsoleinput dd ?
hconsoleoutput dd ?
charswritten dd ?
charsread dd ?
charsattset dd ?
.data
programname db "THE CONSOLE WAY!",0
welcome db "Hi, welcome to this program!",0ah,0dh
text db " "
.code
main proc
invoke GetStdHandle,STD_INPUT_HANDLE
mov hconsoleinput,eax
invoke GetStdHandle,STD_OUTPUT_HANDLE
mov hconsoleoutput,eax
invoke SetConsoleTitle,offset programname
call paintb
invoke SetConsoleTextAttribute,hconsoleoutput,\ ; Set the text and background
FOREGROUND_BLUE or FOREGROUND_GREEN or FOREGROUND_INTENSITY or\ ; colors.
BACKGROUND_GREEN
invoke WriteConsole,hconsoleoutput,offset welcome,sizeof welcome,\
offset charswritten,NULL
invoke ReadConsole,hconsoleinput,offset text,sizeof text,\
offset charsread,NULL
invoke ExitProcess,0
main endp
paintb proc ; Fill into green.
local cc:COORD
mov cc.x,0
mov cc.y,0
mov eax,cc
invoke FillConsoleOutputAttribute,hconsoleoutput,BACKGROUND_GREEN,\
30000,eax,offset charsattset
ret
paintb endp
end main
Here you can enter until 255 chars from the keyboard (including the enter key) But that's crap, how to limit this?
Quote from: felipe on June 10, 2017, 11:02:16 AM
Is there a way to limit input in the console to a maximum of keys?
...
Here you can enter until 255 chars from the keyboard (including the enter key) But that's crap, how to limit this?
This has been answered already:
Quote from: Brannagan on September 04, 2014, 06:43:08 PM
Does MASM32 include a Console string input function which can do the following:
1. Allows me to specify a maximum input length of the string
2. Handles input editing keys, such as arrow keys, backspace, and delete?
Thanks jj. I'm starting to think that if i want to play with a console program, it would better to "emulate" a console by creating a window and writing text there... :P
It is perhaps not totally impossible (GetNumberOfConsoleInputEvents+timer), but I am pessimistic. There are many thousands of absolutely useless functions in the Windows API, but the one function that could prevent buffer overflows doesn't exist. Strange, isn't it? :P
:biggrin:
Hi felipe,
The code below does not replace the traditional input functions and you will have to implement the functionality of the DEL key :
.386
.model flat,stdcall
option casemap:none
include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
include \masm32\include\msvcrt.inc
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\msvcrt.lib
.data
msg1 db 'You can type 10 characters. Hit RETURN to terminate the keyboard input',13,10,0
msg2 db '%c',0
msg3 db 13,10,'You typed : %s',13,10,0
.data?
buffer db 10 dup(?)
.code
start:
call main
invoke ExitProcess,0
main PROC uses esi ebx
invoke crt_printf,ADDR msg1
mov esi,OFFSET buffer
xor ebx,ebx
@@:
invoke crt__getch
cmp eax,13
je finish
push eax
invoke crt_printf,ADDR msg2,eax
pop eax
mov BYTE PTR [esi+ebx],al
inc ebx
cmp ebx,10
jne @b
finish:
invoke crt_printf,ADDR msg3,esi
ret
main ENDP
END start
Reference :
https://msdn.microsoft.com/en-us/library/078sfkak%28v=vs.100%29.aspx
Don't forget to check the StdIn function from masm32.lib
Thanks Vortex, i will check this. :t
Attached a test, let me know if that is what you wanted.
Seems to run OK on Win XP, 7-64 and the latest 10-64.
It's still a beta, and required some acrobatic workarounds ::)
This kind of question did come up several times in the past IIRC, e.g. here:
Win32 Console Addition (http://masm32.com/board/index.php?topic=1778.msg18375#msg18375)
Quote from: jj2007 on June 12, 2017, 09:27:28 AM
Attached a test, let me know if that is what you wanted.
Seems to run OK on Win XP, 7-64 and the latest 10-64.
It's still a beta, and required some acrobatic workarounds ::)
Actually yes.
But what kind of file is the no exe file? :shock:
Quote from: qWord on June 12, 2017, 10:10:08 AM
This kind of question did come up several times in the past IIRC, e.g. here:
Win32 Console Addition (http://masm32.com/board/index.php?topic=1778.msg18375#msg18375)
Thanks qword i will see it tomorrow. (Now i have to go to the bed.. :redface:).
:lol:
Quote from: felipe on June 12, 2017, 12:54:53 PM
But what kind of file is the no exe file? :shock:
In case you mean the *.asc file: the source. If you don't yet have RichMasm (http://masm32.com/board/index.php?topic=5314.0), you can open it in WordPad. Here is the main loop:
.Repeat
Print At(5, Locate(y)) " "
Let esi=Input$("Go ahead, edit that string: ", "123456789012345678", max20)
PrintLine " you typed [", esi, "]"
.Until Len(esi)<5
Well, seems like: "ReadConsole always wants a 256 buffer", (yes, dedndave is right :bgrin:), but maybe is not the end of the world (certainly :biggrin:). So in this program the way to control the input will be allocating a buffer size of 256 bytes for each input (if this size is less and the user writes more chars the program terminates ::)). Doing a clear screen and locating the cursor position will help it the control of the output. Now i have to control the input for just the CR key (probably using SetConsoleMode).
.386
.model flat,stdcall
option casemap:none
include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
includelib \masm32\lib\kernel32.lib
.data?
hconsoleinput dd ?
hconsoleoutput dd ?
charswritten dd ?
charsread dd ?
charsattset dd ?
.data
programname db "THE CONSOLE WAY!",0
welcome db "Hi, welcome to this program!",0ah,0dh
text db 256 dup(" "),0
promptname db "Enter your name: "
saveit db 0ah,0ah,"Exit program?(Y/N): "
usernbuff db 256 dup(" "),0
username db 256 dup(" "),0
inerror db "Error! names allowed of 20 chars max. only...",0
cursorp proto :word,:word
paintb proto :word,:word
.code
main proc
invoke GetStdHandle,STD_INPUT_HANDLE
mov hconsoleinput,eax
invoke GetStdHandle,STD_OUTPUT_HANDLE
mov hconsoleoutput,eax
invoke SetConsoleTitle,offset programname
again:
invoke cursorp,0,0 ; Locates the cursor.
invoke paintb,0,0 ; Clears the screen.
invoke SetConsoleTextAttribute,hconsoleoutput,\ ; Set the text and background
FOREGROUND_BLUE or FOREGROUND_GREEN or FOREGROUND_INTENSITY or\ ; colors for the console.
BACKGROUND_GREEN
invoke WriteConsole,hconsoleoutput,offset welcome,sizeof welcome,\ ; Welcome message in screen.
offset charswritten,NULL
invoke WriteConsole,hconsoleoutput,offset promptname,sizeof promptname,\ ; Prompt for the user's name.
offset charswritten,NULL
invoke ReadConsole,hconsoleinput,offset usernbuff,sizeof usernbuff,\
offset charsread,NULL
cmp charsread,23 ; More chars than allowed?:
jb all_ok ; -no, so continue in all_ok.
invoke cursorp,0,0 ; -yes, so:
invoke paintb,0,0 ; *locate cursor and clears the screen.
invoke WriteConsole,hconsoleoutput,offset inerror,sizeof inerror,\ ; *show error message.
offset charswritten,NULL
invoke ReadConsole,hconsoleinput,offset text,sizeof text,\ ;*****(*Waits for the CR key.)*****
offset charsread,NULL
jmp again
all_ok:
invoke WriteConsole,hconsoleoutput,offset saveit,sizeof saveit,\
offset charswritten,NULL
invoke ReadConsole,hconsoleinput,offset text,sizeof text,\
offset charsread,NULL
invoke ExitProcess,0
main endp
paintb proc colx:word,rowy:word ; Fill into green all the screen,
local cc:COORD ; (background and foreground).
mov ax,colx
mov cc.x,ax
mov ax,rowy
mov cc.y,ax
mov eax,cc
invoke FillConsoleOutputAttribute,hconsoleoutput,BACKGROUND_GREEN or\
FOREGROUND_GREEN,30000,eax,offset charsread
ret
paintb endp
cursorp proc col:word,row:word ; Sets the cursor location.
local cc:COORD
mov ax,col
mov cc.x,ax
mov ax,row
mov cc.y,ax
mov eax,cc
invoke SetConsoleCursorPosition,hconsoleoutput,eax
ret
cursorp endp
end main
Yeah, i added the SetConsoleMode function, first to allow just the CR key, and then for all the others (256 chars in the input buffer ::) :lol:). I guess this would be the most basic 'algo' for some text mode programs. Thanks for all your help! :t
.386
.model flat,stdcall
option casemap:none
include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
includelib \masm32\lib\kernel32.lib
.data?
hconsoleinput dd ?
hconsoleoutput dd ?
charswritten dd ?
charsread dd ?
charsattset dd ?
.data
programname db "THE CONSOLE WAY!",0
welcome db "Hi, welcome to this program!",0ah,0dh
text db 256 dup(" "),0
promptname db "Enter your name: "
saveit db 0ah,0ah,"Exit program?(Y/N): "
usernbuff db 256 dup(" "),0
username db 256 dup(" "),0
inerror db "Error! names allowed of 20 chars max. only...",0
cursorp proto :word,:word
paintb proto :word,:word
.code
main proc
invoke GetStdHandle,STD_INPUT_HANDLE
mov hconsoleinput,eax
invoke GetStdHandle,STD_OUTPUT_HANDLE
mov hconsoleoutput,eax
invoke SetConsoleTitle,offset programname
again:
invoke cursorp,0,0 ; Locates the cursor.
invoke paintb,0,0 ; Clears the screen.
invoke SetConsoleTextAttribute,hconsoleoutput,\ ; Set the text and background
FOREGROUND_BLUE or FOREGROUND_GREEN or FOREGROUND_INTENSITY or\ ; colors for the console.
BACKGROUND_GREEN
invoke WriteConsole,hconsoleoutput,offset welcome,sizeof welcome,\ ; Welcome message in screen.
offset charswritten,NULL
invoke WriteConsole,hconsoleoutput,offset promptname,sizeof promptname,\ ; Prompt for the user's name.
offset charswritten,NULL
invoke ReadConsole,hconsoleinput,offset usernbuff,sizeof usernbuff,\
offset charsread,NULL
cmp charsread,23 ; More chars than allowed?:
jb all_ok ; -no, so continue in all_ok.
invoke cursorp,0,0 ; -yes, so:
invoke paintb,0,0 ; *sets the cursor location and clears the screen.
invoke WriteConsole,hconsoleoutput,offset inerror,sizeof inerror,\ ; *show error message.
offset charswritten,NULL
invoke SetConsoleMode,hconsoleinput,ENABLE_LINE_INPUT
invoke ReadConsole,hconsoleinput,offset text,sizeof text,\ ; *Waits for the CR key.
offset charsread,NULL
invoke SetConsoleMode,hconsoleinput,ENABLE_ECHO_INPUT or\ ; Allow inputs again (256 chars).
ENABLE_LINE_INPUT
jmp again
all_ok:
invoke WriteConsole,hconsoleoutput,offset saveit,sizeof saveit,\
offset charswritten,NULL
invoke ReadConsole,hconsoleinput,offset text,sizeof text,\
offset charsread,NULL
invoke ExitProcess,0
main endp
paintb proc colx:word,rowy:word ; Fill into green all the screen,
local cc:COORD ; (background and foreground).
mov ax,colx
mov cc.x,ax
mov ax,rowy
mov cc.y,ax
mov eax,cc
invoke FillConsoleOutputAttribute,hconsoleoutput,BACKGROUND_GREEN or\
FOREGROUND_GREEN,30000,eax,offset charsread
ret
paintb endp
cursorp proc col:word,row:word ; Sets the cursor location.
local cc:COORD
mov ax,col
mov cc.x,ax
mov ax,row
mov cc.y,ax
mov eax,cc
invoke SetConsoleCursorPosition,hconsoleoutput,eax
ret
cursorp endp
end main
Here one little more addition to this and a fix of some usless buffer: Now checks if you didn't enter any char (only CR key), only accept 2 chars as minimum for the name and a maximum of 20. The username buffer was useless (i think i forget it there... :lol:) so i deleted.
.386
.model flat,stdcall
option casemap:none
include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
includelib \masm32\lib\kernel32.lib
.data?
hconsoleinput dd ?
hconsoleoutput dd ?
charswritten dd ?
charsread dd ?
charsattset dd ?
.data
programname db "THE CONSOLE WAY!",0
welcome db "Hi, welcome to this program!",0ah,0dh
text db 256 dup(" "),0
promptname db "Enter your name: "
saveit db 0ah,0ah,"Exit program?(Y/N): "
usernbuff db 256 dup(" "),0
inerror db "Error! names allowed of 20 chars as maximun only...",0
inerror2 db "Error! you must put a name here of 2 chars as minimum...",0
cursorp proto :word,:word
paintb proto :word,:word
.code
main proc
invoke GetStdHandle,STD_INPUT_HANDLE
mov hconsoleinput,eax
invoke GetStdHandle,STD_OUTPUT_HANDLE
mov hconsoleoutput,eax
invoke SetConsoleTitle,offset programname
again:
invoke cursorp,0,0 ; Locates the cursor.
invoke paintb,0,0 ; Clears the screen.
invoke SetConsoleTextAttribute,hconsoleoutput,\ ; Set the text and background
FOREGROUND_BLUE or FOREGROUND_GREEN or FOREGROUND_INTENSITY or\ ; colors for the console.
BACKGROUND_GREEN
invoke WriteConsole,hconsoleoutput,offset welcome,sizeof welcome,\ ; Welcome message in screen.
offset charswritten,NULL
invoke WriteConsole,hconsoleoutput,offset promptname,sizeof promptname,\ ; Prompt for the user's name.
offset charswritten,NULL
invoke ReadConsole,hconsoleinput,offset usernbuff,sizeof usernbuff,\
offset charsread,NULL
cmp charsread,23 ; More chars than allowed?:
jb all_ok ; -no, so continue in all_ok.
invoke cursorp,0,0 ; -yes, so:
invoke paintb,0,0 ; *clears the screen.
invoke WriteConsole,hconsoleoutput,offset inerror,sizeof inerror,\ ; *show error message.
offset charswritten,NULL
invoke SetConsoleMode,hconsoleinput,ENABLE_LINE_INPUT
invoke ReadConsole,hconsoleinput,offset text,sizeof text,\ ; *Waits for the CR key.
offset charsread,NULL
invoke SetConsoleMode,hconsoleinput,ENABLE_ECHO_INPUT or\ ; Allows inputs again (256 chars).
ENABLE_LINE_INPUT
jmp again
all_ok:
cmp charsread,2
ja all_ok2 ; No input at all (just CR)?
invoke cursorp,0,0 ; if so, set cursor location (0,0)
invoke paintb,0,0 ; clears the screen
invoke WriteConsole,hconsoleoutput,offset inerror2,sizeof inerror2,\ ; show error message.
offset charswritten,NULL
invoke SetConsoleMode,hconsoleinput,ENABLE_LINE_INPUT ; Just CR accepted.
invoke ReadConsole,hconsoleinput,offset text,sizeof text,\
offset charsread,NULL
invoke SetConsoleMode,hconsoleinput,ENABLE_ECHO_INPUT or\ ; All keys accepted from now
ENABLE_LINE_INPUT ; again.
jmp again
all_ok2: ; Correct name format until here.
invoke WriteConsole,hconsoleoutput,offset saveit,sizeof saveit,\
offset charswritten,NULL
invoke ReadConsole,hconsoleinput,offset text,sizeof text,\
offset charsread,NULL
invoke ExitProcess,0
main endp
paintb proc colx:word,rowy:word ; Fill into green all the screen,
local cc:COORD ; (background and foreground).
mov ax,colx
mov cc.x,ax
mov ax,rowy
mov cc.y,ax
mov eax,cc
invoke FillConsoleOutputAttribute,hconsoleoutput,BACKGROUND_GREEN or\
FOREGROUND_GREEN,30000,eax,offset charsread
ret
paintb endp
cursorp proc col:word,row:word ; Sets the cursor location.
local cc:COORD
mov ax,col
mov cc.x,ax
mov ax,row
mov cc.y,ax
mov eax,cc
invoke SetConsoleCursorPosition,hconsoleoutput,eax
ret
cursorp endp
end main
"Exit program?(Y/N): " does not really do what the user expects ;-)
Quote from: jj2007 on June 13, 2017, 07:40:19 AM
"Exit program?(Y/N): " does not really do what the user expects ;-)
Yes,yes, that's right, is just the end of the program, just a mark to distinguish the others parts: the loop back to the beginning, because of the input error, from the correct way. :bgrin:
Thanks for trying it jj! :t
Btw: Also it should say maximum not maximun, right? :bgrin:
Right ;)
In the meantime, I have added the option to limit the input to n characters to the Input$() (http://www.webalice.it/jj2006/MasmBasicQuickReference.htm#Mb1041) macro, see here (http://masm32.com/board/index.php?topic=94.msg67665#msg67665). Thanks for inspiring me, this is a useful feature :t
Thanks jj! :t