Logo Search packages:      
Sourcecode: vdr-plugin-console version File versions

menu.c

/*
 * menu.c: A plugin for the Video Disk Recorder
 *
 * See the README file for copyright information and how to reach the author.
 *
 * $Id: menu.c,v 1.1 2004/10/24 12:57:09 chelli-guest Exp $
 */


#include <vdr/osd.h>
#include <vdr/remote.h>

#include "menu.h"
#include "i18n.h"
#include "engine.h"



#define SYMBOL_KEYBOARD 'K'
#define SYMBOL_BELL 'B'



#include "fontsmall.c"
#include "fontsym.c"



void FlushRemote() {

  eKeys Key;
  do {

    Key = cRemote::Get( 100 );

  } while ( Key != kNone );
}





// Adapted from cFont from VDR by Klaus Schmidinger

cFontConsole::cFontConsole() {

  for ( int i = 0; i < NUMCHARS; i++ ) {

     data[ i ] = (tCharData *)&ConsoleFontSmall[ i < 32 ? 0 : i - 32 ];
  }
}




void WriteChar( cBitmap& bitmap, cFontConsole& font, int x, int y, const unsigned char ch, eDvbColor foreColor = clrWhite, eDvbColor backColor = clrBackground) {

  char fg = bitmap.Index( foreColor );
  char bg = bitmap.Index( backColor );

  int h = font.Height( ch );

  const cFontConsole::tCharData *CharData = font.CharData( ch );
  if ( int( x + CharData->width ) > bitmap.Width() )
    return;

  for ( int row = 0; row < h; ++row ) {

    cFontConsole::tPixelData PixelData = CharData->lines[ row ];

    for ( int col = CharData->width; col > 0; --col ) {

       bitmap.SetIndex( x + col, y + row, (PixelData & 1) ? fg : bg );
       PixelData >>= 1;
    }
  }
}






// --- cMenuEditComboItem ----------------------------------------------------

cMenuEditComboItem::cMenuEditComboItem(const char *Name, int *pValue, sMenuEditComboItemData *data, int dataCount)
:cMenuEditIntItem(Name, &_index, 0, dataCount - 1),
 _index( 0 ),
 _pValue( pValue )
{
  _data = (sMenuEditComboItemData*) malloc( dataCount * sizeof( sMenuEditComboItemData ) );
  assert( _data );
  _dataCount = dataCount;

  for ( int i = 0; i < dataCount; ++i ) {
    _data[ i ].Key   = data[ i ].Key;
    _data[ i ].Value = strdup( data[ i ].Value );

   if ( *pValue == data[ i ].Key )
     _index = i;
  }

  Set();
}



cMenuEditComboItem::~cMenuEditComboItem() {

  if ( _data ) {
    for ( int i = 0; i < _dataCount; ++i ) {
      free( (void*) _data[ i ].Value );
    }
    free( _data );
  }
}



void cMenuEditComboItem::Set(void) {

  *_pValue = _data[ _index ].Key;

  char buf[20];
  snprintf(buf, sizeof(buf), "%2i - %s", _index, _data[ _index ].Value );
  SetValue(buf);
}





// --- cMenuConsoleSetup --------------------------------------------------------

#define ARRAYSIZE( array ) ( sizeof( array ) / sizeof( array[ 0 ] ) )

