#define UML_AE    142
#define UML_ae    132
#define UML_UE    154
#define UML_ue    129
#define UML_OE    153
#define UML_oe    148
#define UML_ss    225

/* 21.12.2002 
static void echo_off()
{
#ifdef _WIN32_WINNT
  HANDLE Input;
  DWORD Mode;

  Input = GetStdHandle(STD_INPUT_HANDLE);
  if (! GetConsoleMode(Input, &Mode)) 
    return;
  Mode &= ~ENABLE_ECHO_INPUT;
  SetConsoleMode(Input, Mode);
#else
#endif
}

static void echo_on()
{
#ifdef _WIN32_WINNT
  HANDLE Input;
  DWORD Mode;

  Input = GetStdHandle(STD_INPUT_HANDLE);
  GetConsoleMode(Input, &Mode);
  Mode |= ENABLE_ECHO_INPUT;
  SetConsoleMode(Input, Mode);
#else
#endif
}
*/
static void echo_off()
{
#ifdef WIN32
  HANDLE Input;
  DWORD Mode;

  Input = GetStdHandle(STD_INPUT_HANDLE);
  if (! GetConsoleMode(Input, &Mode)) 
    return;
  Mode &= ~ENABLE_ECHO_INPUT;
  SetConsoleMode(Input, Mode);
#else
  struct termios settings;
  int result;

  result = tcgetattr (STDOUT_FILENO, &settings);
  if (result < 0) {
    perror ("error in tcgetattr");
    return;
  }

  settings.c_lflag &= ~ECHO;

  result = tcsetattr (STDOUT_FILENO, TCSANOW, &settings);
  if (result < 0) {
    perror ("error in tcgetattr");
    return;
  }
#endif
}

/* 21.12.2002 */
static void echo_on()
{
#ifdef WIN32
  HANDLE Input;
  DWORD Mode;

  Input = GetStdHandle(STD_INPUT_HANDLE);
  GetConsoleMode(Input, &Mode);
  Mode |= ENABLE_ECHO_INPUT;
  SetConsoleMode(Input, Mode);
#else
  struct termios settings;
  int result;

  result = tcgetattr (STDOUT_FILENO, &settings);
  if (result < 0) {
    perror ("error in tcgetattr");
    return;
  }

  settings.c_lflag |= ECHO;

  result = tcsetattr (STDOUT_FILENO, TCSANOW, &settings);
  if (result < 0) {
    perror ("error in tcgetattr");
    return;
  }
#endif
}


static int char_valid(char * fmt, unsigned char ch)
{
  int i = 0;

  if (fmt[0] == '-') {
    if (ch == '-')
      return TRUE;
    i++;
  }
  while (fmt[i] != '\0') {
    if (ch == fmt[i])
      return TRUE;
    if (fmt[i] == 'ä' && ch == UML_ae) 
      return TRUE;
    if (fmt[i] == 'Ä' && ch == UML_AE) 
      return TRUE;
    if (fmt[i] == 'ö' && ch == UML_oe) 
      return TRUE;
    if (fmt[i] == 'Ö' && ch == UML_OE) 
      return TRUE;
    if (fmt[i] == 'ü' && ch == UML_ue) 
      return TRUE;
    if (fmt[i] == 'Ü' && ch == UML_UE) 
      return TRUE;
    if (fmt[i] == 'ß' && ch == UML_ss) 
      return TRUE;
    if (fmt[i + 1] == '-' && fmt[i + 2] != '\0') {
      if (ch > fmt[i] && ch <= fmt[i + 2])
        return TRUE;
      i++; i++;
    }
    i++;
  }
  return FALSE;
}

static int scan_string(char * fmt, char * strg)
{
  unsigned char ch;
  int i = 0;

  while ((ch = getchar()) != '\n') {
    if (! char_valid(fmt, ch)) {
      fprintf(stderr, "character '%c' is not valid!\n", ch);
      while (getchar() != '\n');
      return -1;
    }
    strg[i++] = ch;
  }
  strg[i] = '\0';
  return i; 
}

