/* scriptop.cc
 * This file belongs to Worker, a file manager for UN*X/X11.
 * Copyright (C) 2002-2023 Ralf Hoffmann.
 * You can contact me at: ralf@boomerangsworld.de
 *   or http://www.boomerangsworld.de/worker
 *
 * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "scriptop.h"
#include "listermode.h"
#include "worker.h"
#include "wpucontext.h"
#include "execlass.h"
#include "aguix/acontainerbb.h"
#include "worker_locale.h"
#include "aguix/fieldlistview.h"
#include "aguix/choosebutton.h"
#include "aguix/stringgadget.h"
#include "aguix/button.h"
#include "aguix/cyclebutton.h"
#include "aguix/awindow.h"
#include "aguix/request.h"
#include "datei.h"
#include "wconfig.h"

const char *ScriptOp::name="ScriptOp";

ScriptOp::ScriptOp() : FunctionProto()
{
  type = SCRIPT_NOP;
  label = NULL;
  stack_nr = 0;
  push_string = NULL;
  push_useoutput = false;
  if_test = NULL;
  if_label = NULL;
  description_buf_size = 1024;
  description_buf = (char*)_allocsafe( description_buf_size );
  dodebug = false;
  wpu_recursive = false;
  wpu_take_dirs = false;
  wintype = SCRIPT_WINDOW_LEAVE;
  change_progress = false;
  change_text = false;
  progress = NULL;
  progress_useoutput = false;
  wintext = NULL;
  wintext_useoutput = false;
  hasConfigure = true;
  m_category = FunctionProto::CAT_SCRIPTING;
}

ScriptOp::~ScriptOp()
{
  if ( label != NULL ) _freesafe( label );
  if ( push_string != NULL ) _freesafe( push_string );
  if ( if_test != NULL ) _freesafe( if_test );
  if ( if_label != NULL ) _freesafe( if_label );
  if ( progress != NULL ) _freesafe( progress );
  if ( wintext != NULL ) _freesafe( wintext );
  _freesafe( description_buf );
}

ScriptOp*
ScriptOp::duplicate() const
{
  ScriptOp *ta=new ScriptOp();
  ta->setType( type );
  ta->setLabel( label );
  ta->setStackNr( stack_nr );
  ta->setPushString( push_string );
  ta->setPushUseOutput( push_useoutput );
  ta->setPushOutputReturnCode( m_push_output_return_code );
  ta->setIfTest( if_test );
  ta->setIfLabel( if_label );
  ta->setDoDebug( dodebug );
  ta->setWPURecursive( wpu_recursive );
  ta->setWPUTakeDirs( wpu_take_dirs );
  ta->setWinType( wintype );
  ta->setChangeProgress( change_progress );
  ta->setChangeText( change_text );
  ta->setProgress( progress );
  ta->setProgressUseOutput( progress_useoutput );
  ta->setWinText( wintext );
  ta->setWinTextUseOutput( wintext_useoutput );
  ta->setCommandStr( m_command_str );
  return ta;
}

bool
ScriptOp::isName(const char *str)
{
  if(strcmp(str,name)==0) return true; else return false;
}

const char *
ScriptOp::getName()
{
  return name;
}

int
ScriptOp::run( std::shared_ptr< WPUContext > wpu, ActionMessage *msg )
{
  char *tstr2, *tstr3;
  int erg, l, exeerror = 1;
  
  switch ( type ) {
    case SCRIPT_PUSH:
      /* 1.resolv push_string
         2.if push_useoutput, execute string and get output
         3.push string to stack nr
       */
      if ( push_string != NULL ) {
        std::string res_str;

        if ( wpu->parse( push_string, res_str, a_max( EXE_STRING_LEN - 1024, 256 ),
                         ( ( push_useoutput == true ) ? true : false ),
                         WPUContext::PERSIST_ALL ) == WPUContext::PARSE_SUCCESS ) {
          if ( push_useoutput == true ) {
            int exit_code = 0;
            std::unique_ptr<ExeClass> ec( new ExeClass( msg->getWorker() ) );
            ec->cdDir( wpu->getBaseDir() );
            ec->addCommand( "%s", res_str.c_str() );

            if ( m_push_output_return_code ) {
                tstr2 = NULL;
                if ( ec->getOutputAndRV( &tstr2, &exit_code, &exeerror ) != 0 ) {
                    if ( tstr2 ) {
                        _freesafe( tstr2 );
                        tstr2 = NULL;
                    }
                    exeerror = 3;
                }
            } else {
                tstr2 = ec->getOutput( &exeerror );
            }

            if ( exeerror == 0 ) {
              if ( tstr2 != NULL ) {
                if ( dodebug == true ) {
                  Requester *req;
                  req = new Requester( Worker::getAGUIX() );
                  tstr3 = (char*)_allocsafe( strlen( catalog.getLocale( 485 ) ) +
                                             strlen( tstr2 ) +
                                             A_BYTESFORNUMBER( stack_nr ) + 1 );
                  sprintf( tstr3, catalog.getLocale( 485 ), tstr2, stack_nr );
                  req->request( catalog.getLocale( 124 ), tstr3, catalog.getLocale( 11 ) );
                  _freesafe( tstr3 );
                  delete req;
                }
                wpu->push( stack_nr, tstr2 );
                _freesafe( tstr2 );

                if ( m_push_output_return_code ) {
                    std::string s1 = AGUIXUtils::formatStringToString( "%d", WEXITSTATUS( exit_code ) );

                    if ( dodebug == true ) {
                        Requester req( Worker::getAGUIX() );
                        auto rs1 = AGUIXUtils::formatStringToString( catalog.getLocale( 485 ),
                                                                     s1.c_str(), stack_nr );
                        req.request( catalog.getLocale( 124 ), rs1.c_str(), catalog.getLocale( 11 ) );
                    }

                    wpu->push( stack_nr, s1 );
                }
              }
            } else {
              if ( tstr2 != NULL ) _freesafe( tstr2 );
              if ( Worker::getRequester() != NULL ) {
                char *reqstr;
                std::string error, str1;
                
                reqstr = (char*)_allocsafe( strlen( catalog.getLocale( 750 ) ) + res_str.size() + 1 );
                sprintf( reqstr, catalog.getLocale( 750 ), res_str.c_str() );
                
                ec->readErrorOutput( error, 1024 );
                
                str1 = reqstr;
                str1 += error;
                _freesafe( reqstr );

                RefCount<AFontWidth> lencalc( new AFontWidth( Worker::getAGUIX(), NULL ) );
                auto ts = std::make_shared< TextStorageString >( str1, lencalc );

                Worker::getRequester()->request( catalog.getLocale( 347 ), ts, catalog.getLocale( 11 ) );
              }
              wpu->continueAtLabel( NULL );
            }
          } else {
            if ( dodebug == true ) {
              Requester *req;
              req = new Requester( Worker::getAGUIX() );
              tstr3 = (char*)_allocsafe( strlen( catalog.getLocale( 485 ) ) +
                                         res_str.size() +
                                         A_BYTESFORNUMBER( stack_nr ) + 1 );
              sprintf( tstr3, catalog.getLocale( 485 ), res_str.c_str(), stack_nr );
              req->request( catalog.getLocale( 124 ), tstr3, catalog.getLocale( 11 ) );
              _freesafe( tstr3 );
              delete req;
            }
            wpu->push( stack_nr, res_str );
          }
        }
      }
      break;
    case SCRIPT_LABEL:
      /* nothing to do, label is just symbolic */
      break;
    case SCRIPT_IF:
      l = wpu->getCurrentLine();
      if ( if_test != NULL ) {
        erg = wpu->parse_if ( if_test );
        if ( dodebug == true ) {
          Requester *req;
          req = new Requester( Worker::getAGUIX() );
          char *tstr = (char*)_allocsafe( strlen( catalog.getLocale( 484 ) ) +
                                          strlen( if_test ) +
                                          A_BYTESFORNUMBER( erg ) + 1 );
          sprintf( tstr, catalog.getLocale( 484 ), if_test, erg );
          req->request( catalog.getLocale( 124 ), tstr, catalog.getLocale( 11 ) );
          _freesafe( tstr );
          delete req;
        }
        if ( erg == 1 ) {
          if ( wpu->continueAtLabel( if_label ) != 0 ) {
            Requester *req;
            req = new Requester( Worker::getAGUIX() );
            char *tstr = (char*)_allocsafe( strlen( catalog.getLocale( 459 ) ) +
                                            strlen( if_label ) +
                                            A_BYTESFORNUMBER( l ) + 1 );
            sprintf( tstr, catalog.getLocale( 459 ), if_label, l + 1 );
            req->request( catalog.getLocale( 347 ), tstr, catalog.getLocale( 11 ) );
            _freesafe( tstr );
            delete req;
          }
        } else if ( erg == 0 ) {
        } else {
          Requester *req;
          req = new Requester( Worker::getAGUIX() );
          char *tstr = (char*)_allocsafe( strlen( catalog.getLocale( 460 ) ) + A_BYTESFORNUMBER( l ) + 1 );
          sprintf( tstr, catalog.getLocale( 460 ), l + 1 );
          req->request( catalog.getLocale( 347 ), tstr, catalog.getLocale( 11 ) );
          _freesafe( tstr );
          delete req;
          wpu->continueAtLabel( NULL );
        }
      } else {
        Requester *req;
        req = new Requester( Worker::getAGUIX() );
        char *tstr = (char*)_allocsafe( strlen( catalog.getLocale( 460 ) ) + A_BYTESFORNUMBER( l ) + 1 );
        sprintf( tstr, catalog.getLocale( 460 ), l + 1 );
        req->request( catalog.getLocale( 347 ), tstr, catalog.getLocale( 11 ) );
        _freesafe( tstr );
        delete req;
        wpu->continueAtLabel( NULL );
      }
      break;
    case SCRIPT_END:
      // I use a "feature" of wpu: NULL label will jump to the end
      wpu->continueAtLabel( NULL );
      break;
    case SCRIPT_POP:
      wpu->pop( stack_nr );
      break;
    case SCRIPT_SETTINGS:
      wpu->setRecursive( wpu_recursive );
      wpu->setTakeDirs( wpu_take_dirs );
      break;
    case SCRIPT_WINDOW:
      switch ( wintype ) {
        case SCRIPT_WINDOW_OPEN:
          wpu->openWin();
          break;
        case SCRIPT_WINDOW_CLOSE:
          wpu->closeWin();
          break;
        default:
          break;
      }
      if ( change_progress == true ) {
        if ( progress != NULL ) {
          std::string res_str;
          if ( wpu->parse( progress, res_str, a_max( EXE_STRING_LEN - 1024, 256 ),
                           ( ( progress_useoutput == true ) ? true : false ),
                           WPUContext::PERSIST_ALL ) == WPUContext::PARSE_SUCCESS ) {
            if ( progress_useoutput == true ) {
              std::unique_ptr<ExeClass> ec( new ExeClass() );
              ec->cdDir( wpu->getBaseDir() );
              ec->addCommand( "%s", res_str.c_str() );
              tstr2 = ec->getOutput( &exeerror );
              
              if ( exeerror == 0 ) {
                if ( tstr2 != NULL ) {
                  res_str = tstr2;
                  _freesafe( tstr2 );
                } else {
                  res_str = "";
                }
              } else {
                if ( tstr2 != NULL ) _freesafe( tstr2 );
                if ( Worker::getRequester() != NULL ) {
                  char *reqstr;
                  std::string error, str1;
                  
                  reqstr = (char*)_allocsafe( strlen( catalog.getLocale( 751 ) ) + res_str.size() + 1 );
                  sprintf( reqstr, catalog.getLocale( 751 ), res_str.c_str() );
                  
                  ec->readErrorOutput( error, 1024 );
                  
                  str1 = reqstr;
                  str1 += error;
                  _freesafe( reqstr );
                  
                  RefCount<AFontWidth> lencalc( new AFontWidth( Worker::getAGUIX(), NULL ) );
                  auto ts = std::make_shared< TextStorageString >( str1, lencalc );
                  
                  Worker::getRequester()->request( catalog.getLocale( 347 ), ts, catalog.getLocale( 11 ) );
                }
                res_str = "";
              }
            }
            if ( ! res_str.empty() ) {
                l = atoi( res_str.c_str() );
                if ( l < 0 || l > 100 ) l = 0;
                wpu->setWinProgress( l );
            }
          }
        }
      }
      if ( change_text == true ) {
        if ( wintext != NULL ) {
          std::string res_str;
          bool valid = true;
          if ( wpu->parse( wintext, res_str, a_max( EXE_STRING_LEN - 1024, 256 ),
                           ( ( wintext_useoutput == true ) ? true : false ),
                           WPUContext::PERSIST_ALL ) == WPUContext::PARSE_SUCCESS ) {
            if ( wintext_useoutput == true ) {
              std::unique_ptr<ExeClass> ec( new ExeClass() );
              ec->cdDir( wpu->getBaseDir() );
              ec->addCommand( "%s", res_str.c_str() );
              tstr2 = ec->getOutput( &exeerror );
              
              if ( exeerror == 0 ) {
                if ( tstr2 != NULL ) {
                  res_str = tstr2;
                  _freesafe( tstr2 );
                } else {
                  res_str = "";
                  valid = false;
                }
              } else {
                if ( tstr2 != NULL ) _freesafe( tstr2 );
                if ( Worker::getRequester() != NULL ) {
                  char *reqstr;
                  std::string error, str1;
                  
                  reqstr = (char*)_allocsafe( strlen( catalog.getLocale( 751 ) ) + res_str.size() + 1 );
                  sprintf( reqstr, catalog.getLocale( 751 ), res_str.c_str() );
                  
                  ec->readErrorOutput( error, 1024 );
                  
                  str1 = reqstr;
                  str1 += error;
                  _freesafe( reqstr );
                  
                  RefCount<AFontWidth> lencalc( new AFontWidth( Worker::getAGUIX(), NULL ) );
                  auto ts = std::make_shared< TextStorageString >( str1, lencalc );
                  
                  Worker::getRequester()->request( catalog.getLocale( 347 ), ts, catalog.getLocale( 11 ) );
                }
                res_str = "";
                valid = false;
              }
            }
            if ( valid ) {
                wpu->setWinText( res_str.c_str() );
            }
          }
        }
      }
      break;
    case SCRIPT_GOTO:
      if ( wpu->continueAtLabel( label ) != 0 ) {
        if ( label != NULL ) {
          l = wpu->getCurrentLine();
          Requester *req;
          req = new Requester( Worker::getAGUIX() );
          char *tstr = (char*)_allocsafe( strlen( catalog.getLocale( 514 ) ) +
                                          strlen( label ) +
                                          A_BYTESFORNUMBER( l ) + 1 );
          sprintf( tstr, catalog.getLocale( 514 ), label, l + 1 );
          req->request( catalog.getLocale( 347 ), tstr, catalog.getLocale( 11 ) );
          _freesafe( tstr );
          delete req;
        }
      }
      break;
    case SCRIPT_EVALCOMMAND:
        if ( ! m_command_str.empty() ) {
            std::string res_str;

            if ( wpu->parse( m_command_str.c_str(), res_str, a_max( EXE_STRING_LEN - 1024, 256 ),
                             true,
                             WPUContext::PERSIST_NOTHING ) == WPUContext::PARSE_SUCCESS ) {
                Lister *l1 = msg->getWorker()->getActiveLister();
                if ( l1 != NULL ) {
                    ListerMode *lm1 = l1->getActiveMode();
                    if ( lm1 != NULL ) {
                        lm1->runCommandWithStrArgs( res_str );
                    }
                }
            }
        }
        break;
    default:
      break;
  }
  return 0;
}

