// 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; } } } }
// 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(); }
// 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; } } } }
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 }