#include "bbs.h"


int getcmdline_c(char cmdline[], menuetyp startmenue[], menuetyp sysmenue[],
                 menuetyp bbsmenue[], const char *chrootcwd,
		 confrecordtyp *confrecord)
{
  int arganz, lang;
  static boolean insysmenue = FALSE;
  static boolean inbbsmenue = FALSE;
  char key;
  static char nextkey=NO_KEY;
  SIGSET_T sigset;
  
  lang = confrecord->userrecord.lang;
  noecho();
  crmode();
  arganz = -1;
  if (! insysmenue) {
    sendstatustodaemon(BBS_IDLE,confrecord);
    setsighandler(SIGUSR1, sigtalkaccepthandler);
    sigemptyset(&sigset);
    sigaddset(&sigset, SIGUSR1);
    sigprocmask(SIG_UNBLOCK,&sigset,NULL);
    key = selectmenue_c(cmdline, startmenue, msg("getcmdline_c",0,lang), 
                        nextkey, confrecord);
    sigaddset(&sigset, SIGUSR2);
    sigprocmask(SIG_BLOCK,&sigset,NULL);
    sendstatustodaemon(BBS_BUSY,confrecord);
  }
  else {
    key = SYS_KEY;
  }
  nextkey = NO_KEY;
  switch (key) {
  case HELP_KEY:
    arganz = 0;
    break;
  case DOC_KEY:
    arganz = 0;
    break;
  case SYS_KEY:
    insysmenue = TRUE;
    key = selectmenue_c(cmdline, sysmenue, msg("getcmdline_c",1,lang), 
                        NO_KEY, confrecord);
    switch (key) {
    case ENV_KEY:
      arganz = 0;
      break;
    case LANG_KEY:
      arganz = sprache_c(cmdline, confrecord);
      break;
    case PROT_KEY:
      arganz = protokoll_c(cmdline, confrecord);
      break;
    case AUTOZ_KEY:
      arganz = autozmodem_c(cmdline, confrecord);
      break;
    case FULLIST_KEY:
      arganz = fullist_c(cmdline, confrecord);
      break;
    case TERM_KEY:
      arganz = term_c(cmdline, confrecord);
      break;
    case PASSWD_KEY:
      arganz = newpasswd_c(cmdline, confrecord);
      break;
    case QUIT_KEY:
    case ESCAPE_KEY:
      insysmenue = FALSE;
      break;
    }
    break;
  case DIR_KEY:
    arganz = 0;
    break;
  case CD_KEY:
    arganz = selectdir_c(cmdline, chrootcwd, confrecord);
    if (arganz >= 0) {      
      nextkey = CD_KEY;
    }
    else {
      writetouser(confrecord,msg("getcmdline_c",3,lang),chrootcwd);
    }
    break;
  case PWD_KEY:
    arganz = 0;
    break;
  case SHOW_KEY:
    arganz = selectfiles_c(cmdline, 0, confrecord);
    if (arganz < 1) cmdline[0] = '\0';
    break;
  case DOWNLOAD_KEY:
    arganz = selectfiles_c(cmdline, MAXARGS, confrecord);
    if (arganz < 1) cmdline[0] = '\0';
    break;
  case UPLOAD_KEY:
    arganz = put_c(cmdline, confrecord);
    break;
  case AUTOZDETECTED:
    arganz = 0;
    break;
  case BBS_KEY:
    inbbsmenue = TRUE;
    key = selectmenue_c(cmdline, bbsmenue, msg("getcmdline_c",2,lang), 
                        NO_KEY, confrecord);
    switch (key) {
    case TALK_KEY:
      arganz = talk_c(cmdline, confrecord);
      break;
    case QUIT_KEY:
    case ESCAPE_KEY:
      inbbsmenue = FALSE;
      break;
    }
    break;
  case QUIT_KEY:
    arganz = bbsquit_c(cmdline, confrecord);
    break;
  default:
    cmdline[0] = '\0';
  }
  return arganz;
}


