/* virtualdirmode_config.cc
 * This file belongs to Worker, a file manager for UN*X/X11.
 * Copyright (C) 2019-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 "virtualdirmode.hh"
#include "aguix/acontainer.h"
#include "aguix/fieldlistviewdnd.h"
#include "aguix/awindow.h"
#include "aguix/stringgadget.h"
#include "aguix/kartei.h"
#include "aguix/karteibutton.h"
#include "aguix/button.h"
#include "aguix/acontainerbb.h"
#include "aguix/choosebutton.h"
#include "worker_locale.h"
#include "worker.h"
#include "wconfig.h"
#include "bookmarkdbproxy.hh"
#include "flagreplacer.hh"
#include "filereq.h"

#define WORKER_DEFAULT_CUSTOM_LVB_FORMAT "{indicators} {modeinfo} - {freespace}"

static void updateSortTabTitle( Kartei *k,
                                CycleButton *sort_cyb,
                                ChooseButton *reverse_sort_chb )
{
    std::string new_text = catalog.getLocale( 1217 );
    new_text += " (";

    switch ( sort_cyb->getSelectedOption() ) {
        case 1:
            new_text += "S";
            break;
        case 2:
            new_text += "A";
            break;
        case 3:
            new_text += "M";
            break;
        case 4:
            new_text += "C";
            break;
        case 5:
            new_text += "T";
            break;
        case 6:
            new_text += "O";
            break;
        case 7:
            new_text += "I";
            break;
        case 8:
            new_text += "L";
            break;
        case 9:
            new_text += "P";
            break;
        case 10:
            new_text += "E";
            break;
        case 11:
            new_text += "X";
            break;
        default:
            new_text += "N";
            break;
    }

    if ( reverse_sort_chb->getState() == true ) {
        new_text += "R";
    } else {
        new_text += " ";
    }

    new_text += ")";

    k->updateOption( 0, new_text );
}

static void updateFilterTabTitle( Kartei *k,
                                  ChooseButton *show_hidden_chb,
                                  const std::list < NM_Filter > &filters,
                                  CycleButton *bookmarks_cyb )
{
    std::string new_text = catalog.getLocale( 1218 );
    new_text += " (";

    if ( show_hidden_chb->getState() == true ) {
        new_text += " ";
    } else {
        new_text += "H";
    }

    bool filter_active = false;

    for ( auto &fil_it1 : filters ) {
        if ( fil_it1.getCheck() != NM_Filter::INACTIVE ) {
            filter_active = true;
        }
    }

    if ( filter_active ) {
        new_text += "*";
    } else {
        new_text += " ";
    }

    if ( bookmarks_cyb->getSelectedOption() > 0 ) {
        new_text += "B";
    } else {
        new_text += " ";
    }

    new_text += ")";

    k->updateOption( 1, new_text );
}

static void insertCustomLVBLineFlag( StringGadget *sg )
{
    if ( ! sg ) return;

    FlagReplacer::FlagHelp flags;

    flags.registerFlag( "{indicators}", catalog.getLocale( 1376 ) );
    flags.registerFlag( "{modeinfo}", catalog.getLocale( 1377 ) );
    flags.registerFlag( "{freespace}", catalog.getLocale( 1378 ) );
    flags.registerFlag( "{cdi}", catalog.getLocale( 1379 ) );

    std::string str1 = FlagReplacer::requestFlag( flags );

    if ( str1.length() > 0 ) {
        sg->insertAtCursor( str1.c_str() );
    }
}

static void insertCustomDirectoryInfoCommandFlag( StringGadget *sg )
{
    if ( ! sg ) return;

    FlagReplacer::FlagHelp flags;

    flags.registerFlag( "{p}", catalog.getLocaleFlag( 1 ) );
    flags.registerFlag( "{scripts}", catalog.getLocaleFlag( 53 ) );

    std::string str1 = FlagReplacer::requestFlag( flags );

    if ( str1.length() > 0 ) {
        sg->insertAtCursor( str1.c_str() );
    }
}

int VirtualDirMode::configure()
{
    int endmode = -1;
    auto title = AGUIXUtils::formatStringToString( catalog.getLocale( 293 ),
                                                   getLocaleName() );
    auto win = new AWindow( aguix, 10, 10, 10, 10, title.c_str(), AWindow::AWINDOW_NORMAL );
    win->create();

    AContainer *ac1 = win->setContainer( new AContainer( win, 1, 2 ), true );
    ac1->setMinSpace( 5 );
    ac1->setMaxSpace( 5 );
  
    Kartei *k1 = new Kartei( aguix, 10, 10, 10, 10, "" );
    ac1->add( k1, 0, 0, AContainer::CO_MIN );
    k1->create();

    bool tshowhidden = m_dir_filter_sets.getShowHidden();
    std::list<NM_Filter> tfilters = m_dir_filter_sets.getFilters();
    DirFilterSettings t_dir_settings( m_dir_filter_sets );

    /*****************
     * Sort settings *
     *****************/
    AWindow *subwin1 = new AWindow( aguix, 0, 0, 10, 10, "" );
    k1->add( subwin1 );
    subwin1->create();

    AContainer *sw11_ac1 = subwin1->setContainer( new AContainer( subwin1, 1, 3 ), true );
    sw11_ac1->setMinSpace( 5 );
    sw11_ac1->setMaxSpace( 5 );

    AContainer *ac1_1 = sw11_ac1->add( new AContainer( subwin1, 2, 1 ), 0, 0 );
    ac1_1->setMinSpace( 5 );
    ac1_1->setMaxSpace( 5 );
    ac1_1->setBorderWidth( 0 );
    ac1_1->add( new Text( aguix, 0, 0, catalog.getLocale( 158 ) ), 0, 0, AContainer::CO_FIXNR | AContainer::ACONT_CENTER );

    int sortmode = m_dir_sort_sets.getSortMode();

    auto sort_cyb = ac1_1->addWidget( new CycleButton( aguix, 0, 0, 100, 0 ), 1, 0, AContainer::CO_INCW );
    sort_cyb->addOption( std::string( catalog.getLocale( 160 ) ) + " (N)" );
    sort_cyb->addOption( std::string( catalog.getLocale( 161 ) ) + " (S)" );
    sort_cyb->addOption( std::string( catalog.getLocale( 162 ) ) + " (A)" );
    sort_cyb->addOption( std::string( catalog.getLocale( 163 ) ) + " (M)" );
    sort_cyb->addOption( std::string( catalog.getLocale( 164 ) ) + " (C)" );
    sort_cyb->addOption( std::string( catalog.getLocale( 432 ) ) + " (T)" );
    sort_cyb->addOption( std::string( catalog.getLocale( 433 ) ) + " (O)" );
    sort_cyb->addOption( std::string( catalog.getLocale( 552 ) ) + " (I)" );
    sort_cyb->addOption( std::string( catalog.getLocale( 553 ) ) + " (L)" );
    sort_cyb->addOption( std::string( catalog.getLocale( 907 ) ) + " (P)" );
    sort_cyb->addOption( std::string( catalog.getLocale( 1240 ) ) + " (E)" );
    sort_cyb->addOption( std::string( catalog.getLocale( 1534 ) ) + " (X)" );
    sort_cyb->resize( sort_cyb->getMaxSize(),
                      sort_cyb->getHeight() );

    if ( ( sortmode & 0xff ) == SORT_SIZE ) sort_cyb->setOption( 1 );
    else if ( ( sortmode & 0xff ) == SORT_ACCTIME ) sort_cyb->setOption( 2 );
    else if ( ( sortmode & 0xff ) == SORT_MODTIME ) sort_cyb->setOption( 3 );
    else if ( ( sortmode & 0xff ) == SORT_CHGTIME ) sort_cyb->setOption( 4 );
    else if ( ( sortmode & 0xff ) == SORT_TYPE ) sort_cyb->setOption( 5 );
    else if ( ( sortmode & 0xff ) == SORT_OWNER ) sort_cyb->setOption( 6 );
    else if ( ( sortmode & 0xff ) == SORT_INODE ) sort_cyb->setOption( 7 );
    else if ( ( sortmode & 0xff ) == SORT_NLINK ) sort_cyb->setOption( 8 );
    else if ( ( sortmode & 0xff ) == SORT_PERMISSION ) sort_cyb->setOption( 9 );
    else if ( ( sortmode & 0xff ) == SORT_EXTENSION ) sort_cyb->setOption( 10 );
    else if ( ( sortmode & 0xff ) == SORT_CUSTOM_ATTRIBUTE ) sort_cyb->setOption( 11 );
    else sort_cyb->setOption( 0 );

    auto reverse_sort_chb = sw11_ac1->addWidget( new ChooseButton( aguix, 0, 0,
                                                                   ( ( sortmode & SORT_REVERSE ) == SORT_REVERSE ) ? 1 : 0,
                                                                   ( std::string( catalog.getLocale( 165 ) ) + " (R)" ).c_str(),
                                                                   LABEL_LEFT, 0 ), 0, 1, AContainer::CO_INCWNR );

    AContainer *ac1_2 = sw11_ac1->add( new AContainer( subwin1, 2, 1 ), 0, 2 );
    ac1_2->setMinSpace( 5 );
    ac1_2->setMaxSpace( 5 );
    ac1_2->setBorderWidth( 0 );
    ac1_2->add( new Text( aguix, 0, 0, catalog.getLocale( 353 ) ), 0, 0, AContainer::CO_FIXNR | AContainer::ACONT_CENTER );
    auto dirmode_cyb = ac1_2->addWidget( new CycleButton( aguix, 0, 0, 100, 0 ), 1, 0, AContainer::CO_INCW );
    dirmode_cyb->addOption( catalog.getLocale( 354 ) );
    dirmode_cyb->addOption( catalog.getLocale( 355 ) );
    dirmode_cyb->addOption( catalog.getLocale( 356 ) );
    dirmode_cyb->resize( dirmode_cyb->getMaxSize(),
                         dirmode_cyb->getHeight() );
    if ( ( sortmode & SORT_DIRLAST ) == SORT_DIRLAST ) dirmode_cyb->setOption( 1 );
    else if ( ( sortmode & SORT_DIRMIXED ) == SORT_DIRMIXED ) dirmode_cyb->setOption( 2 );
    else dirmode_cyb->setOption( 0 );

    ac1_1->readLimits();
    ac1_2->readLimits();

    /*******************
     * Filter settings *
     *******************/
    AWindow *subwin2 = new AWindow( aguix, 0, 0, 10, 10, "" );
    k1->add( subwin2 );
    subwin2->create();

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

    ChooseButton *chb = sw2_ac1->addWidget( new ChooseButton( aguix, 0, 0,
                                                              ( tshowhidden == true ) ? 1 : 0,
                                                              ( std::string( catalog.getLocale( 357 ) ) + " (H)" ).c_str(),
                                                              LABEL_RIGHT, 0 ),
                                            0, 0, AContainer::CO_INCWNR );

    ChooseButton *show_dotdot_cb = sw2_ac1->addWidget( new ChooseButton( aguix, 0, 0,
                                                                         m_show_dotdot,
                                                                         catalog.getLocale( 1044 ), LABEL_RIGHT, 0 ), 0, 1, AContainer::CO_INCWNR );

    AContainerBB *ac2_1_0 = static_cast< AContainerBB* >( sw2_ac1->add( new AContainerBB( subwin2, 1, 4 ), 0, 2 ) );
    ac2_1_0->setMinSpace( 5 );
    ac2_1_0->setMaxSpace( 5 );
    ac2_1_0->setBorderWidth( 5 );

    ac2_1_0->add( new Text( aguix, 0, 0,
                            ( std::string( catalog.getLocale( 1220 ) ) + " (*)" ).c_str() ),
                  0, 0, AContainer::CO_INCWNR );

    FieldListView *filv = ac2_1_0->addWidget( new FieldListView( aguix,
                                                                 0,
                                                                 0,
                                                                 100,
                                                                 10 * aguix->getCharHeight(),
                                                                 0 ),
                                              0, 1, AContainer::CO_MIN );
    filv->setHBarState( 2 );
    filv->setVBarState( 2 );
    filv->setNrOfFields( 3 );
    filv->setFieldWidth( 1, 1 );

    AContainer *ac2_1_1 = ac2_1_0->add( new AContainer( subwin2, 3, 1 ), 0, 2 );
    ac2_1_1->setMinSpace( 0 );
    ac2_1_1->setMaxSpace( 0 );
    ac2_1_1->setBorderWidth( 0 );

    Button *newb = ac2_1_1->addWidget( new Button( aguix, 0, 0,
                                                   catalog.getLocale( 167 ), 0 ), 0, 0, AContainer::CO_INCW );
    Button *delb = ac2_1_1->addWidget( new Button( aguix, 0, 0,
                                                   catalog.getLocale( 169 ), 0 ), 1, 0, AContainer::CO_INCW );
    Button *editb = ac2_1_1->addWidget( new Button( aguix, 0, 0,
                                                    catalog.getLocale( 168 ), 0 ), 2, 0, AContainer::CO_INCW );

    Button *uallb = ac2_1_0->addWidget( new Button( aguix, 0, 0,
                                                    catalog.getLocale( 194 ), 0 ), 0, 3, AContainer::CO_INCW );

    AContainerBB *ac2_1_2 = (AContainerBB*)sw2_ac1->add( new AContainerBB( subwin2, 1, 4 ), 0, 3 );
    ac2_1_2->setMinSpace( 5 );
    ac2_1_2->setMaxSpace( -1 );
    ac2_1_2->setBorderWidth( 5 );

    ac2_1_2->add( new Text( aguix, 0, 0,
                            ( std::string( catalog.getLocale( 845 ) ) + " (B)" ).c_str() ),
                  0, 0, AContainer::CO_INCWNR );

    AContainer *ac2_1_2_1 = ac2_1_2->add( new AContainer( subwin2, 2, 1 ), 0, 1 );
    ac2_1_2_1->setMinSpace( 5 );
    ac2_1_2_1->setMaxSpace( 5 );
    ac2_1_2_1->setBorderWidth( 0 );

    ac2_1_2_1->add( new Text( aguix, 0, 0, catalog.getLocale( 840 ) ), 0, 0, AContainer::CO_FIXNR | AContainer::ACONT_CENTER );
    CycleButton *bookmark_filter_cycb = ac2_1_2_1->addWidget( new CycleButton( aguix, 0, 0, 100, 0 ),
                                                              1, 0, AContainer::CO_INCW );
    bookmark_filter_cycb->addOption( catalog.getLocale( 841 ) );
    bookmark_filter_cycb->addOption( catalog.getLocale( 842 ) );
    bookmark_filter_cycb->addOption( catalog.getLocale( 843 ) );
    switch ( t_dir_settings.getBookmarkFilter() ) {
        case DirFilterSettings::SHOW_ONLY_BOOKMARKS:
            bookmark_filter_cycb->setOption( 1 );
            break;
        case DirFilterSettings::SHOW_ONLY_LABEL:
            bookmark_filter_cycb->setOption( 2 );
            break;
        case DirFilterSettings::SHOW_ALL:
        default:
            bookmark_filter_cycb->setOption( 0 );
            break;
    }
    bookmark_filter_cycb->resize( bookmark_filter_cycb->getMaxSize(),
                                  bookmark_filter_cycb->getHeight() );
    ac2_1_2_1->readLimits();

    AContainer *ac2_1_2_2 = ac2_1_2->add( new AContainer( subwin2, 3, 2 ), 0, 2 );
    ac2_1_2_2->setMinSpace( 0 );
    ac2_1_2_2->setMaxSpace( 0 );
    ac2_1_2_2->setBorderWidth( 0 );

    ac2_1_2_2->setMinWidth( 5, 1, 0 );
    ac2_1_2_2->setMaxWidth( 5, 1, 0 );

    ac2_1_2_2->add( new Text( aguix, 0, 0, catalog.getLocale( 844 ) ), 0, 1, AContainer::CO_FIXNR | AContainer::ACONT_CENTER );

    FieldListView *label_lv = ac2_1_2_2->addWidget( new FieldListView( aguix,
                                                                       0, 0,
                                                                       40, 40, 0 ),
                                                    2, 0, AContainer::CO_MIN );
    label_lv->setHBarState( 2 );
    label_lv->setVBarState( 2 );

    std::list<std::string> cats = Worker::getBookmarkDBInstance().getCats();
    const std::map<std::string, WConfig::ColorDef::label_colors_t> labels = wconfig->getColorDefs().getLabelColors();
    std::map<std::string, WConfig::ColorDef::label_colors_t>::const_iterator label_it;
  
    for ( label_it = labels.begin(); label_it != labels.end(); ++label_it ) {
        if ( std::find( cats.begin(), cats.end(),
                        label_it->first ) == cats.end() ) {
            cats.push_back( label_it->first );
        }
    }
    if ( t_dir_settings.getSpecificBookmarkLabel().length() > 0 &&
         std::find( cats.begin(), cats.end(),
                    t_dir_settings.getSpecificBookmarkLabel() ) == cats.end() ) {
        cats.push_back( t_dir_settings.getSpecificBookmarkLabel() );
    }
    for ( std::list<std::string>::iterator it1 = cats.begin();
          it1 != cats.end();
          ++it1 ) {
        int label_row = label_lv->addRow();
        label_lv->setText( label_row, 0, *it1 );
        label_lv->setPreColors( label_row, FieldListView::PRECOLOR_ONLYACTIVE );
    }
    label_lv->resize( label_lv->getWidth(), 6 * aguix->getCharHeight() );
    ac2_1_2_2->readLimits();

    StringGadget *bookmark_label_sg = ac2_1_2_2->addWidget( new StringGadget( aguix, 0, 0, 100,
                                                                              t_dir_settings.getSpecificBookmarkLabel().c_str(), 0 ),
                                                            2, 1, AContainer::CO_INCW );

    ChooseButton *highlight_prefix_cb = ac2_1_2->addWidget( new ChooseButton( aguix, 0, 0,
                                                                              t_dir_settings.getHighlightBookmarkPrefix(),
                                                                              catalog.getLocale( 846 ), LABEL_LEFT,
                                                                              0 ),
                                                            0, 3, AContainer::CO_INCWNR );

    for ( auto fil_it1 = tfilters.begin();
          fil_it1 != tfilters.end();
          fil_it1++ ) {
        int trow = filv->addRow();
        setLVC4Filter( filv, trow, *fil_it1 );
        filv->setPreColors( trow, FieldListView::PRECOLOR_ONLYSELECT );
    }
    filv->redraw();

    /******************
     * Other settings *
     ******************/
    AWindow *subwin3 = new AWindow( aguix, 0, 0, 10, 10, "" );
    k1->add( subwin3 );
    subwin3->create();

    AContainer *sw3_ac = subwin3->setContainer( new AContainer( subwin3, 1, 6 ), true );
    sw3_ac->setMinSpace( 5 );
    sw3_ac->setMaxSpace( 5 );

    AContainerBB *ac3_1 = static_cast<AContainerBB*>( sw3_ac->add( new AContainerBB( subwin3, 1, 2 ), 0, 3 ) );
    ac3_1->setMinSpace( 5 );
    ac3_1->setMaxSpace( 5 );

    auto ucb = ac3_1->addWidget( new ChooseButton( aguix, 0, 0,
                                                   ( m_show_free_space == true ) ? 1 : 0,
                                                   catalog.getLocale( 128 ), LABEL_RIGHT, 0), 0, 0, AContainer::CO_INCWNR );

    AContainer *ac3_1_1 = ac3_1->add( new AContainer( subwin3, 2, 1 ), 0, 1 );
    ac3_1_1->setMinSpace( 5 );
    ac3_1_1->setMaxSpace( 5 );
    ac3_1_1->add( new Text( aguix, 0, 0, catalog.getLocale( 129 ) ), 0, 0, AContainer::CO_FIXNR | AContainer::ACONT_CENTER );

    auto tstr = AGUIXUtils::formatStringToString( "%d", m_update_time );
    auto tsg = ac3_1_1->addWidget( new StringGadget( aguix, 0, 0, 100, tstr.c_str(), 0 ), 1, 0, AContainer::CO_INCW );

    ChooseButton *watch_cb = sw3_ac->addWidget( new ChooseButton( aguix, 0, 0,
                                                                  ( m_dirwatcher.watch_mode == true) ? 1 : 0,
                                                                  catalog.getLocale( 991 ), LABEL_RIGHT, 0 ), 0, 0, AContainer::CO_INCWNR );

    ChooseButton *search_on_key_cb = sw3_ac->addWidget( new ChooseButton( aguix, 0, 0,
                                                                          m_activate_search_on_keypress,
                                                                          catalog.getLocale( 1015 ), LABEL_RIGHT, 0 ), 0, 1, AContainer::CO_INCWNR );

    ChooseButton *show_breadcrumb_cb = sw3_ac->addWidget( new ChooseButton( aguix, 0, 0,
                                                                            m_breadcrumb.enabled,
                                                                            catalog.getLocale( 1045 ), LABEL_RIGHT, 0 ), 0, 2, AContainer::CO_INCWNR );

    AContainerBB *ac3_2 = static_cast<AContainerBB*>( sw3_ac->add( new AContainerBB( subwin3, 1, 3 ), 0, 4 ) );
    ac3_2->setMinSpace( 5 );
    ac3_2->setMaxSpace( 5 );

    ChooseButton *enable_info_line_cb = ac3_2->addWidget( new ChooseButton( aguix, 0, 0,
                                                                            m_enable_info_line,
                                                                            catalog.getLocale( 1057 ), LABEL_RIGHT, 0 ), 0, 0, AContainer::CO_INCWNR );
    ChooseButton *info_line_lua_mode_cb = ac3_2->addWidget( new ChooseButton( aguix, 0, 0,
                                                                              m_info_line_lua_mode,
                                                                              catalog.getLocale( 1058 ), LABEL_RIGHT, 0 ), 0, 1, AContainer::CO_INCWNR );

    AContainer *ac3_2_1 = ac3_2->add( new AContainer( subwin3, 3, 1 ), 0, 2 );
    ac3_2_1->setMinSpace( 5 );
    ac3_2_1->setMaxSpace( 5 );
    ac3_2_1->add( new Text( aguix, 0, 0, catalog.getLocale( 1059 ) ), 0, 0, AContainer::CO_FIXNR | AContainer::ACONT_CENTER );
    StringGadget *info_line_content_sg = ac3_2_1->addWidget( new StringGadget( aguix, 0, 0, 100, m_info_line_content.c_str(), 0 ), 1, 0, AContainer::CO_INCW );
    Button *m_flag_b = ac3_2_1->addWidget( new Button( aguix, 0, 0, catalog.getLocale( 897 ), 0 ),
                                           2, 0, AContainer::CO_FIX );

    AContainerBB *ac3_3 = static_cast<AContainerBB*>( sw3_ac->add( new AContainerBB( subwin3, 1, 3 ), 0, 5 ) );
    ac3_3->setMinSpace( 5 );
    ac3_3->setMaxSpace( 5 );

    ChooseButton *enable_custom_lvb_line_cb = ac3_3->addWidget( new ChooseButton( aguix, 0, 0,
                                                                                  m_enable_custom_lvb_line,
                                                                                  catalog.getLocale( 1380 ), LABEL_RIGHT, 0 ), 0, 0, AContainer::CO_INCWNR );

    AContainer *ac3_3_1 = ac3_3->add( new AContainer( subwin3, 4, 1 ), 0, 1 );
    ac3_3_1->setMinSpace( 5 );
    ac3_3_1->setMaxSpace( 5 );
    ac3_3_1->add( new Text( aguix, 0, 0, catalog.getLocale( 1381 ) ), 0, 0, AContainer::CO_FIXNR | AContainer::ACONT_CENTER );
    StringGadget *custom_lvb_format_sg = ac3_3_1->addWidget( new StringGadget( aguix, 0, 0, 100, m_custom_lvb_line.c_str(), 0 ), 1, 0, AContainer::CO_INCW );
    Button *m_lvb_flag_b = ac3_3_1->addWidget( new Button( aguix, 0, 0, catalog.getLocale( 897 ), 0 ),
                                               2, 0, AContainer::CO_FIX );
    Button *m_lvb_default_b = ac3_3_1->addWidget( new Button( aguix, 0, 0, catalog.getLocale( 196 ), 0 ),
                                                  3, 0, AContainer::CO_FIX );

    AContainer *ac3_3_2 = ac3_3->add( new AContainer( subwin3, 4, 1 ), 0, 2 );
    ac3_3_2->setMinSpace( 5 );
    ac3_3_2->setMaxSpace( 5 );
    ac3_3_2->add( new Text( aguix, 0, 0, catalog.getLocale( 1382 ) ), 0, 0, AContainer::CO_FIXNR | AContainer::ACONT_CENTER );
    StringGadget *custom_directory_info_sg = ac3_3_2->addWidget( new StringGadget( aguix, 0, 0, 100, m_custom_directory_info_command.c_str(), 0 ), 1, 0, AContainer::CO_INCW );
    Button *m_cdi_flag_b = ac3_3_2->addWidget( new Button( aguix, 0, 0, catalog.getLocale( 897 ), 0 ),
                                               2, 0, AContainer::CO_FIX );
    Button *m_cdi_file_b = ac3_3_2->addWidget( new Button( aguix, 0, 0, "F", 0 ),
                                               3, 0, AContainer::CO_FIX );

    k1->setOption( subwin1, 0, catalog.getLocale( 1217 ) );
    k1->setOption( subwin2, 1, catalog.getLocale( 1218 ) );
    k1->setOption( subwin3, 2, catalog.getLocale( 1219 ) );

    updateSortTabTitle( k1, sort_cyb,
                        reverse_sort_chb );
    updateFilterTabTitle( k1, chb,
                          tfilters,
                          bookmark_filter_cycb );

    k1->maximize();
    k1->contMaximize();
    ac1->readLimits();
 
    AContainer *ac1_5 = ac1->add( new AContainer( win, 2, 1 ), 0, 1 );
    ac1_5->setMinSpace( 5 );
    ac1_5->setMaxSpace( -1 );
    ac1_5->setBorderWidth( 0 );
    Button *okb =ac1_5->addWidget( new Button( aguix,
                                               0,
                                               0,
                                               catalog.getLocale( 11 ),
                                               0 ), 0, 0, AContainer::CO_FIX );
    Button *cancelb = ac1_5->addWidget( new Button( aguix,
                                                    0,
                                                    0,
                                                    catalog.getLocale( 8 ),
                                                    0 ), 1, 0, AContainer::CO_FIX );
    win->setDoTabCycling( true );
    win->contMaximize( true );

    win->show();
    k1->show();

    AGMessage *msg;

    while ( endmode == -1 ) {
        msg = aguix->WaitMessage( win );
        if ( msg ==NULL ) continue;

        switch ( msg->type ) {
            case AG_CLOSEWINDOW:
                if ( msg->closewindow.window == win->getWindow() ) endmode = 1;
            case AG_BUTTONCLICKED:
                if ( msg->button.button == okb ) {
                    endmode = 0;
                } else if ( msg->button.button == cancelb ) {
                    endmode = 1;
                } else if ( msg->button.button == m_flag_b ) {
                    insertInfoLineFlag( info_line_content_sg, info_line_lua_mode_cb->getState() );
                } else if ( msg->button.button == newb ) {
                    NM_Filter tfi;
          
                    if ( configureFilter( tfi ) == 0 ) {
                        int trow = filv->addRow();
                        setLVC4Filter( filv, trow, tfi );
                        filv->setPreColors( trow, FieldListView::PRECOLOR_ONLYSELECT );
                        filv->setActiveRow( trow );
                        filv->showActive();
                        tfilters.push_back( tfi );
                        filv->redraw();

                        updateFilterTabTitle( k1, chb,
                                              tfilters,
                                              bookmark_filter_cycb );
                    }
                } else if ( msg->button.button == delb ) {
                    int pos = 0;
                    while ( filv->isValidRow( pos ) == true ) {
                        if ( filv->getSelect( pos ) == true ) {
                            int poscopy = pos;
                            auto fil_it1 = tfilters.begin();
                            while ( fil_it1 != tfilters.end() && poscopy > 0 ) {
                                fil_it1++;
                                poscopy--;
                            }
                
                            if ( fil_it1 != tfilters.end() ) {
                                tfilters.erase( fil_it1 );
                                filv->deleteRow( pos );
                                filv->redraw();
                                pos--;

                                updateFilterTabTitle( k1, chb,
                                                      tfilters,
                                                      bookmark_filter_cycb );
                            }
                        }
                        pos++;
                    }
                } else if ( msg->button.button == editb ) {
                    int pos = 0;
                    while ( filv->isValidRow( pos ) == true ) {
                        if ( filv->getSelect( pos ) == true ) {
                            int poscopy = pos;
                            auto fil_it1 = tfilters.begin();
                            while ( fil_it1 != tfilters.end() && poscopy > 0 ) {
                                fil_it1++;
                                poscopy--;
                            }

                            if ( fil_it1 != tfilters.end() ) {
                                if ( configureFilter( *fil_it1 ) == 0 ) {
                                    setLVC4Filter( filv, pos, *fil_it1 );
                                    filv->redraw();

                                    updateFilterTabTitle( k1, chb,
                                                          tfilters,
                                                          bookmark_filter_cycb );
                                }
                            }
                        }
                        pos++;
                    }
                } else if ( msg->button.button == uallb ) {
                    int pos = 0;
                    for ( auto fil_it1 = tfilters.begin();
                          fil_it1 != tfilters.end();
                          fil_it1++ ) {
                        fil_it1->setCheck( NM_Filter::INACTIVE );
                        if ( filv->isValidRow( pos ) == true ) {
                            setLVC4Filter( filv, pos, *fil_it1 );
                            pos++;
                        }
                    }
                    filv->redraw();

                    updateFilterTabTitle( k1, chb,
                                          tfilters,
                                          bookmark_filter_cycb );
                } else if ( msg->button.button == m_lvb_flag_b ) {
                    insertCustomLVBLineFlag( custom_lvb_format_sg );
                } else if ( msg->button.button == m_lvb_default_b ) {
                    custom_lvb_format_sg->setText( WORKER_DEFAULT_CUSTOM_LVB_FORMAT );
                } else if ( msg->button.button == m_cdi_flag_b ) {
                    insertCustomDirectoryInfoCommandFlag( custom_directory_info_sg );
                } else if ( msg->button.button == m_cdi_file_b ) {
                    FileRequester freq( aguix );
                    std::string scriptdir = Worker::getDataDir();
                    scriptdir += "/scripts";

                    if ( freq.request_entry( catalog.getLocale( 265 ),
                                             scriptdir.c_str(),
                                             catalog.getLocale( 11 ),
                                             catalog.getLocale( 8 ),
                                             catalog.getLocale( 265 ),
                                             false ) > 0 ) {
                        std::string str1 = freq.getLastEntryStr();
                        if ( ! str1.empty() ) {
                            if ( AGUIXUtils::starts_with( str1, scriptdir ) ) {
                                str1 = std::string( "{scripts}" ) + std::string( str1, scriptdir.size() );
                            }
                            
                            std::string current_content = custom_directory_info_sg->getText();
                            int pos = custom_directory_info_sg->getCursor();

                            std::string newstr1( current_content, 0, pos );
                            newstr1 += str1;
                            newstr1 += std::string( current_content, pos );
                            custom_directory_info_sg->setText( newstr1.c_str() );
                        }
                    }
                }
                break;
            case AG_CHOOSECLICKED:
                if ( msg->choose.button == info_line_lua_mode_cb ) {
                    std::string other_default = msg->choose.state ? DEFAULT_INFO_LINE_CONTENT_NOLUA : DEFAULT_INFO_LINE_CONTENT_LUA;
                    std::string this_default = msg->choose.state ? DEFAULT_INFO_LINE_CONTENT_LUA : DEFAULT_INFO_LINE_CONTENT_NOLUA;

                    std::string current_value = info_line_content_sg->getText();

                    if ( current_value.empty()  ||
                         current_value == other_default ) {
                        info_line_content_sg->setText( this_default.c_str() );
                    }
                } else if ( msg->choose.button == chb ) {
                    updateFilterTabTitle( k1, chb,
                                          tfilters,
                                          bookmark_filter_cycb );
                } else if ( msg->choose.button == reverse_sort_chb ) {
                    updateSortTabTitle( k1,
                                        sort_cyb,
                                        reverse_sort_chb );
                }
                break;
            case AG_CYCLEBUTTONCLICKED:
                if ( msg->cyclebutton.cyclebutton == sort_cyb ) {
                    updateSortTabTitle( k1,
                                        sort_cyb,
                                        reverse_sort_chb );
                } else if ( msg->cyclebutton.cyclebutton == bookmark_filter_cycb ) {
                    updateFilterTabTitle( k1, chb,
                                          tfilters,
                                          bookmark_filter_cycb );
                }
            case AG_KEYPRESSED:
                if ( win->isParent( msg->key.window, false ) == true ) {
                    switch ( msg->key.key ) {
                        case XK_Return:
                            if ( cancelb->getHasFocus() == false ) {
                                endmode = 1;
                            }
                            break;
                        case XK_Escape:
                            endmode = 1;
                            break;
                    }
                }
                break;
            case AG_STRINGGADGET_CONTENTCHANGE:
                if ( msg->stringgadget.sg == bookmark_label_sg ) {
                    bookmark_filter_cycb->setOption( 2 );

                    updateFilterTabTitle( k1, chb,
                                          tfilters,
                                          bookmark_filter_cycb );
                }
                break;
            case AG_FIELDLV_ONESELECT:
            case AG_FIELDLV_MULTISELECT:
                if ( msg->fieldlv.lv == label_lv ) {
                    int label_row = label_lv->getActiveRow();
                    if ( label_lv->isValidRow( label_row ) == true ) {
                        bookmark_label_sg->setText( label_lv->getText( label_row, 0 ).c_str() );
                    }
                    bookmark_filter_cycb->setOption( 2 );

                    updateFilterTabTitle( k1, chb,
                                          tfilters,
                                          bookmark_filter_cycb );
                }
                break;
        }
        aguix->ReplyMessage( msg );
    }

    if ( endmode == 0 ) {
        // ok
        int tsortmode = 0;
        switch ( sort_cyb->getSelectedOption() ) {
            case 1:
                tsortmode = SORT_SIZE;
                break;
            case 2:
                tsortmode = SORT_ACCTIME;
                break;
            case 3:
                tsortmode = SORT_MODTIME;
                break;
            case 4:
                tsortmode = SORT_CHGTIME;
                break;
            case 5:
                tsortmode = SORT_TYPE;
                break;
            case 6:
                tsortmode = SORT_OWNER;
                break;
            case 7:
                tsortmode = SORT_INODE;
                break;
            case 8:
                tsortmode = SORT_NLINK;
                break;
            case 9:
                tsortmode = SORT_PERMISSION;
                break;
            case 10:
                tsortmode = SORT_EXTENSION;
                break;
            case 11:
                tsortmode = SORT_CUSTOM_ATTRIBUTE;
                break;
            default:
                tsortmode = SORT_NAME;
                break;
        }

        if ( reverse_sort_chb->getState() == true ) tsortmode |= SORT_REVERSE;

        switch ( dirmode_cyb->getSelectedOption() ) {
            case 1:
                tsortmode |= SORT_DIRLAST;
                break;
            case 2:
                tsortmode |= SORT_DIRMIXED;
                break;
            default:
                break;
        }

        tshowhidden = chb->getState();

        t_dir_settings.setHighlightBookmarkPrefix( highlight_prefix_cb->getState() );
        t_dir_settings.setSpecificBookmarkLabel( bookmark_label_sg->getText() );

        switch ( bookmark_filter_cycb->getSelectedOption() ) {
            case 1:
                t_dir_settings.setBookmarkFilter( DirFilterSettings::SHOW_ONLY_BOOKMARKS );
                break;
            case 2:
                t_dir_settings.setBookmarkFilter( DirFilterSettings::SHOW_ONLY_LABEL );
                break;
            case 0:
            default:
                t_dir_settings.setBookmarkFilter( DirFilterSettings::SHOW_ALL );
                break;
        }

        setSortmode( tsortmode );
        setShowHidden( tshowhidden );
        setFilters( tfilters );
        setShowFreeSpace( ucb->getState() );
        int tut = atoi( tsg->getText() );
        setUpdatetime( tut );

        setWatchMode( watch_cb->getState() );
        setActivateSearchModeOnKeyPress( search_on_key_cb->getState() );
        setShowDotDot( show_dotdot_cb->getState() );
        setShowBreadcrumb( show_breadcrumb_cb->getState() );

        setHighlightBookmarkPrefix( t_dir_settings.getHighlightBookmarkPrefix() );
        setBookmarkFilter( t_dir_settings.getBookmarkFilter() );
        setSpecificBookmarkLabel( t_dir_settings.getSpecificBookmarkLabel() );

        setEnableInfoLine( enable_info_line_cb->getState() );
        setInfoLineLUAMode( info_line_lua_mode_cb->getState() );
        setInfoLineContent( info_line_content_sg->getText() );

        setEnableCustomLVBLine( enable_custom_lvb_line_cb->getState() );
        setCustomLVBLine( custom_lvb_format_sg->getText() );
        setCustomeDirectoryInfoCommand( custom_directory_info_sg->getText() );
    }

    delete win;

    return endmode;
}

