/* basic_actions.cc
 * This file belongs to Worker, a file manager for UN*X/X11.
 * Copyright (C) 2001-2021 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 "basic_actions.h"
#include "listermode.h"
#include "worker.h"
#include "wcfiletype.hh"
#include "fileentry.hh"
#include "nmspecialsourceext.hh"
#include "worker_locale.h"
#include "dnd.h"
#include "aguix/button.h"
#include "aguix/cyclebutton.h"
#include "aguix/awindow.h"
#include "wconfig.h"
#include "datei.h"
#include "virtualdirmode.hh"

/***********
  DNDAction
************/

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

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

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

DNDAction::DNDAction() : FunctionProto()
{
    m_category = FunctionProto::CAT_FILETYPE;
}

DNDAction::~DNDAction()
{
}

DNDAction *DNDAction::duplicate() const
{
  DNDAction *dnda=new DNDAction();
  return dnda;
}

int DNDAction::run( std::shared_ptr< WPUContext > wpu, ActionMessage *msg )
{
    // do nothing in case of DND
    if(msg->mode!=msg->AM_MODE_DNDACTION) {
        normalmodedndaction( msg );
    }
    return 0;
}

const char *DNDAction::getDescription()
{
  return catalog.getLocale(1241);
}

void DNDAction::normalmodedndaction( ActionMessage *am )
{
  ListerMode *lm1 = NULL;
  Lister *l1 = am->getWorker()->getActiveLister();
  ActionMessage amsg( am->getWorker() );
  const FileEntry *fe = NULL;

  switch ( am->mode ) {
    case ActionMessage::AM_MODE_DNDACTION:
      break;
    case ActionMessage::AM_MODE_SPECIAL:
      fe = am->getFE();
      if ( fe != NULL ) {
        WCFiletype *ft;
      
        amsg.mode = amsg.AM_MODE_SPECIAL;
      
	if ( am->filetype != NULL ) ft = am->filetype;
	else ft = fe->filetype;
        if ( ft == NULL ) {
          ft = wconfig->getnotyettype(); // not yet checked
        }
        if ( ft != NULL ) {
	  // FE is already a copy of the real FE so we don't need to make another copy
	  // but setFE does make a copy currently which doesn't hurt
          amsg.setFE( fe );
	  amsg.filetype = ft;
          amsg.m_action_descr = RefCount<ActionDescr>( new DNDAction::DNDActionDescr() );
          am->getWorker()->interpret( ft->getDNDActions(), &amsg );
        }
      }
      break;
    case ActionMessage::AM_MODE_ONLYACTIVE:
    default:
      if(l1!=NULL) {
        lm1=l1->getActiveMode();
      }
      if (lm1 != NULL ) {
        std::list< NM_specialsourceExt > files;
        lm1->getSelFiles( files,
                         ( am->mode == ActionMessage::AM_MODE_ONLYACTIVE ) ? ListerMode::LM_GETFILES_ONLYACTIVE :
                                                                             ListerMode::LM_GETFILES_SELORACT,
                         false );
        WCFiletype *ft;
        
        amsg.startLister=l1;
        amsg.mode=amsg.AM_MODE_SPECIAL;
        
        if ( files.size() == 0 ) {
          ft = wconfig->getvoidtype();
          if(ft!=NULL) {
            amsg.setFE( NULL );
            amsg.filetype = ft;
            amsg.m_action_descr = RefCount<ActionDescr>( new DNDAction::DNDActionDescr() );
            am->getWorker()->interpret(ft->getDNDActions(),&amsg);
          }
        } else {
            for ( auto &ss1 : files ) {
                fe = ss1.entry();
                if ( fe != NULL ) {
                    ft = fe->filetype;
                    if ( ft == NULL ) {
                        if ( fe->isDir() == true ) ft = wconfig->getdirtype();
                        else ft = wconfig->getnotyettype();
                    }
                    if ( ft != NULL ) {
                        // NM_specialsourceExt already contains a duplicated FE so we can use
                        // it here without another copy
                        amsg.setFE( fe );
                        amsg.filetype = ft;
                        amsg.m_action_descr = RefCount<ActionDescr>( new DNDAction::DNDActionDescr() );
                        am->getWorker()->interpret( ft->getDNDActions(), &amsg );
                    }
                }
            }
        }
      }
      break;
  }
}