char selectmenue_c(char cmd[], menuetyp menue[], const char *kopfstr,
                   const char nextkey, confrecordtyp *confrecord)
{
  int lang, z, k;
  char c, key, cset[100];
  
  if (nextkey == NO_KEY) {
    lang = confrecord->userrecord.lang;
    for (k=0, z=0; (c=menue[k].key)!='\0'; k++) {
      if (*(menue[k].dec) != '\0') cset[z++] = c;
    }
    cset[z] = '\0';
    clear();
    move(0, (COLS - strlen(kopfstr)) / 2);
    addstr(kopfstr);
    for (k=0,z=2; (c=menue[k].key)!='\0'; k++,z++) {
      if (c == ' ') continue;
      move(z,10);
      addch('[');
      standout();
      addch(c);
      standend();
      addch(']');
      move(z,16);
      addstr(menue[k].dec[lang]);
    }
    key = getkeyonprompt(msg("selectmenue_c",0,lang), cset,TRUE,TRUE,confrecord);
  }
  else {
    key = nextkey;
  }
  if (key == ESCAPE_KEY) return key;
  if (key == AUTOZDETECTED) {
    c = UPLOAD_KEY;
  }
  else {
    c = key;
  }
  k = 0;
  while (menue[k].key!='\0') {
    if (menue[k].key==c && *(menue[k].dec)!='\0') break;
    k++;
  }
  strcpy(cmd,menue[k].cmd);
  return key;
}


int talk_c(char cmd[], confrecordtyp *confrecord)
{
  int k, n, nr, anz, lang;
  PID_T mypid;
  char *sp, key, str[2*S_STRLEN+1], *params[10];
  sessionrecordtyp sessionrecords[MAXSESSIONS];
  tlistetyp *tliste;

  lang = confrecord->userrecord.lang;
  mypid = getpid();
  if ((anz=getsessions(sessionrecords,MAXSESSIONS,confrecord)) < 0) {
    return(-1);
  }
  tliste = (tlistetyp *)0;
  addstrtoliste(&tliste,TRUE,0,TL_BLOCKLEN,"",confrecord);
  n = 0;
  for (nr=0; nr<anz; nr++) {
    if (sessionrecords[nr].pid != mypid) {
      if (sessionrecords[nr].talking_to > 0) {
        sp = msg("talk_c",0,lang);
      }
      else if (sessionrecords[nr].status == BBS_BUSY) {
        sp= msg("talk_c",1,lang);
      }
      else {
        sp="";
      }
      sprintf(str,"F%s   (TTY %s, PID %ld) %s",sessionrecords[nr].user,
              sessionrecords[nr].tty,(long)sessionrecords[nr].pid,sp);
      addstrtoliste(&tliste,TRUE,n++,TL_BLOCKLEN,str,confrecord);
    }
  }
  anz = n;
  sortliste(tliste,TL_BLOCKLEN,anz,confrecord);

  key = selectpager_c(tliste, anz, msg("talk_c",2,confrecord->userrecord.lang),
                      NULL, TRUE, confrecord);
  n = 0;
  if (key != ESCAPE_KEY) {
    for (k=0; k<anz; k++) {
      readliste(&tliste,FALSE,k,TL_BLOCKLEN,&sp,confrecord);
      if (*sp == 'T') {
        splitparams(params,sp);
        strcat(cmd," ");
        strcat(cmd,params[4]);
	cmd[strlen(cmd)-1] = '\0';
        n++;
      }
    }
  }
  removeliste(tliste,TRUE,TL_BLOCKLEN);
  
  return n;
}