cMenuConsoleSetup::cMenuConsoleSetup()
: data( config )
{
  sMenuEditComboItemData colors[] = {
                                    //{ -2, tr("Transparent")},
                                      { -1, tr("Background") },
                                      {  0, tr("Black")      },
                                    //{  1, tr("Red")        },
                                    //{  2, tr("Green")      },
                                    //{  3, tr("Yellow")     }, 
                                    //{  4, tr("Blue")       },
                                    //{  5, tr("Magenta")    },
                                      {  6, tr("Cyan")       },
                                      {  7, tr("White")      }
                                    };

  AddNewCategory( tr("Look") );
  Add(new cMenuEditComboItem( tr("Normal text color"),             &data.TextColor,     colors, ARRAYSIZE( colors ) ));
  Add(new cMenuEditComboItem( tr("Bold text color"),               &data.BoldTextColor, colors, ARRAYSIZE( colors ) ));
  Add(new cMenuEditComboItem( tr("Background color"),              &data.TextBackColor, colors, ARRAYSIZE( colors ) ));
  Add(new cMenuEditBoolItem(  tr("Compress text"),                 &data.CompressText));

  AddNewCategory( tr("Behaviour") );
  Add(new cMenuEditBoolItem(  tr("Automatic enter keyboard mode"), &data.AutoEnterKeyboardMode));
  Add(new cMenuEditIntItem(   tr("Bell timeout (s)"),              &data.BellTimeout, 0, 15 ));

  SetCurrent( Get( 1 ) );
}



void cMenuConsoleSetup::AddNewCategory( const char* title ) {

  char *buffer = NULL;
  asprintf(&buffer, "--- %s ----------------------------------------------------------------", title );
  assert( buffer );
  cOsdItem* item = new cOsdItem( buffer );
  free( buffer );
  assert( item );
  item->SetColor( clrCyan, clrBackground );
  Add( item );
}



void cMenuConsoleSetup::Store(void) {

  config = data;

  SetupStore( "TextColor",             data.TextColor );
  SetupStore( "BoldTextColor",         data.BoldTextColor );
  SetupStore( "TextBackColor",         data.TextBackColor );
  SetupStore( "CompressText",          data.CompressText );
  SetupStore( "AutoEnterKeyboardMode", data.AutoEnterKeyboardMode );
  SetupStore( "BellTimeout",           data.BellTimeout );
}





// --- cMenuConsoleItem ---------------------------------------------------------

cMenuConsoleItem::cMenuConsoleItem(int consoleNr, int X, int Y, int W, int H)
: _x( X ), _y( Y ), _w( W ), _h( H ),
  _pBitmap( NULL ), _pBitmapBottom( NULL ),
  _inputActivated( false ),
  _blink(true), _blinkOld(false),
  _inputState(0),
  _needClear(true),
  _toRing(0)
{
  _pConsole = &gl_pConsoles->getItem( consoleNr );


  // Calculate new size
  _pixelW = W * cOsd::CellWidth();
  _pixelH = H * cOsd::LineHeight();


  // The space between the chars can shrink, so more chars can go to the screen.
  int shrink = (config.CompressText) ? 1 : 0;
  _charW = _font.Width( 'A' )  - shrink;
  _charH = _font.Height( 'A' ) - shrink;

  _charsW = _pixelW / _charW;
  _charsH = _pixelH / _charH;

  //fprintf( stderr, "OSD x=%i, OSD y=%i, Pixel w=%i, Pixel h=%i, char w=%i, char h=%i, chars W=%i, chars H=%i\n", W, H, _pixelW, _pixelH, _charW, _charH, _charsW, _charsH );

  _pBitmap = new cBitmap( _pixelW, _pixelH, 2 );

  _pBitmapBottom = new cBitmap( _pixelW, cOsd::LineHeight(), 2 );

  // It can be that the OSD size has changed
  _pConsole->setTerminalSize( _charsW, _charsH, _pixelW, _pixelH );

  // prepare STDIN for Console
  if ( config.AutoEnterKeyboardMode &&  _pConsole->IsOpen() )
    // Simulate a press on the OK button.
    // So the new State will be shown on the display at once.
    cRemote::Put( (eKeys)kOk );

  _pConsole->getScreen().WantRefreshEvent( true );
}



cMenuConsoleItem::~cMenuConsoleItem() {

  _pConsole->getScreen().WantRefreshEvent(false);

  // resetting console
  if ( _inputActivated )
    ReleaseKeyboard();

  delete _pBitmap;
  delete _pBitmapBottom;
}



