curses 사용 중에 질문..

moonzoo의 이미지

curses를 사용해서 화면을 구성중입니다.

화살표 키 등을 처리하기 위해서

KEYPAD를 TRUE에 설정하고 wgetch 등을 이용해서

key입력을 받고 있는데..

다른 키들을 DELAY없이 바로바로 처리가 되는데

ESC키를 받을때는 약간(0.5총 정도.)의 DELAY가 발생하네요..

이 DELAY를 어떻게 없애야 할까요?

참고로
KEYPAD를 FALSE로 놓고 하면 DELAY는 발생하지 않습니다..
근데 화살표 등을 처리하기 위해 TRUE로 처리해야 될 상황..
cbreak , nodelay 등도 써봤는데 효과 없었습니다...

elfs의 이미지

'keypad mode'를 사용하면 세가지의 제한사항을 감수해야 한다.
...략..

첫번째.이스케이스 시퀀스를 인식하는것은 타이밍에 의존하게 되며,많은 네트워크 문자들은(기능키 시퀀스를 escape와 개별적인 문자로 인식하도록)분리한다.

두번째. curses 는 키보드에서 Escape 로 시작하는 시퀀스와 ...략..
Escape 키를 처리하는데 조금의 지연이 있음을 알 수 있을 것이다..

에이..배끼기 힘들다..

wrox press 한글 번역판 리눅스 프로그래밍(빨간책)
235 페이지에 있는 내용입니다.:-)

이 책에서 저자는 취소의 개념으로 curses 에서 ESC 키를 쓰는것 그다지 바람직 하지 않다고 말하고 있습니다.

이유는 해당 Escape 가 그냥 하나의 escape 인지(?) 아니면 여러 이스케이프시퀀스의 시작부분인지 알아내기 위해서 조금의 시간을 필요로 한다고 하네요.

그러고 보니 대부분의 curses 로 작성된 프로그램에서 esc 키를 쓰는건 별로 본적이 없네요.. vi 를 빼고는..도움이 안되지요..--a..

익명 사용자의 이미지

Curses 를 사용치 않고 하는 저레벨 키보드 제어 소스 만든적이 있어서
해당 부분만 소스 공개합니다.
그냥 이런 방법도 있다고 알려드리고 싶네요.
완전히 하나의 소스로 독립적이지 못하게 올리는거는 시간관계상 죄송하네요.

중요한것은 이러한 방식을 사용하게 되면
해당 PC의 물리적 키보드에 대해서는 전부 받을수도 있도록
코딩될수 있으며
반대로 그 의미를 해석하면 다른 유저의 키보드를
퍼미션이 허용한다면 가로챌수 있게 됩니다.
그리고 키보드 누름 및 떼는 동작을 2가지로 분류해서
코드를 받을수 있으며 동시 입력키도 다중으로 처리 가능하도록
코딩될수 있습니다.
이러한 방식은 정확한 Keyboard처리의 이해가 필요해서
사실 추천하지는 않지만 훨씬 많은것을 할수 있죠.
또한 Ctrl + Alt + Del 키도 먹통이 되게 할수 있는 응용도 있습니다.

중요한것은 Device 를 정확히 시스템에 따라서 선택해야 하는데
좀 어려운 일중에 하나고요.

if(s_Keyboard->Mode != (-1))ioctl(s_Keyboard->Handle, KDSKBMODE, s_Keyboard->Mode, sizeof(s_Keyboard->Mode)); 

이부분에 의해서 저레벨의 키보드를 얻을수 있는지 아니면 자신이
Terminal 상에 입력이 발생하는지.. 알수 있는 트릭도 있고요....

암튼 도저히 ESC에 대해 사용해야 하는되지만
해결책에 대한 설명이 리플되지 않는다면
고려해보세요.

ncurses사용을 해본적이 없고 맨날 이방식을 사용한지라
저는 답변을 못드리겠네요.