int newpasswd_c(char cmd[], confrecordtyp *confrecord)
{
  int lang;
  char str[PASS_MAX+S_STRLEN+10], username[S_STRLEN+1], newpasswd[PASS_MAX+1];

  lang = confrecord->userrecord.lang;
  move(0,0);
  clear();
  standout();
  printw(msg("newpasswd_c",0,lang),PASS_MAX);
  standend();
  refresh();
  if (confrecord->userrecord.seclevel == HIGHSECURITY) {
    writetouser(confrecord,msg("newpasswd_c",1,lang));
    cmd[0] = '\0';
    return(0);
  }
  if (strcmp(confrecord->userrecord.name,confrecord->sysop) == 0) {
    move(2,0);
    addstr(msg("newpasswd_c",2,lang));
    readfromuser(username,S_STRLEN,TRUE);
  }
  else {
    strcpy(username,confrecord->userrecord.name);
  }
  if (*username=='\0' || strchr(username,ESCAPE_KEY)!=NULL) {
    cmd[0] = '\0';
    return(0);
  }    
  move(4,0);
  addstr(msg("newpasswd_c",3,lang));
  readfromuser(str,PASS_MAX,FALSE);
  if (*str=='\0' || strchr(str,ESCAPE_KEY)!=NULL) {
    cmd[0] = '\0';
    return(0);
  }
  strcpy(newpasswd,str);
  move(5,0);
  addstr(msg("newpasswd_c",4,lang));
  readfromuser(str,PASS_MAX,FALSE);
  if (strncmp(newpasswd,str,PASS_MAX) != 0) {
    writetouser(confrecord,msg("newpasswd_c",5,lang));
    cmd[0] = '\0';
    return(0);
  }    
  
  strcpy(str,cmd);
  sprintf(cmd,"%s %s %s",str,username,newpasswd);
  
  return(2);
}


int sprache_c(char cmd[], confrecordtyp *confrecord)
{
  int lang, ypos, k;
  char key;
  char cset[] = {'A','B','Q','\0'};
  
  lang = confrecord->userrecord.lang;
  move(0,0);
  clear();
  standout();
  addstr(msg("sprache_c",0,lang));
  standend();
  move(2,2);
  addstr(msg("sprache_c",1,lang));
  addstr(sprachennamen[confrecord->userrecord.lang]);
  for (k=0; k<2; k++) {
    ypos = k + 5;
    move(ypos,2);
    addch('[');
    standout();
    addch('A'+k);
    standend();
    addch(']');
    move(ypos,6);
    addstr(sprachennamen[k]);
  }
  ypos = k + 6;
  move(ypos,2);
  addch('[');
  standout();
  addch('Q');
  standend();
  addch(']');
  move(ypos,6);
  addstr(msg("sprache_c",2,lang));
  key = getkeyonprompt(msg("sprache_c",3,lang), cset,TRUE,FALSE,confrecord);
  if (key==ESCAPE_KEY || key=='Q')  return(0);
  k = 1;
  if (key == 'A') {
    strcat(cmd," d");
  }
  else if (key == 'B') {
    strcat(cmd," e");
  }
  else {
    k = 0;
  }
  return(k);
}


int autozmodem_c(char cmd[], confrecordtyp *confrecord)
{
  int lang, ypos, k;
  char key;
  char cset[] = {'A','Q','\0'};
  
  lang = confrecord->userrecord.lang;
  move(0,0);
  clear();
  standout();
  addstr(msg("autozmodem_c",0,lang));
  standend();
  move(2,2);
  if (confrecord->userrecord.autozmodem) {
    addstr(msg("autozmodem_c",1,lang));
  }
  else {
    addstr(msg("autozmodem_c",2,lang));
  }
  ypos = 4;
  move(ypos,2);
  addch('[');
  standout();
  addch('A');
  standend();
  addch(']');
  move(ypos,6);
  addstr(msg("autozmodem_c",3,lang));
  ypos += 2;
  move(ypos,2);
  addch('[');
  standout();
  addch('Q');
  standend();
  addch(']');
  move(ypos,6);
  addstr(msg("autozmodem_c",4,lang));
  key = getkeyonprompt(msg("autozmodem_c",5,lang), cset,TRUE,FALSE,confrecord);
  if (key==ESCAPE_KEY || key=='Q')  return(0);
  k = 1;
  if (key == 'A') {
    if (confrecord->userrecord.autozmodem) {
      strcat(cmd," n");
    }
    else {
      strcat(cmd," j");
    }
  }
  else {
    k = 0;
  }
  return(k);
}