void cMenuConsoleItem::CaptureKeyboard() {

  _inputActivated = true;
  cKbdRemote::SetRawMode( true );
  gl_pConsoles->activateInputForTerminal();
}



void cMenuConsoleItem::ReleaseKeyboard() {

  // resetting console
  gl_pConsoles->deactivateInputForTerminal();
  cKbdRemote::SetRawMode( false );
  _inputActivated = false;
}



eDvbColor ConScreenGetColor( int AnsiColor ) {

  eDvbColor color;

  switch ( AnsiColor ) {
  case -2:  //color = clrTransparent;  break;
  case -1:  color = clrBackground;   break;
  case 0:   color = clrBlack;        break;
  case 1:   //color = clrRed;          break;
  case 2:   //color = clrGreen;        break;
  case 3:   //color = clrYellow;       break;
  case 5:   //color = clrMagenta;      break;
  case 6:   color = clrCyan;         break;
  case 4:   //color = clrBlue;         break;
  case 7:
  default:  color = clrWhite;        break;
  }

  return color;
}



eDvbColor ConScreenGetBackColor( int AnsiColor ) {

  eDvbColor color;

  switch ( AnsiColor ) {
  case -2:  //color = clrTransparent;  break;
  case 4:   //color = clrBlue;         break;
  case -1:  color = clrBackground;   break;
  case 0:   color = clrBlack;        break;
  case 1:   //color = clrRed;          break;
  case 2:   //color = clrGreen;        break;
  case 3:   //color = clrYellow;       break;
  case 5:   //color = clrMagenta;      break;
  case 6:   color = clrCyan;         break;
  case 7:
  default:  color = clrWhite;        break;
  }

  return color;
}



void ConScreenDetermineColors( const sConScreenChar& ch, eDvbColor& foreColor, eDvbColor& backColor, bool blink ) {

  // preset colors
  foreColor = ConScreenGetColor( config.TextColor );
  backColor = ConScreenGetBackColor( config.TextBackColor );


  // overwrite colors
  if ( ch.useFore )
    foreColor = ConScreenGetColor( ch.foreColor );

  if ( ch.useBack )
    backColor = ConScreenGetBackColor( ch.backColor );


  // interpret attributes
  if ( ch.Bold ) {
    foreColor = ConScreenGetColor( config.BoldTextColor );
//    backColor = ConScreenGetColor( config.TextBackColor );
  }


  // prevent unvisible colors
  if ( foreColor == backColor ) {
    if ( foreColor != clrBackground && foreColor != clrBlack )
      backColor = clrBackground;
    else
      backColor = clrWhite;
  }


  if ( ch.Inverted ) {
    eDvbColor tmpColor = foreColor;
    foreColor = backColor;
    backColor = tmpColor;
  }

  if ( ch.Concealed )
    foreColor = backColor;

  if ( ch.Blink && ! blink )
    foreColor = backColor;

}


#ifdef DEBUG_OSD

void cMenuConsoleItem::Clear(void) {

  Interface->Fill(_x, _y, _w, _h-1, ConScreenGetColor( config.TextBackColor ));
  // Ensure that also the status line will be cleared.
  Interface->Fill(_x, _y+_h-1, _w, 1, ConScreenGetColor( config.TextBackColor ));
}



