/* This file is part of Lcrzo.
*/

/* Developper note :
   Following functions should be rewritten (they are too complicated
   for stdin dealing) :
    lcrzo_priv_wait_file_wait
    lcrzo_priv_wait_file_read
    lcrzo_file_flush
    lcrzo_stream_flush
    lcrzo_stdin_char
    lcrzo_stdin_press
    lcrzo_priv_stdin
    lcrzo_priv_passwd
*/
int lcrzo_priv_wait_file_wait(lcrzo_file *pfile,
			      int waitaction,
                              lcrzo_time *pmaxwaitingtime, 
                              lcrzo_bool *pevent)
#if defined LCRZODEF_SYSTEM_Unix
{ struct termios old_termios, new_termios;
  int ret;

  if (pfile->fd==STDIN_FILENO && waitaction!=LCRZO_PRIV_WAIT_ACTION_READ_LINE)
  { /* change attributes */
    if (tcgetattr(pfile->fd, &old_termios)) return(LCRZO_ERR_FUTCGETATTR);
    new_termios=old_termios;
    new_termios.c_lflag &= (~ICANON); /*desactive le mode canonique*/
#ifdef LCRZODEF_SYSTEM_Linux
      /* nothing to do */
#elif defined LCRZODEF_SYSTEM_FreeBSD || defined LCRZODEF_SYSTEM_OpenBSD
      /* nothing to do */
#elif defined LCRZODEF_SYSTEM_Solaris
    new_termios.c_lflag |= PENDIN; /*activate immediate info*/
    /* otherwise, 2 characters are displayed */
    new_termios.c_lflag &= (~ECHO);
#else
 #error "Unknown value for LCRZODEF_SYSTEM"
#endif
    new_termios.c_cc[VMIN] = 1; /*passe si au moins un caractere*/
    new_termios.c_cc[VTIME] = 0; /*attend indefiniment l'appui*/
    if (tcsetattr(pfile->fd, TCSANOW, &new_termios))
      return(LCRZO_ERR_FUTCSETATTR);
  }

  /* wait */
  ret=lcrzo_priv_wait_fd_wait(pfile->fd, pmaxwaitingtime, pevent);

  /* restore attributes */
  if (pfile->fd==STDIN_FILENO && waitaction!=LCRZO_PRIV_WAIT_ACTION_READ_LINE)
  { if (tcsetattr(pfile->fd, TCSANOW, &old_termios))
      return(LCRZO_ERR_FUTCSETATTR);
  }

  return(ret);
}
#elif defined LCRZODEF_SYSTEM_Windows
{ HANDLE fdhandle;
  DWORD err, msec;

  if (pfile->fd!=0)
  { /* suppose it's a filehandle for a disk file, for which there is
       only data, or endoffile. So there is no need to wait. */
    if (pevent!=NULL) *pevent=LCRZO_TRUE;
    return(LCRZO_ERR_OK);
  }

  /* Developper note : is GetNumberOfConsoleInputEvents good for this case ? */

  /* get the file handle associated to stdin */
  fdhandle=GetStdHandle(STD_INPUT_HANDLE);
  if (fdhandle==INVALID_HANDLE_VALUE) return(LCRZO_ERR_FUGETSTDHANDLE);
  /* wait during the specified time */
  lcrzo_er(lcrzo_priv_wait_winmsec_init_time(pmaxwaitingtime, &msec));
  err=WaitForSingleObject(fdhandle, msec);
  if (err==WAIT_FAILED) return(LCRZO_ERR_FUWAITFORSINGLEOBJECT);

  /* no data to read */
  if (err==WAIT_TIMEOUT)
  { *pevent=LCRZO_FALSE;
    return(LCRZO_ERR_OK);
  }
  else if (err==WAIT_OBJECT_0)
  { *pevent=LCRZO_TRUE;
    return(LCRZO_ERR_OK);
  }
  else
  { return(LCRZO_ERR_FUWAITFORSINGLEOBJECT);
  }

#if 0 
  /* Note : a key up is considered as an event, so we could use PeekConsoleInput to
     really check there is data to read. However, it's not useful because
     _kbhit is used in lcrzo_priv_wait_read_file. 
  */
    INPUT_RECORD ir[5];
    DWORD n, i;
    err=PeekConsoleInput(fdhandle, ir, 4, &n);
    if (!err) return(LCRZO_ERR_FUPEEKCONSOLEINPUT);
    for ( i=0; i<n; i++)
    { printf("Type=%d\t", ir[i].EventType);
      printf("c=%c=%02x b=%d\n", ir[i].Event.KeyEvent.uChar.AsciiChar,
             ir[i].Event.KeyEvent.uChar.AsciiChar,
             ir[i].Event.KeyEvent.bKeyDown);
    }
    /* ignore, cases when there is no data to read */
    if ( n==0 )
    { *pevent=LCRZO_FALSE;
      return(LCRZO_ERR_OK);
    }
    else if ( !ir[0].Event.KeyEvent.bKeyDown )
    { *pevent=LCRZO_FALSE;
      /* need also to check ir[0].Event.KeyEvent.uChar.AsciiChar ? */
      return(LCRZO_ERR_OK);
    }
    else
    { /* there is really data to read */
      *pevent=LCRZO_TRUE;
      return(LCRZO_ERR_OK);
    }
#endif

  return(lcrzo_ierp("lcrzo_priv_wait_wait_file"));
  /* just for the compiler warning */
  waitaction=waitaction;
}
#else
 #error "Unknown value for LCRZODEF_SYSTEM"
#endif

