gcmdline.cc

来自「Gambit 是一个游戏库理论软件」· CC 代码 · 共 546 行

CC
546
字号
//// $Source: /home/gambit/CVS/gambit/sources/gcl/gcmdline.cc,v $// $Date: 2002/08/27 18:57:16 $// $Revision: 1.4 $//// DESCRIPTION:// Implementation of editing interface for GCL//// This file is part of Gambit// Copyright (c) 2002, The Gambit Project//// This program 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 of the License, or// (at your option) any later version.//// This program 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-1307, USA.//#include <ctype.h>#ifdef __GNUG__#include <unistd.h>#endif   // __GNUG__#include "gcmdline.h"int gCmdLineInput::s_NumInstances = 0;#ifdef __GNUG__struct termios gCmdLineInput::s_TermAttr;#endif // __GNUG__void gCmdLineInput::SaveTermAttr( void ){#ifdef __GNUG__  // save the current terminal attributes  tcgetattr( STDIN_FILENO, &s_TermAttr );#endif // __GNUG__}void gCmdLineInput::RestoreTermAttr( void ){#ifdef __GNUG__  // restore the terminal attributes to the original  tcsetattr( STDIN_FILENO, TCSANOW, &s_TermAttr );#endif // __GNUG__}void gCmdLineInput::SetRawTermAttr( void ){#ifdef __GNUG__  struct termios rawTerm;  tcgetattr( STDIN_FILENO, &rawTerm );  // system( "stty raw -echo opost" );  /*     stty [-]raw     Same  as  -ignbrk  -brkint  -ignpar  -parmrk -inpck     -istrip -inlcr -igncr -icrnl  -ixon  -ixoff  -iuclc     -ixany  -imaxbel  -opost -isig -icanon -xcase min 1     time 0.  With `-', same as cooked.     */  rawTerm.c_iflag &= ~IGNBRK;  rawTerm.c_iflag &= ~BRKINT;  rawTerm.c_iflag &= ~IGNPAR;  rawTerm.c_iflag &= ~PARMRK;  rawTerm.c_iflag &= ~INPCK;  rawTerm.c_iflag &= ~ISTRIP;  rawTerm.c_iflag &= ~INLCR;  rawTerm.c_iflag &= ~IGNCR;  rawTerm.c_iflag &= ~ICRNL;  rawTerm.c_iflag &= ~IXON;  rawTerm.c_iflag &= ~IXOFF;  rawTerm.c_iflag &= ~IUCLC;  rawTerm.c_iflag &= ~IXANY;  rawTerm.c_iflag &= ~IMAXBEL;  rawTerm.c_oflag |= OPOST;  // rawTerm.c_lflag &= ~ISIG;  rawTerm.c_lflag |= ISIG;  rawTerm.c_lflag &= ~ICANON;  rawTerm.c_lflag &= ~XCASE;  rawTerm.c_lflag &= ~ECHO;  rawTerm.c_cc[VTIME] = 0;  rawTerm.c_cc[VMIN] = 1;  tcsetattr( STDIN_FILENO, TCSANOW, &rawTerm );#endif // __GNUG__}gCmdLineInput::gCmdLineInput( int historyDepth )  : GCL::CommandLine(historyDepth),    m_NumInvoke(0), m_EOF(false), m_Verbose(true), m_Prompt(true){  if( s_NumInstances == 0 )  {    SaveTermAttr();    SetRawTermAttr();  }  ++s_NumInstances;}gCmdLineInput::~gCmdLineInput(){  --s_NumInstances;  if( s_NumInstances == 0 )    RestoreTermAttr();}char gCmdLineInput::GetNextChar(void){  char c;  gStandardInput gin;  gin.get(c);  return c;}void gCmdLineInput::GetCmdExec( void ){  // number of invokations thus far  unsigned int i = 0;  if( m_CmdExec.Length() > 0 )    return;  // set up the editable prompt  char buf[32];  if( m_Prompt )  {    ++m_NumInvoke;    if( m_Verbose )    {      if( m_NumInvoke < HistoryDepth() )	sprintf( buf, "GCL%d:= << ", m_NumInvoke );      else	sprintf( buf, "GCL%d:=; GCL%d:= << ",		m_NumInvoke - HistoryDepth(),		m_NumInvoke );    }    else    {      if( m_NumInvoke < HistoryDepth() )	sprintf( buf, "GCL%d:= ", m_NumInvoke );      else	sprintf( buf, "GCL%d:=; GCL%d:= ",		m_NumInvoke - HistoryDepth(),		m_NumInvoke );    }  }  else    sprintf( buf, "%s","" );  gText cmdBuf = buf;  gText cmdBufOld;  unsigned int curPos = cmdBuf.Length();  char c = 0;  int historyPos = m_History.Length() + 1;  gStandardOutput gout;  gout << (const char *) cmdBuf;  for( ; ; ) { // infinite loop    c = GetNextChar();    if( c == EOF || c == '\r' || c == '\n' )      break;    if( c == 27 ) // escape sequences    {      EscapeCode code = GetEscapeSequence();      switch( code )      {      case ESC_LEFT:	if( curPos > 0 )	{	  --curPos;	  gout << '\b';	}	else // can't move left, beep	  gout << '\a';	break;      case ESC_RIGHT:	if( curPos < cmdBuf.Length() )	{	  gout << cmdBuf[curPos];	  ++curPos;	}	else // can't move right, beep	  gout << '\a';	break;      case ESC_UP:	if( historyPos > 1 )	{	  // clear the current line#ifdef USE_CR	  gout << '\r';#else	  for ( i = 0; i < curPos; ++i)	    gout << '\b';#endif	  for ( i = 0; i < cmdBuf.Length(); ++i )	    gout << ' ';#ifndef USE_CR	  for ( i = 0; i < cmdBuf.Length(); ++i )	    gout << '\b';#endif	  // save the latest line	  if( historyPos > m_History.Length() )	    cmdBufOld = cmdBuf;	  --historyPos;	  cmdBuf = m_History[historyPos];#ifndef USE_OLD_PROMPT	  cmdBuf = UpdatePromptNum( cmdBuf );#endif	  curPos = cmdBuf.Length();	  // display the new line#ifdef USE_CR	  gout << '\r';#endif	  gout << (const char *) cmdBuf;	}	else // can't go up, beep	  gout << '\a';	break;      case ESC_DOWN:	if( historyPos <= m_History.Length() )	{	  // clear the current line#ifdef USE_CR	  gout << '\r';#else	  for( i = 0; i < curPos; ++i )	    gout << '\b';#endif	  for( i = 0; i < cmdBuf.Length(); ++i )	    gout << ' ';#ifndef USE_CR	  for( i = 0; i < cmdBuf.Length(); ++i )	    gout << '\b';#endif	  ++historyPos;	  if( historyPos <= m_History.Length() )	  {	    cmdBuf = m_History[historyPos];#ifndef USE_OLD_PROMPT	    cmdBuf = UpdatePromptNum( cmdBuf );#endif	  }	  else // restore the latest line	    cmdBuf = cmdBufOld;	  curPos = cmdBuf.Length();	  	  // display the new line#ifdef USE_CR	  gout << '\r';#endif	  gout << (const char *) cmdBuf;	}	else // can't go up, beep	  gout << '\a';	break;      case ESC_DELETE:	if( curPos < cmdBuf.Length() )	{	  cmdBuf.Remove( curPos );	  // print the entire string after the current cursor position	  gout << (const char *) cmdBuf.Right(cmdBuf.Length() - curPos);	  gout << ' '; // this to erase the last character	  // reposition the cursor	  for( i = 0; i < cmdBuf.Length() - curPos + 1; ++i )	    gout << '\b';	}	else // nothing to delete, beep	  gout << '\a';	break;      default: // bad escape sequence, beep	gout << '\a';      }    }    else if( c == 'R' - 'A' + 1 ) // ^R, refreshes the line    {      gout << "^R\n";      gout << (const char *) cmdBuf;      curPos = cmdBuf.Length();    }    else if( c == '\b' || c == 127 ) // backspace    {      if( curPos > 0 )      {	cmdBuf.Remove( curPos - 1 );	--curPos;	// print the entire string after the current cursor position	gout << '\b';	gout << (const char *) cmdBuf.Right( cmdBuf.Length() - curPos );	gout << ' '; // this to erase the last character	// reposition the cursor	for( i = 0; i < cmdBuf.Length() - curPos + 1; ++i )	  gout << '\b';      }    }    else if( isprint( c ) )// normal characters    {      cmdBuf.Insert( c, curPos );      ++curPos;            // print the entire string after the current cursor position      gout << (const char *) cmdBuf.Right(cmdBuf.Length() - curPos + 1);            // reposition the cursor      for( i = 0; i < cmdBuf.Length() - curPos; ++i )	gout << '\b';    }  }#ifdef USE_OLD_PROMPT  if( historyPos < m_History.Length() + 1 )    --m_NumInvoke;#endif  if (c == EOF) {    m_EOF = true;  }  m_History.Append( cmdBuf );  m_CmdExec = cmdBuf + "\n";  gout << '\n';  // if the history is too long now, get rid of the first one  if( m_History.Length() > HistoryDepth() )    m_History.Remove( 1 );  }gCmdLineInput::EscapeCode gCmdLineInput::GetEscapeSequence(void){  char c1 = 0;  char c2 = 0;  char c3 = 0;  // remember that the first Escape has already been caught  // the second char must be '[' in an escape sequence  gStandardInput gin;  if (!gin.eof()) {    c1 = GetNextChar();  }  if (c1 != '[') {    return ESC_ERROR;  }  if (!gin.eof()) {    c2 = GetNextChar();  }  switch( c2 )  {  case 65: // up arrow    return ESC_UP;  case 66: // down arrow    return ESC_DOWN;  case 68: // left arrow    return ESC_LEFT;  case 67: // right arrow    return ESC_RIGHT;  case 51: // delete key, if followed by 126    if (!gin.eof()) {      c3 = GetNextChar();    }    if( c3 == 126 )      return ESC_DELETE;    else      return ESC_ERROR;    break;  default:    return ESC_ERROR;  }}void gCmdLineInput::EatSpace( int num ){  for (int i = 0; i < num; i++)    m_CmdExec.Remove(0);}gInput& gCmdLineInput::operator >> (int &x){  int tokens = 0;  while (tokens == 0) {    GetCmdExec();    int num = 0;    tokens = sscanf( m_CmdExec, "%d%n", &x, &num );    EatSpace( num );  }  return *this; }gInput& gCmdLineInput::operator >> (unsigned int &x){  int tokens = 0;  while (tokens == 0) {    GetCmdExec();        int num = 0;    tokens = sscanf( m_CmdExec, "%d%n", &x, &num );    EatSpace( num );  }  return *this; }gInput& gCmdLineInput::operator >> (long &x){  int tokens = 0;  while( tokens == 0 )  {    GetCmdExec();        int num = 0;    tokens = sscanf( m_CmdExec, "%ld%n", &x, &num );    EatSpace( num );  }  return *this; }gInput& gCmdLineInput::operator >> (char &x) {  int tokens = 0;  while( tokens == 0 )  {    GetCmdExec();        int num = 0;    tokens = sscanf( m_CmdExec, "%c%n", &x, &num );    EatSpace( num );  }  return *this; }gInput& gCmdLineInput::operator >> (double &x){  int tokens = 0;  while( tokens == 0 )  {    GetCmdExec();    int num = 0;    tokens = sscanf( m_CmdExec, "%lf%n", &x, &num );    EatSpace( num );  }  return *this;}gInput& gCmdLineInput::operator >> (float &x){  int tokens = 0;  while( tokens == 0 )  {    GetCmdExec();        int num = 0;    tokens = sscanf( m_CmdExec, "%f%n", &x, &num );    EatSpace( num );  }  return *this; }gInput& gCmdLineInput::operator >> (char *x){  int tokens = 0;  while( tokens == 0 )  {    GetCmdExec();    int num = 0;    tokens = sscanf( m_CmdExec, "%s%n", x, &num );    EatSpace( num );  }  return *this; }gText gCmdLineInput::UpdatePromptNum( gText cmdBuf ) const{  char buf[512] = "";  int val0 = 0;  int val1 = 0;  int numchars0 = 0;  int numchars1 = 0;  int match = sscanf( cmdBuf, "GCL%d:=%n; GCL%d:=%n", 		     &val0, &numchars0, &val1, &numchars1 );  if( match == 1 )  {    sprintf( buf, "GCL%d:=%s", m_NumInvoke, &cmdBuf[(unsigned int) numchars0] );    cmdBuf = buf;  }  else if( match == 2 )  {    sprintf( buf, "GCL%d:=; GCL%d:=%s",	    m_NumInvoke - HistoryDepth(), m_NumInvoke, 	    &cmdBuf[(unsigned int) numchars1] );    cmdBuf = buf;  }  return cmdBuf;}#include "base/gstack.imp"template class gStack<bool>;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?