const char *
ScriptOp::getDescription()
{
  int s = description_buf_size - 1;
  std::string str1;
  char buf[A_BYTESFORNUMBER(stack_nr)];
  
  sprintf( buf, "%d", stack_nr );
#if 1
  str1 = catalog.getLocale( 1285 );
  str1 += ": ";
#else
  str1 = "";
#endif
  switch( type ) {
    case SCRIPT_PUSH:
      str1 += "push ";
      if ( push_useoutput == true )
        str1 += "the output of ";
      str1 += ( push_string != NULL ) ? push_string : "";
      str1 += " at stack ";
      str1 += buf;

      if ( m_push_output_return_code ) {
          str1 += " (including return code)";
      }
      break;
    case SCRIPT_POP:
      str1 += "pop ";
      str1 += buf;
      break;
    case SCRIPT_LABEL:
      str1 += ( label != NULL ) ? label : "";
      str1 += ":";
      break;
    case SCRIPT_IF:
      str1 += "if ( ";
      str1 += ( if_test != NULL ) ? if_test : "";
      str1 += " ) then goto ";
      str1 += ( if_label != NULL ) ? if_label : "";
      break;
    case SCRIPT_END:
      str1 += "end";
      break;
    case SCRIPT_SETTINGS:
      str1 += "set recursive=";
      if ( wpu_recursive == true )
        str1 += "true, ";
      else
        str1 += "false, ";
      str1 += "take dirs=";
      if ( wpu_take_dirs == true )
        str1 += "true";
      else
        str1 += "false";
      break;
    case SCRIPT_WINDOW:
      str1 += "change user window";
      break;
    case SCRIPT_GOTO:
      str1 += "goto ";
      str1 += ( label != NULL ) ? label : "";
      break;
    case SCRIPT_EVALCOMMAND: {
        std::vector< std::string > v;
        str1 += "evaluate ";
        str1 += m_command_str;

        AGUIXUtils::split_string( v, m_command_str, ' ' );

        if ( ! v.empty() ) {
            auto res = wconfig->getWorker()->getCommandInfo( v[0], v.size() == 1 ? false : true );

            if ( ! res.name.empty() ) {
                str1 += " (";
                str1 += res.description;
                str1 += ")";
            }
        }

        break;
    }
    default:
      str1 += "nop";
      break;
  }
  strncpy( description_buf, str1.c_str(), s );
  description_buf[s] = '\0';
  return description_buf;
}