int fullist_c(char cmd[], confrecordtyp *confrecord)
{
  int lang, ypos, k;
  char key;
  char cset[] = {'A','Q','\0'};
  
  lang = confrecord->userrecord.lang;
  move(0,0);
  clear();
  standout();
  addstr(msg("fullist_c",0,lang));
  standend();
  move(2,2);
  if (confrecord->userrecord.fullist_on_cd) {
    addstr(msg("fullist_c",1,lang));
  }
  else {
    addstr(msg("fullist_c",2,lang));
  }
  ypos = 4;
  move(ypos,2);
  addch('[');
  standout();
  addch('A');
  standend();
  addch(']');
  move(ypos,6);
  addstr(msg("fullist_c",3,lang));
  ypos += 2;
  move(ypos,2);
  addch('[');
  standout();
  addch('Q');
  standend();
  addch(']');
  move(ypos,6);
  addstr(msg("fullist_c",4,lang));
  key = getkeyonprompt(msg("fullist_c",5,lang), cset,TRUE,FALSE,confrecord);
  if (key==ESCAPE_KEY || key=='Q')  return(0);
  k = 1;
  if (key == 'A') {
    if (confrecord->userrecord.fullist_on_cd) {
      strcat(cmd," n");
    }
    else {
      strcat(cmd," j");
    }
  }
  else {
    k = 0;
  }
  return(k);
}


int put_c(char cmd[], confrecordtyp *confrecord)
{
  if (confrecord->userrecord.protokoll == ZMODEMPROTO &&
      confrecord->userrecord.autozmodem) {
    writetouser(confrecord,msg("put_c",0,confrecord->userrecord.lang));
    cmd[0] = '\0';
  }
  return(0);
}


int protokoll_c(char cmd[], confrecordtyp *confrecord)
{
  int lang, ypos, k;
  char key;
  char cset[] = {'A','B','Q','\0'};
  
  lang = confrecord->userrecord.lang;
  move(0,0);
  clear();
  standout();
  addstr(msg("protokoll_c",0,lang));
  standend();
  move(2,2);
  addstr(msg("protokoll_c",1,lang));
  addstr(protokollnamen[confrecord->userrecord.protokoll]);
  for (k=0; k<2; k++) {
    ypos = k + 5;
    move(ypos,2);
    addch('[');
    standout();
    addch('A'+k);
    standend();
    addch(']');
    move(ypos,6);
    addstr(protokollnamen[k]);
  }
  ypos = k + 6;
  move(ypos,2);
  addch('[');
  standout();
  addch('Q');
  standend();
  addch(']');
  move(ypos,6);
  addstr(msg("protokoll_c",2,lang));
  key = getkeyonprompt(msg("protokoll_c",3,lang), cset,TRUE,FALSE,confrecord);
  if (key==ESCAPE_KEY || key=='Q')  return(0);
  k = 1;
  if (key == 'A') {
    strcat(cmd," k");
  }
  else if (key == 'B') {
    strcat(cmd," z");
  }
  else {
    k = 0;
  }
  return(k);
}


int term_c(char cmd[], confrecordtyp *confrecord)
{
  int lang, n;
  boolean notexists, action = FALSE;
  char buf[S_STRLEN+1], str[3*S_STRLEN+1];

  lang = confrecord->userrecord.lang;  
  move(0,0);
  clear();
  standout();
  addstr(msg("term_c",4,lang));
  standend();
  printw(msg("term_c",0,lang),confrecord->userrecord.term);
  strcpy(str," ");
  do {
    refresh();
    n = readfromuser(buf, S_STRLEN, TRUE);
    if (n>0 && ! termexists(buf)) {
      notexists = TRUE;
      printw(msg("term_c",1,lang),buf);
    }
    else {
      notexists = FALSE;
    }
  } while (notexists);
  if (n > 0) {
    action = TRUE;
  }
  else {
    strcpy(buf,confrecord->userrecord.term);
  }
  strcat(str,buf);

  printw(msg("term_c",2,lang),confrecord->userrecord.lines);
  refresh();
  strcat(str," ");
  if (readfromuser(buf, S_STRLEN, TRUE) > 0) {
    action = TRUE;
  }
  else {
    sprintf(buf,"%d",confrecord->userrecord.lines);
  }
  strcat(str,buf);
    
  printw(msg("term_c",3,lang),confrecord->userrecord.columns);
  refresh();
  strcat(str," ");
  if (readfromuser(buf, S_STRLEN, TRUE) > 0) {
    action = TRUE;
  }
  else {
    sprintf(buf,"%d",confrecord->userrecord.columns);
  }
  strcat(str,buf);
  refresh();

  if (! action) return(0);
  strcat(cmd,str);

  return(3);
}