/*
 Copyright (c) Information Equipment co.,LTD.
 Code by JaeHyuk Cho <mailto:minzkn@infoeq.co.kr>
*/

#if !defined(DEF_SOURCE_keyboard_c)
#define DEF_SOURCE_keyboard_c "keyboard.c"

#if !defined(DEF_DEBUG)
#define DEF_DEBUG (0)
#endif

#if DEF_DEBUG == (1)
#include <stdio.h>
#endif
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/kd.h> /* Need kernel header (/usr/include/linux/kd.h) */
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>

#include "mztools.h"

#define __DEF_KEYBOARD_DEFAULT_DEVICE_NAME__ "/dev/tty"
#define __DEF_KEYBOARD_DEFAULT_BUFFER_SIZE__ (1 << 10)

DEF_COMPLETE_TYPE_KEYBOARD *MT_CloseKeyboard(DEF_COMPLETE_TYPE_KEYBOARD *s_Keyboard)
{
 if(s_Keyboard)
 {
  if(s_Keyboard->PrevTermios)
  {
   if(s_Keyboard->Handle >= 0)
   {	   
    if(tcsetattr(s_Keyboard->Handle, TCSANOW, (struct termios *)s_Keyboard->PrevTermios) != 0)
    {
#if DEF_DEBUG == (1)
     fprintf(stderr, "%s: %s - [ERROR] Can not tcsetattr (Restore) !!!\n", DEF_SOURCE_keyboard_c, __FUNCTION__); 
#endif 
    }
    if(s_Keyboard->Mode != (-1))ioctl(s_Keyboard->Handle, KDSKBMODE, s_Keyboard->Mode, sizeof(s_Keyboard->Mode)); 
   }
   MT_Free(s_Keyboard->PrevTermios); 
  }
  if(s_Keyboard->NewTermios)MT_Free(s_Keyboard->NewTermios); 
  if(s_Keyboard->Que)(void)MT_CloseBuffer(s_Keyboard->Que);  
  if(s_Keyboard->DeviceName)MT_Free(s_Keyboard->DeviceName);
  if(s_Keyboard->Handle >= 0)close(s_Keyboard->Handle);	 
  MT_Free(s_Keyboard);	 
  s_Keyboard = (DEF_COMPLETE_TYPE_KEYBOARD *)0; 
 }
#if DEF_DEBUG == (1)
 else fprintf(stderr, "%s: %s - [ERROR] s_Keyboard is null !!!\n", DEF_SOURCE_keyboard_c, __FUNCTION__); 
#endif 
 return(s_Keyboard);
}