command_list_t DNDAction::DNDActionDescr::get_action_list( WCFiletype *ft ) const
{
    if ( ft == NULL ) return {};
    return ft->getDNDActions();
}

/***************
 Ende DNDAction
****************/

/*******************
  DoubleClickAction
********************/

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

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

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

DoubleClickAction::DoubleClickAction() : FunctionProto()
{
    m_category = FunctionProto::CAT_FILETYPE;
}

DoubleClickAction::~DoubleClickAction()
{
}

DoubleClickAction *DoubleClickAction::duplicate() const
{
  DoubleClickAction *ta=new DoubleClickAction();
  return ta;
}

int DoubleClickAction::run( std::shared_ptr< WPUContext > wpu, ActionMessage *msg )
{
    normalmodeddaction( msg );
    return 0;
}

const char *DoubleClickAction::getDescription()
{
  return catalog.getLocale(1242);
}

void DoubleClickAction::normalmodeddaction( ActionMessage *am )
{
  ListerMode *lm1 = NULL;
  Lister *l1;
  ActionMessage amsg( am->getWorker() );
  const FileEntry *fe = NULL;

  switch ( am->mode ) {
    case ActionMessage::AM_MODE_DNDACTION:
      l1 = am->dndmsg->getSourceLister();
      if(l1==NULL) return;
  
      fe = am->dndmsg->getFE();
      if(fe!=NULL) {
        WCFiletype *ft;
      
        amsg.startLister=l1;
        amsg.mode=amsg.AM_MODE_SPECIAL;
      
	if ( am->filetype != NULL ) ft = am->filetype;
	else ft = fe->filetype;
        if(ft==NULL) {
          if ( fe->isDir() == false ) ft = wconfig->getnotyettype(); // not yet checked
          else ft = wconfig->getdirtype(); // dir
        }
        if(ft!=NULL) {
	  // I need to make a copy of fe as DNDMsg->getFE returns a pointer to the actual FE
	  // setFE takes care of this at the moment
          amsg.setFE( fe );
	  amsg.filetype = ft;
          amsg.m_action_descr = RefCount<ActionDescr>( new DoubleClickAction::DoubleClickActionDescr() );
          am->getWorker()->interpret(ft->getDoubleClickActions(),&amsg);
        }
      }
      break;
    case ActionMessage::AM_MODE_SPECIAL:
      fe = am->getFE();
      if ( fe != NULL ) {
        WCFiletype *ft;
      
        amsg.mode = amsg.AM_MODE_SPECIAL;
      
	if ( am->filetype != NULL ) ft = am->filetype;
	else ft = fe->filetype;
        if ( ft == NULL ) {
          ft = wconfig->getnotyettype(); // not yet checked
        }
        if ( ft != NULL ) {
	  // FE is already a copy of the real FE so we don't need to make another copy
	  // but setFE does make a copy currently which doesn't hurt
          amsg.setFE( fe );
	  amsg.filetype = ft;
          amsg.m_action_descr = RefCount<ActionDescr>( new DoubleClickAction::DoubleClickActionDescr() );
          am->getWorker()->interpret( ft->getDoubleClickActions(), &amsg );
        }
      }
      break;
    case ActionMessage::AM_MODE_ONLYACTIVE:
    default:
      l1 = am->getWorker()->getActiveLister();
      if(l1!=NULL) {
        lm1=l1->getActiveMode();
      }
      if ( lm1 != NULL ) {
        std::list< NM_specialsourceExt > files;
        lm1->getSelFiles( files,
                         ( am->mode == ActionMessage::AM_MODE_ONLYACTIVE ) ? ListerMode::LM_GETFILES_ONLYACTIVE :
                                                                             ListerMode::LM_GETFILES_SELORACT,
                         false );
        WCFiletype *ft;
      
        amsg.startLister=l1;
        amsg.mode=amsg.AM_MODE_SPECIAL;
      
        if ( files.size() == 0 ) {
          ft = wconfig->getvoidtype();
          if(ft!=NULL) {
            amsg.setFE( NULL );
            amsg.filetype = ft;
            amsg.m_action_descr = RefCount<ActionDescr>( new DoubleClickAction::DoubleClickActionDescr() );
            am->getWorker()->interpret(ft->getDoubleClickActions(),&amsg);
          }
        } else {
            for ( auto &ss1 : files ) {
                fe = ss1.entry();
                if ( fe != NULL ) {
                    ft = fe->filetype;
                    if ( ft == NULL ) {
                        if ( fe->isDir() == true ) ft = wconfig->getdirtype();
                        else ft = wconfig->getnotyettype();
                    }
                    if ( ft != NULL ) {
                        // NM_specialsourceExt already contains a duplicated FE so we can use
                        // it here without another copy
                        amsg.setFE( fe );
                        amsg.filetype = ft;
                        amsg.m_action_descr = RefCount<ActionDescr>( new DoubleClickAction::DoubleClickActionDescr() );
                        am->getWorker()->interpret( ft->getDoubleClickActions(), &amsg );
                    }
                }
            }
        }
      }
      break;
  }
}

