view pwplib/tty.c @ 71:a87eb778f225

Improvements to the MinGW crossbuild. Should now build with default tools from Debian mingw packages, though you need Win32 version of libSDL with the necessary headers and so on in addition. 64-bit builds not tested and probably won't work. Tested on Debian 7.0, earlier won't work. binutils-mingw-w64-i686 gcc-mingw-w64-i686 mingw-w64-i686-dev
author Matti Hamalainen <ccr@tnsp.org>
date Tue, 14 Aug 2012 03:08:10 +0300
parents 7d4f6c33a6ac
children
line wrap: on
line source

#include "config.h"
#ifdef DRIVE_TTY

#include "pwplib.h"

#define __TTY_C

#include "tty.h"

/****************/

#ifdef HAVE_TTYSTUFF

static void tty_restore_termios(void)
{
   tcsetattr(STDIN,TCSADRAIN,&pwp_tty.setup);
}

static void tty_init_termios(void)
{
   struct termios t;
   tcgetattr(STDIN,&t);
   memcpy(&pwp_tty.setup,&t,sizeof(struct termios));
   
   t.c_lflag=ISIG; /* &=~(ECHO+ECHOE+ECHOK+ECHONL+NOFLSH);*/
   
/*   t.c_lflag=t.c_oflag=0; */
   t.c_cc[VMIN]=1;
   t.c_cc[VTIME]=0;
   tcsetattr(STDIN,TCSADRAIN,&t);

   pwplib_regdestr(tty_restore_termios);
}

static void tty_getwinsize(void)
{
#  ifdef TIOCGWINSZ
  {struct winsize wsz;
  if(ioctl(0,TIOCGWINSZ,&wsz)>=0){
     pwp_tty.width=wsz.ws_col;pwp_tty.height=wsz.ws_row;
     if(pwp_tty.width>0 && pwp_tty.height>0) return;
  }}
#  endif

  {char*tmp;
  pwp_tty.height=((tmp=getenv("LINES"))?atoi(tmp):0);
  pwp_tty.width=((tmp=getenv("COLUMNS"))?atoi(tmp):0);
  if(pwp_tty.height>0 && pwp_tty.width>0)return;}

  pwp_tty.height=24;
  pwp_tty.width=80;
}

void tty_write(void *data, int lgt)
{
   if (lgt < 0) lgt = strlen((char *) data);
   write(pwp_tty.fd, data, lgt);
   pwplib.timer_counter += lgt;
}

/******************************************************************/

static void tty_probe_raw(void)
{
   fd_set fdset;
   struct timeval timeout;

   tty_init_termios();

   memset(&fdset, 0, sizeof(fd_set));
   FD_SET(0,&fdset);
   timeout.tv_sec=0;
   timeout.tv_usec=250000;

   write(STDOUT,"\33[c",3*sizeof(char));

   usleep(250000); /* give it some time to react */

   select(0,&fdset,NULL,NULL,&timeout);

   if(FD_ISSET(STDIN,&fdset))
   {
      char buf[40],*b;
      int lgt,num;

      lgt=read(STDIN,buf,40*sizeof(char))/sizeof(char);

      if(lgt<3) return;
      if( (buf[0]!=27) ||
          (buf[1]!='[') ||
          (buf[2]!='?')) return;

      b=buf+3;lgt-=3;num=0;

      pwp_tty.type=TTY_VT1XX;
      pwp_tty.minor=0;
      pwp_tty.vtcap=0;

      while(lgt)
      {
         char c=*b++;
         if(c>='0' && c<='9')
            num=(num*10)+c-'0';
         else
         {
            /*fprintf(stderr,"NUMBAH %d\n",num);*/
            if(num>=62)
            {
               pwp_tty.type =TTY_VT2XX;
               pwp_tty.minor=20+(num-60)*100;
            }
            else
            if(num<32)pwp_tty.vtcap|=(1<<num);
            
            num=0;
         }
         lgt--;
      }

      if(pwp_tty.vtcap&(1<<3)) /* ReGIS */
      {
         if(pwp_tty.minor==220)
            pwp_tty.minor=240;
         if(pwp_tty.minor==320)
         {
            pwp_tty.minor=330;
            /* how to check 340? */
         }
         /* ... otherz */
      }

      /* protection from vt2xx wannabes - enable after lag fix */
#ifdef DRIVE_TTY_VT2XX      
/*      if( (pwp_tty.type==TTY_VT2XX) &&
          (!(pwp_tty.vtcap&(1<<7))))
      {
         pwp_tty.type=TTY_VT1XX;
      }*/
#else
	if(pwp_tty.type==TTY_VT2XX)pwp_tty.type=TTY_VT1XX;
#endif

   }
    else
         pwp_tty.type=TTY_DUMB;

   tty_restore_termios();
}