DEF_COMPLETE_TYPE_KEYBOARD *MT_OpenKeyboard(const char *s_DeviceName)
{
 DEF_COMPLETE_TYPE_KEYBOARD *s_Return;
 int s_KeyboardMode = K_RAW, s_Check;
 s_Return = (DEF_COMPLETE_TYPE_KEYBOARD *)MT_Alloc(sizeof(DEF_COMPLETE_TYPE_KEYBOARD));
 if(s_Return)
 {
  MT_ZeroMemory((void *)s_Return, sizeof(DEF_COMPLETE_TYPE_KEYBOARD));
  s_Return->Mode = (-1);
  s_Return->DeviceName = MT_AllocString(s_DeviceName ? s_DeviceName : __DEF_KEYBOARD_DEFAULT_DEVICE_NAME__, 0);
  if(s_Return->DeviceName)
  {
   s_Return->Handle = open(s_Return->DeviceName, O_RDONLY | O_NDELAY, 0);
   if(s_Return->Handle >= 0)
   {
    s_Return->PrevTermios = (void *)MT_Alloc(sizeof(struct termios));
    s_Return->NewTermios  = (void *)MT_Alloc(sizeof(struct termios));
    if(s_Return->PrevTermios && s_Return->NewTermios)
    {
     if(tcgetattr(s_Return->Handle, (struct termios *)s_Return->PrevTermios) == 0)
     {
      s_Check = ioctl(s_Return->Handle, KDGKBMODE, &s_Return->Mode, sizeof(s_KeyboardMode)); 
      if(s_Check == 0)s_Check = ioctl(s_Return->Handle, KDSKBMODE, s_KeyboardMode, sizeof(s_KeyboardMode)); 
      else 
      {
       s_Check = 0;
       s_Return->Mode = (-1);
      }
      if(s_Check == 0)
      {
       MT_CopyMemory(s_Return->NewTermios, s_Return->PrevTermios, sizeof(struct termios));
       ((struct termios *)s_Return->NewTermios)->c_iflag = (IGNPAR | IGNBRK) & (~PARMRK) & (~ISTRIP);
       ((struct termios *)s_Return->NewTermios)->c_oflag = 0;
       ((struct termios *)s_Return->NewTermios)->c_cflag = CREAD | CS8;
       ((struct termios *)s_Return->NewTermios)->c_lflag = 0;
       ((struct termios *)s_Return->NewTermios)->c_cc[VTIME] = 0;
       ((struct termios *)s_Return->NewTermios)->c_cc[VMIN] = 1;
       if(cfsetispeed((struct termios *)s_Return->NewTermios, B9600) == 0)
       {
        if(cfsetospeed((struct termios *)s_Return->NewTermios, B9600) == 0)
	{
         if(tcsetattr(s_Return->Handle, TCSANOW, (struct termios *)s_Return->NewTermios) == 0)
	 { 
#if DEF_DEBUG == (1)
          fprintf(stdout, "%s: %s - [MESSAGE] Keyboard open \"%s\".\r\n", DEF_SOURCE_keyboard_c, __FUNCTION__, s_Return->DeviceName);
#endif 
          return(s_Return); /* Success open. */
	 }
#if DEF_DEBUG == (1)
         else fprintf(stderr, "%s: %s - [ERROR] Can not tcsetattr !!!\n", DEF_SOURCE_keyboard_c, __FUNCTION__);
#endif 
	}
#if DEF_DEBUG == (1)
        else fprintf(stderr, "%s: %s - [ERROR] Can not cfsetospeed (B9600) !!!\n", DEF_SOURCE_keyboard_c, __FUNCTION__);
#endif 
       }
#if DEF_DEBUG == (1)
       else fprintf(stderr, "%s: %s - [ERROR] Can not cfsetispeed (B9600) !!!\n", DEF_SOURCE_keyboard_c, __FUNCTION__);
#endif 
      }
#if DEF_DEBUG == (1)
      else fprintf(stderr, "%s: %s - [ERROR] Can not ioctl (K_RAW) s_Check = %d !!!\n", DEF_SOURCE_keyboard_c, __FUNCTION__, s_Check);
#endif 
     }
#if DEF_DEBUG == (1)
     else fprintf(stderr, "%s: %s - [ERROR] Can not tcgetattr !!!\n", DEF_SOURCE_keyboard_c, __FUNCTION__);
#endif 
    }
#if DEF_DEBUG == (1)
    else fprintf(stderr, "%s: %s - [ERROR] s_Return->[Prev|New]Termios is null !!!\n", DEF_SOURCE_keyboard_c, __FUNCTION__);
#endif 
   }
#if DEF_DEBUG == (1)
   else fprintf(stderr, "%s: %s - [ERROR] s_Return->Handle < 0 !!!\n", DEF_SOURCE_keyboard_c, __FUNCTION__);
#endif 
  }
#if DEF_DEBUG == (1)
  else fprintf(stderr, "%s: %s - [ERROR] s_DeviceName is null !!!\n", DEF_SOURCE_keyboard_c, __FUNCTION__);
#endif 
  s_Return = MT_CloseKeyboard(s_Return); 
 }
#if DEF_DEBUG == (1)
 else fprintf(stderr, "%s: %s - [ERROR] s_Return is null !!!\n", DEF_SOURCE_keyboard_c, __FUNCTION__); 
#endif 
 return(s_Return);
}

