¿Cómo se permiten los espacios en blanco en modo no búfer / no canónico?

Estoy trabajando en múltiples progtwigs C, como un shell y un editor de text que requieren ejecutarse sin los indicadores ECHO e ICANON. Inhabilité estos usando termios.h y logré escribir mi propia function gets que puede retransmitir cadenas devueltas a mi progtwig y hacer cosas especiales para los caracteres de escape. Lo único que creo que no puedo hacer es imprimir un retroceso. Si, por ejemplo, uso este código:

void mgets(char *str) { int c, i = 0; while((c = getchar()) != '\n') if(c == 27) // the user hit ESC, ignore it for now else if(c == '\b') puts("\b \b") // this is where it SHOULD backspace // else if it's a regular character: else { str+i = c; i++; // write that to the string... putchar(c); // ...and echo it to the screen } } 

Todo funciona bien, pero el progtwig simplemente no responde cuando retrocedo. si cambio un poco mi sentencia if …

 if(c == '\b') printf("You hit a backspace!"); 

Pero aún no responde. Sé que puts ("\ b \ b") funciona, por lo que la única conclusión es que mi key de retroceso no se detecta como '\ b'. ¿Que puedo hacer? ¿Por favor ayuda? ¡Gracias por adelantado!

Related of "¿Cómo se permiten los espacios en blanco en modo no búfer / no canónico?"

Antes de cambiar la configuration de termios, guárdalos. Esa información es la "misma" que se puede ver con stty -a .

Por ejemplo

 $ stty -a speed 38400 baud; rows 40; columns 80; line = 0; intr = ^C; quit = ^\; erase = ^H; kill = ^U; eof = ^D; eol = <undef>; eol2 = <undef>; swtch = <undef>; start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R; werase = ^W; lnext = ^V; flush = ^O; min = 1; time = 0; -parenb -parodd cs8 -hupcl -cstopb cread -clocal -crtscts -ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr icrnl ixon -ixoff -iuclc -ixany -imaxbel -iutf8 opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0 isig icanon iexten echo echoe echok -echonl -noflsh -xcase -tostop -echoprt echoctl echoke 

El valor mostrado después de erase es el carácter al que se refiere como "retroceso". Dependiendo de las convenciones del sistema que podrían ser ^H (8, o espacio en blanco ASCII) o ^? (127, o ASCII DEL).

En la configuration de termios, por ejemplo,

 #include <termios.h> ... struct termios data; tcgetattr(0, &data); 

entonces

 data.c_cc[VERASE] 

es el mismo carácter de borrado (con algunas advertencias cuando los datos nunca se han establecido: stty mostraría "undef").

A diferencia de algunas de las otras configuraciones, el significado del carácter de borrado sigue siendo relevante en los modos raw / cbreak, ya que es una configuration que le dice al controller del terminal qué se espera que envíe su terminal. No está de más comprobar ambas posibilidades, en caso de que su configuration no sea correcta …

Otras lecturas:

  • Página de manual de tcgetattr
  • página de manual stty

mi key de retroceso no se detecta como '\ b'. ¿Que puedo hacer?

Qué secuencias de control o escape generan las teclas (retroceso) y (borrar).

En terminales que intentan ser como DEC VTs:

  • La tecla emit emite una secuencia de control DECFNK.
  • El comportamiento de es conmutable entre los caracteres ASCII BS y DEL, con una secuencia de control llamada DECBKM emitida al terminal.

Pero no todos los terminales (emuladores) siquiera intentan ser como un DEC VT, y mucho less implementan el mecanismo DECBKM. No puede simplemente cablear las secuencias de input del keyboard y esperar que funcionen en todas las circunstancias.

La forma en que su progtwig necesita funcionar es la siguiente: necesita tomar el tipo de terminal de la variable de entorno TERM , get el logging correspondiente de la terminfo datos terminfo (o termcap ) y search dos capacidades:

  • kbs ( kb ) – la secuencia enviada por la tecla
  • kdch1 ( kD ) – la secuencia enviada por la tecla

Debe hacer coincidir esas cadenas con la input que lee. Para distinguir entre las secuencias de control reales y las presiones simples de Esc, su progtwig necesita ser más complejo que un bucle fgetc() . Debe establecer el modo no canónico y establecer un time de espera de lectura (corto). Solo si read() devuelve una cadena completa dentro de un período de time de espera debe tratarse como una secuencia de control de input.

Tenga en count que los caracteres especiales establecidos por stty son prácticamente un arenque rojo aquí. No se aplican en modo no canónico, y solo afectan la disciplina de línea de todos modos. El comportamiento de la terminal está completamente determinado por cómo se mapean los events de la key de hardware para controlar las secuencias que envía "por cable" a la disciplina de la línea. Los terminales, como se mencionó anteriormente, son libres de hacerlo en una variedad de forms, desde el empleo de maps cargables entre códigos de tecla y secuencias de control (emulador de terminal de kernel integrado de FreeBSD) hasta resources X.

Otras lecturas

  • Información del progtwigdor de terminal de video VT510 . EK-VT510-RM. Noviembre de 1993. DEC.
  • Información del progtwigdor de terminal de video VT520 / VT525 . EK-VT520-RM. Julio de 1994. DEC.
  • ¿Por qué "shift-tab" resulta en "Escape" en la terminal?
  • https://unix.stackexchange.com/a/299423/5132