[c][unix] séquences touches directionnelles

Résolu/Fermé
Dr.W Messages postés 390 Date d'inscription jeudi 15 avril 2010 Statut Membre Dernière intervention 29 juin 2011 - Modifié par Dr.W le 16/04/2010 à 00:07
Dr.W Messages postés 390 Date d'inscription jeudi 15 avril 2010 Statut Membre Dernière intervention 29 juin 2011 - 17 avril 2010 à 16:21
Bonjour a tous !

Je suis actuelement sur un projet qui consiste a reproduire un shell tel que le tcsh ou le bash.

J'ai un probleme avec les termcap (ca marche sous Freebsd , mais pas sous Ubuntu), j'ai longement cherche sur le net sans succes... Je vous expose le probleme:

Je n'arrive pas a intercepté les séquences de caractères des touches directionnelles via un read sur stdin (Sous ubuntu, sous FreeBSD ça marche nickel).

Je procède comme suis:

J'ai desactiver le mode echo et le mode canonique de mon term grace a ioctl:

void                conf_term()  
{  
  struct termios        term;  
    
  if (ioctl(0, TCGETS, &term) < 0)  
    my_aff_error("TCGETS failed.");  
  term.c_lflag &= ~(ICANON|ECHO);  
  term.c_cc[VMIN] = 1;  
  term.c_cc[VTIME] = 0;  
  if (ioctl(0, TCSETS, &term) < 0)  
    my_aff_error("TCSETS failed");  
}

Ensuite je recuperes les sequences grace a cette fonction:


   
char                *xtgetstr(char *id, char **area)  
{  
  char                *tmp;  

  if ((tmp = tgetstr(id, area)) != NULL)  
    return (tmp);  
  my_puterror("Failed to get id: ", id);  
  return (NULL);  
}  

t_termcap            *init_termcap(char **ae)  
{  
  char                *bp;  
  char                *area;  
  t_termcap            *tc;  
    
  area = xmalloc(4096);  
  bp = xmalloc(4096);  
  tc = xmalloc(sizeof(*tc));  
  if (tgetent(bp, get_name_term(ae)) <= 0)  
    my_aff_error("tgetent app failed");  
  tc->ue = xtgetstr("ue", &area);  
  tc->ul = xtgetstr("us", &area);  
  tc->so = xtgetstr("so", &area);  
  tc->se = xtgetstr("se", &area);  
  tc->cl = xtgetstr("cl", &area);  
  tc->vi = xtgetstr("vi", &area);  
  tc->ve = xtgetstr("ve", &area);  
  tc->kD = xtgetstr("kD", &area);  
  tc->nd = xtgetstr("nd", &area);  
  if (!strcmp(my_trunc_str(my_getenv(ae, "HOSTTYPE", 8), '='), "FreeBSD", 0))  
  if (tgetent(bp, my_strcat(get_name_term(ae), "-noapp")) <= 0)  
    my_aff_error("tgetent -noapp failed");  
  tc->kb = xtgetstr("kb", &area);  
  tc->ku.noapp = xtgetstr("ku", &area);  // Voila les sequences qui pose probleme  
  tc->kd.noapp = xtgetstr("kd", &area);  
  tc->kr.noapp = xtgetstr("kr", &area);  
  tc->kl.noapp = xtgetstr("kl", &area);  
  tc->dc = xtgetstr("dc", &area);  
  return (tc);  
}

1er probleme, je n'arrive pas a passe en mode non-applicatif sous Ubuntu (tgentent echoue), donc j'ai rajoute une ligne pour verifie si je suis sous Freebsd et le cas echeant passe en mode non applicatif.

Ensuite je commence a lire sur stdin pour recuperer les caracteres que l'utilisateur m'envoi, c'est ici que je bloque:



void                get_command(t_store *stor)  
{  
  char                *buffer;  
  char                *buffer_cpy;  
  int                pos;  

  pos = 0;  
  buffer_cpy = xmalloc(BUFF_SIZE);  
  memset(buffer_cpy, 0, BUFF_SIZE);  
  buffer = xmalloc(5);  
  aff_prompt(stor->me, stor->nbr_cmd, stor->conf);  
  while (*buffer != '\n')  
    {  
      memset(buffer,  0, 5);  
      xread(0, buffer, 5);  
      if  (!strcmp(buffer, stor->tc->ku.noapp))  // Je ne rentre jamais dans cette condition peu importe quel sequence je compare (ku, kd, kl, kr) ca echoue toujours sous ubuntu (sous freebsd ca marche nickel)  
    {  
      my_printf("OK");  
      if (pos > 0)  
        {  
          pos --;  
          my_printf("\b");  
        }  
    }  
      else if (!my_strcmp(buffer, stor->tc->kb)) // ici c'est pour intercepte backspace (ca marche nickel sous Ubuntu && freebsd)  
    {  
      if (pos > 0)  
        {  
          pos --;  
          my_printf("\b \b");  
          buffer_cpy[my_strlen(buffer_cpy) - 1] = '\0';  
        }  
    }  
      else if (*buffer >= ' ' && *buffer <= '~')  
    {  
      buffer_cpy = strcat(buffer_cpy, buffer);  
      my_putchar(*buffer);  
      pos ++;  
    }  
    }  
  stor->buffer = buffer_cpy;  
  free(buffer);  
  my_putchar('\n');  
  stor->nbr_cmd ++;  
  what_to_do(buffer_cpy, stor); // ici j'envoi la command pour la parses et l'executer  
}

Quelqu'un saurait pourquoi je n'arrive pas a intercepte les sequences des fleches: gauche, droite, haut et bas?

Merci d'avance.


3 réponses

Char Snipeur Messages postés 9813 Date d'inscription vendredi 23 avril 2004 Statut Contributeur Dernière intervention 3 octobre 2023 1 298
16 avril 2010 à 08:30
Ton problème semble lié au mode non applicatif, non ? C'est les touches que tu utilises avec .noapp qui merdent.
Si tu essayais de traité les touches de direction comme des touches "normales" comme backspace par exemple ?
Sinon, regarde dans les sources de bash (par exemple) comment c'est fait.
0
Dr.W Messages postés 390 Date d'inscription jeudi 15 avril 2010 Statut Membre Dernière intervention 29 juin 2011 40
16 avril 2010 à 11:46
Ouais, en faite sous Ubuntu je recupere les touches en mode applicatif a default de pouvoir les recuperer autrement, c'est juste la structure qui les contient qui s'appell noapp. Sinon ouais j'ai essayer de regarder les sources du bash, mais visblement il ont trouve un moyen pour ne pas utilise les termcap qui me depasse completement... Voir la ligne dans bashline.c: /* To avoid including curses.h/term.h/termcap.h and that whole mess. */

Je vais alle voir dans le sources du tcsh pour voir...
0
Dr.W Messages postés 390 Date d'inscription jeudi 15 avril 2010 Statut Membre Dernière intervention 29 juin 2011 40
17 avril 2010 à 16:21
Problème resolu, il faut comparer les octet de la sequence 1 par 1 et ça marche !
0