command_list_t DoubleClickAction::DoubleClickActionDescr::get_action_list( WCFiletype *ft ) const
{
    if ( ft == NULL ) return {};
    return ft->getDoubleClickActions();
}

/***************
 Ende DoubleClickAction
****************/

/***********
  ShowAction
************/

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

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

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

ShowAction::ShowAction() : FunctionProto()
{
    m_category = FunctionProto::CAT_FILETYPE;
}

ShowAction::~ShowAction()
{
}

ShowAction *ShowAction::duplicate() const
{
  ShowAction *ta=new ShowAction();
  return ta;
}

int ShowAction::run( std::shared_ptr< WPUContext > wpu, ActionMessage *msg )
{
    normalmodeshow( msg );
    return 0;
}

const char *ShowAction::getDescription()
{
  return catalog.getLocale(1243);
}

void ShowAction::normalmodeshow( ActionMessage *am )
{
  ListerMode *lm1 = NULL;
  ActionMessage amsg( am->getWorker() );
  Lister *l1;
  const FileEntry *fe = NULL;

  switch ( am->mode ) {
    case ActionMessage::AM_MODE_DNDACTION:
      l1 = am->dndmsg->getSourceLister();
      if(l1==NULL) return;
  
      fe = am->dndmsg->getFE();
      if(fe!=NULL) {
        WCFiletype *ft;
      
        amsg.startLister=l1;
        amsg.mode=amsg.AM_MODE_SPECIAL;
      
	if ( am->filetype != NULL ) ft = am->filetype;
	else ft = fe->filetype;
        if(ft==NULL) {
          if ( fe->isDir() == false ) ft = wconfig->getnotyettype(); // not yet checked
          else ft = wconfig->getdirtype(); // dir
        }
        if(ft!=NULL) {
	  // I need to make a copy of fe as DNDMsg->getFE returns a pointer to the actual FE
	  // setFE takes care of this at the moment
          amsg.setFE( fe );
	  amsg.filetype = ft;
          amsg.m_action_descr = RefCount<ActionDescr>( new ShowAction::ShowActionDescr() );
          am->getWorker()->interpret(ft->getShowActions(),&amsg);
        }
      }
      break;
    case ActionMessage::AM_MODE_SPECIAL:
      fe = am->getFE();
      if ( fe != NULL ) {
        WCFiletype *ft;
      
        amsg.mode = amsg.AM_MODE_SPECIAL;
      
	if ( am->filetype != NULL ) ft = am->filetype;
	else ft = fe->filetype;
        if ( ft == NULL ) {
          ft = wconfig->getnotyettype(); // not yet checked
        }
        if ( ft != NULL ) {
	  // FE is already a copy of the real FE so we don't need to make another copy
	  // but setFE does make a copy currently which doesn't hurt
          amsg.setFE( fe );
	  amsg.filetype = ft;
          amsg.m_action_descr = RefCount<ActionDescr>( new ShowAction::ShowActionDescr() );
          am->getWorker()->interpret( ft->getShowActions(), &amsg );
        }
      }
      break;
    case ActionMessage::AM_MODE_ONLYACTIVE:
    default:
      l1 = am->getWorker()->getActiveLister();
      if(l1!=NULL) {
        lm1=l1->getActiveMode();
      }
      if ( lm1 != NULL ) {
        std::list< NM_specialsourceExt > files;
        lm1->getSelFiles( files,
                         ( am->mode == ActionMessage::AM_MODE_ONLYACTIVE ) ? ListerMode::LM_GETFILES_ONLYACTIVE :
                                                                             ListerMode::LM_GETFILES_SELORACT,
                         false );
        WCFiletype *ft;
      
        amsg.startLister=l1;
        amsg.mode=amsg.AM_MODE_SPECIAL;
      
        if ( files.size() == 0 ) {
          ft = wconfig->getvoidtype();
          if(ft!=NULL) {
            amsg.setFE( NULL );
            amsg.filetype = ft;
            amsg.m_action_descr = RefCount<ActionDescr>( new ShowAction::ShowActionDescr() );
            am->getWorker()->interpret(ft->getShowActions(),&amsg);
          }
        } else {
            for ( auto &ss1 : files ) {
                fe = ss1.entry();
                if ( fe != NULL ) {
                    ft = fe->filetype;
                    if ( ft == NULL ) {
                        if ( fe->isDir() == true ) ft = wconfig->getdirtype();
                        else ft = wconfig->getnotyettype();
                    }
                    if ( ft != NULL ) {
                        // NM_specialsourceExt already contains a duplicated FE so we can use
                        // it here without another copy
                        amsg.setFE( fe );
                        amsg.filetype = ft;
                        amsg.m_action_descr = RefCount<ActionDescr>( new ShowAction::ShowActionDescr() );
                        am->getWorker()->interpret( ft->getShowActions(), &amsg );
                    }
                }
            }
        }
      }
      break;
  }
}

