View mode: basic / threaded / horizontal-split · Log in · Help
March 21, 2011
Re: Get single keystroke?
On 3/21/11, Sean Eskapp <eatingstaples@gmail.com> wrote:
> What about on Linux?
>

I'm not sure. Both DMD and GDC can run the example on Windows. Perhaps
they've got these functions implemented for Linux as well. But
according to this:
https://secure.wikimedia.org/wikipedia/en/wiki/Conio.h

it seems these functions are usually only available for compilers
targeting Windows. Have you tried compiling it on Linux, or does it
fail to link?
March 21, 2011
Re: Get single keystroke?
It looks like its not available on Linux, I've just tried with DMD.
March 21, 2011
Re: Get single keystroke?
I believe I've found you a solution:

import std.c.stdio;
import std.c.linux.termios;

extern(C) void cfmakeraw(termios *termios_p);

void main() {
termios  ostate;                 /* saved tty state */
termios  nstate;                 /* values for editor mode */

   // Open stdin in raw mode
   /* Adjust output channel        */
tcgetattr(1, &ostate);                       /* save old state */
tcgetattr(1, &nstate);                       /* get base of new state */
cfmakeraw(&nstate);
tcsetattr(1, TCSADRAIN, &nstate);      /* set mode */

  // Read characters in raw mode
writefln("The key hit is %s", cast(char)fgetc(stdin));

   // Close
tcsetattr(1, TCSADRAIN, &ostate);       // return to original mode
}

I've tested this under Ubuntu and DMD 2.052 and it works.
March 21, 2011
Re: Get single keystroke?
Woops forgot to add import std.stdio, here's a fixed version:

import std.stdio : writefln;
import std.c.stdio;
import std.c.linux.termios;

extern(C) void cfmakeraw(termios *termios_p);

void main()
{
   termios  ostate;                 /* saved tty state */
   termios  nstate;                 /* values for editor mode */

      // Open stdin in raw mode
      /* Adjust output channel        */
   tcgetattr(1, &ostate);                       /* save old state */
   tcgetattr(1, &nstate);                       /* get base of new state */
   cfmakeraw(&nstate);
   tcsetattr(1, TCSADRAIN, &nstate);      /* set mode */

     // Read characters in raw mode
   writefln("The key hit is %s", cast(char)fgetc(stdin));

      // Close
   tcsetattr(1, TCSADRAIN, &ostate);       // return to original mode
}
March 21, 2011
Re: Get single keystroke?
== Quote from Andrej Mitrovic (andrej.mitrovich@gmail.com)'s article
> I believe I've found you a solution:
> import std.c.stdio;
> import std.c.linux.termios;
> extern(C) void cfmakeraw(termios *termios_p);
> void main() {
> termios  ostate;                 /* saved tty state */
> termios  nstate;                 /* values for editor mode */
>     // Open stdin in raw mode
>     /* Adjust output channel        */
> tcgetattr(1, &ostate);                       /* save old state */
> tcgetattr(1, &nstate);                       /* get base of new
state */
> cfmakeraw(&nstate);
> tcsetattr(1, TCSADRAIN, &nstate);      /* set mode */
>    // Read characters in raw mode
> writefln("The key hit is %s", cast(char)fgetc(stdin));
>     // Close
> tcsetattr(1, TCSADRAIN, &ostate);       // return to original mode
> }
> I've tested this under Ubuntu and DMD 2.052 and it works.

Great, thanks!
March 21, 2011
Re: Get single keystroke?
On Mon, 21 Mar 2011 23:22:17 +0100, Andrej Mitrovic wrote:

> Woops forgot to add import std.stdio, here's a fixed version:
> 
> import std.stdio : writefln;
> import std.c.stdio;
> import std.c.linux.termios;
> 
> extern(C) void cfmakeraw(termios *termios_p);
> 
> void main()
> {
>     termios  ostate;                 /* saved tty state */ termios 
>     nstate;                 /* values for editor mode */
> 
>        // Open stdin in raw mode
>        /* Adjust output channel        */
>     tcgetattr(1, &ostate);                       /* save old state */
>     tcgetattr(1, &nstate);                       /* get base of new
>     state */ cfmakeraw(&nstate);
>     tcsetattr(1, TCSADRAIN, &nstate);      /* set mode */
> 
>       // Read characters in raw mode
>     writefln("The key hit is %s", cast(char)fgetc(stdin));
> 
>        // Close
>     tcsetattr(1, TCSADRAIN, &ostate);       // return to original mode
> }