int MT_DoKeyboard(DEF_COMPLETE_TYPE_KEYBOARD *s_Keyboard)
{
 unsigned char s_KeyboardBuffer[ 0x80 ];
 int s_Return = (-1), s_Index, s_ReadBytes; 
 if(s_Keyboard)
 {
  if(s_Keyboard->Handle >= 0)
  {
   s_ReadBytes = read(s_Keyboard->Handle, (void *)(&s_KeyboardBuffer[0]), sizeof(s_KeyboardBuffer));
   s_Index = 0;
   while(s_Index < s_ReadBytes)
   {
    if(s_KeyboardBuffer[s_Index] == 0x00)
    { /* Paste code */

    }	    
    else if(s_KeyboardBuffer[s_Index] == 0xe0)
    { /* Extended key */

    }
    else
    {
     if(s_Keyboard->Que)
     {
      s_Return = MT_CheckBuffer(s_Keyboard->Que);
      if(s_Return >= __DEF_KEYBOARD_DEFAULT_BUFFER_SIZE__)
      { /* Keyboard buffer full !!! */
#if DEF_DEBUG == (1)
       fprintf(stderr, "%s: %s - [ERROR] Keyboard buffer full (%d bytes) !!!\n", DEF_SOURCE_keyboard_c, __FUNCTION__, __DEF_KEYBOARD_DEFAULT_BUFFER_SIZE__);
#endif 
       break; 
      }
     }
     else s_Return = 0;
     s_Keyboard->Que = MT_PushBuffer(s_Keyboard->Que, (void *)(&s_KeyboardBuffer[s_Index]), sizeof(unsigned char));  
     s_Return++;
    }
    s_Index++;
   }
  }
#if DEF_DEBUG == (1)
  else fprintf(stderr, "%s: %s - [ERROR] s_Keyboard->Handle < 0 !!!\n", DEF_SOURCE_keyboard_c, __FUNCTION__); 
#endif 
 } 
#if DEF_DEBUG == (1)
 else fprintf(stderr, "%s: %s - [ERROR] s_Keyboard is null !!!\n", DEF_SOURCE_keyboard_c, __FUNCTION__); 
#endif 
 return(s_Return);
}

int MT_ReadKeyboard(DEF_COMPLETE_TYPE_KEYBOARD *s_Keyboard)
{
 int s_Return;
 if(s_Keyboard)
 {
  if(s_Keyboard->Que)
  {
   if(MT_CheckBuffer(s_Keyboard->Que) > 0)
   {
    if(MT_PopBuffer(s_Keyboard->Que, &s_Return, sizeof(unsigned char)) == sizeof(unsigned char))
    {
     /* Byte keyboard code --> (s_Return & 0x80) ? UnPress : Press */	    
     s_Return &= 0xff;
    }
    else s_Return = (-1);
   }
   else s_Return = (-1);
  }
  else s_Return = (-1);
 }
 else 
 {
  s_Return = (-1);
#if DEF_DEBUG == (1)
  fprintf(stderr, "%s: %s - [ERROR] s_Keyboard is null !!!\n", DEF_SOURCE_keyboard_c, __FUNCTION__); 
#endif 
 }
 return(s_Return);
}

void MT_FlushKeyboard(DEF_COMPLETE_TYPE_KEYBOARD *s_Keyboard)
{
 if(s_Keyboard)
 {
  if(s_Keyboard->Que)s_Keyboard->Que = MT_CloseBuffer(s_Keyboard->Que);
 }
#if DEF_DEBUG == (1)
 else fprintf(stderr, "%s: %s - [ERROR] s_Keyboard is null !!!\n", DEF_SOURCE_keyboard_c, __FUNCTION__); 
#endif 
}

#endif

/* End of source */
moonzoo의 이미지

답변에 감사드립니다..

원래 그런 문제가 발생하는 것이었군여..

소스도 감사합니다.

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.