bool ScriptOp::isLabel( const char *str )
{
  if ( str != NULL ) {
    if ( type == SCRIPT_LABEL ) {
      if ( label != NULL ) {
        if ( strcmp( str, label ) == 0 ) return true;
      }
    }
  }
  return false;
}

void ScriptOp::setType( scriptop_type_t ntype )
{
  type = ntype;
}

void ScriptOp::setLabel( const char *nlabel )
{
  if ( label != NULL ) _freesafe( label );
  if ( nlabel != NULL ) {
    label = dupstring( nlabel );
  } else {
    label = NULL;
  }
}

void ScriptOp::setStackNr( int nv )
{
  if ( nv >= 0 ) {
    stack_nr = nv;
  }
}

void ScriptOp::setPushString( const char *nstr )
{
  if ( push_string != NULL ) _freesafe( push_string );
  if ( nstr != NULL ) {
    push_string = dupstring( nstr );
  } else {
    push_string = NULL;
  }
}

void ScriptOp::setPushUseOutput( bool nv )
{
  push_useoutput = nv;
}

void ScriptOp::setPushOutputReturnCode( bool nv )
{
    m_push_output_return_code = nv;
}

void ScriptOp::setIfTest( const char *nstr )
{
  if ( if_test != NULL ) _freesafe( if_test );
  if ( nstr != NULL ) {
    if_test = dupstring( nstr );
  } else {
    if_test = NULL;
  }
}

void ScriptOp::setIfLabel( const char *nstr )
{
  if ( if_label != NULL ) _freesafe( if_label );
  if ( nstr != NULL ) {
    if_label = dupstring( nstr );
  } else {
    if_label = NULL;
  }
}

ScriptOp::scriptop_type_t ScriptOp::getType()
{
  return type;
}

const char *ScriptOp::getLabel()
{
  return label;
}

int ScriptOp::getStackNr()
{
  return stack_nr;
}

const char *ScriptOp::getPushString()
{
  return push_string;
}

bool ScriptOp::getPushUseOutput()
{
  return push_useoutput;
}

const char *ScriptOp::getIfTest()
{
  return if_test;
}

const char *ScriptOp::getIfLabel()
{
  return if_label;
}