int selectdir_c(char argstr[], const char *chrootcwd,
		confrecordtyp *confrecord)
{
  UID_T euid;
  GID_T egid;
  int k, n, dnr, danz, lang, len, maxlen;
  char key, str[S_STRLEN+NAME_MAX+2], *sp;
  char *homedirstr = "FHOME (Homedirectory)";
  const char *csp;
  boolean fullist;
  DIR *dp;
  struct dirent *dirp;
  struct stat stats;
  tlistetyp *tliste;

  lang = confrecord->userrecord.lang;
  fullist = confrecord->userrecord.fullist_on_cd;
  if ((dp=opendir(".")) == NULL) {
    errormsg(E_LOGFILE|E_USER,confrecord,"bbs","selectdir_c","opendir .: %m");
    return(-1);
  }
  euid = geteuid();
  egid = getegid();
  tliste = (tlistetyp *)0;
  dnr = 0;
  addstrtoliste(&tliste,TRUE,dnr,TL_BLOCKLEN,homedirstr,confrecord);
  while ((dirp=readdir(dp)) != NULL) {
    if (strcmp(dirp->d_name,".") == 0) continue;
    if (stat(dirp->d_name,&stats) < 0) {
      errormsg(E_LOGFILE|E_USER,confrecord,"bbs","selectdir_c","stat %s: %m",
               dirp->d_name);
      continue;
    }
    if (S_ISDIR(stats.st_mode)) {
      n = getperms(&stats,euid,egid);
      if ((n & PERM_R) && (n & PERM_X)) {
        dnr++;
        strcpy(str,"F");
	strcat(str,dirp->d_name);
        addstrtoliste(&tliste,TRUE,dnr,TL_BLOCKLEN,str,confrecord);
      }
    }
    else if (fullist && S_ISREG(stats.st_mode) &&
             (PERM_R & getperms(&stats,euid,egid))) {
      dnr++;
      sprintf(str,"X(%s)  %s",msg("selectdir_c",2,lang),dirp->d_name);
      addstrtoliste(&tliste,TRUE,dnr,TL_BLOCKLEN,str,confrecord);
    }
  }
  closedir(dp);
  danz = dnr + 1;
  sortliste(tliste,TL_BLOCKLEN,danz,confrecord);

  maxlen = COLS - strlen(msg("selectdir_c",1,lang)) - 2;
  len = strlen(chrootcwd);
  if (len > maxlen) {
    maxlen -= 4;
    csp = strchr(chrootcwd,'/');
    while (len > maxlen) {
      csp = strchr(++csp,'/');
      if (csp == NULL)  return(-1);
      len = strlen(csp);
    }
    sprintf(str,"%s: ....%s",msg("selectdir_c",1,lang),csp);
  }
  else {
    sprintf(str,"%s: %s",msg("selectdir_c",1,lang),chrootcwd);
  }
  key = selectpager_c(tliste,danz,msg("selectdir_c",0,lang),str,TRUE,
		      confrecord);
  
  n = -1;
  if (key != ESCAPE_KEY) {
    for (k=0; k<danz; k++) {
      readliste(&tliste,FALSE,k,TL_BLOCKLEN,&sp,confrecord);
      if (*sp == 'T') {
        if (strcmp(&(homedirstr[1]),&(sp[1])) == 0) {
          n = 0;
        }
        else {
          strmaxcat(argstr," ",PATH_MAX);
          strmaxcat(argstr,&(sp[1]),PATH_MAX);
	  n = 1;
        }
	break;
      }
    }
  }
  else {
    n = -1;
  }
  removeliste(tliste,TRUE,TL_BLOCKLEN);
  
  return n;
}


