Reading characters from STDIN

Q&A's, tips, howto's
Locked
pjot
Posts: 733
Joined: Thu Feb 26, 2004 10:19 pm
Location: The Hague, The Netherlands
Contact:

Reading characters from STDIN

Post by pjot »

Hi,

In my current program I try to read a character from the input prompt:

Code: Select all

(set 'tmp (read-char 0))
This works, however, I need to press the <enter>-key in order to continue the program. So, if I send a message to the console like "Do you want to continue (Y/N)", and the user presses "Y", he also have to press <enter> after that to continue.

Actually I want *just* to press "Y" after which program continues. How can I do that in newLisp?

Peter

Lutz
Posts: 5289
Joined: Thu Sep 26, 2002 4:45 pm
Location: Pasadena, California
Contact:

Post by Lutz »

Norman has an example on his site how to use the ncurses library to do this:

http://www.nodep.nl/downloads/newlisp/ncurses.lsp

On Win32 MinGW has a getch(), which you could import somehow.

Whe you are done writing the newMACS editor, let us know :)

Lutz

Lutz
Posts: 5289
Joined: Thu Sep 26, 2002 4:45 pm
Location: Pasadena, California
Contact:

Post by Lutz »

here is a solution for making a library with MinGW on Win32.
The 'C' file:

Code: Select all

/* getchar.c - library getchar.dll to get character from keyboard */

#include <stdio.h>
#include <conio.h>

int GetChar(void)
{
return(getch());
}
The 'getchar.def' file:

Code: Select all

LIBRARY    getchar.dll 

EXPORTS
    GetChar         @1 GetChar
The 'Makefile':

Code: Select all

# makefile for getchar.dll for MinGW compiler
#

OBJS = getchar.o

CFLAGS = -Wall -pedantic -c -O3 -DMINGW 

CC = c:/MinGW/bin/gcc
STRIP = c:/MinGW/bin/strip
WRAP = c:/MinGW/bin/dllwrap

VERSION = 0.0.2

default: $(OBJS)
	$(WRAP) *.o --enable-stdcall-fixup --def getchar.def -o getchar.dll -lws2_32
	$(STRIP) getchar.dll

.c.o:
	$(CC) $(CFLAGS) $<

$(OBJS): getchar.c getchar.def Makefile
The just do:

(import "getchar.dll" "GetChar")

(GetChar)

Lutz

pjot
Posts: 733
Joined: Thu Feb 26, 2004 10:19 pm
Location: The Hague, The Netherlands
Contact:

Post by pjot »

Hmm... I thought of that (e.g. importing a C-function), but it is not possible within newLisp itself?

(Actually, I am not creating an editor but I was trying to create the smallest interpreter on earth using newLisp... really!)

Lutz
Posts: 5289
Joined: Thu Sep 26, 2002 4:45 pm
Location: Pasadena, California
Contact:

Post by Lutz »

I have not found a way to do this on Linux/UNIX using standard 'libc' calls (not curses !). If someone can show me how, I will put a keyboard function in the next release.

Lutz

pjot
Posts: 733
Joined: Thu Feb 26, 2004 10:19 pm
Location: The Hague, The Netherlands
Contact:

Post by pjot »

Isn't "int getchar(void)" part of the STDIO library? I can't remember; I will look into it tonight.

pjot
Posts: 733
Joined: Thu Feb 26, 2004 10:19 pm
Location: The Hague, The Netherlands
Contact:

Post by pjot »

Looking into my old personal sources I found this:

Code: Select all

int kb_hit(void)
{
#ifdef WIN32
char c;
while(!kbhit()){};     //wait for user to press a key
return(int)getch();
#else	       // Should work for most Unices
struct termios term, oterm;
int fd = 0;
int c = 0;

/* get the terminal settings */
tcgetattr(fd, &oterm);

/* get a copy of the settings, which we modify */
memcpy(&term, &oterm, sizeof(term));

/* put the terminal in non-canonical mode, any 
reads timeout after 0.1 seconds or when a 
single character is read */
term.c_lflag = term.c_lflag & (!ICANON);
term.c_cc[VMIN] = 0;
term.c_cc[VTIME] = 1;
tcsetattr(fd, TCSANOW, &term);

/* get input - timeout after 0.1 seconds or 
when one character is read. If timed out
getchar() returns -1, otherwise it returns
the character */
c=getchar();

/* reset the terminal to original state */
tcsetattr(fd, TCSANOW, &oterm);

/* return character */
return c;
#endif
}
This code I ripped from a webpage which does not exist anymore... I have adjusted it a little bit to fit my needs at the time, but I think it is suitable for a generic GETCHAR, also on most unices. I have tested it only with Linux.

Lutz
Posts: 5289
Joined: Thu Sep 26, 2002 4:45 pm
Location: Pasadena, California
Contact:

Post by Lutz »

>>> Isn't "int getchar(void)" part of the STDIO library?

Yes it is, but it sits in the functions until you hit <enter>, just like (read-char 0) does. 'C' getchar() is really a macro around the 'C' read(int handle ...) function newLISP is using.

Lutz

Lutz
Posts: 5289
Joined: Thu Sep 26, 2002 4:45 pm
Location: Pasadena, California
Contact:

Post by Lutz »

Thanks for 'C' code, I will experiment with this.

Lutz

pjot
Posts: 733
Joined: Thu Feb 26, 2004 10:19 pm
Location: The Hague, The Netherlands
Contact:

Post by pjot »

One addition: I see I have included <termios.h> to get this code working... I hope Solaris has this header file.

Lutz
Posts: 5289
Joined: Thu Sep 26, 2002 4:45 pm
Location: Pasadena, California
Contact:

Post by Lutz »

Have it working on Linux/Solaris/MinGW/CYGWIN/Win32-Borland, but cannot get it to work on BSD. Anybody out there who can help with BSD (I tried on freeBSD 4.7) ???

This is what I have so far on UNIX:

Code: Select all

struct termios term, oterm;
int c = 0;

tcgetattr(0, &oterm);

memcpy(&term, &oterm, sizeof(term));

/* put the terminal in non-canonical mode, any
reads timeout after 0.1 seconds or when a
single character is read */
term.c_lflag &= ~(ICANON | ECHO);
term.c_cc[VMIN] = 0;
term.c_cc[VTIME] = 1;
tcsetattr(0, TCSANOW, &term);

while((c=getchar()) == -1);

/* reset the terminal to original state */
tcsetattr(0, TCSANOW, &oterm);
Lutz

pjot
Posts: 733
Joined: Thu Feb 26, 2004 10:19 pm
Location: The Hague, The Netherlands
Contact:

Post by pjot »

I just tested the code on OpenBSD 3.4 and it seems to work fine. Unfortunately I can not have a FreeBSD machine available...

Locked