command_list_t ShowAction::ShowActionDescr::get_action_list( WCFiletype *ft ) const
{
    if ( ft == NULL ) return {};
    return ft->getShowActions();
}

/***************
 Ende ShowAction
****************/

/***********
 RawShowAction
************/

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

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

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

RawShowAction::RawShowAction() : FunctionProto()
{
    m_category = FunctionProto::CAT_FILETYPE;
}

RawShowAction::~RawShowAction()
{
}

RawShowAction *RawShowAction::duplicate() const
{
  RawShowAction *ta=new RawShowAction();
  return ta;
}

int RawShowAction::run( std::shared_ptr< WPUContext > wpu, ActionMessage *msg )
{
    normalmoderawshow( msg );
    return 0;
}

const char *RawShowAction::getDescription()
{
  return catalog.getLocale(1244);
}

void RawShowAction::normalmoderawshow( ActionMessage *am )
{
  ListerMode *lm1 = NULL;
  ActionMessage amsg( am->getWorker() );
  Lister *l1;
  const FileEntry *fe = NULL;

  switch ( am->mode ) {
    case ActionMessage::AM_MODE_DNDACTION:
      l1 = am->dndmsg->getSourceLister();
      if(l1==NULL) return;
  
      fe = am->dndmsg->getFE();
      if(fe!=NULL) {
        WCFiletype *ft;
      
        amsg.startLister=l1;
        amsg.mode=amsg.AM_MODE_SPECIAL;
      
	if ( am->filetype != NULL ) ft = am->filetype;
	else ft = fe->filetype;
        if(ft==NULL) {
          if ( fe->isDir() == false ) ft = wconfig->getnotyettype(); // not yet checked
          else ft = wconfig->getdirtype(); // dir
        }
        if(ft!=NULL) {
	  // I need to make a copy of fe as DNDMsg->getFE returns a pointer to the actual FE
	  // setFE takes care of this at the moment
          amsg.setFE( fe );
	  amsg.filetype = ft;
          amsg.m_action_descr = RefCount<ActionDescr>( new RawShowAction::RawShowActionDescr() );
          am->getWorker()->interpret(ft->getRawShowActions(),&amsg);
        }
      }
      break;
    case ActionMessage::AM_MODE_SPECIAL:
      fe = am->getFE();
      if ( fe != NULL ) {
        WCFiletype *ft;
      
        amsg.mode = amsg.AM_MODE_SPECIAL;
      
	if ( am->filetype != NULL ) ft = am->filetype;
	else ft = fe->filetype;
        if ( ft == NULL ) {
          ft = wconfig->getnotyettype(); // not yet checked
        }
        if ( ft != NULL ) {
	  // FE is already a copy of the real FE so we don't need to make another copy
	  // but setFE does make a copy currently which doesn't hurt
          amsg.setFE( fe );
	  amsg.filetype = ft;
          amsg.m_action_descr = RefCount<ActionDescr>( new RawShowAction::RawShowActionDescr() );
          am->getWorker()->interpret( ft->getRawShowActions(), &amsg );
        }
      }
      break;
    case ActionMessage::AM_MODE_ONLYACTIVE:
    default:
      l1 = am->getWorker()->getActiveLister();
      if(l1!=NULL) {
        lm1=l1->getActiveMode();
      }
      if ( lm1 != NULL ) {
        std::list< NM_specialsourceExt > files;
        lm1->getSelFiles( files,
                          ( am->mode == ActionMessage::AM_MODE_ONLYACTIVE ) ? ListerMode::LM_GETFILES_ONLYACTIVE :
                          ListerMode::LM_GETFILES_SELORACT,
                          false );
        WCFiletype *ft;
      
        amsg.startLister=l1;
        amsg.mode=amsg.AM_MODE_SPECIAL;
      
        if ( files.size() == 0 ) {
          ft = wconfig->getvoidtype();
          if(ft!=NULL) {
            amsg.setFE( NULL );
            amsg.filetype = ft;
            amsg.m_action_descr = RefCount<ActionDescr>( new RawShowAction::RawShowActionDescr() );
            am->getWorker()->interpret(ft->getRawShowActions(),&amsg);
          }
        } else {
            for ( auto &ss1 : files ) {
                fe = ss1.entry();
                if ( fe != NULL ) {
                    ft=fe->filetype;
                    if ( ft == NULL ) {
                        if ( fe->isDir() == true ) ft = wconfig->getdirtype();
                        else ft = wconfig->getnotyettype();
                    }
                    if ( ft != NULL ) {
                        // NM_specialsourceExt already contains a duplicated FE so we can use
                        // it here without another copy
                        amsg.setFE( fe );
                        amsg.filetype = ft;
                        amsg.m_action_descr = RefCount<ActionDescr>( new RawShowAction::RawShowActionDescr() );
                        am->getWorker()->interpret( ft->getRawShowActions(), &amsg );
                    }
                }
            }
        }
      }
      break;
  }
}