void cMenuConsoleItem::Display(int Offset, eDvbColor FgColor, eDvbColor BgColor) {

  eDvbFont oldFont = Interface->SetFont(fontFix);

  if ( _needClear ) {
    Clear();
    _needClear = false;
  }

  // the screen shouldn't be changed while we are painting
  cMutexLock l( _pConsole->getScreen().getMutex() );

  char tmp[] = " ";  // helper for printing a single char

  cTerminalEmulation& screen = _pConsole->getScreen();

  for ( int row = 0; row < _h; ++row ) {

    const sConScreenChar* screenRow = screen.getScreen()[ row ];

    for ( int col = 0; col < _w; ++col ) {

      sConScreenChar &cell = (sConScreenChar&)screenRow[ col ];
      *tmp = cell.ch;

      eDvbColor foreColor, backColor;
      ConScreenDetermineColors( cell, foreColor, backColor, _blink );
      
      // print char
      Interface->Write( _x + col, _y + row, tmp, foreColor, backColor );
    }
  }


  // let the cursor blink
  bool cursorVisible = ( _blink && _pConsole->IsOpen() && _pConsole->getScreen().getCursorVisible() );

  // show cursor
  if ( cursorVisible ) {
    
    int row = screen.getCursorY(), col = screen.getCursorX();
    if ( row < _h ) { 

      // the cursor can't get out of the screen
      if ( col >= _w )
        col = _w - 1;

      sConScreenChar &cell = (sConScreenChar&) screen.getScreen()[ row ][ col ];
      *tmp = '_';

      eDvbColor foreColor, backColor;
      ConScreenDetermineColors( cell, foreColor, backColor, true );

      // use the colors inverse!
      Interface->Write( _x + col, _y + row, tmp, backColor, foreColor );
    }
  }

  _blinkOld = _blink;

  Interface->SetFont(oldFont);

  screen.Refreshed();
}



#else



void cMenuConsoleItem::Clear(void) {

  _pBitmap->Fill( 0, 0, _pixelW, _pixelH, ConScreenGetColor( config.TextBackColor ));
}



void cMenuConsoleItem::Display(int Offset, eDvbColor FgColor, eDvbColor BgColor) {

  if ( _needClear ) {
    Clear();
    _needClear = false;
  }

  // the screen content shouldn't be changed while we are painting
  cMutexLock l( _pConsole->getScreen().getMutex() );

  cTerminalEmulation& screen = _pConsole->getScreen();

  for ( int row = 0; row < _charsH; ++row ) {

    const sConScreenChar* screenRow = screen.getScreen()[ row ];

    for ( int col = 0; col < _charsW; ++col ) {

      sConScreenChar &cell = (sConScreenChar&)screenRow[ col ];

      eDvbColor foreColor, backColor;
      ConScreenDetermineColors( cell, foreColor, backColor, _blink );
      
      // print char
      WriteChar( *_pBitmap, _font, col * _charW, row * _charH, cell.ch, foreColor, backColor );

      // Draw if underlined
      if ( cell.Underscore ) {
        for ( int i = col * _charW; i < col * _charW + _charW; ++i ) {
          _pBitmap->SetPixel( i, row * _charH + _charH - 1, foreColor );
        }
      }
    }
  }


  // let the cursor blink
  bool cursorVisible = ( _blink && _pConsole->IsOpen() && _pConsole->getScreen().getCursorVisible() );

  // show cursor
  if ( cursorVisible ) {
    
    int col = screen.getCursorX(), row = screen.getCursorY();
    if ( row < _charsH ) { 

      // the cursor can't get out of the screen
      if ( col >= _charsW )
        col = _charsW - 1;

      if ( 1 ) {

        sConScreenChar &cell = (sConScreenChar&) screen.getScreen()[ row ][ col ];

        eDvbColor foreColor, backColor;
        ConScreenDetermineColors( cell, foreColor, backColor, true );

        // use the colors inverse!
        WriteChar( *_pBitmap, _font, col * _charW, row * _charH, cell.ch, backColor, foreColor );

      } else {

        int colorIndex = _pBitmap->Index( ConScreenGetColor( config.TextColor ) );

        for ( int x = col * _charW + 1; x <= col * _charW + 2; ++x ) {
          for ( int y = row * _charH; y < row * _charH + _charH; ++y ) {

            _pBitmap->SetIndex( x, y, colorIndex );
          }
        }
      }
    }
  }


  // Draw the Bitmap to the screen
  // -----------------------------
  Interface->SetBitmap( _x * cOsd::CellWidth(), _y * cOsd::LineHeight(), *_pBitmap );

  // The bottom line is in a separate Window, so draw this separate

  unsigned char Indexes[MAXNUMCOLORS];
  _pBitmapBottom->Take( *_pBitmap, &Indexes );
  for ( int row = 0; row < cOsd::LineHeight(); ++row ) {

    for ( int col = 0; col < _pixelW; ++col ) {

      _pBitmapBottom->SetIndex( col, row, Indexes[ *_pBitmap->Data( col, row + (_h - 1) * cOsd::LineHeight() ) ] );
    }
  }
  Interface->SetBitmap( _x * cOsd::CellWidth(), _h * cOsd::LineHeight(), *_pBitmapBottom );

  _blinkOld = _blink;

  screen.Refreshed();

  // decrease the display latency
  Interface->Flush();
}



