/* This file is part of Lcrzo.
*/

int lcrzo_priv_wait_file_read(lcrzo_file *pfile,
			      int waitaction)
{ lcrzo_int32 readsize;
  lcrzo_data ptr;

  lcrzo_er(lcrzo_data_alloc(LCRZO_PRIV_READMAXMSGSIZE, &ptr));

  /* read */
#if defined LCRZODEF_SYSTEM_Unix
  { struct termios old_termios, new_termios;
    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
      /* otherwise, 2 characters are displayed */
      new_termios.c_lflag &= (~ECHO);
#elif defined LCRZODEF_SYSTEM_Solaris
      /* nothing to do */
#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);
    }
    /* read */
    readsize=read(pfile->fd, ptr, LCRZO_PRIV_READMAXMSGSIZE);
    /* 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);
    }
  }
#elif defined LCRZODEF_SYSTEM_Windows
  if (pfile->fd==0)
  { /* special case for stdin */
    char c;
    readsize=0;
    while ( _kbhit() && readsize<LCRZO_PRIV_READMAXMSGSIZE-1 )
    { c=(char)_getch();
	  if (c==0x08) /* backspace */
      { if (readsize>0) readsize--;
		else ptr[readsize++]=c;
        if ( pfile->storeddatasize )
		{ /* otherwise, we delete previously printed text */
		  putchar(0x08);
	 	  putchar(' ');
		  putchar(0x08);
		}
	  }
	  else if (c==0x0D)
      { ptr[readsize++]=0x0D;
	    /* we never get 0x0A, so force it */
        ptr[readsize++]=0x0A;
		putchar(0x0D);
		putchar(0x0A);
      }
      else
      { ptr[readsize++]=c;
		putchar(c);
      }
    }
    lcrzo_err_purge();
    if (readsize==0)
    { lcrzo_data_free(ptr);
      return(LCRZO_ERR_OKTEMPDATAEND);
    }
  }
  else
  { readsize=_read(pfile->fd, ptr, LCRZO_PRIV_READMAXMSGSIZE);
  }
#else
 #error "Unknown value for LCRZODEF_SYSTEM"
#endif

  /* an error occured*/
  if (readsize==-1)
  { lcrzo_data_free(ptr);
    if (errno==EAGAIN)
    { /* nothing was available */
      errno=0;
      return(LCRZO_ERR_OKTEMPDATAEND);
    }
    else if (errno==EBADF)
    { /* reached end */
      errno=0;
      return(LCRZO_ERR_OKDATAEND);
    }
    else
    { /* fatal error */
      return(LCRZO_ERR_FUREAD);
    }
  }

  /* if we read 0, we are at end of file */
  if (readsize==0)
  { lcrzo_data_free(ptr);
    return(LCRZO_ERR_OKDATAEND);
  }

  /* put read data in stored data */
  lcrzo_er(lcrzo_priv_storeddata_append(ptr, readsize, &(pfile->storeddata), &(pfile->storeddatasize)));
  lcrzo_data_free(ptr);

  /* remove characters before backspace */
#if defined LCRZODEF_SYSTEM_Unix
#elif defined LCRZODEF_SYSTEM_Windows
  if (pfile->fd==0)
  { lcrzo_int32 i, j;
    lcrzo_uint8 c;
	for ( i=0, j=0 ; i<pfile->storeddatasize ; i++ )
	{ c=pfile->storeddata[i];
	  if ( c==0x08 )
	  { if (j>0) pfile->storeddata[--j]=c;
	  }
	  else
	  { pfile->storeddata[j++]=c;
	  }
	}
    pfile->storeddatasize=j;
  }
#else
 #error "Unknown value for LCRZODEF_SYSTEM"
#endif

  return(LCRZO_ERR_OK);
  /* just for the compiler warning */
  waitaction=waitaction;
}