int selectfiles_c(char argstr[], const int maxn, confrecordtyp *confrecord)
{
  UID_T euid;
  GID_T egid;
  int k, n, fnr, fanz;
  char key, str[NAME_MAX+2], *sp;
  DIR *dp;
  struct dirent *dirp;
  struct stat stats;
  tlistetyp *tliste;

  if ((dp=opendir(".")) == NULL) {
    errormsg(E_LOGFILE|E_USER,confrecord,"bbs","selectfiles_c",
             "opendir .: %m");
    return(-1);
  }
  euid = geteuid();
  egid = getegid();
  tliste = (tlistetyp *)0;
  addstrtoliste(&tliste,TRUE,0,TL_BLOCKLEN,"",confrecord);
  fnr = -1;
  while ((dirp=readdir(dp)) != NULL) {
    if (stat(dirp->d_name,&stats) < 0) {
      errormsg(E_LOGFILE|E_USER,confrecord,"bbs","selectfiles_c","stat %s: %m",
               dirp->d_name);
      removeliste(tliste,TRUE,TL_BLOCKLEN);
      closedir(dp);
      return(-1);
    }
    if (S_ISREG(stats.st_mode) && (PERM_R & getperms(&stats,euid,egid))) {
      fnr++;
      strcpy(str,"F");
      strcat(str,dirp->d_name);
      addstrtoliste(&tliste,TRUE,fnr,TL_BLOCKLEN,str,confrecord);
    }
  }
  closedir(dp);
  fanz = fnr + 1;
  sortliste(tliste,TL_BLOCKLEN,fanz,confrecord);

  switch (maxn) {
  case 0:
    sp = msg("selectfiles_c",0,confrecord->userrecord.lang);
    break;
  case 1:
    sp = msg("selectfiles_c",1,confrecord->userrecord.lang);
    break;
  default:
    sp = msg("selectfiles_c",2,confrecord->userrecord.lang);
    break;
  }
  key = selectpager_c(tliste, fanz, sp, NULL, maxn==0, confrecord);
  if (key != ESCAPE_KEY) {
    for (k=0, n=0; k<fanz; k++) {
      readliste(&tliste,FALSE,k,TL_BLOCKLEN,&sp,confrecord);
      if (*sp == 'T') {
        strmaxcat(argstr," ",PATH_MAX);
        strmaxcat(argstr,&(sp[1]),PATH_MAX);
        n++;
      }
    }
  }
  else {
    n = -1;
  }
  removeliste(tliste,TRUE,TL_BLOCKLEN);
  
  return n;
}


char selectpager_c(tlistetyp *tliste, const int anz, const char *header,
                   const char *subheader, const boolean hotselect,
		   confrecordtyp *confrecord)
{
  int kopfzeilen, lines, zstep, offset, ypos, kmax, k, n;
  char *zary[MAXMEN], key;

  clear();
  move(0,0);
  standout();
  addstr(header);
  standend();
  if (subheader != (char *)0) {
    kopfzeilen = 3;
    move(1,0);
    addstr(subheader);
  }
  else {
    kopfzeilen = 2;
  }
  lines = confrecord->userrecord.lines - kopfzeilen -1;
  if (lines > MAXMEN) lines = MAXMEN;
  zstep = lines - 2;
  offset = 0;
  do {
    move(kopfzeilen,0);
    clrtobot();
    kmax = offset+lines > anz ? anz : offset+lines;
    for (k=offset,n=0; k<kmax; k++,n++) {
      ypos = kopfzeilen + k - offset;
      readliste(&tliste,FALSE,k,TL_BLOCKLEN,&(zary[n]),confrecord);
      if (*zary[n]!='X') {
	move(ypos,2);
	addch('[');
	standout();
	addch('A'+k-offset);
	standend();
	addch(']');
      }
      move(ypos,6);
      addstr(&(zary[n][1]));
    }
    if (anz > lines) {
      if (offset+lines < anz) {
        n = offset +1;
      }
      else {
        n = 0;
      }
    }
    else {
      n = -1;      
    }
    key = menueselect_c(zary,kmax-offset,n,kopfzeilen,hotselect,confrecord);
    if (key == ALLQUANTOR_KEY) {
      wildcardselect_c(key,tliste,anz,confrecord);
    }
    if (pagerstep(key) < 0) {
      offset -= zstep;
    }
    else if (pagerstep(key) > 0) {
      offset += zstep;
    }
    if (offset > anz-lines) offset = anz-lines;
    if (offset < 0) offset = 0;
  } while (selectpagerquit_c(key) == 0);
  
  return key;
}