#endif



eOSState cMenuConsoleItem::ProcessKey(eKeys Key) {

  eOSState state = osContinue;

  switch ( BASICKEY( Key) ) {

    case kKbd:{     uint64 buf = cKbdRemote::MapFuncToCode( KEYKBD( Key ) );
                    WriteToConsole( buf );

                    // On every key press, we show the cursor immediately
                    // so the user can see where it stayes.
                    _blink = true;


                    if ( _inputState == 1 ) {
                      assert( _inputActivated );   // How can that be? We must handle this case!

                      ReleaseKeyboard();           // Release, so the user can use RC keys

                      // A kRefresh shouldn't cancel the confirmation
                      _pConsole->getScreen().WantRefreshEvent( false );
                      FlushRemote();
                      if ( Interface->Confirm(tr("Press OK key to leave keyboard mode")) ) {
                        state = osUser1;           // refresh the title bar
                      } else {
                        CaptureKeyboard();         // reenter old mode...
                        unsigned char tmp = ESC;   // ...and post the suppressed {esc}
                        _pConsole->Write( &tmp, 1 );
                      }
                      _pConsole->getScreen().WantRefreshEvent( true );

                      // reset state machine
                      _inputState = 0;
                      _needClear = true; Display();  // After confirm we have to repaint the screen
                    }

                    // if the console were closed then release the captured keyboard
                    if ( _inputActivated && !_pConsole->IsOpen() ) {
                      ReleaseKeyboard();
                      state = osUser1;    // refresh the title bar
                    }

                    break;
    }
    case kNone:
    case kRefresh:{
                    if ( _pConsole->getScreen().ToRefresh() || _blink != _blinkOld ) {
                      Display();
                    }

                    // if the console were closed then release the captured keyboard
                    if ( _inputActivated && !_pConsole->IsOpen() ) {
                      ReleaseKeyboard();
                      state = osUser1;    // refresh the title bar
                    }

                    if ( _pConsole->getScreen().ToRing() ) {
                      _pConsole->getScreen().BellSeen();
                      
                      if ( config.BellTimeout ) {
                        _toRing = time_ms() + config.BellTimeout * 1000;
                        state = osUser1;
                      }
                    } else if ( _toRing && time_ms() > _toRing ) {
                      _toRing = 0;
                      state = osUser1;
                    }

                    // We have to shutdown a terminated process
                    if ( !_pConsole->IsOpen() )
                      _pConsole->HasClosed( true );

                    _blink = !_blink;
                    break;
    }
    case kOk:       if ( ! _inputActivated && _pConsole->IsOpen() ) {
                      CaptureKeyboard();
                      state = osUser1;
                    }
                    break;

                    // this is a trick to redraw the status bar
    case INT_MAX:   _needClear = true; Display(); break;

    default:        state = osUnknown;
  }

  return state;
}