static int read_string(char * prompt, char * strg, int len, int min)
{
  int iRc;

  do {
    if (prompt[0] != '\0')
      fprintf(stdout, "%s", prompt);
    else 
      fprintf(stdout, "# ");
    if ((iRc = scan_string("-+a-zA-Z/ _0-9äöüÄÖÜß*@.(),;'%=<>:\\?!", strg)) <= 0) {
      if (iRc == 0 && min == 0) {
        strg[0] = '\0'; break;
      }
      continue;
    }
    if (strcmp(strg, "q") == 0) {
      return FALSE;
    }
    if ((int)strlen(strg) > len) {
      fprintf(stdout, "string too long (max = %d)!\n", len);
      continue;
    }
    if ((int)strlen(strg) < min) {
      fprintf(stdout, "string too small (min = %d)!\n", min);
      continue;
    }
    break;
  } while (1 == 1);
  return TRUE;
}

static int change_string(char * prompt, char * ostrg, char * strg, int len)
{
  do {
    if (prompt[0] != '\0')
      fprintf(stdout, "%s", prompt);
    else 
      fprintf(stdout, "# ");
    if (ostrg[0] != '\0')
      fprintf(stdout, "(%s) ", ostrg);
    if (! scan_string("-+a-zA-Z/ _0-9äöüÄÖÜß*@.(),;'%=<>:\\?!", strg) < 0) {
      continue;
    }
    if (strcmp(strg, "q") == 0) {
      return FALSE;
    }
    if ((int)strlen(strg) > len) {
      fprintf(stdout, "string too long (max = %d)!\n", len);
      continue;
    }
    if (strg[0] == '\0') {
      strcpy(strg, ostrg);
    }
    break;
  } while (1 == 1);
  return TRUE;
}

static int read_password(char * prompt, char * strg, int len, int min)
{
  do {
    if (prompt[0] != '\0')
      fprintf(stdout, "%s", prompt);
    else 
      fprintf(stdout, "# ");
    echo_off();
    if (scan_string("-+a-zA-Z/ _0-9äöüÄÖÜß*@.(),;'%=<>", strg) <= 0) {
      if (min == 0) {
        strg[0] = '\0'; break;
      }
      continue;
    }
    /* 4.7.2002 */
    if (strcmp(strg, "q") == 0) {
      fprintf(stdout, "\n");
      echo_on();
      return FALSE;
    }
    if ((int)strlen(strg) > len) {
      fprintf(stdout, "string too long (max = %d)!\n", len);
      continue;
    }
    if ((int)strlen(strg) < min) {
      fprintf(stdout, "string too small (min = %d)!\n", min);
      continue;
    }
    break;
  } while (1 == 1);
  fprintf(stdout, "\n");
  echo_on();
  return TRUE;
}

/* -------- */

static int read_date(char * prompt, TFDate * date, int min)
{
  char strg[MAXSTRG];
  int iRc;

  INIT_FDate(*date);
  do {
    if (prompt[0] != '\0')
      fprintf(stdout, "%s", prompt);
    else 
      fprintf(stdout, "# ");
    if ((iRc = scan_string("0-9.=<>q", strg)) <= 0) {
      if (iRc == 0 && min == 0) {
        break;
      }
      continue;
    }
    if (strcmp(strg, "q") == 0) {
      return FALSE;
    }
    if ((int)strlen(strg) < min) {
      fprintf(stdout, "string too small (min = %d)!\n", min);
      continue;
    }
    DATE_FromString(date, strg, DATE_DDMMYYYY);
    if (! DATE_IsValid(date)) {
      fprintf(stdout, "invalid date!\n");
      continue;
    }
    break;
  } while (1 == 1);
  return TRUE;
}

static int change_date(char * prompt, TFDate * dat1, TFDate * dat2, int min)
{
  char strg[MAXSTRG], iRc;

  INIT_FDate(*dat2);
  do {
    if (prompt[0] != '\0')
      fprintf(stdout, "%s", prompt);
    else 
      fprintf(stdout, "# ");
    if (! CMP_FDate(dat1, DEF_FDate)) {
      char str1[MAXSTRG];

      DATE_ToString(dat1, str1, DATE_DDMMYYYY);
      fprintf(stdout, "(%s) ", str1);
    }
    if ((iRc = scan_string("0-9.=<>q", strg)) < 0) {
      continue;
    } 
    if (iRc == 0) {
      DATE_Copy(dat2, dat1);
      break;
    }
    if ((int)strlen(strg) < min) {
      fprintf(stdout, "date required!\n", min);
      continue;
    }
    if (strcmp(strg, "q") == 0) {
      return FALSE;
    }
    DATE_FromString(dat2, strg, DATE_DDMMYYYY);
    if (! DATE_IsValid(dat2)) {
      fprintf(stdout, "invalid date!\n");
      continue;
    }
    break;
  } while (1 == 1);
  return TRUE;
}