int ScriptOp::configure()
{
  AGUIX *aguix = Worker::getAGUIX();
  AWindow *win;
  FieldListView *lv;
  ChooseButton *chb;
  AGMessage *msg;
  int endmode=-1;
  char *tstr;
  char buf[ A_BYTESFORNUMBER( int ) ];
  AWindow *push_win, *label_win, *if_win, *nop_win, *pop_win, *end_win, *set_win, *win_win, *goto_win, *command_win;
  StringGadget *popsg;
  AWindow *winlist[10];
  int cur_win;
  int trow, i, tw, th;
  const int cincw = AContainer::ACONT_MINH +
                    AContainer::ACONT_MINW +
                    AContainer::ACONT_MAXH;
  const int cincwnr = cincw +
                      AContainer::ACONT_NORESIZE;
  const int cfix = AContainer::ACONT_MINH +
                   AContainer::ACONT_MINW +
                   AContainer::ACONT_MAXH +
                   AContainer::ACONT_MAXW;
  const int cfixnr = cfix + AContainer::ACONT_NORESIZE;
  const int cmin = AContainer::ACONT_MINH +
                   AContainer::ACONT_MINW;
  char **liness;
  int lines;
  
  tstr=(char*)_allocsafe(strlen(catalog.getLocale(293))+strlen(getName())+1);
  sprintf(tstr,catalog.getLocale(293),getName());
  win = new AWindow( aguix, 10, 10, 10, 10, tstr, AWindow::AWINDOW_DIALOG );
  win->create();
  _freesafe(tstr);

  AContainer *ac1 = win->setContainer( new AContainer( win, 1, 4 ), true );
  ac1->setMinSpace( 5 );
  ac1->setMaxSpace( 5 );

  ac1->add( new Text( aguix, 0, 0, catalog.getLocale( 461 ) ), 0, 0, cincwnr );

  lv = (FieldListView*)ac1->add( new FieldListView( aguix, 0, 0, 100, 50, 0 ), 0, 1, cincwnr );
  lv->setVBarState( 0 );
  lv->setHBarState( 0 );
  lv->setDisplayFocus( true );
  lv->setAcceptFocus( true );
  trow = lv->addRow();
  lv->setText( trow, 0, catalog.getLocale ( 462 ) );
  lv->setPreColors( trow, FieldListView::PRECOLOR_ONLYACTIVE );
  trow = lv->addRow();
  lv->setText( trow, 0, catalog.getLocale ( 463 ) );
  lv->setPreColors( trow, FieldListView::PRECOLOR_ONLYACTIVE );
  trow = lv->addRow();
  lv->setText( trow, 0, catalog.getLocale ( 464 ) );
  lv->setPreColors( trow, FieldListView::PRECOLOR_ONLYACTIVE );
  trow = lv->addRow();
  lv->setText( trow, 0, catalog.getLocale ( 465 ) );
  lv->setPreColors( trow, FieldListView::PRECOLOR_ONLYACTIVE );
  trow = lv->addRow();
  lv->setText( trow, 0, catalog.getLocale ( 466 ) );
  lv->setPreColors( trow, FieldListView::PRECOLOR_ONLYACTIVE );
  trow = lv->addRow();
  lv->setText( trow, 0, catalog.getLocale ( 467 ) );
  lv->setPreColors( trow, FieldListView::PRECOLOR_ONLYACTIVE );
  trow = lv->addRow();
  lv->setText( trow, 0, catalog.getLocale ( 486 ) );
  lv->setPreColors( trow, FieldListView::PRECOLOR_ONLYACTIVE );
  trow = lv->addRow();
  lv->setText( trow, 0, catalog.getLocale ( 488 ) );
  lv->setPreColors( trow, FieldListView::PRECOLOR_ONLYACTIVE );
  trow = lv->addRow();
  lv->setText( trow, 0, catalog.getLocale ( 515 ) );
  lv->setPreColors( trow, FieldListView::PRECOLOR_ONLYACTIVE );
  trow = lv->addRow();
  lv->setText( trow, 0, catalog.getLocale ( 988 ) );
  lv->setPreColors( trow, FieldListView::PRECOLOR_ONLYACTIVE );
  lv->maximizeX();
  lv->maximizeY();
  if ( type == SCRIPT_PUSH ) lv->setActiveRow( 1 );
  else if ( type == SCRIPT_POP ) lv->setActiveRow( 2 );
  else if ( type == SCRIPT_LABEL ) lv->setActiveRow( 3 );
  else if ( type == SCRIPT_IF ) lv->setActiveRow( 4 );
  else if ( type == SCRIPT_END ) lv->setActiveRow( 5 );
  else if ( type == SCRIPT_SETTINGS ) lv->setActiveRow( 6 );
  else if ( type == SCRIPT_WINDOW ) lv->setActiveRow( 7 );
  else if ( type == SCRIPT_GOTO ) lv->setActiveRow( 8 );
  else if ( type == SCRIPT_EVALCOMMAND ) lv->setActiveRow( 9 );
  else lv->setActiveRow( 0 );
  ac1->readLimits();

  push_win = new AWindow( aguix, 0, 0, 10, 10, "" );
  ac1->add( push_win, 0, 2, cmin );
  push_win->create();
  push_win->setBorderWidth( 0 );

  AContainer *push_win_ac1 = push_win->setContainer( new AContainer( push_win, 1, 6 ), true );
  push_win_ac1->setMinSpace( 5 );
  push_win_ac1->setMaxSpace( 5 );
  push_win_ac1->add( new Text( aguix, 0, 0, catalog.getLocale( 468 ) ), 0, 0, cincwnr );

  chb = (ChooseButton*)push_win_ac1->add( new ChooseButton( aguix, 0, 0,
							    ( push_useoutput == true ) ? 1 : 0,
							    catalog.getLocale( 469 ), LABEL_RIGHT, 0 ), 0, 1, cincwnr );
  auto push_rv_cb = push_win_ac1->addWidget( new ChooseButton( aguix, 0, 0,
                                                               ( m_push_output_return_code == true ) ? 1 : 0,
                                                               catalog.getLocale( 1529 ), LABEL_RIGHT, 0 ), 0, 2, cincwnr );

  AContainer *push_win_ac1_1 = push_win_ac1->add( new AContainer( push_win, 2, 1 ), 0, 3);
  push_win_ac1_1->setMinSpace( 5 );
  push_win_ac1_1->setMaxSpace( 5 );
  push_win_ac1_1->setBorderWidth( 0 );

  sprintf( buf, "%d", stack_nr );
  push_win_ac1_1->add( new Text( aguix, 0, 0, catalog.getLocale( 470 ) ), 0, 0, cfix );
  StringGadget *psnsg = (StringGadget*)push_win_ac1_1->add( new StringGadget( aguix,
									      0,
									      0,
									      100,
									      buf,
									      0 ), 1, 0, cincw );

  AContainer *push_win_ac1_2 = push_win_ac1->add( new AContainer( push_win, 3, 1 ), 0, 4 );
  push_win_ac1_2->setMinSpace( 5 );
  push_win_ac1_2->setMaxSpace( 5 );
  push_win_ac1_2->setBorderWidth( 0 );

  push_win_ac1_2->add( new Text( aguix, 0, 0, catalog.getLocale( 471 ) ), 0, 0, cfix );
  StringGadget *pssg = (StringGadget*)push_win_ac1_2->add( new StringGadget( aguix,
									     0,
									     0,
									     100,
									     ( push_string != NULL ) ? push_string : "",
									     0 ), 1, 0, cincw );
  Button *psb = (Button*)push_win_ac1_2->add( new Button( aguix,
							  0,
							  0,
							  "F",
							  0 ), 2, 0, cfix );
  
  ChooseButton *pdcb = (ChooseButton*)push_win_ac1->add( new ChooseButton( aguix,
									   0,
									   0,
									   dodebug,
									   catalog.getLocale( 474 ),
									   LABEL_RIGHT,
									   0 ), 0, 5, cincwnr );
  
  pop_win = new AWindow( aguix, 0, 0, 10, 10, "" );
  ac1->add( pop_win, 0, 2, cmin );
  pop_win->create();
  pop_win->setBorderWidth( 0 );

  AContainer *pop_win_ac1 = pop_win->setContainer( new AContainer( pop_win, 1, 2 ), true );
  pop_win_ac1->setMinSpace( 5 );
  pop_win_ac1->setMaxSpace( 5 );

  pop_win_ac1->add( new Text( aguix, 0, 0, catalog.getLocale( 472 ) ), 0, 0, cincwnr  );

  AContainer *pop_win_ac1_1 = pop_win_ac1->add( new AContainer( pop_win, 2, 1 ), 0, 1 );
  pop_win_ac1_1->setMinSpace( 5 );
  pop_win_ac1_1->setMaxSpace( 5 );
  pop_win_ac1_1->setBorderWidth( 0 );

  sprintf( buf, "%d", stack_nr );
  pop_win_ac1_1->add( new Text( aguix, 0, 0, catalog.getLocale( 470 ) ), 0, 0, cfix );
  popsg = (StringGadget*)pop_win_ac1_1->add( new StringGadget( aguix,
							       0,
							       0,
							       100,
							       buf,
							       0 ), 1, 0, cincw );
  
  label_win = new AWindow( aguix, 0, 0, 10, 10, "" );
  ac1->add( label_win, 0, 2, cmin );
  label_win->create();
  label_win->setBorderWidth( 0 );

  AContainer *label_win_ac1 = label_win->setContainer( new AContainer( label_win, 2, 1 ), true );
  label_win_ac1->setMinSpace( 5 );
  label_win_ac1->setMaxSpace( 5 );

  label_win_ac1->add( new Text( aguix, 0, 0, catalog.getLocale( 475 ) ), 0, 0, cfix );
  StringGadget *labelsg = (StringGadget*)label_win_ac1->add( new StringGadget( aguix,
									       0,
									       0,
									       100,
									       ( label != NULL ) ? label : "",
									       0 ), 1, 0, cincw );

  
  nop_win = new AWindow( aguix, 0, 0, 10, 10, "" );
  ac1->add( nop_win, 0, 2, cmin );
  nop_win->create();
  nop_win->setBorderWidth( 0 );

  AContainer *nop_win_ac1 = nop_win->setContainer( new AContainer( nop_win, 1, 1 ), true );
  ac1->setMinSpace( 5 );
  ac1->setMaxSpace( 5 );

  nop_win_ac1->add( new Text( aguix, 0, 0, catalog.getLocale( 476 ) ), 0, 0, cincwnr );
  
  end_win = new AWindow( aguix, 0, 0, 10, 10, "" );
  ac1->add( end_win, 0, 2, cmin );
  end_win->create();
  end_win->setBorderWidth( 0 );

  AContainer *end_win_ac1 = end_win->setContainer( new AContainer( end_win, 1, 1 ), true );
  end_win_ac1->setMinSpace( 5 );
  end_win_ac1->setMaxSpace( 5 );

  end_win_ac1->add( new Text( aguix, 0, 0, catalog.getLocale( 477 ) ), 0, 0, cincwnr );
  
  if_win = new AWindow( aguix, 0, 0, 10, 10, "" );
  ac1->add( if_win, 0, 2, cmin );
  if_win->create();
  if_win->setBorderWidth( 0 );

  AContainer *if_win_ac1 = if_win->setContainer( new AContainer( if_win, 1, 4 ), true );
  if_win_ac1->setMinSpace( 5 );
  if_win_ac1->setMaxSpace( 5 );

  AContainer *if_win_ac1_1 = if_win_ac1->add( new AContainer( if_win, 2, 1 ), 0, 0 );
  if_win_ac1_1->setMinSpace( 5 );
  if_win_ac1_1->setMaxSpace( 5 );
  if_win_ac1_1->setBorderWidth( 0 );

  if_win_ac1_1->add( new Text( aguix, 0, 0, catalog.getLocale( 478 ) ), 0, 0, cfix );
  Button *ifhelpb = (Button*)if_win_ac1_1->add( new Button( aguix, 0, 0, catalog.getLocale( 483 ), 0 ), 1, 0, cincw );

  AContainer *if_win_ac1_2 = if_win_ac1->add( new AContainer( if_win, 3, 1 ), 0, 1 );
  if_win_ac1_2->setMinSpace( 5 );
  if_win_ac1_2->setMaxSpace( 5 );
  if_win_ac1_2->setBorderWidth( 0 );

  if_win_ac1_2->add( new Text( aguix, 0, 0, catalog.getLocale( 479 ) ), 0, 0, cfix );
  StringGadget *iftsg = (StringGadget*)if_win_ac1_2->add( new StringGadget( aguix,
									    0,
									    0,
									    100,
									    ( if_test != NULL ) ? if_test : "",
									    0 ), 1, 0, cincw );
  Button *iftb = (Button*)if_win_ac1_2->add( new Button( aguix,
							 0,
							 0,
							 "F",
							 0 ), 2, 0, cfix );

  AContainer *if_win_ac1_3 = if_win_ac1->add( new AContainer( if_win, 2, 1 ), 0, 2 );
  if_win_ac1_3->setMinSpace( 5 );
  if_win_ac1_3->setMaxSpace( 5 );
  if_win_ac1_3->setBorderWidth( 0 );

  if_win_ac1_3->add( new Text( aguix, 0, 0, catalog.getLocale( 475 ) ), 0, 0, cfix );
  StringGadget *iflsg = (StringGadget*)if_win_ac1_3->add( new StringGadget( aguix,
									    0,
									    0,
									    100,
									    ( if_label != NULL ) ? if_label : "",
									    0 ), 1, 0, cincw );

  ChooseButton *idcb = (ChooseButton*)if_win_ac1->add( new ChooseButton( aguix,
									 0,
									 0,
									 dodebug,
									 catalog.getLocale( 474 ),
									 LABEL_RIGHT,
									 0 ), 0, 3, cincwnr );

  
  set_win = new AWindow( aguix, 0, 0, 10, 10, "" );
  ac1->add( set_win, 0, 2, cmin );
  set_win->create();
  set_win->setBorderWidth( 0 );

  lines = createLines( catalog.getLocale( 487 ), &liness );

  AContainer *set_win_ac1 = set_win->setContainer( new AContainer( set_win, 1, lines + 2 ), true );
  set_win_ac1->setMinSpace( 5 );
  set_win_ac1->setMaxSpace( 5 );

  for ( i = 0; i < lines; i++ ) {
    set_win_ac1->add( new Text( aguix, 0, 0, liness[i] ), 0, i, cincwnr );
  }

  for ( i = 0; i < lines; i++ ) _freesafe( liness[i] );
  _freesafe( liness );

  ChooseButton *setrcb = (ChooseButton*)set_win_ac1->add( new ChooseButton( aguix,
									    0,
									    0,
									    wpu_recursive,
									    catalog.getLocale( 330 ),
									    LABEL_RIGHT,
									    0 ), 0, lines, cincwnr );

  ChooseButton *settdcb = (ChooseButton*)set_win_ac1->add( new ChooseButton( aguix,
									     0,
									     0,
									     wpu_take_dirs,
									     catalog.getLocale( 513 ),
									     LABEL_RIGHT,
									     0 ), 0, lines + 1, cincwnr );
  
  win_win = new AWindow( aguix, 0, 0, 10, 10, "" );
  ac1->add( win_win, 0, 2, cmin );
  win_win->create();
  win_win->setBorderWidth( 0 );

  AContainer *win_win_ac1 = win_win->setContainer( new AContainer( win_win, 1, 4 ), true );
  win_win_ac1->setMinSpace( 5 );
  win_win_ac1->setMaxSpace( 5 );

  Button *winhelpb = (Button*)win_win_ac1->add( new Button( aguix, 0, 0, catalog.getLocale( 483 ), 0 ), 0, 0, cincwnr );

  AContainer *win_win_ac1_1 = win_win_ac1->add( new AContainer( win_win, 2, 1 ), 0, 1 );
  win_win_ac1_1->setMinSpace( 5 );
  win_win_ac1_1->setMaxSpace( 5 );
  win_win_ac1_1->setBorderWidth( 0 );

  ChooseButton *cwcb = (ChooseButton*)win_win_ac1_1->add( new ChooseButton( aguix, 0, 0,
									    ( wintype == SCRIPT_WINDOW_LEAVE ) ? 0 : 1,
									    catalog.getLocale( 490 ), LABEL_RIGHT, 0 ), 0, 0, cfixnr );
  CycleButton *cwcycb = (CycleButton*)win_win_ac1_1->add( new CycleButton( aguix, 0, 0, 100, 0 ), 1, 0, cincw );
  cwcycb->addOption( catalog.getLocale( 491 ) );
  cwcycb->addOption( catalog.getLocale( 492 ) );
  cwcycb->resize( cwcycb->getMaxSize(), cwcycb->getHeight() );
  if ( wintype == SCRIPT_WINDOW_CLOSE ) cwcycb->setOption( 1 );
  else cwcycb->setOption( 0 );
  win_win_ac1_1->readLimits();

  AContainerBB *win_win_ac1_2 = static_cast<AContainerBB*>( win_win_ac1->add( new AContainerBB( win_win, 1, 2 ), 0, 2 ) );
  win_win_ac1_2->setMinSpace( 5 );
  win_win_ac1_2->setMaxSpace( 5 );

  ChooseButton *cpcb = (ChooseButton*)win_win_ac1_2->add( new ChooseButton( aguix, 0, 0,
									    ( change_progress == true ) ? 1 : 0,
									    catalog.getLocale( 493 ), LABEL_RIGHT, 0 ), 0, 0, cincwnr );
  AContainer *win_win_ac1_2_1 = win_win_ac1_2->add( new AContainer( win_win, 2, 2 ), 0, 1 );
  win_win_ac1_2_1->setMinSpace( 5 );
  win_win_ac1_2_1->setMaxSpace( 5 );
  win_win_ac1_2_1->setBorderWidth( 0 );
  win_win_ac1_2_1->setMinWidth( 5, 0, 0 );
  win_win_ac1_2_1->setMaxWidth( 5, 0, 0 );

  AContainer *win_win_ac1_2_1_1 = win_win_ac1_2_1->add( new AContainer( win_win, 3, 1 ), 1, 0 );
  win_win_ac1_2_1_1->setMinSpace( 5 );
  win_win_ac1_2_1_1->setMaxSpace( 5 );

  win_win_ac1_2_1_1->add( new Text( aguix, 0, 0, catalog.getLocale( 494 ) ), 0, 0, cfix );
  StringGadget *prosg = (StringGadget*)win_win_ac1_2_1_1->add( new StringGadget( aguix,
										 0,
										 0,
										 100,
										 ( progress != NULL ) ? progress : "",
										 0 ), 1, 0, cincw );
  Button *prob = (Button*)win_win_ac1_2_1_1->add( new Button( aguix,
							      0,
							      0,
							      "F",
							      0 ), 2, 0, cfix );

  ChooseButton *prouocb = (ChooseButton*)win_win_ac1_2_1->add( new ChooseButton( aguix, 0, 0,
										 ( progress_useoutput == true ) ? 1 : 0,
										 catalog.getLocale( 495 ), LABEL_RIGHT, 0 ), 1, 1, cincwnr );

  AContainerBB *win_win_ac1_3 = static_cast<AContainerBB*>( win_win_ac1->add( new AContainerBB( win_win, 1, 2 ), 0, 3 ) );
  win_win_ac1_3->setMinSpace( 5 );
  win_win_ac1_3->setMaxSpace( 5 );

  ChooseButton *cwtcb = (ChooseButton*)win_win_ac1_3->add( new ChooseButton( aguix, 0, 0,
									     ( change_text == true ) ? 1 : 0,
									     catalog.getLocale( 496 ), LABEL_RIGHT, 0 ), 0, 0, cincwnr );

  AContainer *win_win_ac1_3_1 = win_win_ac1_3->add( new AContainer( win_win, 2, 2 ), 0, 1 );
  win_win_ac1_3_1->setMinSpace( 5 );
  win_win_ac1_3_1->setMaxSpace( 5 );
  win_win_ac1_3_1->setBorderWidth( 0 );
  win_win_ac1_3_1->setMinWidth( 5, 0, 0 );
  win_win_ac1_3_1->setMaxWidth( 5, 0, 0 );

  AContainer *win_win_ac1_3_1_1 = win_win_ac1_3_1->add( new AContainer( win_win, 3, 1 ), 1, 0 );
  win_win_ac1_3_1_1->setMinSpace( 5 );
  win_win_ac1_3_1_1->setMaxSpace( 5 );

  win_win_ac1_3_1_1->add( new Text( aguix, 0, 0, catalog.getLocale( 497 ) ), 0, 0, cfix );
  StringGadget *wintextsg = (StringGadget*)win_win_ac1_3_1_1->add( new StringGadget( aguix,
										     0,
										     0,
										     100,
										     ( wintext != NULL ) ? wintext : "",
										     0 ), 1, 0, cincw );
  Button *wintextb = (Button*)win_win_ac1_3_1_1->add( new Button( aguix,
								  0,
								  0,
								  "F",
								  0 ), 2, 0, cfix );

  ChooseButton *wintextuocb = (ChooseButton*)win_win_ac1_3_1->add( new ChooseButton( aguix, 0, 0,
										     ( wintext_useoutput == true ) ? 1 : 0,
										     catalog.getLocale( 498 ), LABEL_RIGHT, 0 ), 1, 1, cincwnr );

  
  goto_win = new AWindow( aguix, 0, 0, 10, 10, "" );
  ac1->add( goto_win, 0, 2, cmin );
  goto_win->create();
  goto_win->setBorderWidth( 0 );

  AContainer *goto_win_ac1 = goto_win->setContainer( new AContainer( goto_win, 2, 1 ), true );
  goto_win_ac1->setMinSpace( 5 );
  goto_win_ac1->setMaxSpace( 5 );
  
  goto_win_ac1->add( new Text( aguix, 0, 0, catalog.getLocale( 475 ) ), 0, 0, cfix );
  StringGadget *gotosg = (StringGadget*)goto_win_ac1->add( new StringGadget( aguix,
									     0,
									     0,
									     100,
									     ( label != NULL ) ? label : "",
									     0 ), 1, 0, cincw );
  
  command_win = new AWindow( aguix, 0, 0, 10, 10, "" );
  ac1->add( command_win, 0, 2, cmin );
  command_win->create();
  command_win->setBorderWidth( 0 );

  AContainer *command_win_ac1 = command_win->setContainer( new AContainer( command_win, 1, 2 ), true );
  command_win_ac1->setMinSpace( 5 );
  command_win_ac1->setMaxSpace( 5 );
  command_win_ac1->add( new Text( aguix, 0, 0, catalog.getLocale( 989 ) ), 0, 0, cincwnr );

  AContainer *command_win_ac1_2 = command_win_ac1->add( new AContainer( command_win, 5, 1 ), 0, 1 );
  command_win_ac1_2->setMinSpace( 0 );
  command_win_ac1_2->setMaxSpace( 0 );
  command_win_ac1_2->setBorderWidth( 0 );

  command_win_ac1_2->add( new Text( aguix, 0, 0, catalog.getLocale( 990 ) ), 0, 0, cfix );
  command_win_ac1_2->setMaxWidth( 5, 1, 0 );
  StringGadget *cmdsg = (StringGadget*)command_win_ac1_2->add( new StringGadget( aguix,
                                                                                 0,
                                                                                 0,
                                                                                 100,
                                                                                 m_command_str.c_str(),
                                                                                 0 ), 2, 0, cincw );
  Button *cmd_command_b = command_win_ac1_2->addWidget( new Button( aguix,
                                                                    0,
                                                                    0,
                                                                    "C",
                                                                    0 ), 3, 0, cfix );
  Button *cmd_flag_b = (Button*)command_win_ac1_2->add( new Button( aguix,
                                                                 0,
                                                                 0,
                                                                 "F",
                                                                 0 ), 4, 0, cfix );

  AContainer *ac1_2 = ac1->add( new AContainer( win, 2, 1 ), 0, 3 );
  ac1_2->setMinSpace( 5 );
  ac1_2->setMaxSpace( -1 );
  ac1_2->setBorderWidth( 0 );
  Button *okb =(Button*)ac1_2->add( new Button( aguix,
                                                0,
                                                0,
                                                catalog.getLocale( 11 ),
                                                0 ), 0, 0, cfix );
  Button *cb = (Button*)ac1_2->add( new Button( aguix,
						0,
						0,
						catalog.getLocale( 8 ),
						0 ), 1, 0, cfix );

  win->setDoTabCycling( true );

  winlist[0] = nop_win;
  winlist[1] = push_win;
  winlist[2] = pop_win;
  winlist[3] = label_win;
  winlist[4] = if_win;
  winlist[5] = end_win;
  winlist[6] = set_win;
  winlist[7] = win_win;
  winlist[8] = goto_win;
  winlist[9] = command_win;

  tw = 0;
  th = 0;
  AWindow *twin;
  for ( i = 0; i < 10; i++ ) {
    twin = winlist[i];
    twin->contMaximize();
    if ( twin->getWidth() > tw ) tw = twin->getWidth();
    if ( twin->getHeight() > th ) th = twin->getHeight();
  }
  ac1->setMinWidth( tw, 0, 2 );
  ac1->setMinHeight( th, 0, 2 );

  win->contMaximize( true );
  
  switch( type ) {
    case SCRIPT_PUSH:
      cur_win = 1;
      break;
    case SCRIPT_POP:
      cur_win = 2;
      break;
    case SCRIPT_LABEL:
      cur_win = 3;
      break;
    case SCRIPT_IF:
      cur_win = 4;
      break;
    case SCRIPT_END:
      cur_win = 5;
      break;
    case SCRIPT_SETTINGS:
      cur_win = 6;
      break;
    case SCRIPT_WINDOW:
      cur_win = 7;
      break;
    case SCRIPT_GOTO:
      cur_win = 8;
      break;
    case SCRIPT_EVALCOMMAND:
      cur_win = 9;
      break;
    default:
      cur_win = 0;
      break;
  }
  for ( i = 0; i < 10; i++ ) {
    if ( i != cur_win )
      winlist[i]->hide();
    else {
      winlist[i]->show();
      ac1->add( winlist[i], 0, 2 );
      ac1->rearrange();
    }
  }
  
  win->show();
  for(;endmode==-1;) {
    msg=aguix->WaitMessage(win);
    if(msg!=NULL) {
      switch(msg->type) {
        case AG_CLOSEWINDOW:
          if(msg->closewindow.window==win->getWindow()) endmode=1;
          break;
        case AG_BUTTONCLICKED:
          if(msg->button.button==okb) endmode=0;
          else if(msg->button.button==cb) endmode=1;
          else if ( msg->button.button == psb ) {
            tstr = getPushFlag();
            if ( tstr != NULL ) {
              pssg->insertAtCursor( tstr );
              _freesafe( tstr );
            }
          } else if ( msg->button.button == iftb ) {
            tstr = getIfFlag();
            if ( tstr != NULL ) {
              iftsg->insertAtCursor( tstr );
              _freesafe( tstr );
            }
          } else if ( msg->button.button == prob ) {
            tstr = getPushFlag();
            if ( tstr != NULL ) {
              prosg->insertAtCursor( tstr );
              _freesafe( tstr );
            }
          } else if ( msg->button.button == wintextb ) {
            tstr = getPushFlag();
            if ( tstr != NULL ) {
              wintextsg->insertAtCursor( tstr );
              _freesafe( tstr );
            }
          } else if ( msg->button.button == ifhelpb ) {
            Requester *req = new Requester( aguix );
            req->request( catalog.getLocale( 124 ), catalog.getLocale( 482 ), catalog.getLocale( 11 ) );
            delete req;
          } else if ( msg->button.button == winhelpb ) {
            Requester *req = new Requester( aguix );
            req->request( catalog.getLocale( 124 ), catalog.getLocale( 489 ), catalog.getLocale( 11 ) );
            delete req;
          } else if ( msg->button.button == cmd_flag_b ) {
            tstr = getPushFlag();
            if ( tstr != NULL ) {
              cmdsg->insertAtCursor( tstr );
              _freesafe( tstr );
            }
          } else if ( msg->button.button == cmd_command_b ) {
            tstr = getRegisteredCommand();
            if ( tstr != NULL ) {
              cmdsg->insertAtCursor( tstr );
              _freesafe( tstr );
            }
          }
          break;
        case AG_FIELDLV_ONESELECT:
        case AG_FIELDLV_MULTISELECT:
          if ( msg->fieldlv.lv == lv ) {
            cur_win = lv->getActiveRow();
            if ( ( cur_win < 0 ) || ( cur_win > 9 ) ) cur_win = 0;
	    for ( i = 0; i < 10; i++ ) {
	      if ( i != cur_win )
		winlist[i]->hide();
	      else {
		winlist[i]->show();
		ac1->add( winlist[i], 0, 2 );
		ac1->rearrange();
	      }
	    }
          }
          break;
          case AG_KEYPRESSED:
            if ( win->isParent( msg->key.window, false ) == true ) {
                switch ( msg->key.key ) {
                    case XK_Escape:
                        endmode = 1;
                        break;
                }
            }
            break;
      }
      aguix->ReplyMessage(msg);
    }
  }
  
  if ( endmode == 0 ) {
    // ok
    switch ( lv->getActiveRow() ) {
      case 1:
        type = SCRIPT_PUSH;
        if ( chb->getState() == true ) push_useoutput = true;
        else push_useoutput = false;
        m_push_output_return_code = push_rv_cb->getState();
        stack_nr = atoi( psnsg->getText() );
        if ( stack_nr < 0 ) stack_nr = 0;
        setPushString( pssg->getText() );
        setDoDebug( pdcb->getState() );
        break;
      case 2:
        type = SCRIPT_POP;
        stack_nr = atoi( popsg->getText() );
        if ( stack_nr < 0 ) stack_nr = 0;
        break;
      case 3:
        type = SCRIPT_LABEL;
        setLabel( labelsg->getText() );
        break;
      case 4:
        type = SCRIPT_IF;
        setIfTest( iftsg->getText() );
        setIfLabel( iflsg->getText() );
        setDoDebug( idcb->getState() );
        break;
      case 5:
        type = SCRIPT_END;
        break;
      case 6:
        type = SCRIPT_SETTINGS;
        setWPURecursive( setrcb->getState() );
        setWPUTakeDirs( settdcb->getState() );
        break;
      case 7:
        type = SCRIPT_WINDOW;
        if ( cwcb->getState() == true ) {
          switch ( cwcycb->getSelectedOption() ) {
            case 1:
              setWinType( SCRIPT_WINDOW_CLOSE );
              break;
            default:
              setWinType( SCRIPT_WINDOW_OPEN );
              break;
          }
        } else {
          setWinType( SCRIPT_WINDOW_LEAVE );
        }
        if ( cpcb->getState() == true ) {
          setChangeProgress( true );
          setProgress( prosg->getText() );
          setProgressUseOutput( prouocb->getState() );
        } else {
          setChangeProgress( false );
        }
        if ( cwtcb->getState() == true ) {
          setChangeText( true );
          setWinText( wintextsg->getText() );
          setWinTextUseOutput( wintextuocb->getState() );
        } else {
          setChangeText( false );
        }
        break;
      case 8:
        type = SCRIPT_GOTO;
        setLabel( gotosg->getText() );
        break;
      case 9:
        type = SCRIPT_EVALCOMMAND;
        setCommandStr( cmdsg->getText() );
        break;
      default:
        type = SCRIPT_NOP;
        break;
    }
  }
  delete win;

  return endmode;
}