void cMenuConsoleItem::WriteToConsole(const uint64& code) {

  unsigned char* data = (unsigned char*)(void*)&code;

  for ( int i = 7; i >= 0; --i ) {

    if ( data[ i ] > 0 ) {

      switch (_inputState) {

        // Normal state
        case 0:{

          // esc detected. Ask for exit
          if ( data[ i ] == ESC ) {

            _inputState = 1;

          } else
            _pConsole->Write( data + i, 1 );

          break;
        }
        // asked for exit
        case 1:{
          // post esc + new char
          unsigned char tmp = ESC;
          _pConsole->Write( &tmp, 1 );
          _pConsole->Write( data + i, 1 );

          _inputState = 0;
          break;
        }
        default: assert( false );// ERROR: Shit happened
      }
    }
  }
}






// --- cMenuConsole -------------------------------------------------------------


cMenuConsole::cMenuConsole( int consoleNr )
: cOsdMenu(""),
  _consoleNr(consoleNr)
{
  Add(new cMenuConsoleItem(consoleNr, 0, 1, Setup.OSDwidth, Setup.OSDheight-2));

#ifndef DEBUG_OSD

  cMenuConsoleItem* pItem = (cMenuConsoleItem*)Get( 0 );
  assert( pItem );

  char buf[40];
  snprintf(buf, sizeof(buf), "%s %i - %s\t", tr("Console"), _consoleNr+1, pItem->getTitle() );
  SetTitle(buf, false);

#endif

  RefreshTitle();
}



void cMenuConsole::RefreshTitle() {

  cMenuConsoleItem* pItem = (cMenuConsoleItem*)Get( 0 );
  assert( pItem );

#ifdef DEBUG_OSD

  char buf[40];
  snprintf(buf, sizeof(buf), "%s %i - %s\t%c %c", tr("Console"), _consoleNr+1, pItem->getTitle(), pItem->getCaptured() ? SYMBOL_KEYBOARD : ' ', pItem->getToRing() ? SYMBOL_BELL : ' ' );
  SetTitle(buf, false);
  Display();

#else

  cFontConsole font( ConsoleFontSym );

  cBitmap bitmap( 64, 27, 2 );
  bitmap.Fill( 0, 0, 63, 26, clrCyan );

  // Symbol for captured keyboard
  if ( pItem->getCaptured() )
    WriteChar( bitmap, font, 0, 0, 33, clrBlack, clrCyan );

  // Symbol for bell signal
  if ( pItem->getToRing() )
    WriteChar( bitmap, font, 38, 0, 34, clrBlack, clrCyan );

  Interface->SetBitmap( cOsd::CellWidth() * ( Setup.OSDwidth - 6 ), 0, bitmap );

#endif

  SetHelp( tr("New"), _consoleNr>0 ? "<<":NULL, _consoleNr<gl_pConsoles->getCount()-1 ? ">>":NULL, gl_pConsoles->getItem(_consoleNr).IsOpen() ? tr("Terminate") : tr("Close"));

}


eOSState cMenuConsole::ProcessKey(eKeys Key) {

  eOSState state = cOsdMenu::ProcessKey(Key);

  if (state == osUnknown) {
     switch (Key) {
       case kRed:     return osUser1;
       case kGreen:   return osUser2;
       case kYellow:  return osUser3;
       case kBlue:    return osUser4;
       default:       state = osUnknown;
     }

  } else if (state == osUser1) {
    RefreshTitle();
    state = osContinue;
  }

  return state;
}





// --- cMenuConsoleListItem -----------------------------------------------------

class cMenuConsoleListItem : public cOsdItem
{
private:
  int _Nr;

public:
  cMenuConsoleListItem( int Nr );
  virtual void Display(int Offset = -1, eDvbColor FgColor = clrWhite, eDvbColor BgColor = clrBackground);
};





cMenuConsoleListItem::cMenuConsoleListItem( int Nr )
: _Nr( Nr )
{
}