char menueselect_c(char *zary[], const int lines, const int position,
                   const int kopfzeilen, const boolean hotselect,
		   confrecordtyp *confrecord)
{
  int k, lang;
  char prompt[S_STRLEN+1], keyset[MAXMEN+10], lastselkey, key;
  
  lang = confrecord->userrecord.lang;
  lastselkey = 'A';
  for (k=0; k<lines; k++) {
    if (*zary[k] != 'X') {
      lastselkey = 'A' + k;
      keyset[k] = lastselkey;
    }
  }
  keyset[k++] = SPACE_KEY;
  keyset[k++] = BACKSPACE_KEY;
  keyset[k++] = DELETE_KEY;
  keyset[k++] = NEWLINE_KEY;
  keyset[k++] = RETURN_KEY;
  if (! hotselect)  keyset[k++] = ALLQUANTOR_KEY;
  keyset[k] = '\0';
  if (lines > 0) {
    if (position == 0) {
      strcpy(prompt,msg("menueselect_c",0,lang));
    }
    else if (position == 1) {
      strcpy(prompt,msg("menueselect_c",1,lang));
    }
    else if (position > 0) {
      sprintf(prompt,msg("menueselect_c",2,lang), position);
    }
    else {
      strcpy(prompt,msg("menueselect_c",3,lang));
    }
    k = strlen(prompt);
    prompt[k++] = lastselkey;
    if (! hotselect) {
      prompt[k++] = ',';
      prompt[k++] = ALLQUANTOR_KEY;
    }
    prompt[k] = '\0';
    strcat(prompt,"]>");
  }
  else {
    strcpy(prompt,msg("menueselect_c",4,lang));
  }
  do {
    for (k=0; k<lines; k++) {
      move(k+kopfzeilen,0);
      if (*zary[k] == 'T') {
	addch('*');
      }
      else {
        addch(' ');
      }
    }
    key = getkeyonprompt(prompt,keyset,TRUE,FALSE,confrecord);
    if (key >= 'A' && key <= 'Z') {
      k = key - 'A';
      if (k>=0 && k<lines) {
        if (*zary[k] == 'F') {
          *zary[k] = 'T';
	  if (hotselect) key = RETURN_KEY;
        }
        else {
          *zary[k] = 'F';
        }
      }
    }
  } while (selectpagerquit_c(key) == 0 && pagerstep(key) == 0 &&
           wildcardchar_c(key) == 0);
  return key;
}