void VirtualDirMode::setLVC4Filter( FieldListView *filv, int row, NM_Filter &fi )
{
    if ( filv == NULL ) return;
    const char *p = fi.getPattern();
  
    filv->setText( row, 0, ( p != NULL ) ? p : "" );
    if ( fi.getCheck() == 1 ) filv->setText( row, 2, catalog.getLocale( 170 ) );
    else if ( fi.getCheck() == 2 ) filv->setText( row, 2, catalog.getLocale( 171 ) );
    else filv->setText( row, 2, "" );
}

int VirtualDirMode::configureFilter( NM_Filter &fi )
{
    const char *tstr;
    const int cincw = AContainer::ACONT_MINH +
        AContainer::ACONT_MINW +
        AContainer::ACONT_MAXH;
    const int cfix = AContainer::ACONT_MINH +
        AContainer::ACONT_MINW +
        AContainer::ACONT_MAXH +
        AContainer::ACONT_MAXW;

    AWindow *win = new AWindow( aguix, 10, 10, 10, 10, catalog.getLocale( 172 ), AWindow::AWINDOW_DIALOG );
    win->create();

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

    AContainer *ac1_1 = ac1->add( new AContainer( win, 2, 1 ), 0, 0 );
    ac1_1->setMinSpace( 5 );
    ac1_1->setMaxSpace( 5 );
    ac1_1->setBorderWidth( 0 );
    ac1_1->add( new Text( aguix, 0, 0, catalog.getLocale( 93 ) ), 0, 0, cfix );

    tstr = fi.getPattern();
    StringGadget *tsg = (StringGadget*)ac1_1->add( new StringGadget( aguix, 0, 0, 100,
                                                                     ( tstr != NULL ) ? tstr : "", 0 ), 1, 0, cincw );

    CycleButton *cyb = (CycleButton*)ac1->add( new CycleButton( aguix, 0, 0, 100, 0 ), 0, 1, cincw );
    cyb->addOption(catalog.getLocale(358));
    cyb->addOption(catalog.getLocale(170));
    cyb->addOption(catalog.getLocale(171));
    if ( fi.getCheck() == 1 ) cyb->setOption(1);
    else if ( fi.getCheck() == 2 ) cyb->setOption(2);
    else cyb->setOption(0);
    cyb->resize(cyb->getMaxSize(),cyb->getHeight());
    ac1->readLimits();

    AContainer *ac1_2 = ac1->add( new AContainer( win, 2, 1 ), 0, 2 );
    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 *cancelb = (Button*)ac1_2->add( new Button( aguix,
                                                       0,
                                                       0,
                                                       catalog.getLocale( 8 ),
                                                       0 ), 1, 0, cfix );
  
    win->setDoTabCycling( true );
    win->contMaximize( true );
    win->show();
    AGMessage *msg;
    while((msg=aguix->GetMessage(NULL))!=NULL) aguix->ReplyMessage(msg);
    int ende=0;
    while(ende==0) {
        msg=aguix->WaitMessage(win);
        if(msg!=NULL) {
            if(msg->type==AG_CLOSEWINDOW) {
                if(msg->closewindow.window==win->getWindow()) ende=-1;
            } else if(msg->type==AG_BUTTONCLICKED) {
                if(msg->button.button==okb) ende=1;
                else if(msg->button.button==cancelb) ende=-1;
            }
            aguix->ReplyMessage(msg);
        }
    }
    if(ende==1) {
        switch(cyb->getSelectedOption()) {
            case 1:
                fi.setCheck( NM_Filter::INCLUDE );
                break;
            case 2:
                fi.setCheck( NM_Filter::EXCLUDE );
                break;
            default:
                fi.setCheck( NM_Filter::INACTIVE );
                break;
        }
        fi.setPattern( tsg->getText() );
    }
  
    delete win;
    return (ende==1)?0:1;
}