void cMenuConsoleListItem::Display(int Offset, eDvbColor FgColor, eDvbColor BgColor ) {

  if ( Offset >= 0 ) {

    cVirtualConsole& console = gl_pConsoles->getItem( _Nr );

    bool closed = ! console.IsOpen();
    bool bell   =   console.getScreen().ToRing();

    char buf[40];

#ifdef DEBUG_OSD

    snprintf(buf, sizeof(buf), "%c %s%s%s%s%c",
                  _Nr < 9 ? _Nr + '1' : ' ',
                  console.getTitle(), 
                  closed || bell ? " - "         : "", 
                  closed         ? tr("stopped") : "",
                  closed && bell ? " "           : "", 
                  bell           ? SYMBOL_BELL   : ' ' );

#else

    snprintf(buf, sizeof(buf), "%c %s%s%s",
                  _Nr < 9 ? _Nr + '1' : ' ',
                  console.getTitle(), 
                  closed ? " - "         : "", 
                  closed ? tr("stopped") : ""  );

#endif

    Interface->WriteText( 0, Offset + 2, buf, FgColor, BgColor );


#ifndef DEBUG_OSD

    // Symbol for bell signal
    if ( bell ) {

      cFontConsole font( ConsoleFontSym );

      cBitmap bitmap( 20, cOsd::LineHeight(), 1 );
      bitmap.Fill( 0, 0, 19, cOsd::LineHeight() - 1, BgColor );

      WriteChar( bitmap, font, 0, 0, 34, FgColor, BgColor );

      Interface->SetBitmap( cOsd::CellWidth() * ( Setup.OSDwidth - 6 ), cOsd::LineHeight() * ( Offset + 2 ), bitmap );

    }

#endif

  }
}





// --- cMenuConsoleList ---------------------------------------------------------


cMenuConsoleList::cMenuConsoleList()
: cOsdMenu(tr("Consoles"))
{
  Set();
  gl_pConsoles->WantAllRefreshEvents( true );
}



cMenuConsoleList::~cMenuConsoleList() {

  gl_pConsoles->WantAllRefreshEvents( false );
}



void cMenuConsoleList::Set(void) {

  int oldCur = Current();

  Clear();
  SetHasHotkeys();

  { cThreadLock l( gl_pConsoles );

    for ( int i = 0; i < gl_pConsoles->getCount(); ++i ) {
      Add(new cMenuConsoleListItem( i ));
    }
  }

  // try to set the last used item
  SetCurrent( Get( oldCur >= 0 ? ( oldCur >= Count() ? Count()-1 : oldCur ) : 0 ) );

  UpdateHelp();
}



void cMenuConsoleList::UpdateHelp() {

  SetHelp( tr("New"),
           gl_ConsoleCommands.Count() > 0 ? tr("Commands") : NULL,
           NULL, 
           gl_pConsoles->getCount() > 0 && Current() >= 0 ? gl_pConsoles->getItem(Current()).IsOpen() ? tr("Terminate") : tr("Close") : NULL );
}



bool cMenuConsoleList::TerminateConsole() {

  if ( Current() >= 0 ) {
    assert( Current() < gl_pConsoles->getCount() );
    cVirtualConsole& console = gl_pConsoles->getItem( Current() );
    if ( ! console.IsOpen() || Interface->Confirm(tr("Terminate console?")) ) {
      Interface->Status(tr("Terminate console..."));
      Interface->Flush();
      console.Close();
      gl_pConsoles->Remove( &console );
      Set();
      return true;
    }
  }
  return false;
}



