// getstr.c - este programa implementa a funcao getstr, que le uma 
//            string do teclado e suporta as teclas de edicao, INS,
//            HOME, DEL, END, BACKSPACE e setas p/ Esquerda e Direita.
//
// Uso:
//  char *str = GetStr(maxChar);
//      Onde maxChar e o tamanho maximo da string, se for especificado
//      um numero menor ou igual a zero, e usado 255 como default.
//      Caso seja pressionado ESC durante a leitura, NULL é retornado.
//
// Obs.: A string devolvida precisa ser desalocada pelo programa.
///
// Bugs: Não trabalha corretamente com o caracter TAB.
//       Não suporta multiplas linhas.
//
// Data       Autor                   Descricao
//  22/06/99 - Wenderson Teixeira      Data de criacao
//

#include <stdio.h>
#include <string.h>
#include <conio.h>
#include <malloc.h>
#include <dos.h>
#include <readkey.h>

typedef enum { emInsert, emOverwrite } TEditMode;

void Beep(void)
{
  sound(800);
  delay(50);
  nosound();
}

char *RemoveChar(char *str, int pos)
{
  memmove(&str[pos], &str[pos + 1], strlen(&str[pos]) + 1);
  return str;
}

char *InsertChar(char *str, int pos, char ch)
{
  memmove(&str[pos + 1], &str[pos], strlen(&str[pos]) + 1);
  str[pos] = ch;
  return str;
}

char *GetStr(int size)
{
  TEditMode EditMode = emInsert;
  int len = 0, pos = 0, c, key, x;
  char *str = (char *)malloc(size <= 0 ? 255 : size);
  
  do
  {
    key = ReadKeyWait();
    switch(key)
    {
      case DELETE:
        if(pos < len)
        {
          RemoveChar(str, pos);
          len--;

          x = wherex();
          printf("%s ", &str[pos]);

          gotoxy(x, wherey());
        }
      break;
      
      case INSERT:
        EditMode = EditMode == emInsert ? emOverwrite : emInsert;
      break;
      
      case BKSPC:
        if(len == 0 || pos == 0)
          Beep();
        else
        {
          RemoveChar(str, --pos);
          len--;

          printf("%c", key);
          x = wherex();
          printf("%s ", &str[pos]);

          gotoxy(x, wherey());
        }
      break;
      
      case ENTER:
      return str;
      
      case ESC:
        free(str);
      return 0;
      
      case UP:
      case DOWN:
      break;
      
      case LEFT:
        if(pos)
        {
          pos--;
          gotoxy(wherex() - 1, wherey());
        }
        else
          Beep();
      break;
      
      case RIGHT:
        if(pos < len)
        {
          pos++;
          gotoxy(wherex() + 1, wherey());
        }
        else
          Beep();
      break;
      
      case HOME:
        gotoxy(wherex() - pos, wherey());
        pos = 0;
      break;
      
      case END:
        gotoxy(wherex() + len - pos, wherey());
        pos = len;
      break;
      
      default:
        if(key < 256 && len < (size <= 0 ? 255 : size))
        {
          if(EditMode == emInsert)
          {
            InsertChar(str, pos++, key);
            len++;
          }
          else
          {
            pos == len ? len++ : 0;
            str[pos++] = key;
          }
          
          str[len] = '\0';

          printf("%c", key);
          x = wherex();
          if(pos < len)
          {
            printf(&str[pos]);
            gotoxy(x, wherey());
          }
        }
        else
          Beep();
    }
    
  } while(key != ENTER && key != ESC);

  return str;
}

void main()
{
  char *str;

  puts("String <no maximo 10 caracteres>: ");
  str = GetStr(10);
  
  clrscr();
  if(str)
  {
    printf("String digitada: %s", str);
    free(str);
  }
  
  getch();
}

1