/*-------------------------------------------------------------------------*/
/* GNU Prolog                                                              */
/*                                                                         */
/* Part  : line-edit library                                               */
/* File  : char_io.c                                                       */
/* Descr.: basic character input/output                                    */
/* Author: Daniel Diaz                                                     */
/*                                                                         */
/* Copyright (C) 1999,2000 Daniel Diaz                                     */
/*                                                                         */
/* GNU Prolog is free software; you can redistribute it and/or modify it   */
/* under the terms of the GNU General Public License as published by the   */
/* Free Software Foundation; either version 2, or any later version.       */
/*                                                                         */
/* GNU Prolog 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        */
/* General Public License for more details.                                */
/*                                                                         */
/* You should have received a copy of the GNU General Public License along */
/* with this program; if not, write to the Free Software Foundation, Inc.  */
/* 59 Temple Place - Suite 330, Boston, MA 02111, USA.                     */
/*-------------------------------------------------------------------------*/
#include <ctype.h>

#if defined(__unix__) || defined(__CYGWIN__)
#include <sys/types.h>
#include <sys/uio.h>
#include <unistd.h>

#elif defined(_WIN32)

#include <io.h>
#include <conio.h>

#endif

#include "char_io.h"
#include "stty.h"
#include "linedit.h"




/*---------------------------------*/
/* Constants                       */
/*---------------------------------*/

/*---------------------------------*/
/* Type Definitions                */
/*---------------------------------*/

/*---------------------------------*/
/* Global Variables                */
/*---------------------------------*/

/*---------------------------------*/
/* Function Prototypes             */
/*---------------------------------*/



/*-------------------------------------------------------------------------*/
/* LE_EMIT_BEEP                                                            */
/*                                                                         */
/*-------------------------------------------------------------------------*/
void LE_Emit_Beep(int fd_out)

{
#if defined(_WIN32) && !defined(__CYGWIN__)

 if (w32gc_emit_beep)
     (*w32gc_emit_beep)();
  else
     Beep(800,220);
     /* MessageBeep(MB_ICONASTERISK); */

#else

 LE_Put_Char('\a',fd_out);

#endif
}




/*-------------------------------------------------------------------------*/
/* LE_PUT_CHAR                                                             */
/*                                                                         */
/*-------------------------------------------------------------------------*/
void LE_Put_Char(int c,int fd_out)

{
#if defined(__unix__) || defined(__CYGWIN__)

 char c0=c;

 write(fd_out,&c0,1);

#elif defined(_WIN32)

 if (w32gc_put_char)
     (*w32gc_put_char)(c);
   else
    {
     CONSOLE_SCREEN_BUFFER_INFO csbi; 

     if (c!='\b')
        {
         _putch(c);
         return;
        }
 
     GetConsoleScreenBufferInfo(h_stdout,&csbi);

     if (csbi.dwCursorPosition.X==0)
        {
         csbi.dwCursorPosition.X=csbi.dwSize.X-1;
         csbi.dwCursorPosition.Y--;
        }
     else
         csbi.dwCursorPosition.X--;

     SetConsoleCursorPosition(h_stdout,csbi.dwCursorPosition);
    }

#endif
}




/*-------------------------------------------------------------------------*/
/* LE_GET_CHAR0                                                            */
/*                                                                         */
/*-------------------------------------------------------------------------*/
int LE_Get_Char0(int fd_in)

{
#if defined(__unix__) || defined(__CYGWIN__)
 unsigned char c;

 if (read(fd_in,&c,1)!=1)
     return KEY_CTRL('D');
 return (int) c;

#elif defined(_WIN32)

 if (w32gc_get_char0)
     return (*w32gc_get_char0)();
  else
    {
     INPUT_RECORD ir;
     DWORD        nb;
     int          c;

read_char:
     if (!ReadConsoleInput(GetStdHandle(STD_INPUT_HANDLE),&ir,1,&nb))
         return -1;

     switch(ir.EventType)
        {
         case KEY_EVENT:
             if (!ir.Event.KeyEvent.bKeyDown)
                 goto read_char;
             c=(unsigned char) ir.Event.KeyEvent.uChar.AsciiChar;
             if (c==0 || c==0xe0)
                {
                 c=ir.Event.KeyEvent.wVirtualKeyCode;
                 if (c<0x15 || c>0x87)              /* e.g. CTRL key alone */
                     goto read_char;
                 if (ir.Event.KeyEvent.dwControlKeyState & 
                     (RIGHT_CTRL_PRESSED | LEFT_CTRL_PRESSED))
                     c=(2<<8)|c;
                  else
                     c=(1<<8)|c;
                }
             break;

         case MOUSE_EVENT:
         case WINDOW_BUFFER_SIZE_EVENT:
         case MENU_EVENT:
         case FOCUS_EVENT:
             goto read_char;
             break;
        }

     return c;
    }

#endif
}




/*-------------------------------------------------------------------------*/
/* LE_GET_CHAR                                                             */
/*                                                                         */
/*-------------------------------------------------------------------------*/
int LE_Get_Char(int fd_in)

{
 int c;

 c=LE_Get_Char0(fd_in);

 if (c==0x1b)
    {
     int esc_c;

     esc_c=LE_Get_Char0(fd_in);
#if defined(__unix__) || defined(__CYGWIN__)
     if (esc_c=='[')                                  /* ANSI ESC sequence */
        {
         c=LE_Get_Char0(fd_in);
         if (isdigit(c))
            {
             esc_c=c;
             c=0;
             while(esc_c!='~')
                {
                 c=c*10+esc_c-'0';
                 esc_c=LE_Get_Char0(fd_in);
                }
            }
         c=(1<<8)|c;
        }
      else
#endif
         c=KEY_ESC(esc_c);
    }

 return c;
}





/*-------------------------------------------------------------------------*/
/* LE_INS_MODE                                                             */
/*                                                                         */
/*-------------------------------------------------------------------------*/
void LE_Ins_Mode(int ins_mode)

{
#if defined(_WIN32) && !defined(__CYGWIN__)

 if (w32gc_ins_mode)
     (*w32gc_ins_mode)(ins_mode);
  else
    {
     CONSOLE_CURSOR_INFO cci; 

     if (!GetConsoleCursorInfo(h_stdout,&cci))
         return;

     cci.dwSize=(ins_mode) ? 5 : 50;

     SetConsoleCursorInfo(h_stdout,&cci); 
    }

#endif
}