bool ScriptOp::save(Datei *fh)
{
  if ( fh == NULL ) return false;
  switch(type) {
    case SCRIPT_PUSH:
      fh->configPutPair( "type", "push" );
      break;
    case SCRIPT_LABEL:
      fh->configPutPair( "type", "label" );
      break;
    case SCRIPT_IF:
      fh->configPutPair( "type", "if" );
      break;
    case SCRIPT_END:
      fh->configPutPair( "type", "end" );
      break;
    case SCRIPT_POP:
      fh->configPutPair( "type", "pop" );
      break;
    case SCRIPT_SETTINGS:
      fh->configPutPair( "type", "settings" );
      break;
    case SCRIPT_WINDOW:
      fh->configPutPair( "type", "window" );
      break;
    case SCRIPT_GOTO:
      fh->configPutPair( "type", "goto" );
      break;
    case SCRIPT_EVALCOMMAND:
      fh->configPutPair( "type", "evalcommand" );
      break;
    default:
      fh->configPutPair( "type", "nop" );
      break;
  }
  fh->configPutPairBool( "pushuseoutput", push_useoutput );
  if ( m_push_output_return_code ) {
      fh->configPutPairBool( "pushoutputreturncode", m_push_output_return_code );
  }
  fh->configPutPairBool( "dodebug", dodebug );
  fh->configPutPairBool( "wpurecursive", wpu_recursive );
  fh->configPutPairBool( "wputakedirs", wpu_take_dirs );
  fh->configPutPairNum( "stacknr", stack_nr );
  if ( label != NULL ) {
    fh->configPutPairString( "label", label );
  }
  if ( push_string != NULL ) {
    fh->configPutPairString( "pushstring", push_string );
  }
  if ( if_test != NULL ) {
    fh->configPutPairString( "iftest", if_test );
  }
  if ( if_label != NULL ) {
    fh->configPutPairString( "iflabel", if_label );
  }

  switch ( wintype ) {
    case SCRIPT_WINDOW_OPEN:
      fh->configPutPair( "wintype", "open" );
      break;
    case SCRIPT_WINDOW_CLOSE:
      fh->configPutPair( "wintype", "close" );
      break;
    default:
      fh->configPutPair( "wintype", "leave" );
      break;
  }
  fh->configPutPairBool( "changeprogress", change_progress );
  fh->configPutPairBool( "changetext", change_text );
  fh->configPutPairBool( "progressuseoutput", progress_useoutput );
  fh->configPutPairBool( "wintextuseoutput", wintext_useoutput );
  if ( progress != NULL ) {
    fh->configPutPairString( "progress", progress );
  }
  if ( wintext != NULL ) {
    fh->configPutPairString( "wintext", wintext );
  }

  if ( ! m_command_str.empty() ) {
      fh->configPutPairString( "commandstring", m_command_str.c_str() );
  }

  return true;
}