#ifndef NO_REGCOMP
#define NO_RE_COMP
#endif
int wildcardselect_c(const char key, tlistetyp *f_tliste, const int fanz,
                     confrecordtyp *confrecord)
{
  int p, k, n;
  char str[STRLEN+1], pattern[STRLEN+1], *sp, c;
#ifndef NO_REGCOMP
  regex_t preg;
  regmatch_t pmatch[1];
#else
#endif
  
  move(LINES-1,0);
  clrtoeol();
  standout();
  addstr(msg("wildcardselect_c",1,confrecord->lang));
  standend();
  refresh();
  c = getch();
  if (c == '?') {
#ifndef NO_REGCOMP
    writetouser(confrecord,msg("wildcardselect_c",2,confrecord->lang));
#else
#ifndef NO_RE_COMP
    writetouser(confrecord,msg("wildcardselect_c",3,confrecord->lang));
#endif
#endif
    refresh();
    c = getch();
  }
  k = 0;
  while (c!=ESCAPE_KEY && c!=RETURN_KEY && c!=NEWLINE_KEY && k<STRLEN) {
    if (k>0 && (c==BACKSPACE_KEY || c==DELETE_KEY)) {
      getyx(stdscr,n,p);
      mvdelch(n,--p);
      k--;
    }
    else {
      addch(c);
      str[k++] = c;
    }
    refresh();
    c = getch();
  };
  if (c == ESCAPE_KEY) return(0);
  str[k] = '\0';
  
  /* Shell-Metazeichen umwandeln in RE */
  p = 0;
  pattern[p++] = '^';
  k = 0;
  while ((c=str[k++]) != '\0') {
    switch (c) {
    case '.':
      pattern[p++] = '\\';
      pattern[p++] = '.';
      break;
    case '*':
      pattern[p++] = '.';
      pattern[p++] = '*';
      break;
#ifndef NO_REGCOMP
    case '?':
      pattern[p++] = '.';
      break;
#endif
    default:
      pattern[p++] = c;
    }
  }
  pattern[p++] = '$';
  pattern[p] = '\0';
/*
writetouser(confrecord,pattern);
*/
  /* RE compilieren */
#ifndef NO_REGCOMP
  if ((k=regcomp(&preg,pattern,REG_EXTENDED|REG_NOSUB)) != 0) {
    regerror(k,&preg,pattern,STRLEN);
#else
#ifndef NO_RE_COMP
  if ((sp=re_comp(pattern)) != (char *)0) {
    strcpy(str,sp);
#endif
#endif
    errormsg(E_LOGFILE|E_USER,confrecord,"bbs","wildcardselect_c",
	      msg("wildcardselect_c",0,confrecord->lang),pattern);
    return(-1);
  }
  for (k=0,n=0; k<fanz; k++) {
    readliste(&f_tliste,FALSE,k,TL_BLOCKLEN,&sp,confrecord);
#ifndef NO_REGCOMP
    if ((p=regexec(&preg,&(sp[1]),0,pmatch,0)) == 0) {
#else
#ifndef NO_RE_COMP
    if ((p=re_exec(&(sp[1]))) == 1) {
#endif
#endif
      n++;
      *sp = (*sp == 'T') ? 'F' : 'T';
    }
#ifndef NO_REGCOMP
    else if (p != REG_NOMATCH) {
      regerror(k,&preg,pattern,STRLEN);
      errormsg(E_LOGFILE|E_USER,confrecord,"bbs","wildcardselect_c",
		"regexec: %s",pattern);
      regfree(&preg);
#else
#ifndef NO_RE_COMP
    else if (p < 0) {
      errormsg(E_LOGFILE|E_USER,confrecord,"bbs","wildcardselect_c",
		"re_exec: internal error");
#endif
#endif
      return(-1);
    }
  }
#ifndef NO_REGCOMP
  regfree(&preg);
#endif
  return(n);
}


int selectpagerquit_c(const char key)
{
  switch (key) {
  case NEWLINE_KEY:
  case RETURN_KEY:
    return(1);
    break;
  case ESCAPE_KEY:
    return(-1);
    break;
  }
  return(0);
}


int bbsquit_c(char argstr[], confrecordtyp *confrecord)
{
  char key, cset[] = {'Y','J','N','\0'};
  
  key = getkeyonprompt(msg("bbsquit_c",0,confrecord->userrecord.lang),
                       cset,TRUE,FALSE,confrecord);
  if (key != 'Y' && key != 'J') {
    argstr[0] = '\0';
    return(-1);
  }
  return(0);
}


int wildcardchar_c(const char key)
{
  if (key == ALLQUANTOR_KEY) return(1);
  return(0);
}