command_list_t RawShowAction::RawShowActionDescr::get_action_list( WCFiletype *ft ) const
{
    if ( ft == NULL ) return {};
    return ft->getRawShowActions();
}

/***************
 Ende RawShowAction
****************/

/***********
  UserAction
************/

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

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

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

UserAction::UserAction() : FunctionProto()
{
  nr=0;
  hasConfigure = true;
  m_category = FunctionProto::CAT_FILETYPE;
}

UserAction::~UserAction()
{
}

UserAction *UserAction::duplicate() const
{
  UserAction *ta=new UserAction();
  ta->nr=nr;
  return ta;
}

int UserAction::run( std::shared_ptr< WPUContext > wpu, ActionMessage *msg )
{
    normalmodeuseraction( msg );
    return 0;
}

const char *UserAction::getDescription()
{
  return catalog.getLocale(1245);
}

void UserAction::normalmodeuseraction( ActionMessage *am )
{
  ListerMode *lm1 = NULL;
  ActionMessage amsg( am->getWorker() );
  Lister *l1;
  const FileEntry *fe = NULL;

  switch ( am->mode ) {
    case ActionMessage::AM_MODE_DNDACTION:
      l1 = am->dndmsg->getSourceLister();
      if(l1==NULL) return;
  
      fe = am->dndmsg->getFE();
      if(fe!=NULL) {
        WCFiletype *ft;
      
        amsg.startLister=l1;
        amsg.mode=amsg.AM_MODE_SPECIAL;
      
	if ( am->filetype != NULL ) ft = am->filetype;
	else ft = fe->filetype;
        if(ft==NULL) {
          if ( fe->isDir() == false ) ft = wconfig->getnotyettype(); // not yet checked
          else ft = wconfig->getdirtype(); // dir
        }
        if(ft!=NULL) {
	  // I need to make a copy of fe as DNDMsg->getFE returns a pointer to the actual FE
	  // setFE takes care of this at the moment
          amsg.setFE( fe );
	  amsg.filetype = ft;
          amsg.m_action_descr = RefCount<ActionDescr>( new UserAction::UserActionDescr( nr ) );
          am->getWorker()->interpret(ft->getUserActions(nr),&amsg);
        }
      }
      break;
    case ActionMessage::AM_MODE_SPECIAL:
      fe = am->getFE();
      if ( fe != NULL ) {
        WCFiletype *ft;
      
        amsg.mode = amsg.AM_MODE_SPECIAL;
      
	if ( am->filetype != NULL ) ft = am->filetype;
	else ft = fe->filetype;
        if ( ft == NULL ) {
          ft = wconfig->getnotyettype(); // not yet checked
        }
        if ( ft != NULL ) {
	  // FE is already a copy of the real FE so we don't need to make another copy
	  // but setFE does make a copy currently which doesn't hurt
          amsg.setFE( fe );
	  amsg.filetype = ft;
          amsg.m_action_descr = RefCount<ActionDescr>( new UserAction::UserActionDescr( nr ) );
          am->getWorker()->interpret( ft->getUserActions( nr ), &amsg );
        }
      }
      break;
    case ActionMessage::AM_MODE_ONLYACTIVE:
    default:
      l1 = am->getWorker()->getActiveLister();
      if(l1!=NULL) {
        lm1=l1->getActiveMode();
      }
      if ( lm1 != NULL ) {
        std::list< NM_specialsourceExt > files;
        lm1->getSelFiles( files,
                          ( am->mode == ActionMessage::AM_MODE_ONLYACTIVE ) ? ListerMode::LM_GETFILES_ONLYACTIVE :
                          ListerMode::LM_GETFILES_SELORACT,
                          false );
        WCFiletype *ft;
      
        amsg.startLister=l1;
        amsg.mode=amsg.AM_MODE_SPECIAL;
      
        if ( files.size() == 0 ) {
          ft = wconfig->getvoidtype();
          if(ft!=NULL) {
            amsg.setFE( NULL );
            amsg.filetype = ft;
            amsg.m_action_descr = RefCount<ActionDescr>( new UserAction::UserActionDescr( nr ) );
            am->getWorker()->interpret(ft->getUserActions(nr),&amsg);
          }
        } else {
            for ( auto &ss1 : files ) {
                fe = ss1.entry();
                if ( fe != NULL ) {
                    ft=fe->filetype;
                    if ( ft == NULL ) {
                        if ( fe->isDir() == true ) ft = wconfig->getdirtype();
                        else ft = wconfig->getnotyettype();
                    }
                    if ( ft != NULL ) {
                        // NM_specialsourceExt already contains a duplicated FE so we can use
                        // it here without another copy
                        amsg.setFE( fe );
                        amsg.filetype = ft;
                        amsg.m_action_descr = RefCount<ActionDescr>( new UserAction::UserActionDescr( nr ) );
                        am->getWorker()->interpret( ft->getUserActions( nr ), &amsg );
                    }
                }
            }
        }
      }
      break;
  }
}