It looks like this can be dangerous, because the terminal can be left in 
an unusable state. Please read this:
http://groups.google.com/group/comp.os.linux.development.apps/
browse_thread/thread/0667d16089e2b6fc
March 21, 2011
Re: Get single keystroke?
On 3/21/11, teo <teo.ubuntu@yahoo.com> wrote:
> On Mon, 21 Mar 2011 23:22:17 +0100, Andrej Mitrovic wrote:
>
>> Woops forgot to add import std.stdio, here's a fixed version:
>>
>> import std.stdio : writefln;
>> import std.c.stdio;
>> import std.c.linux.termios;
>>
>> extern(C) void cfmakeraw(termios *termios_p);
>>
>> void main()
>> {
>>     termios  ostate;                 /* saved tty state */ termios
>>     nstate;                 /* values for editor mode */
>>
>>        // Open stdin in raw mode
>>        /* Adjust output channel        */
>>     tcgetattr(1, &ostate);                       /* save old state */
>>     tcgetattr(1, &nstate);                       /* get base of new
>>     state */ cfmakeraw(&nstate);
>>     tcsetattr(1, TCSADRAIN, &nstate);      /* set mode */
>>
>>       // Read characters in raw mode
>>     writefln("The key hit is %s", cast(char)fgetc(stdin));
>>
>>        // Close
>>     tcsetattr(1, TCSADRAIN, &ostate);       // return to original mode
>> }
>
> It looks like this can be dangerous, because the terminal can be left in
> an unusable state. Please read this:
> http://groups.google.com/group/comp.os.linux.development.apps/
> browse_thread/thread/0667d16089e2b6fc
>

H mentions using tcgetattr to save old state and restoring it with
tcsetattr. This is what this code does. Btw this code is not mine,
Walter posted it and I just added the cfmakeraw prototype. So kudos
goes to him.
March 22, 2011
Re: Get single keystroke?
On 03/21/2011 03:37 PM, Andrej Mitrovic wrote:
> On 3/21/11, teo<teo.ubuntu@yahoo.com>  wrote:
>> On Mon, 21 Mar 2011 23:22:17 +0100, Andrej Mitrovic wrote:
>>
>>> Woops forgot to add import std.stdio, here's a fixed version:
>>>
>>> import std.stdio : writefln;
>>> import std.c.stdio;
>>> import std.c.linux.termios;
>>>
>>> extern(C) void cfmakeraw(termios *termios_p);
>>>
>>> void main()
>>> {
>>>      termios  ostate;                 /* saved tty state */ termios
>>>      nstate;                 /* values for editor mode */
>>>
>>>         // Open stdin in raw mode
>>>         /* Adjust output channel        */
>>>      tcgetattr(1,&ostate);                       /* save old state */
>>>      tcgetattr(1,&nstate);                       /* get base of new
>>>      state */ cfmakeraw(&nstate);
>>>      tcsetattr(1, TCSADRAIN,&nstate);      /* set mode */
>>>
>>>        // Read characters in raw mode
>>>      writefln("The key hit is %s", cast(char)fgetc(stdin));
>>>
>>>         // Close
>>>      tcsetattr(1, TCSADRAIN,&ostate);       // return to original mode
>>> }
>>
>> It looks like this can be dangerous, because the terminal can be left in
>> an unusable state. Please read this:
>> http://groups.google.com/group/comp.os.linux.development.apps/
>> browse_thread/thread/0667d16089e2b6fc
>>
>
> H mentions using tcgetattr to save old state and restoring it with
> tcsetattr. This is what this code does. Btw this code is not mine,
> Walter posted it and I just added the cfmakeraw prototype. So kudos
> goes to him.

Thanks for posting this.

It can be improved by moving the last tcsetattr to an earlier 
scope(exit) statement:

    termios  ostate;
    tcgetattr(1, &ostate);
    scope (exit) tcsetattr(1, TCSADRAIN, &ostate);

Ali
Next ›   Last »
1 2
Top | Discussion index | About this forum | D home