예제 #1
0
// outputs game over menu and waits for selection
void showGameOver(GameState* gameState, int* score, int* level,
        const int* maxLevel) {
  verifyClear();
  resizeTerminal(24, 73);

  if (*level >= *maxLevel) {
    printGameOverWon(score);
  } else {
    printGameOverLost(score);
  }
  verifyRefresh();

  nodelay(stdscr, false);

  int c;

  while (*gameState == GameOver) {
    if ((c = wgetch(stdscr)) != ERR) {
      if (c == 'y') {
        // clear bucket
        int i;
        for (i = 0; i < tetrisBucket.height; i++) {
          free(tetrisBucket.bucket[i]);
        }
        free(tetrisBucket.bucket);

        int size = (sizeof(brickPack.bricks) / sizeof(brickPack.bricks[0]));
        // clear remaining bricks in current brickpack
        for (i = size -
                brickPack.size; i < size; i++) {
          free(brickPack.bricks[i]);
        }

        // clear active bricks
        free(currentbrick);
        free(nextBrick);

        delwin(scoreWin);
        delwin(bucketWin);
        delwin(nextBrickWin);

        *gameState = GameInit;
        break;
      } else if (c == 'n') {
        break;
      }
    }
  }
}
예제 #2
0
// restes terminal to standard, frees resources and checks threadexecution
// then quits
void cleanUp(pthread_t musicThread) {
  resizeTerminal(24, 80);
  verifyClear();
  verifyRefresh();
  attroff(COLOR_PAIR(1));

  delwin(scoreWin);
  delwin(bucketWin);
  delwin(nextBrickWin);

  endwin();

  int i;
  for (i = 0; i < tetrisBucket.height; i++) {
    free(tetrisBucket.bucket[i]);
  }

  free(tetrisBucket.bucket);

  for (i = 7 - brickPack.size; i < 7; i++) {
    free(brickPack.bricks[i]);
  }

  // free music
  Mix_FreeMusic(korobeiniki);
  Mix_FreeMusic(introMusic);
  Mix_FreeMusic(gameOverMusic);

  // free chunks
  Mix_FreeChunk(moveSound);
  Mix_FreeChunk(rotateSound);
  Mix_FreeChunk(landSound);
  Mix_FreeChunk(levelUpSound);
  Mix_FreeChunk(clearLineSound);
  Mix_FreeChunk(tetrisSound);

  // don't exit before musicThread is done executing
  pthread_cancel(musicThread);
  pthread_join(musicThread, NULL);

  Mix_CloseAudio();
}
예제 #3
0
// outputs start menu and waits for selection
void showStartMenu(pthread_t* musicThread, GameState* gameState) {
  int c;

  while (*gameState == GameInit) {
    verifyClear();
    resizeTerminal(24, 73);
    printGameMenu();
    verifyRefresh();

    if ((c = wgetch(stdscr)) != ERR) {
      if (c == 10) {
        verifyClear();
        verifyRefresh();
        *gameState = GameRunning;
        break;
      } else if (c == 27) {
        *gameState = GameOver;
        break;
      }
    }
  }
}
예제 #4
0
QgsGrassShell::QgsGrassShell( QgsGrassTools *tools,
                              QTabWidget * parent, const char * name ):
    QDialog( parent ), QgsGrassShellBase(), mTools( tools )
{
  mValid = false;
  mSkipLines = 2;
  mTabWidget = parent;

#ifdef WIN32
  QMessageBox::warning( 0, "Warning",
                        "GRASS Shell is not supported on Windows." );
  return;
#else

  setupUi( this );

  QGridLayout *layout = new QGridLayout( mTextFrame, 1, 1 );
  mText = new QgsGrassShellText( this, mTextFrame );
  layout->addWidget( mText, 0, 0 );
  mText->show();

  connect( mCloseButton, SIGNAL( clicked() ), this, SLOT( closeShell() ) );

  mFont = QFont( "Courier", 10 );

  mAppDir = mTools->appDir();

#ifndef Q_WS_MAC
  // Qt4.3.2/Mac Q3TextEdit readOnly property causes keys to be processed as keyboard actions
  mText->setReadOnly( TRUE );
#endif
  //mText->setFocusPolicy ( QWidget::NoFocus ); // To get key press directly

#ifndef HAVE_OPENPTY
  mText->append( "GRASS shell is not supported" );
  return;
#endif

  // TODO set cursor IbeamCursor
  // This does not work - the cursor is used for scrollbars -> disabled
  //mText->setCursor ( QCursor(Qt::IbeamCursor) );
  mParagraph = -1; // first will be 0
  mIndex = -1;

  mNewLine = true;

  for ( int i = 0; i < ModeCount; i++ )
  {
    resetMode( i );
  }

  int uid;
  seteuid( uid = getuid() ); /* Run unprivileged */

  // Get and open pseudo terminal
  // Note: 0 (stdin), 1 (stdout) or 2 (stderr)
  int fdSlave; // slave file descriptor
  seteuid( 0 );
  int ret =  openpty( &mFdMaster, &fdSlave, NULL, NULL, NULL );
  if ( ret != 0 )
  {
    QMessageBox::warning( 0, "Warning", "Cannot open pseudo terminal" );
    return;
  }
  fchown( fdSlave, uid, ( gid_t ) - 1 );
  fchmod( fdSlave, S_IRUSR | S_IWUSR );
  seteuid( uid );

  QgsDebugMsg( QString( "mFdMaster = %1" ).arg( mFdMaster ) );
  QgsDebugMsg( QString( "fdSlave = %1" ).arg( fdSlave ) );

  fcntl( mFdMaster, F_SETFL, O_NDELAY );
  //fcntl( fdSlave, F_SETFL, O_NDELAY); // enable?

  QString slaveName = ttyname( fdSlave );
  QgsDebugMsg( QString( "master ttyname = %1" ).arg( ttyname( mFdMaster ) ) );
  QgsDebugMsg( QString( "slave ttyname = %1" ).arg( ttyname( fdSlave ) ) );

  //::close( fdSlave ); // -> crash

  // Fork slave and open shell
  int pid = fork();
  QgsDebugMsg( QString( "pid = %1" ).arg( pid ) );
  if ( pid == -1 )
  {
    QMessageBox::warning( 0, "Warning", "Cannot fork shell" );
    return;
  }

  // Child - slave
  if ( pid == 0 )
  {
    QgsDebugMsg( "child ->" );

    // TODO close all opened file descriptors - close(0)???
    ::close( mFdMaster );

    //::close( fdSlave ); // -> freeze

    setsid();
    seteuid( 0 );

    int fd = ::open(( char* ) slaveName.ascii(), O_RDWR );
    if ( fd < 0 )
    {
      QMessageBox::warning( 0, "Warning", "Cannot open slave file "
                            "in child process" );
      return;
    }

    fchown( fd, uid, ( gid_t ) - 1 );
    fchmod( fd, S_IRUSR | S_IWUSR );
    setuid( uid );

    dup2( fd, 0 ); /* stdin */
    dup2( fd, 1 ); /* stdout */
    dup2( fd, 2 ); /* stderr */

    // TODO: test if shell is available
    QString shell = ( getenv( "SHELL" ) );
    if ( shell.isEmpty() )
    {
      shell = "/bin/bash";
    }

    const char *norc = "";
    QFileInfo si( shell );
    if ( si.fileName() ==  "bash" || si.fileName() ==  "sh" )
    {
      norc = "--norc";
    }
    else if ( si.fileName() ==  "tcsh" || si.fileName() ==  "csh" )
    {
      norc = "-f";
    }

    // Warning: execle + --norc will not inherit not given variables
    // -> overwrite here
    const char *env = "GRASS_MESSAGE_FORMAT=gui";
    char *envstr = new char[strlen( env )+1];
    strcpy( envstr, env );
    putenv( envstr );

    putenv(( char * ) "GISRC_MODE_MEMORY" );  // unset

    env = "PS1=GRASS > ";
    envstr = new char[strlen( env )+1];
    strcpy( envstr, env );
    putenv( envstr );

    env = "TERM=vt100";
    envstr = new char[strlen( env )+1];
    strcpy( envstr, env );
    putenv( envstr );

    //char *envar[] = { "PS1=GRASS > ", "TERM=vt100", "GISRC_MODE_MEMORY=",
    //                  "GRASS_MESSAGE_FORMAT=gui", (char *)0 };

    //execle ( (char*)shell.ascii(), (char *)si.fileName().ascii(),
    //         norc, (char *) 0, envar);
    execl(( char* )shell.ascii(), ( char * )si.fileName().ascii(),
          norc, ( char * ) 0 );

    // Failed (QMessageBox here does not work)
    fprintf( stderr, "GRASS_INFO_ERROR(1,1): Cannot start shell %s\n",
             ( char* )shell.ascii() );
    exit( 1 );
  }

  mPid = pid;

  // Create socket notifier
  mOutNotifier = new QSocketNotifier( mFdMaster, QSocketNotifier::Read, this );

  QObject::connect( mOutNotifier, SIGNAL( activated( int ) ),
                    this, SLOT( readStdout( int ) ) );

  // Set tab stops ???
  mTabStop.resize( 200 );
  for ( int i = 0 ; i * 8 < ( int )mTabStop.size(); i++ )
  {
    mTabStop[i*8] = true;
  }

  // Set trap to write history on SIGUSR1
  //QString trap = "trap 'history -w' SIGUSR1\015\012";
  QString trap = "trap 'history -w' SIGUSR1\015";
  write( mFdMaster, trap.ascii(), trap.length() );
  mText->clear();

  resizeTerminal();
  mValid = true;
#endif // !WIN32
}