eOSState cMenuConsoleList::ProcessKey(eKeys Key) {

  eOSState state = cOsdMenu::ProcessKey(Key);

  switch (state) {
    case osUser1: {
      int newIndex = gl_pConsoles->CreateConsole();
      if (newIndex >= 0) {
        cOsdMenu::ProcessKey(kBack); // calls Display()
        Add(new cOsdItem(hk(gl_pConsoles->getItem(newIndex).getTitle())), true);
        UpdateHelp();
        return AddSubMenu(new cMenuConsole(newIndex));
      }
      return osContinue;
    }

    case osUser2:{
      cOsdMenu::ProcessKey(kBack); // calls Display()
      CursorUp();
      return AddSubMenu(new cMenuConsole(Current()));
    }

    case osUser3:{
      cOsdMenu::ProcessKey(kBack); // calls Display()
      CursorDown();
      return AddSubMenu(new cMenuConsole(Current()));
    }
  
    case osUser4:{
      if ( TerminateConsole() ) {
        cOsdMenu::ProcessKey(kBack); // calls Display()
        gl_pConsoles->WantAllRefreshEvents( true );
      } else
        cOsdMenu::ProcessKey((eKeys)INT_MAX); // redraw the status bar
      return osContinue;
    }

    case osUser5: {
      int newIndex = gl_pConsoles->getCount() - 1;
      if (newIndex >= 0) {
        cOsdMenu::ProcessKey(kBack); // calls Display()
        Add(new cOsdItem( hk(gl_pConsoles->getItem(newIndex).getTitle()) ), true);
        UpdateHelp();
        return AddSubMenu(new cMenuConsole(newIndex));
      }
      return osContinue;
    }

    case osContinue:
      // if a console window has closed then we have to refresh the list...
      if ( Key == kBack ) { 
        Set();
        Display();
        // ...and to capture all console events
        gl_pConsoles->WantAllRefreshEvents( true );
      }
      break;

    case osUnknown: {

      switch (Key) {
        case kOk:      if ( Current() >= 0 ) {
                         gl_pConsoles->WantAllRefreshEvents( false );
                         gl_pConsoles->getItem(Current()).getScreen().BellSeen();
                         return AddSubMenu(new cMenuConsole(Current()));
                       }
                       return osContinue;

        case kRed:{    int newIndex = gl_pConsoles->CreateConsole();
                       if (newIndex >= 0) {
                         gl_pConsoles->WantAllRefreshEvents( false );
                         Add(new cOsdItem(hk(gl_pConsoles->getItem(newIndex).getTitle())), true);
                         UpdateHelp();
                         return AddSubMenu(new cMenuConsole(newIndex));
                       }
                       return osContinue;
        }
        case kGreen:   if ( gl_ConsoleCommands.Count() > 0 ) {
                         gl_pConsoles->WantAllRefreshEvents( false );
                         return AddSubMenu(new cMenuConsoleCommands());
                       }
                       return osContinue;

        case kBlue:    gl_pConsoles->WantAllRefreshEvents( false );
                       if ( TerminateConsole() )
                         Display();
                       gl_pConsoles->WantAllRefreshEvents( true );
                       return osContinue;

        case kRefresh: // A console has changed its state -> refresh the list
                       Set();
                       Display();
                       return osContinue;

        default:       state = osContinue;
      }
    }
    default: break;
  }

  if ( Key != kNone && !HasSubMenu() )
    UpdateHelp();
 
  return state;
}





// --- cMenuConsoleCommands --------------------------------------------------


cMenuConsoleCommands::cMenuConsoleCommands(void)
: cOsdMenu( tr("Commands") )
{
  SetHasHotkeys();

  int i = 0;
  cConsoleCommand *pCommand;

  while ( (pCommand = gl_ConsoleCommands.Get( i ) ) != NULL) {
    Add( new cOsdItem( hk( pCommand->Title() ) ) );
    i++;
  }
}



eOSState cMenuConsoleCommands::Execute() {

  cConsoleCommand *pCommand = gl_ConsoleCommands.Get( Current() );
  if ( pCommand ) {
     int newIndex = gl_pConsoles->CreateCommand( pCommand->Title(), pCommand->Command() );
     if (newIndex >= 0)
       return osUser5;
  }
  return osContinue;
}



eOSState cMenuConsoleCommands::ProcessKey(eKeys Key) {

  eOSState state = cOsdMenu::ProcessKey(Key);

  if (state == osUnknown) {
     switch (Key) {
       case kOk:  return Execute();
       default:   break;
     }
  }
  return state;
}


Generated by  Doxygen 1.6.0   Back to index