/* $Id: TerminalStream,v 1.16 2009/03/01 03:44:47 kiesling Exp $ -*-c-*-*/

/*
  This file is part of Ctalk.
  Copyright  2005 - 2009  Robert Kiesling, ctalk@ctalklang.org.
  Permission is granted to copy this software provided that this copyright
  notice is included in all source code modules.

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2 of the License, or (at your option) any later version.

  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.

  You should have received a copy of the GNU Lesser General Public
  License along with this library; if not, write to the Free Software
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
*/

/*
 *    TerminalStream Class.  
 */

#include <stdio.h>
#if defined(__sparc__) && defined(__svr4__)
#include <sys/time.h>
#include <fcntl.h>
#else /* Linux */
#include <sys/select.h>
#endif
#include <sys/types.h>
#include <sys/stat.h>
#include <termios.h>

Stream class TerminalStream;
TerminalStream instanceVariable inputQueue List 0x0;
TerminalStream instanceVariable inputQueueMax Integer 64;
TerminalStream instanceVariable nInputEvents Integer 0;

#ifndef KBDCHAR
#define KBDCHAR (1 << 0)
#endif
#ifndef KBDCUR
#define KBDCUR  (1 << 1)
#endif

TerminalStream instanceMethod queueInputEvent (int class, int data) {
  InputEvent new __nEvent;
  InputEvent new __oEvent;

  __nEvent eventClass = class;
  __nEvent eventData = data;

  if (self nInputEvents > self inputQueueMax) {
    __oEvent become self inputQueue unshift;
    __oEvent delete;
    self nInputEvents = self nInputEvents - 1;
  }
  self inputQueue push __nEvent;
  self nInputEvents = self nInputEvents + 1;
  methodReturnSelf;
}

TerminalStream instanceMethod nextInputEvent (void) {

  InputEvent new __nEvent;

  returnObjectClass InputEvent;

  if (self nInputEvents) {
    self nInputEvents = self nInputEvents - 1;
    /* This should be able to follow return directly. */
    /* Should also generate a warning if there's an 
       erroneous expression like "inputEvents unshift"
       and recover from it.
    */
    __nEvent become self inputQueue unshift;
    methodReturnObject (__nEvent);
  } else {
    methodReturnNULL;
  }
}

TerminalStream instanceMethod isATty (void) {

  int rval, cval;
  struct stat statbuf;
  
  returnObjectClass Integer;

  if ((rval = stat (self ttyDevice, &statbuf)) == SUCCESS) {
    /***/
    cval = S_ISCHR(statbuf.st_mode);
    methodReturnInteger(cval);
  }
  methodReturnFalse;
}