char *ScriptOp::getPushFlag()
{
  OwnOp *o;
  char *tstr;
  
  o = new OwnOp();
  tstr = o->getFlag();
  delete o;
  return tstr;
}

char *ScriptOp::getIfFlag()
{
  AGUIX *aguix = Worker::getAGUIX();
  AWindow *win;
  FieldListView *lv;
  AGMessage *msg;
  int endmode=-1;
  char *returnstr;
  int i, trow, nr, nr2;
  
  win = new AWindow( aguix, 10, 10, 10, 10, catalog.getLocale( 338 ), AWindow::AWINDOW_DIALOG );
  win->create();

  AContainer *ac1 = win->setContainer( new AContainer( win, 1, 3 ), true );
  ac1->setMinSpace( 5 );
  ac1->setMaxSpace( 5 );
  ac1->setBorderWidth( 5 );

  win->addMultiLineText( catalog.getLocale( 481 ), *ac1, 0, 0, NULL, NULL );

  lv = (FieldListView*)ac1->add( new FieldListView( aguix,
                                                    0,
                                                    0,
                                                    400,
                                                    300,
                                                    0 ),
                                 0, 1, AContainer::CO_MIN );
  lv->setHBarState(2);
  lv->setVBarState(2);

  lv->setNrOfFields( 3 );
  lv->setFieldWidth( 1, 3 );
  
  nr = sizeof( scriptop_flags ) / sizeof( scriptop_flags[0] );
  nr2 = sizeof( ownop_flags ) / sizeof( ownop_flags[0] );
  
  for ( i = 0; i < nr; i++ ) {
    trow = lv->addRow();
    lv->setText( trow, 0, scriptop_flags[i].flag );
    lv->setText( trow, 2, catalog.getLocaleFlag( scriptop_flags[i].catcode ) );
    lv->setPreColors( trow, FieldListView::PRECOLOR_ONLYACTIVE );
    lv->setData( trow, i );
  }
  
  for( i = 0; i < nr2; i++ ) {
    trow = lv->addRow();
    lv->setText( trow, 0, ownop_flags[ i ].flag );
    lv->setText( trow, 2, catalog.getLocaleFlag( ownop_flags[ i ].catcode ) );
    lv->setPreColors( trow, FieldListView::PRECOLOR_ONLYACTIVE );
    lv->setData( trow, i + nr );
  }

  AContainer *ac1_1 = ac1->add( new AContainer( win, 2, 1 ), 0, 2 );
  ac1_1->setMinSpace( 5 );
  ac1_1->setMaxSpace( -1 );
  ac1_1->setBorderWidth( 0 );
  Button *okb =(Button*)ac1_1->add( new Button( aguix,
                                                0,
                                                0,
                                                catalog.getLocale( 11 ),
                                                0 ), 0, 0, AContainer::CO_FIX );
  Button *cancelb = (Button*)ac1_1->add( new Button( aguix,
						     0,
						     0,
						     catalog.getLocale( 8 ),
						     0 ), 1, 0, AContainer::CO_FIX );

  win->setDoTabCycling( true );
  win->contMaximize( true );
  win->show();
  for(;endmode==-1;) {
    msg=aguix->WaitMessage(win);
    if(msg!=NULL) {
      switch(msg->type) {
        case AG_CLOSEWINDOW:
          if(msg->closewindow.window==win->getWindow()) endmode=1;
          break;
        case AG_BUTTONCLICKED:
          if(msg->button.button==okb) endmode=0;
          else if(msg->button.button==cancelb) endmode=1;
          break;
      }
      aguix->ReplyMessage(msg);
    }
  }
  
  returnstr=NULL;
  if(endmode==0) {
    // ok
    trow = lv->getActiveRow();
    if ( lv->isValidRow( trow ) == true ) {
      i = lv->getData( trow, 0 );
      if ( i >= nr ) {
        returnstr = dupstring( ownop_flags[i - nr].flag );
      } else {
        returnstr = dupstring( scriptop_flags[i].flag );
      }
    }
  }
  
  delete win;

  return returnstr;
}