/******************************************************************/

static int tty_probe(void)
{
   char*tt;

   pwp_tty.type=TTY_DUMB;

   pwpwrite("* getting terminal type..\n");

   tt=pwplib.set.term;
   if(tt==NULL)
   {
      tty_probe_raw();
      tt=getenv("TERM");
      if(tt==NULL)return pwp_tty.type;
   }

   if(tt[0]=='x')pwp_tty.type=TTY_XVT_MONO;

   if( (!strcmp(tt,"xterm-color")) ||
       (!strcmp(tt,"aixterm"))
      )
   {
      return TTY_XVT_COLOR;
   }

   if( (pwp_tty.type==TTY_VT1XX) ||
       (pwp_tty.type==TTY_DUMB))
   {
      if(tt[0]=='v')
      {
         pwp_tty.minor=atoi(tt+2);

         if(pwp_tty.minor>=200 && pwp_tty.type!=TTY_VT1XX)
                  return TTY_VT2XX;
             else return TTY_VT1XX;
      }

      if(tt[0]=='a')
         return TTY_ANSISYS;

      if(tt[0]=='l')
         return TTY_LINUX;

      if(!strcmp(tt,"dumb"))
         return TTY_DUMB;
   }

   return pwp_tty.type;
}

#endif

/******************************************************************/

int tty_init(void)
{
#ifdef HAVE_TTYSTUFF

  /* int colors=2,chars=2,rasters=1; */

  pwp_tty.fd=2; /* stderr */

  tty_init_termios();

  tty_getwinsize();
  pwp_tty.type=tty_probe();
#endif
  pwplib.videobuf.width=pwp_tty.width;
  pwplib.videobuf.height=pwp_tty.height;
  pwplib.videobuf.d=malloc(pwplib.videobuf.width*
    pwplib.videobuf.height*sizeof(u16));
#ifdef HAVE_TTYSTUFF
  pwp_tty.prevbuf=malloc(pwplib.videobuf.width*
    pwplib.videobuf.height*sizeof(u16));

  pwpwrite("* terminal on stdout: ");

  switch(pwp_tty.type)
  {
     case(TTY_DUMB):
        pwpwrite("dumb or unsupported\n");
        tty_dumb_init();
        break;

     case(TTY_VT2XX):
#ifdef DRIVE_TTY_VT2XX
        pwpwrite("vt220/compatible (vt%d)\n",pwp_tty.minor);
        tty_vt2xx_init();
        break;
#endif
     case(TTY_VT1XX):
        pwpwrite("vt100/compatible");
        if (pwp_tty.minor>=200)
            pwpwrite(" (a vt%d wannabe)\n",pwp_tty.minor);
        else
            pwpwrite("\n");
        tty_vt1xx_init();
        break;


#     ifdef DRIVE_LINUXCON
     case(TTY_LINUX):
        pwpwrite("linux console\n");
        tty_linux_init();
        break;
#     endif

     case(TTY_XVT_COLOR):
        pwpwrite("xterm/compatible with color\n");
        tty_ansicol_init();
        break;

     case(TTY_XVT_MONO):
        pwpwrite("xterm (monochrome)\n");
        tty_vt1xx_init();
        break;

     case(TTY_ANSISYS):
        pwpwrite("msdos ansi or compatible\n");
        tty_ansisys_init();
        break;
   }
#endif
   return 1;
}

#endif