int UserAction::configure()
{
  AGUIX *aguix = Worker::getAGUIX();
  AWindow *win;
  CycleButton *rcyb;
  AGMessage *msg;
  int endmode=-1;
  char *tstr;
  
  tstr=(char*)_allocsafe(strlen(catalog.getLocale(293))+strlen(getDescription())+1);
  sprintf(tstr,catalog.getLocale(293),getDescription());
  win =new AWindow( aguix, 10, 10, 10, 10, tstr, AWindow::AWINDOW_DIALOG );
  win->create();
  _freesafe(tstr);

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

  rcyb = (CycleButton*)ac1->add( new CycleButton( aguix, 0, 0, 100, 0 ), 0, 0, AContainer::CO_INCW );
  rcyb->addOption(catalog.getLocale(255));
  rcyb->addOption(catalog.getLocale(256));
  rcyb->addOption(catalog.getLocale(257));
  rcyb->addOption(catalog.getLocale(258));
  rcyb->addOption(catalog.getLocale(259));
  rcyb->addOption(catalog.getLocale(260));
  rcyb->addOption(catalog.getLocale(261));
  rcyb->addOption(catalog.getLocale(262));
  rcyb->addOption(catalog.getLocale(263));
  rcyb->addOption(catalog.getLocale(264));
  rcyb->resize(rcyb->getMaxSize(),rcyb->getHeight());
  rcyb->setOption(nr);
  
  ac1->readLimits();
  
  AContainer *ac1_1 = ac1->add( new AContainer( win, 2, 1 ), 0, 1 );
  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 *cb = (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==cb) endmode=1;
          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
    nr=rcyb->getSelectedOption();
  }
  
  delete win;

  return endmode;
}

bool UserAction::save(Datei *fh)
{
  if ( fh == NULL ) return false;
  
  fh->configPutPairNum( "actionnumber", nr );
  return true;
}