char *ScriptOp::getRegisteredCommand()
{
  AGUIX *aguix = Worker::getAGUIX();
  AWindow *win;
  FieldListView *lv;
  AGMessage *msg;
  int endmode=-1;
  char *returnstr;
  
  win = new AWindow( aguix, 10, 10, 10, 10, catalog.getLocale( 1318 ), AWindow::AWINDOW_DIALOG );
  win->create();

  AContainer *ac1 = win->setContainer( new AContainer( win, 1, 3 ), true );
  ac1->setMinSpace( 5 );
  ac1->setMaxSpace( 5 );
  ac1->setBorderWidth( 5 );

  win->addMultiLineText( catalog.getLocale( 1038 ), *ac1, 0, 0, NULL, NULL );

  lv = (FieldListView*)ac1->add( new FieldListView( aguix,
                                                    0,
                                                    0,
                                                    600,
                                                    300,
                                                    0 ),
                                 0, 1, AContainer::CO_MIN );
  lv->setHBarState(2);
  lv->setVBarState(2);
  lv->setDefaultColorMode( FieldListView::PRECOLOR_ONLYACTIVE );
  lv->setNrOfFields( 3 );
  lv->setGlobalFieldSpace( 5 );
  lv->setDisplayFocus( true );
  lv->setAcceptFocus( true );
  lv->setShowHeader( true );
  lv->setFieldText( 0, catalog.getLocale( 951 ) );
  lv->setFieldText( 1, catalog.getLocale( 1319 ) );
  lv->setFieldText( 2, catalog.getLocale( 1391 ) );

  {
      Lister *l1 = wconfig->getWorker()->getLister( 0 );
                
      if ( l1 != NULL ) {
          ListerMode *lm1 = l1->getActiveMode();

          if ( lm1 != NULL ) {
              auto l = lm1->getListOfCommandsWithoutArgs();
              for ( auto &e : lm1->getListOfCommandsWithArgs() ) {
                  l.push_back( e );
              }

              l.sort( []( const auto &lhs,
                          const auto &rhs ) {
                  return lhs.name < rhs.name;
              } );

              for ( auto &e : l ) {
                  int trow = lv->addRow();
                  lv->setText( trow, 0, e.name );
                  lv->setText( trow, 1, e.description );

                  if ( e.has_args ) {
                      lv->setText( trow, 2, catalog.getLocale( 801 ) );
                  } else {
                      lv->setText( trow, 2, catalog.getLocale( 802 ) );
                  }
              }
          }
      }
  }
  
  AContainer *ac1_1 = ac1->add( new AContainer( win, 2, 1 ), 0, 2 );
  ac1_1->setMinSpace( 5 );
  ac1_1->setMaxSpace( -1 );
  ac1_1->setBorderWidth( 0 );
  Button *okb =(Button*)ac1_1->add( new Button( aguix,
                                                0,
                                                0,
                                                catalog.getLocale( 11 ),
                                                0 ), 0, 0, AContainer::CO_FIX );
  Button *cancelb = (Button*)ac1_1->add( new Button( aguix,
						     0,
						     0,
						     catalog.getLocale( 8 ),
						     0 ), 1, 0, AContainer::CO_FIX );

  win->setDoTabCycling( true );
  win->contMaximize( true );
  win->show();
  lv->takeFocus();
  for(;endmode==-1;) {
    msg=aguix->WaitMessage(win);
    if(msg!=NULL) {
      switch(msg->type) {
        case AG_CLOSEWINDOW:
          if(msg->closewindow.window==win->getWindow()) endmode=1;
          break;
        case AG_BUTTONCLICKED:
          if(msg->button.button==okb) endmode=0;
          else if(msg->button.button==cancelb) endmode=1;
          break;
      }
      aguix->ReplyMessage(msg);
    }
  }
  
  returnstr=NULL;
  if(endmode==0) {
    // ok
    int trow = lv->getActiveRow();
    if ( lv->isValidRow( trow ) == true ) {
        returnstr = dupstring( lv->getText( trow, 0 ).c_str() );
    }
  }
  
  delete win;

  return returnstr;
}

void ScriptOp::setDoDebug( bool nv )
{
  dodebug = nv;
}

bool ScriptOp::getDoDebug()
{
  return dodebug;
}

void ScriptOp::setWPURecursive( bool nv )
{
  wpu_recursive = nv;
}

bool ScriptOp::getWPURecursive()
{
  return wpu_recursive;
}

void ScriptOp::setWPUTakeDirs( bool nv )
{
  wpu_take_dirs = nv;
}

bool ScriptOp::getWPUTakeDirs()
{
  return wpu_take_dirs;
}

void ScriptOp::setWinType( scriptop_window_t nv )
{
  wintype = nv;
}

ScriptOp::scriptop_window_t ScriptOp::getWinType()
{
  return wintype;
}

void ScriptOp::setChangeProgress( bool nv )
{
  change_progress = nv;
}

bool ScriptOp::getChangeProgress()
{
  return change_progress;
}

void ScriptOp::setChangeText( bool nv )
{
  change_text = nv;
}

bool ScriptOp::getChangeText()
{
  return change_text;
}

void ScriptOp::setProgress( const char *str )
{
  if ( progress != NULL ) _freesafe( progress );
  if ( str != NULL ) {
    progress = dupstring( str );
  } else {
    progress = NULL;
  }
}

const char *ScriptOp::getProgress()
{
  return progress;
}

void ScriptOp::setProgressUseOutput( bool nv )
{
  progress_useoutput = nv;
}

bool ScriptOp::getProgressUseOutput()
{
  return progress_useoutput;
}

void ScriptOp::setWinText( const char *str )
{
  if ( wintext != NULL ) _freesafe( wintext );
  if ( str != NULL ) {
    wintext = dupstring( str );
  } else {
    wintext = NULL;
  }
}

const char *ScriptOp::getWinText()
{
  return wintext;
}

void ScriptOp::setWinTextUseOutput( bool nv )
{
  wintext_useoutput = nv;
}

bool ScriptOp::getWinTextUseOutput()
{
  return wintext_useoutput;
}

void ScriptOp::setCommandStr( const std::string &str )
{
    m_command_str = str;
}

std::string ScriptOp::getCommandStr() const
{
    return m_command_str;
}