int UserAction::getNr() const
{
  return nr;
}

void UserAction::setNr( int n )
{
  nr = n;
  if ( nr < 0 ) nr = 0;
  if ( nr > 9 ) nr = 9;
}

UserAction::UserActionDescr::UserActionDescr( int id ) : m_id( id )
{
}

command_list_t UserAction::UserActionDescr::get_action_list( WCFiletype *ft ) const
{
    if ( ft == NULL ) return {};
    return ft->getUserActions( m_id );
}

/***************
 Ende UserAction
****************/

/*****************
 ChangeHiddenFlag
******************/

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

ChangeHiddenFlag::ChangeHiddenFlag() : FunctionProto()
{
  mode=0;
  hasConfigure = true;
    m_category = FunctionProto::CAT_FILELIST;
}

ChangeHiddenFlag::~ChangeHiddenFlag()
{
}

ChangeHiddenFlag *ChangeHiddenFlag::duplicate() const
{
  ChangeHiddenFlag *ta=new ChangeHiddenFlag();
  ta->mode=mode;
  return ta;
}

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

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

int ChangeHiddenFlag::run( std::shared_ptr< WPUContext > wpu, ActionMessage *msg )
{
  ListerMode *lm1;
  if(msg->mode!=msg->AM_MODE_DNDACTION) {
    Lister *l1 = msg->getWorker()->getActiveLister();
    if(l1!=NULL) {
      lm1=l1->getActiveMode();
      if(lm1!=NULL) {
        if ( auto vdm = dynamic_cast< VirtualDirMode * >( lm1 ) ) {
            switch ( mode ) {
                case 1:
                    vdm->setShowHidden( false );
                    break;
                case 2:
                    vdm->setShowHidden( true );
                    break;
                default:
                    vdm->toggleHidden();          
            }
        } else {
            lm1->not_supported();
        }
      }
    }
  }
  return 0;
}

bool ChangeHiddenFlag::save(Datei *fh)
{
  if ( fh == NULL ) return false;
  switch ( mode ) {
    case 1:
      fh->configPutPair( "hiddenfiles", "hide" );
      break;
    case 2:
      fh->configPutPair( "hiddenfiles", "show" );
      break;
    default:
      fh->configPutPair( "hiddenfiles", "toggle" );
      break;
  }
  return true;
}

const char *ChangeHiddenFlag::getDescription()
{
  return catalog.getLocale(1248);
}

int ChangeHiddenFlag::configure()
{
  AGUIX *aguix = Worker::getAGUIX();
  AWindow *win;
  CycleButton *rcyb;
  AGMessage *msg;
  int endmode=-1;
  char *tstr;
  
  tstr=(char*)_allocsafe(strlen(catalog.getLocale(293))+strlen(getDescription())+1);
  sprintf(tstr,catalog.getLocale(293),getDescription());
  win=new AWindow( aguix, 10, 10, 10, 10, tstr, AWindow::AWINDOW_DIALOG );
  win->create();
  _freesafe(tstr);

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

  rcyb = (CycleButton*)ac1->add( new CycleButton( aguix, 0, 0, 100, 0 ), 0, 0, AContainer::CO_INCW );
  rcyb->addOption(catalog.getLocale(360));
  rcyb->addOption(catalog.getLocale(361));
  rcyb->addOption(catalog.getLocale(362));
  rcyb->resize(rcyb->getMaxSize(),rcyb->getHeight());
  switch(mode) {
    case 1:
      rcyb->setOption(1);
      break;
    case 2:
      rcyb->setOption(2);
      break;
    default:
      rcyb->setOption(0);
      break;
  }
  ac1->readLimits();
  
  AContainer *ac1_1 = ac1->add( new AContainer( win, 2, 1 ), 0, 1 );
  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 *cb = (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==cb) endmode=1;
          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(rcyb->getSelectedOption()) {
      case 1:
        mode=1;
        break;
      case 2:
        mode=2;
        break;
      default:
        mode=0;
        break;
    }
  }
  
  delete win;

  return endmode;
}

int ChangeHiddenFlag::getMode() const
{
  return mode;
}

void ChangeHiddenFlag::setMode( int m )
{
  mode = m;
  if ( mode < 0 ) mode = 0;
  if ( mode > 2 ) mode = 2;
}

/**********************
 Ende ChangeHiddenFlag
***********************/

