"Fossies" - the Fresh Open Source Software Archive

Member "worker-4.1.0/src/startprogop.cc" (10 Sep 2019, 44714 Bytes) of package /linux/privat/worker-4.1.0.tar.bz2:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "startprogop.cc" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 4.0.1_vs_4.1.0.

    1 /* startprogop.cc
    2  * This file belongs to Worker, a file manager for UN*X/X11.
    3  * Copyright (C) 2001-2019 Ralf Hoffmann.
    4  * You can contact me at: ralf@boomerangsworld.de
    5  *   or http://www.boomerangsworld.de/worker
    6  *
    7  * This program is free software; you can redistribute it and/or modify
    8  * it under the terms of the GNU General Public License as published by
    9  * the Free Software Foundation; either version 2 of the License, or
   10  * (at your option) any later version.
   11  *
   12  * This program is distributed in the hope that it will be useful,
   13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   15  * GNU General Public License for more details.
   16  *
   17  * You should have received a copy of the GNU General Public License
   18  * along with this program; if not, write to the Free Software
   19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
   20  */
   21 
   22 #include "startprogop.h"
   23 #include "listermode.h"
   24 #include "worker.h"
   25 #include <string>
   26 #include <aguix/kartei.h>
   27 #include <aguix/acontainerbb.h>
   28 #include "execlass.h"
   29 #include "basic_actions.h"
   30 #include "wcfiletype.hh"
   31 #include "avfssupport.hh"
   32 #include "fileentry.hh"
   33 #include "nmspecialsourceext.hh"
   34 #include "fileviewer.hh"
   35 #include "processexitaction.hh"
   36 #include "datei.h"
   37 #include "worker_locale.h"
   38 #include <aguix/fieldlistview.h>
   39 #include <aguix/cyclebutton.h>
   40 #include <aguix/choosebutton.h>
   41 #include <aguix/stringgadget.h>
   42 #include <aguix/button.h>
   43 #include <aguix/textview.h>
   44 #include "wconfig.h"
   45 #include "flattypelist.hh"
   46 #include "argclass.hh"
   47 #include "nwc_path.hh"
   48 #include "pers_string_list.hh"
   49 #include "wpucontext.h"
   50 #include "ownop.h"
   51 #include "ajson.hh"
   52 
   53 const char *StartProgOp::name="StartProgOp";
   54 
   55 StartProgOp::StartProgOp() : FunctionProto()
   56 {
   57   startprogstart=STARTPROGOP_START_NORMAL;
   58 
   59   view_str = "";
   60   
   61   global=false;
   62   inbackground = false;
   63   dontcd = false;
   64   hasConfigure = true;
   65 
   66   gui_msg = "";
   67 
   68   m_cmd_sg = nullptr;
   69   m_cmd_flag_b = nullptr;
   70 }
   71 
   72 StartProgOp::~StartProgOp()
   73 {
   74 }
   75 
   76 StartProgOp*
   77 StartProgOp::duplicate() const
   78 {
   79   StartProgOp *ta=new StartProgOp();
   80   ta->startprogstart=startprogstart;
   81 
   82   ta->view_str = view_str;
   83   ta->global=global;
   84   ta->inbackground = inbackground;
   85   ta->dontcd = dontcd;
   86   return ta;
   87 }
   88 
   89 bool
   90 StartProgOp::isName(const char *str)
   91 {
   92   if(strcmp(str,name)==0) return true; else return false;
   93 }
   94 
   95 const char *
   96 StartProgOp::getName()
   97 {
   98   return name;
   99 }
  100 
  101 int
  102 StartProgOp::run( WPUContext *wpu, ActionMessage *msg )
  103 {
  104   if(msg->mode!=msg->AM_MODE_DNDACTION) {
  105     Lister *l1 = msg->getWorker()->getActiveLister();
  106     if(l1!=NULL) {
  107       startlister=l1;
  108       endlister = msg->getWorker()->getOtherLister(startlister);
  109       startprog( wpu, msg );
  110     }
  111   }
  112   return 0;
  113 }
  114 
  115 bool
  116 StartProgOp::save(Datei *fh)
  117 {
  118   if ( fh == NULL ) return false;
  119   switch(startprogstart) {
  120     case STARTPROGOP_START_IN_TERMINAL:
  121       fh->configPutPair( "start", "terminal" );
  122       break;
  123     case STARTPROGOP_START_IN_TERMINAL_AND_WAIT4KEY:
  124       fh->configPutPair( "start", "terminalwait" );
  125       break;
  126     case STARTPROGOP_SHOW_OUTPUT:
  127       fh->configPutPair( "start", "showoutput" );
  128       break;
  129     case STARTPROGOP_SHOW_OUTPUT_INT:
  130       fh->configPutPair( "start", "showoutputint" );
  131       break;
  132     default:
  133       fh->configPutPair( "start", "normal" );
  134       break;
  135   }
  136   fh->configPutPairString( "viewstr", view_str.c_str() );
  137   fh->configPutPairBool( "global", global );
  138   fh->configPutPairBool( "inbackground", inbackground );
  139   fh->configPutPairBool( "dontcd", dontcd );
  140   return true;
  141 }
  142 
  143 const char *
  144 StartProgOp::getDescription()
  145 {
  146   return catalog.getLocale(1273);
  147 }
  148 
  149 /* replace backslash with double backslash and backslash { and } */
  150 static std::string protectForParsing( const char *str1 )
  151 {
  152     std::string res;
  153 
  154     if ( str1 != NULL ) {
  155         for ( ; *str1 != '\0'; str1++ ) {
  156             switch ( *str1 ) {
  157                 case '\\':
  158                     res += "\\\\";
  159                     break;
  160                 case '{':
  161                     res += "\\{";
  162                     break;
  163                 case '}':
  164                     res += "\\}";
  165                     break;
  166                 default:
  167                     res += *str1;
  168                     break;
  169             }
  170         }
  171     }
  172 
  173     return res;
  174 }
  175 
  176 int
  177 StartProgOp::startprog( WPUContext *wpu, ActionMessage *am )
  178 {
  179   ListerMode *lm1 = NULL;
  180 
  181   char *tmpname, *tmpoutput, *tstr;
  182   std::string string1;
  183   bool useint;
  184   bool removeTMPFiles;
  185   std::string fullname;
  186 
  187   if ( startlister == NULL ) return 1;
  188   lm1 = startlister->getActiveMode();
  189   if ( lm1 == NULL ) return 1;
  190 
  191   std::list< NM_specialsourceExt > filelist;
  192 
  193   lm1->getSelFiles( filelist, ListerMode::LM_GETFILES_ONLYACTIVE );
  194 
  195   const FileEntry *tfe;
  196   if ( am->mode == am->AM_MODE_SPECIAL ) {
  197     // Copy of FE is not necessary because it's already duplicated in ActionMessage
  198     tfe = am->getFE();
  199   } else if ( ! filelist.empty() &&
  200               filelist.begin()->entry() != NULL ) {
  201     tfe = filelist.begin()->entry();
  202   } else {
  203     tfe = NULL;
  204   }
  205   if ( tfe != NULL ) {
  206       std::string cwd = lm1->getCurrentDirectory();
  207 
  208       default_file = tfe->name;
  209       fullname = tfe->fullname;
  210 
  211       if ( ! cwd.empty() ) {
  212           std::string name_string = NWC::Path::get_extended_basename( cwd,
  213                                                                       tfe->fullname );
  214           if ( ! name_string.empty() ) {
  215               default_file = name_string;
  216           }
  217       }
  218 
  219       if ( tfe->filetype ) {
  220           m_default_file_filetype = tfe->filetype->getName();
  221       } else {
  222           m_default_file_filetype = "";
  223       }
  224   } else {
  225     default_file = "";
  226   }
  227 
  228   std::unique_ptr< StartSettings > m1;
  229   m1 = showGUI();
  230   if ( m1->_startmode == StartSettings::STARTPROG ) {
  231     tmpname = Datei::createTMPName();
  232     tmpoutput = Datei::createTMPName();
  233 
  234     if ( tmpname != NULL && tmpoutput != NULL ) {
  235       removeTMPFiles = true;
  236 
  237       std::string tmpoutput_lnk;
  238 
  239       RefCount< GenericCallbackArg< void, int > > pea( NULL );
  240       
  241       if ( m1->_start == STARTPROGOP_SHOW_OUTPUT_INT ) {
  242           tmpoutput_lnk = Datei::createTMPHardlink( tmpoutput );
  243 
  244           wpu->ref();
  245 
  246           pea = new ProcessExitAction( true,
  247                                        tmpoutput_lnk,
  248                                        am->getWorker(), wpu );
  249       } else {
  250           wpu->ref();
  251 
  252           pea = new ProcessExitAction( false,
  253                                        "",
  254                                        am->getWorker(), wpu );
  255       }
  256 
  257       Datei fp;
  258       if ( fp.open( tmpname, "w" ) == 0 ) {
  259         fp.putString( "#! /bin/sh\n" );
  260         if ( ! lm1->getCurrentDirectory().empty() ) {
  261             if ( ( worker_islocal( lm1->getCurrentDirectory().c_str() ) == 1 ) &&
  262                  ( m1->_dontcd == false ) ) {
  263                 tstr = AGUIX_catTrustedAndUnTrusted( "cd ", lm1->getCurrentDirectory().c_str() );
  264                 fp.putString( tstr );
  265                 _freesafe( tstr );
  266                 fp.putString( "\n" );
  267             }
  268         }
  269         if ( m1->_global == false ) fp.putString( "./" );
  270 
  271         std::string res_str;
  272         if ( wpu->parse( m1->_command.c_str(),
  273                          res_str,
  274                          EXE_STRING_LEN - strlen( tmpoutput ) - 3,
  275                          true,
  276                          WPUContext::PERSIST_FLAGS ) == WPUContext::PARSE_SUCCESS ) {
  277             string1 = Worker_secureCommandForShell( res_str.c_str() );
  278 
  279             if ( m1->_global ) {
  280                 // as for now only store global programs and the file
  281                 // in the persistent database
  282                 if ( wpu->getPathDBFilename().empty() ) {
  283                     am->getWorker()->storePathPers( fullname,
  284                                                     res_str,
  285                                                     time( NULL ) );
  286                 } else {
  287                     am->getWorker()->storePathPers( wpu->getPathDBFilename(),
  288                                                     res_str,
  289                                                     time( NULL ) );
  290                 }
  291             }
  292         }
  293 
  294         if ( string1.length() > 0 ) {
  295           if ( m1->_start == STARTPROGOP_SHOW_OUTPUT ||
  296                m1->_start == STARTPROGOP_SHOW_OUTPUT_INT ) {
  297             string1 += " >";
  298             string1 += tmpoutput;
  299           }
  300           fp.putString( string1.c_str() );
  301           fp.putString( "\n" );
  302         }
  303 
  304         std::string exestr;
  305 
  306         if ( ( m1->_start == STARTPROGOP_START_IN_TERMINAL_AND_WAIT4KEY )||
  307              ( m1->_start == STARTPROGOP_START_IN_TERMINAL ) ) {
  308           /* in terminal starten */
  309           if ( m1->_start == STARTPROGOP_START_IN_TERMINAL_AND_WAIT4KEY ) {
  310             fp.putStringExt( "echo %s\n", catalog.getLocale( 201 ) );
  311             fp.putString( "read x\n" );
  312           }
  313           exestr = AGUIXUtils::formatStringToString( wconfig->getTerminalStr(),
  314                                                      tmpname );
  315         } else {
  316             exestr = "/bin/sh ";
  317             exestr += tmpname;
  318         }
  319         if ( m1->_start == STARTPROGOP_SHOW_OUTPUT ) {
  320           useint = true;
  321           if ( m1->_view_str.length() > 2 )
  322             if ( strstr( m1->_view_str.c_str(), "%s" ) != NULL ) useint = false;
  323           if ( useint == true ) fp.putStringExt( OUTPUT_BIN, tmpoutput );
  324           else fp.putStringExt( m1->_view_str.c_str(), tmpoutput );
  325           fp.putString( "\n" );
  326         }
  327         fp.close();
  328 
  329         if ( fp.errors() == 0 ) {
  330           worker_chmod( tmpname, 0700 );
  331           removeTMPFiles = false;
  332           am->getWorker()->runCommand( exestr.c_str(), tmpname, tmpoutput, m1->_inbackground, pea );
  333         } else {
  334           Requester req( Worker::getAGUIX() );
  335           char *textstr = (char*)_allocsafe( strlen( catalog.getLocale( 647 ) ) + strlen( tmpname ) + 1 );
  336 
  337           sprintf( textstr, catalog.getLocale( 647 ), tmpname );
  338           std::string button = catalog.getLocale( 11 );
  339           req.request( catalog.getLocale( 347 ), textstr, button.c_str() );
  340           _freesafe( textstr );
  341         }
  342       }
  343       if ( removeTMPFiles == true ) {
  344         worker_unlink( tmpname );
  345         worker_unlink( tmpoutput );
  346 
  347         if ( pea.getVal() != NULL ) {
  348             pea->callback( 0 );
  349         }
  350       }
  351     } else {
  352       Requester req( Worker::getAGUIX() );
  353       char *textstr = (char*)_allocsafe( strlen( catalog.getLocale( 647 ) ) + strlen( "" ) + 1 );
  354       
  355       sprintf( textstr, catalog.getLocale( 647 ), "" );
  356       std::string button = catalog.getLocale( 11 );
  357       req.request( catalog.getLocale( 347 ), textstr, button.c_str() );
  358       _freesafe( textstr );
  359     }
  360     
  361     if ( tmpname != NULL ) _freesafe( tmpname );
  362     if ( tmpoutput != NULL ) _freesafe( tmpoutput );
  363   } else if ( m1->_startmode == StartSettings::HANDLE_TYPE ) {
  364     WCFiletype *ft = m1->_type;
  365     if ( ( ft != NULL ) && ( tfe != NULL ) ) {
  366       List *l = ft->getDoubleClickActions();
  367       if ( l != NULL ) {
  368     ActionMessage amsg( am->getWorker() );
  369     
  370     amsg.mode = amsg.AM_MODE_SPECIAL;
  371     
  372     amsg.setFE( tfe );
  373     amsg.filetype = ft;
  374         amsg.m_action_descr = RefCount<ActionDescr>( new DoubleClickAction::DoubleClickActionDescr() );
  375     am->getWorker()->interpret( l, &amsg );
  376       }
  377     }
  378   } else if ( m1->_startmode == StartSettings::HANDLE_ARCHIVE ) {
  379     std::string dir;
  380 
  381     if ( tfe != NULL ) {
  382       dir = tfe->fullname;
  383       dir += "#";
  384       dir += m1->_archive;
  385 
  386       std::list< RefCount< ArgClass > > args;
  387 
  388       args.push_back( new StringArg( dir ) );
  389       lm1->runCommand( "enter_dir", args );
  390     }
  391   }
  392 
  393   if ( m1->_startmode != StartSettings::CANCEL ) {
  394       am->getWorker()->storePathPersIfInProgress( fullname );
  395   }
  396 
  397   return 0;
  398 }
  399 
  400 int
  401 StartProgOp::configure()
  402 {
  403   return doconfigure();
  404 }
  405 
  406 std::unique_ptr< StartProgOp::SettingsWidgets > StartProgOp::buildW( AWindow *win )
  407 {
  408   SettingsWidgets *m1;
  409 
  410   AGUIX *aguix = Worker::getAGUIX();
  411   StringGadget *sg;
  412   CycleButton *cyb;
  413   ChooseButton *gcb, *ibcb, *dcdcb;
  414   const int cincw = AContainer::ACONT_MINH +
  415                     AContainer::ACONT_MINW +
  416                     AContainer::ACONT_MAXH;
  417   const int cincwnr = cincw +
  418                       AContainer::ACONT_NORESIZE;
  419   const int cfix = AContainer::ACONT_MINH +
  420                    AContainer::ACONT_MINW +
  421                    AContainer::ACONT_MAXH +
  422                    AContainer::ACONT_MAXW;
  423   
  424   AContainer *ac1 = win->setContainer( new AContainerBB( win, 1, 6 ), true );
  425   ac1->setMinSpace( 5 );
  426   ac1->setMaxSpace( 5 );
  427 
  428   ac1->add( new Text( aguix, 0, 0, catalog.getLocale( 638 ) ), 0, 0, cincwnr );
  429 
  430   AContainer *ac1_1 = ac1->add( new AContainer( win, 2, 1 ), 0, 1 );
  431   ac1_1->setMinSpace( 5 );
  432   ac1_1->setMaxSpace( 5 );
  433   ac1_1->setBorderWidth( 0 );
  434 
  435   ac1_1->add( new Text( aguix, 0, 0, catalog.getLocale( 331 ) ), 0, 0, cfix );
  436   cyb = (CycleButton*)ac1_1->add( new CycleButton( aguix, 0, 0, 100, 0 ), 1, 0, cincw );
  437   cyb->addOption(catalog.getLocale(332));
  438   cyb->addOption(catalog.getLocale(333));
  439   cyb->addOption(catalog.getLocale(334));
  440   cyb->addOption(catalog.getLocale(335));
  441   cyb->addOption( catalog.getLocale( 911 ) );
  442   cyb->resize(cyb->getMaxSize(),cyb->getHeight());
  443   switch(startprogstart) {
  444     case STARTPROGOP_START_IN_TERMINAL:
  445       cyb->setOption(1);
  446       break;
  447     case STARTPROGOP_START_IN_TERMINAL_AND_WAIT4KEY:
  448       cyb->setOption(2);
  449       break;
  450     case STARTPROGOP_SHOW_OUTPUT:
  451       cyb->setOption(3);
  452       break;
  453     case STARTPROGOP_SHOW_OUTPUT_INT:
  454       cyb->setOption( 4 );
  455       break;
  456     default:
  457       cyb->setOption(0);
  458       break;
  459   }
  460   ac1_1->readLimits();
  461   
  462   AContainer *ac1_2 = ac1->add( new AContainer( win, 2, 1 ), 0, 2 );
  463   ac1_2->setMinSpace( 5 );
  464   ac1_2->setMaxSpace( 5 );
  465   ac1_2->setBorderWidth( 0 );
  466 
  467   ac1_2->add( new Text( aguix, 0, 0, catalog.getLocale( 337 ) ), 0, 0, cfix );
  468   sg = (StringGadget*)ac1_2->add( new StringGadget( aguix, 0, 0, 100, view_str.c_str(), 0 ), 1, 0, cincw );
  469 
  470   gcb = (ChooseButton*)ac1->add( new ChooseButton( aguix, 0, 0, ( global == true ) ? 1 : 0,
  471                            catalog.getLocale( 343 ), LABEL_RIGHT, 0 ), 0, 3, cincwnr );
  472   ibcb = (ChooseButton*)ac1->add( new ChooseButton( aguix,
  473                                                     0,
  474                                                     0,
  475                                                     ( inbackground == true ) ? 1 : 0,
  476                                                     catalog.getLocale( 435 ),
  477                                                     LABEL_RIGHT,
  478                                                     0 ), 0, 4, cincwnr );
  479 
  480   dcdcb = (ChooseButton*)ac1->add( new ChooseButton( aguix,
  481                              0,
  482                              0,
  483                              ( dontcd == true ) ? 1 : 0,
  484                              catalog.getLocale( 617 ),
  485                              LABEL_RIGHT,
  486                              0 ), 0, 5, cincwnr );
  487 
  488   win->contMaximize( true );
  489   win->show();
  490   
  491   m1 = new SettingsWidgets( sg, cyb, gcb, ibcb, dcdcb );
  492 
  493   return std::unique_ptr< SettingsWidgets >( m1 );
  494 }
  495 
  496 int StartProgOp::doconfigure()
  497 {
  498   AGUIX *aguix = Worker::getAGUIX();
  499   Button *okb,*cb;
  500   AWindow *win;
  501   AGMessage *msg;
  502   int endmode=-1;
  503   char *tstr;
  504   int i;
  505   const int cfix = AContainer::ACONT_MINH +
  506                    AContainer::ACONT_MINW +
  507                    AContainer::ACONT_MAXH +
  508                    AContainer::ACONT_MAXW;
  509   const int cmin = AContainer::ACONT_MINH +
  510                    AContainer::ACONT_MINW;
  511   
  512   tstr=(char*)_allocsafe(strlen(catalog.getLocale(293))+strlen(getDescription())+1);
  513   sprintf(tstr,catalog.getLocale(293),getDescription());
  514   win = new AWindow( aguix, 10, 10, 10, 10, tstr, AWindow::AWINDOW_DIALOG );
  515   win->create();
  516   _freesafe(tstr);
  517 
  518   AContainer *ac1 = win->setContainer( new AContainer( win, 1, 2 ), true );
  519   ac1->setMinSpace( 5 );
  520   ac1->setMaxSpace( 5 );
  521 
  522   AWindow *subwin1 = new AWindow( aguix, 10, 10, 10, 10, "" );
  523   ac1->add( subwin1, 0, 0, cmin );
  524 
  525   std::unique_ptr< SettingsWidgets > m1 = buildW( subwin1 );
  526   ac1->readLimits();
  527 
  528   AContainer *ac1_3 = ac1->add( new AContainer( win, 2, 1 ), 0, 1 );
  529   ac1_3->setMinSpace( 5 );
  530   ac1_3->setMaxSpace( -1 );
  531   ac1_3->setBorderWidth( 0 );
  532   okb =(Button*)ac1_3->add( new Button( aguix,
  533                     0,
  534                     0,
  535                     catalog.getLocale( 11 ),
  536                     0 ), 0, 0, cfix );
  537   cb = (Button*)ac1_3->add( new Button( aguix,
  538                     0,
  539                     0,
  540                     catalog.getLocale( 8 ),
  541                     0 ), 1, 0, cfix );
  542 
  543   okb->takeFocus();
  544   win->setDoTabCycling( true );
  545   win->contMaximize( true );
  546   win->show();
  547 
  548   for(;endmode==-1;) {
  549     msg=aguix->WaitMessage(win);
  550     if(msg!=NULL) {
  551       switch(msg->type) {
  552         case AG_CLOSEWINDOW:
  553           if(msg->closewindow.window==win->getWindow()) endmode=1;
  554           break;
  555         case AG_BUTTONCLICKED:
  556           if(msg->button.button==okb) {
  557         if ( m1->validate() == 1 ) endmode = 0;
  558           } else if(msg->button.button==cb) endmode=1;
  559           break;
  560     case AG_STRINGGADGET_DEACTIVATE:
  561           if(msg->stringgadget.sg==m1->_sg) {
  562         m1->validate();
  563           }
  564       break;
  565         case AG_KEYPRESSED:
  566           if(win->isParent(msg->key.window,false)==true) {
  567             switch(msg->key.key) {
  568               case XK_1:
  569                 i=m1->_cyb->getSelectedOption()+1;
  570                 if(i>=4) i=0;
  571                 m1->_cyb->setOption(i);
  572                 break;
  573               case XK_2:
  574                 m1->_gcb->setState((m1->_gcb->getState()==true)?false:true);
  575                 break;
  576               case XK_3:
  577                 m1->_ibcb->setState( ( m1->_ibcb->getState() == true ) ? false : true );
  578                 break;
  579               case XK_Return:
  580                 if ( cb->getHasFocus() == false ) {
  581           if ( m1->validate() == 1 ) endmode = 0;
  582                 }
  583                 break;
  584               case XK_Escape:
  585                 endmode=1;
  586                 break;
  587             }
  588           }
  589           break;
  590       }
  591       aguix->ReplyMessage(msg);
  592     }
  593   }
  594   
  595   if(endmode==0) {
  596     // ok
  597     view_str = m1->_sg->getText();
  598     switch(m1->_cyb->getSelectedOption()) {
  599       case 1:
  600     startprogstart=STARTPROGOP_START_IN_TERMINAL;
  601     break;
  602       case 2:
  603     startprogstart=STARTPROGOP_START_IN_TERMINAL_AND_WAIT4KEY;
  604     break;
  605       case 3:
  606     startprogstart=STARTPROGOP_SHOW_OUTPUT;
  607     break;
  608       case 4:
  609     startprogstart = STARTPROGOP_SHOW_OUTPUT_INT;
  610     break;
  611       default:
  612     startprogstart=STARTPROGOP_START_NORMAL;
  613     break;
  614     }
  615     global = m1->_gcb->getState();
  616     inbackground = m1->_ibcb->getState();
  617     dontcd = m1->_dcdcb->getState();
  618   }
  619   
  620   delete win;
  621 
  622   return endmode;
  623 }
  624 
  625 void StartProgOp::setStart(startprogstart_t nv)
  626 {
  627   startprogstart=nv;
  628 }
  629 
  630 void StartProgOp::setGlobal(bool nv)
  631 {
  632   global=nv;
  633 }
  634 
  635 void StartProgOp::setRequestFlags(bool nv)
  636 {
  637 }
  638 
  639 void StartProgOp::setInBackground( bool nv )
  640 {
  641   inbackground = nv;
  642 }
  643 
  644 void StartProgOp::setDontCD( bool nv )
  645 {
  646   dontcd = nv;
  647 }
  648 
  649 void StartProgOp::setViewStr( std::string nv )
  650 {
  651   view_str = nv;
  652 }
  653 
  654 StartProgOp::SettingsWidgets::SettingsWidgets( StringGadget *sg,
  655                                                CycleButton *cyb,
  656                                                ChooseButton *gcb,
  657                                                ChooseButton *ibcb,
  658                                                ChooseButton *dcdcb ) : _sg( sg ),
  659                                                                        _cyb( cyb ),
  660                                                                        _gcb( gcb ),
  661                                                                        _ibcb( ibcb ),
  662     _dcdcb( dcdcb )
  663 {
  664 }
  665 
  666 static bool isCorrectViewProg( const char *str )
  667 {
  668     const char *pos;
  669     if ( strlen( str ) < 1 ) return true;
  670     pos = strstr( str, "%s" );
  671     if ( pos != NULL ) return true;
  672     return false;
  673 }
  674 
  675 int StartProgOp::SettingsWidgets::validate()
  676 {
  677   const char *textstr;
  678   char *buttonstr;
  679   int erg;
  680   Requester req( Worker::getAGUIX() );
  681 
  682   if ( isCorrectViewProg( _sg->getText() ) == false ) {
  683     // show requester
  684     textstr = catalog.getLocale( 312 );
  685     buttonstr = (char*)_allocsafe( strlen( catalog.getLocale( 313 ) ) + 1 +
  686                    strlen( catalog.getLocale( 314 ) ) + 1 );
  687     sprintf( buttonstr, "%s|%s", catalog.getLocale( 313 ),
  688          catalog.getLocale( 314 ) );
  689     erg = req.request( catalog.getLocale( 125 ), textstr, buttonstr );
  690     _freesafe( buttonstr );
  691     if ( erg == 0 ) {
  692       _sg->activate();
  693     } else {
  694       _sg->setText( "" );
  695     }
  696   } else return 1;
  697   return 0;
  698 }
  699 
  700 std::unique_ptr< StartProgOp::StartSettings > StartProgOp::showGUI()
  701 {
  702   AGUIX *aguix = Worker::getAGUIX();
  703   int w, h, sw;
  704   AWindow *win;
  705   int row;
  706   const int cincw = AContainer::ACONT_MINH +
  707                     AContainer::ACONT_MINW +
  708                     AContainer::ACONT_MAXH;
  709   const int cincwnr = cincw +
  710                       AContainer::ACONT_NORESIZE;
  711   const int cfix = AContainer::ACONT_MINH +
  712                    AContainer::ACONT_MINW +
  713                    AContainer::ACONT_MAXH +
  714                    AContainer::ACONT_MAXW;
  715   const int cmin = AContainer::ACONT_MINH +
  716                    AContainer::ACONT_MINW;
  717   int i;
  718   std::string str1;
  719 
  720   if ( gui_msg.length() < 1 )
  721     gui_msg = catalog.getLocale( 645 );
  722 
  723   win = new AWindow( aguix, 10, 10, 10, 10, getDescription() );
  724   win->create();
  725 
  726   AContainer *ac1 = win->setContainer( new AContainer( win, 1, 3 ), true );
  727   ac1->setMinSpace( 5 );
  728   ac1->setMaxSpace( 5 );
  729   
  730   ac1->add( new Text( aguix, 0, 0, gui_msg.c_str() ), 0, 0, cincwnr );
  731 
  732   Kartei *k1 = new Kartei( aguix, 10, 10, 10, 10, "" );
  733   ac1->add( k1, 0, 1, cmin );
  734   k1->create();
  735 
  736   AWindow *subwin11 = new AWindow( aguix, 0, 0, 10, 10, "" );
  737   k1->add( subwin11 );
  738   subwin11->create();
  739   
  740   AContainer *acsw11 = subwin11->setContainer( new AContainer( subwin11, 1, 3 ), true );
  741   acsw11->setMinSpace( 5 );
  742   acsw11->setMaxSpace( 5 );
  743   acsw11->setBorderWidth( 5 );
  744 
  745   RefCount<AFontWidth> lencalc( new AFontWidth( aguix, NULL ) );
  746   TextStorageString help_ts( catalog.getLocale( 1076 ), lencalc );
  747   TextView *help_tv = (TextView*)acsw11->add( new TextView( aguix,
  748                                                             0, 0, 50, 80, "", help_ts ),
  749                                               0, 0, AContainer::CO_INCW );
  750   help_tv->setLineWrap( true );
  751   help_tv->maximizeX( 500 );
  752   help_tv->maximizeYLines( 10 );
  753   help_tv->showFrame( false );
  754   acsw11->readLimits();
  755   help_tv->show();
  756   help_tv->setAcceptFocus( false );
  757 
  758   TextView::ColorDef tv_cd = help_tv->getColors();
  759   tv_cd.setBackground( 0 );
  760   tv_cd.setTextColor( 1 );
  761   help_tv->setColors( tv_cd );
  762 
  763   AContainer *acsw11_1 = acsw11->add( new AContainer( subwin11, 2, 2 ), 0, 1 );
  764   acsw11_1->setMinSpace( 5 );
  765   acsw11_1->setMaxSpace( 5 );
  766   acsw11_1->setBorderWidth( 0 );
  767 
  768   std::string cmd_string;
  769   {
  770       char *tstr = AGUIX_catQuotedAndUnQuoted( "", default_file.c_str() );
  771       cmd_string = protectForParsing( tstr );
  772       _freesafe( tstr );
  773   }
  774 
  775   acsw11_1->add( new Text( aguix, 0, 0, catalog.getLocale( 639 ) ), 0, 0, cfix );
  776 
  777   AContainer *acsw11_1_1 = acsw11_1->add( new AContainer( subwin11, 2, 1 ), 1, 0 );
  778   acsw11_1_1->setMinSpace( 0 );
  779   acsw11_1_1->setMaxSpace( 0 );
  780   acsw11_1_1->setBorderWidth( 0 );
  781 
  782   m_cmd_sg = acsw11_1_1->addWidget( new StringGadget( aguix, 0,
  783                                                       0, 100, cmd_string.c_str(), 0 ), 0, 0, cincw );
  784 
  785   m_cmd_flag_b = acsw11_1_1->addWidget( new Button( aguix,
  786                                                     0,
  787                                                     0,
  788                                                     "F",
  789                                                     0 ), 1, 0, cfix );
  790   m_cmd_flag_b->setBubbleHelpText( catalog.getLocale( 1131 ) );
  791 
  792   acsw11_1->add( new Text( aguix, 0, 0, catalog.getLocale( 1035 ) ), 0, 1,
  793                  AContainer::ACONT_MINH +
  794                  AContainer::ACONT_MINW +
  795                  AContainer::ACONT_MAXW +
  796                  AContainer::ACONT_NORESIZE );
  797   m_completion_lv = acsw11_1->addWidget( new FieldListView( aguix, 0, 0, 100, 75, 0 ),
  798                                          1, 1,
  799                                          cmin );
  800   m_completion_lv->setHBarState( 2 );
  801   m_completion_lv->setVBarState( 2 );
  802   m_completion_lv->setNrOfFields( 2 );
  803   m_completion_lv->setGlobalFieldSpace( 5 );
  804 
  805   AWindow *subwin11_2 = new AWindow( aguix, 0, 0, 10, 10, "" );
  806   acsw11->add( subwin11_2, 0, 2, cmin );
  807   subwin11_2->create();
  808   std::unique_ptr< SettingsWidgets > m1 = buildW( subwin11_2 );
  809   acsw11->readLimits();
  810 
  811   AWindow *subwin12 = new AWindow( aguix, 0, 0, 10, 10, "" );
  812   k1->add( subwin12 );
  813   subwin12->create();
  814 
  815   std::unique_ptr< FiletypeWindow > ftw = buildFTWindow( subwin12 );
  816 
  817   AWindow *subwin13 = new AWindow( aguix, 0, 0, 10, 10, "" );
  818   k1->add( subwin13 );
  819   subwin13->create();
  820 
  821   std::unique_ptr< ArchiveWindow > arcw = buildArcWindow( subwin13 );
  822 
  823   str1 = catalog.getLocale( 641 );
  824   str1 += " - F1";
  825   k1->setOption( subwin11, 0, str1.c_str() );
  826   str1 = catalog.getLocale( 642 );
  827   str1 += " - F2";
  828   k1->setOption( subwin12, 1, str1.c_str() );
  829   str1 = catalog.getLocale( 643 );
  830   str1 += " - F3";
  831   k1->setOption( subwin13, 2, str1.c_str() );
  832   k1->maximize();
  833   k1->contMaximize();
  834   ac1->readLimits();
  835 
  836   AContainer *ac1_5 = ac1->add( new AContainer( win, 2, 1 ), 0, 2 );
  837   ac1_5->setMinSpace( 5 );
  838   ac1_5->setMaxSpace( -1 );
  839   ac1_5->setBorderWidth( 0 );
  840   Button *okb =(Button*)ac1_5->add( new Button( aguix,
  841                                                 0,
  842                                                 0,
  843                                                 catalog.getLocale( 11 ),
  844                                                 0 ), 0, 0, cfix );
  845   Button *cancelb = (Button*)ac1_5->add( new Button( aguix,
  846                                                      0,
  847                                                      0,
  848                                                      catalog.getLocale( 8 ),
  849                                                      0 ), 1, 0, cfix );
  850   win->setDoTabCycling( true );
  851   win->contMaximize( true );
  852 
  853   w = win->getWidth();
  854   h = win->getHeight();
  855 
  856   int rx, ry, rw, rh;
  857 
  858   aguix->getLargestDimensionOfCurrentScreen( &rx, &ry,
  859                                              &rw, &rh );
  860 
  861   sw = rw;
  862   sw = (int)( (double)sw * 0.8 );
  863   if ( sw < 200 ) sw = 200;
  864   if ( w < sw ) w = sw;
  865   win->resize( w, h );
  866 
  867   win->show();
  868   k1->show();
  869 
  870   m_cmd_sg->takeFocus();
  871 
  872   std::string cfgfile = Worker::getWorkerConfigDir();
  873 #ifdef USEOWNCONFIGFILES
  874   cfgfile = NWC::Path::join( cfgfile, "startprog-history2" );
  875 #else
  876   cfgfile = NWC::Path::join( cfgfile, "startprog-history" );
  877 #endif
  878 
  879   PersistentStringList history( cfgfile );
  880   m_current_original_file = m_cmd_sg->getText();
  881   m_completion_enabled = true;
  882   m_previous_sg_content = "";
  883 
  884   cfgfile += "-filetype.json";
  885 
  886   auto filetype_history = AJSON::load( cfgfile );
  887   if ( ! AJSON::as_object( filetype_history ) ) {
  888       filetype_history = AJSON::make_object();
  889   }
  890 
  891   updateSGFromComplete( m_cmd_sg, history, filetype_history, m_completion_lv );
  892 
  893   AGMessage *msg;
  894   while((msg=aguix->GetMessage(NULL))!=NULL) aguix->ReplyMessage(msg);
  895   int ende=0;
  896   while(ende==0) {
  897     msg=aguix->WaitMessage(win);
  898     if(msg!=NULL) {
  899       switch ( msg->type ) {
  900           case AG_CLOSEWINDOW:
  901               if ( msg->closewindow.window == win->getWindow() ) ende = -1;
  902           case AG_BUTTONCLICKED:
  903               if ( msg->button.button == okb ) {
  904                   if ( m1->validate() == 1 ) ende = 1;
  905               } else if ( msg->button.button== cancelb ) ende = -1;
  906               else if ( msg->button.button == m_cmd_flag_b ) {
  907                   char *tstr = OwnOp::getFlag();
  908                   if ( tstr != NULL ) {
  909                       m_cmd_sg->insertAtCursor( tstr );
  910                       _freesafe( tstr );
  911                   }
  912               }
  913               break;
  914     case AG_STRINGGADGET_DEACTIVATE:
  915           if ( msg->stringgadget.sg == m1->_sg ) {
  916         m1->validate();
  917       }
  918       break;
  919         case AG_FIELDLV_ONESELECT:
  920         case AG_FIELDLV_MULTISELECT:
  921           if ( msg->fieldlv.lv == arcw->_lv ) {
  922             row = arcw->_lv->getActiveRow();
  923             if ( arcw->_lv->isValidRow( row ) == true ) {
  924           arcw->_sg->setText( arcw->_lv->getText( row, 0 ).c_str() );
  925             }
  926           } else if ( msg->fieldlv.lv == m_completion_lv ) {
  927               updateSGFromRow( msg->fieldlv.row, history, filetype_history );
  928           }
  929           break;
  930     case AG_STRINGGADGET_OK:
  931       if ( msg->stringgadget.sg == m_cmd_sg ) {
  932         if ( m1->validate() == 1 ) ende = 1;
  933       }
  934       break;
  935     case AG_STRINGGADGET_CURSORCHANGE:
  936         if ( msg->stringgadget.sg == m_cmd_sg ) {
  937             m_completion_enabled = false;
  938         }
  939         break;
  940     case AG_STRINGGADGET_CONTENTCHANGE:
  941         if ( msg->stringgadget.sg == ftw->m_filter_sg ) {
  942             ftw->updateView();
  943         } else if ( msg->stringgadget.sg == m_cmd_sg ) {
  944             updateSGFromComplete( m_cmd_sg, history, filetype_history, m_completion_lv );
  945         }
  946         break;
  947         case AG_KEYPRESSED:
  948           if ( win->isParent( msg->key.window, false ) == true ) {
  949             switch ( msg->key.key ) {
  950               case XK_1:
  951                 i = m1->_cyb->getSelectedOption() + 1;
  952                 if ( i >= 4 ) i = 0;
  953                 m1->_cyb->setOption( i );
  954                 break;
  955               case XK_2:
  956                 m1->_gcb->setState( ( m1->_gcb->getState() == true ) ? false : true );
  957                 break;
  958               case XK_3:
  959                 m1->_ibcb->setState( ( m1->_ibcb->getState() == true ) ? false : true );
  960                 break;
  961               case XK_4:
  962                 m1->_dcdcb->setState( ( m1->_dcdcb->getState() == true ) ? false : true );
  963                 break;
  964               case XK_Return:
  965                   if ( cancelb->getHasFocus() == false ) {
  966                       if ( m1->validate() == 1 ) ende = 1;
  967                   }
  968                   break;
  969                 case XK_Escape:
  970                     ende = -1;
  971                     break;
  972                 case XK_F1:
  973                     //TODO Was passiert mit Focus, wenn ich per Key die Kartei wechsle?
  974                     k1->optionChange( 0 );
  975                     break;
  976                 case XK_F2:
  977                     k1->optionChange( 1 );
  978                     break;
  979                 case XK_F3:
  980                     k1->optionChange( 2 );
  981                     break;
  982                 case XK_Down:
  983                     if ( m_completion_lv->getElements() > 0 ) {
  984                         int trow = m_completion_lv->getActiveRow();
  985 
  986                         trow++;
  987 
  988                         if ( trow >= m_completion_lv->getElements() ) {
  989                             trow = m_completion_lv->getElements() - 1;
  990                         }
  991 
  992                         m_completion_lv->setActiveRow( trow );
  993                         m_completion_lv->showActive();
  994 
  995                         updateSGFromRow( trow, history, filetype_history );
  996                     }
  997                     break;
  998                 case XK_Up:
  999                     if ( m_completion_lv->getElements() > 0 ) {
 1000                         int trow = m_completion_lv->getActiveRow();
 1001 
 1002                         if ( trow > 0 ) {
 1003                             trow--;
 1004                         }
 1005 
 1006                         m_completion_lv->setActiveRow( trow );
 1007                         m_completion_lv->showActive();
 1008 
 1009                         updateSGFromRow( trow, history, filetype_history );
 1010                     }
 1011                     break;
 1012             }
 1013           }
 1014           break;
 1015       }
 1016       aguix->ReplyMessage(msg);
 1017     }
 1018   }
 1019 
 1020   StartSettings *sets = new StartSettings();
 1021 
 1022   if ( ende == 1 ) {
 1023       if ( k1->getCurOption() == 0 ) {
 1024           sets->_startmode = StartSettings::STARTPROG;
 1025           sets->_command = m_cmd_sg->getText();
 1026 
 1027           if ( AGUIXUtils::ends_with( sets->_command, m_current_original_file ) ) {
 1028               std::string base = sets->_command;
 1029               base.resize( base.length() - m_current_original_file.length() );
 1030 
 1031               AGUIXUtils::rstrip( base );
 1032 
 1033               if ( ! base.empty() ) {
 1034                   if ( base[0] != ' ' ) {
 1035                       history.removeEntry( base );
 1036                       history.pushFrontEntry( base );
 1037 
 1038                       updateFiletypeHistory( filetype_history, base );
 1039                   }
 1040               }
 1041           } else {
 1042               std::string base = sets->_command;
 1043               if ( AGUIXUtils::ends_with( base, "}" ) ) {
 1044                   AGUIXUtils::rstrip( base );
 1045 
 1046                   if ( ! base.empty() ) {
 1047                       if ( base[0] != ' ' ) {
 1048                           history.removeEntry( base );
 1049                           history.pushFrontEntry( base );
 1050 
 1051                           updateFiletypeHistory( filetype_history, base );
 1052                       }
 1053                   }
 1054               }
 1055           }
 1056 
 1057           sets->_view_str = m1->_sg->getText();
 1058           switch ( m1->_cyb->getSelectedOption() ) {
 1059               case 1:
 1060                   sets->_start = STARTPROGOP_START_IN_TERMINAL;
 1061                   break;
 1062               case 2:
 1063                   sets->_start = STARTPROGOP_START_IN_TERMINAL_AND_WAIT4KEY;
 1064                   break;
 1065               case 3:
 1066                   sets->_start = STARTPROGOP_SHOW_OUTPUT;
 1067                   break;
 1068               case 4:
 1069                   sets->_start = STARTPROGOP_SHOW_OUTPUT_INT;
 1070                   break;
 1071               default:
 1072                   sets->_start = STARTPROGOP_START_NORMAL;
 1073                   break;
 1074           }
 1075           sets->_global = m1->_gcb->getState();
 1076           sets->_inbackground = m1->_ibcb->getState();
 1077           sets->_dontcd = m1->_dcdcb->getState();
 1078 
 1079           AJSON::dump( filetype_history, cfgfile );
 1080       } else if ( k1->getCurOption() == 1 ) {
 1081           sets->_startmode = StartSettings::HANDLE_TYPE;
 1082 
 1083           row = ftw->_lv->getActiveRow();
 1084           if ( ( ftw->_lv->isValidRow( row ) == true ) &&
 1085                ( row < ftw->_flatlist->getNrOfEntries() ) ) {
 1086               WCFiletype *ft = ftw->_flatlist->getEntry( row ).filetype;
 1087               if ( ft != NULL ) {
 1088                   sets->_type = ft;
 1089               }
 1090           }
 1091       } else if ( k1->getCurOption() == 2 ) {
 1092           sets->_startmode = StartSettings::HANDLE_ARCHIVE;
 1093           sets->_archive = arcw->_sg->getText();
 1094       }
 1095   }
 1096   delete win;
 1097 
 1098   m_cmd_sg = nullptr;
 1099   m_cmd_flag_b = nullptr;
 1100 
 1101   return std::unique_ptr< StartSettings >( sets );
 1102 }
 1103 
 1104 StartProgOp::StartSettings::StartSettings() : _startmode( CANCEL ),
 1105                                               _type( NULL ),
 1106                                               _start( STARTPROGOP_START_NORMAL ),
 1107                                               _global( true ),
 1108                                               _inbackground( false ),
 1109                                               _dontcd( false )
 1110 {
 1111 }
 1112 
 1113 std::unique_ptr< StartProgOp::FiletypeWindow > StartProgOp::buildFTWindow( AWindow *win )
 1114 {
 1115   FiletypeWindow *m1;
 1116 
 1117   AGUIX *aguix = Worker::getAGUIX();
 1118   FieldListView *lv;
 1119   const int cmin = AContainer::ACONT_MINH +
 1120                    AContainer::ACONT_MINW;
 1121   const int cincw = AContainer::ACONT_MINH +
 1122                     AContainer::ACONT_MINW +
 1123                     AContainer::ACONT_MAXH;
 1124   const int cincwnr = cincw +
 1125                       AContainer::ACONT_NORESIZE;
 1126   
 1127   AContainer *ac1 = win->setContainer( new AContainerBB( win, 1, 3 ), true );
 1128   ac1->setMinSpace( 5 );
 1129   ac1->setMaxSpace( 5 );
 1130 
 1131   ac1->add( new Text( aguix, 0, 0, catalog.getLocale( 644 ) ), 0, 0, cincwnr );
 1132 
 1133   AContainer *ac1_sub1 = ac1->add( new AContainer( win, 2, 1 ),
 1134                                    0, 1 );
 1135   ac1_sub1->setMinSpace( 5 );
 1136   ac1_sub1->setMaxSpace( 5 );
 1137 
 1138   ac1_sub1->add( new Text( aguix, 0, 0, catalog.getLocale( 793 ) ), 0, 0, AContainer::CO_FIX );
 1139   auto sg = ac1_sub1->addWidget( new StringGadget( aguix, 0, 0, 50, "", 0 ),
 1140                                  1, 0, cincw );
 1141 
 1142   lv = (FieldListView*)ac1->add( new FieldListView( aguix, 0, 0, 100, 100, 0 ), 0, 2, cmin );
 1143   lv->setHBarState( 2 );
 1144   lv->setVBarState( 2 );
 1145   lv->setDisplayFocus( true );
 1146   lv->setAcceptFocus( true );
 1147   lv->setDefaultColorMode( FieldListView::PRECOLOR_ONLYACTIVE );
 1148 
 1149   FlatTypeList *l1 = wconfig->getFlatTypeList();
 1150   l1->buildLV( lv, NULL );
 1151 
 1152   win->contMaximize( true );
 1153   
 1154   m1 = new FiletypeWindow( lv, sg, l1 );
 1155 
 1156   return std::unique_ptr< FiletypeWindow >( m1 );
 1157 }
 1158 
 1159 StartProgOp::FiletypeWindow::FiletypeWindow( FieldListView *lv,
 1160                                              StringGadget *sg,
 1161                                              FlatTypeList *flatlist ) : _lv( lv ),
 1162                                                                         m_filter_sg( sg ),
 1163                                                                         _flatlist( flatlist )
 1164 {
 1165 }
 1166 
 1167 StartProgOp::FiletypeWindow::~FiletypeWindow()
 1168 {
 1169   if ( _flatlist != NULL ) delete _flatlist;
 1170 }
 1171 
 1172 void StartProgOp::FiletypeWindow::updateView()
 1173 {
 1174     delete _flatlist;
 1175 
 1176     _flatlist = new FlatTypeList( wconfig->getFiletypes(),
 1177                                   m_filter_sg->getText() );
 1178     _flatlist->buildLV( _lv, NULL );
 1179 
 1180     _lv->redraw();
 1181 }
 1182 
 1183 std::unique_ptr< StartProgOp::ArchiveWindow > StartProgOp::buildArcWindow( AWindow *win )
 1184 {
 1185   ArchiveWindow *m1;
 1186   
 1187   AGUIX *aguix = Worker::getAGUIX();
 1188   FieldListView *lv;
 1189   const int cmin = AContainer::ACONT_MINH +
 1190                    AContainer::ACONT_MINW;
 1191   const int cincw = AContainer::ACONT_MINH +
 1192                     AContainer::ACONT_MINW +
 1193                     AContainer::ACONT_MAXH;
 1194   const int cincwnr = cincw +
 1195                       AContainer::ACONT_NORESIZE;
 1196   int row;
 1197   std::vector<std::string> v;
 1198   
 1199   AContainer *ac1 = win->setContainer( new AContainerBB( win, 1, 3 ), true );
 1200   ac1->setMinSpace( 5 );
 1201   ac1->setMaxSpace( 5 );
 1202 
 1203   ac1->add( new Text( aguix, 0, 0, catalog.getLocale( 640 ) ), 0, 0, cincwnr );
 1204 
 1205   StringGadget *sg = (StringGadget*)ac1->add( new StringGadget( aguix, 0, 0, 100, "", 0 ), 0, 1, cincw );
 1206 
 1207   lv = (FieldListView*)ac1->add( new FieldListView( aguix, 0, 0, 100, 100, 0 ), 0, 2, cmin );
 1208   lv->setHBarState( 2 );
 1209   lv->setVBarState( 2 );
 1210   lv->setDisplayFocus( true );
 1211   lv->setAcceptFocus( true );
 1212 
 1213   v = AVFSSupport::getAVFSModules();
 1214 
 1215   for ( std::vector<std::string>::iterator it = v.begin(); it != v.end(); it++ ) {
 1216     row = lv->addRow();
 1217     lv->setText( row, 0, *it );
 1218     lv->setPreColors( row, FieldListView::PRECOLOR_ONLYACTIVE );
 1219   }
 1220 
 1221   win->contMaximize( true );
 1222   m1 = new ArchiveWindow( lv, sg );
 1223 
 1224   return std::unique_ptr< ArchiveWindow >( m1 );
 1225 }
 1226 
 1227 StartProgOp::ArchiveWindow::ArchiveWindow( FieldListView *lv,
 1228                        StringGadget *sg ) : _lv( lv ),
 1229                                 _sg( sg )
 1230 {
 1231 }
 1232 
 1233 void StartProgOp::setGUIMsg( std::string msg )
 1234 {
 1235   gui_msg = msg;
 1236 }
 1237 
 1238 void StartProgOp::updateCompletionList( const std::string &base,
 1239                                         PersistentStringList &history,
 1240                                         std::shared_ptr< AJSON::JSONType > &filetype_history )
 1241 {
 1242 
 1243    std::list< std::string > l;
 1244    std::set< std::string > commands_in_use;
 1245 
 1246    l = history.getList();
 1247 
 1248    m_current_completions.clear();
 1249 
 1250    auto jobj = AJSON::as_object( filetype_history );
 1251 
 1252    if ( jobj ) {
 1253        auto jft = AJSON::as_object( jobj->get( "filetype" ) );
 1254 
 1255        if ( jft ) {
 1256            auto jcommands = AJSON::as_array( jft->get( m_default_file_filetype ) );
 1257 
 1258            if ( jcommands ) {
 1259                for ( size_t pos = 0; pos < jcommands->size(); pos++ ) {
 1260                    auto jcommand = AJSON::as_object( jcommands->get( pos ) );
 1261 
 1262                    if ( ! jcommand ) continue;
 1263 
 1264                    auto jcmd = AJSON::as_string( jcommand->get( "command" ) );
 1265 
 1266                    if ( ! jcmd ) continue;
 1267 
 1268                    if ( AGUIXUtils::starts_with( jcmd->get_value(), base ) ) {
 1269                        m_current_completions.push_back( std::make_pair( FILETYPE_COMPLETION,
 1270                                                                         jcmd->get_value() ) );
 1271                        commands_in_use.insert( jcmd->get_value() );
 1272                    }
 1273                }
 1274            }
 1275        }
 1276    }
 1277    
 1278    for ( auto &s : l ) {
 1279        if ( commands_in_use.count( s ) == 0 ) {
 1280            if ( AGUIXUtils::starts_with( s, base ) ) {
 1281                m_current_completions.push_back( std::make_pair( ANY_COMPLETION, s ) );
 1282            }
 1283        }
 1284    }
 1285 }
 1286 
 1287 void StartProgOp::updateSGFromComplete( StringGadget *sg,
 1288                                         PersistentStringList &history,
 1289                                         std::shared_ptr< AJSON::JSONType > &filetype_history,
 1290                                         FieldListView *lv )
 1291 {
 1292     std::string old_base;
 1293 
 1294     old_base = sg->getText();
 1295 
 1296     std::string prefix( old_base );
 1297 
 1298     if ( sg->getCursor() < (int)prefix.length() ) {
 1299         prefix.resize( sg->getCursor() );
 1300     }
 1301     
 1302     updateCompletionList( prefix, history, filetype_history );
 1303 
 1304     lv->setSize( m_current_completions.size() );
 1305 
 1306     int row = 0;
 1307     for ( auto &s : m_current_completions ) {
 1308         std::string s2( s.second );
 1309 
 1310         if ( ! AGUIXUtils::ends_with( s2, "}" ) ) {
 1311             s2 += " ";
 1312             s2 += m_current_original_file;
 1313         }
 1314 
 1315         if ( s.first == FILETYPE_COMPLETION ) {
 1316             lv->setText( row, 1, catalog.getLocale( 1321 ) );
 1317         } else {
 1318             lv->setText( row, 1, catalog.getLocale( 1322 ) );
 1319         }
 1320 
 1321         lv->setText( row, 0, s2 );
 1322         lv->setPreColors( row, FieldListView::PRECOLOR_ONLYACTIVE );
 1323 
 1324         row++;
 1325     }
 1326     lv->redraw();
 1327 
 1328     if ( ! m_completion_enabled ) return;
 1329 
 1330     if ( old_base == m_previous_sg_content ||
 1331          old_base.length() < m_previous_sg_content.length() ) {
 1332         m_completion_enabled = false;
 1333         return;
 1334     }
 1335 
 1336     if ( m_current_completions.empty() ) {
 1337         std::string new_text( prefix );
 1338 
 1339         if ( ! AGUIXUtils::ends_with( new_text, "}" ) ) {
 1340             new_text += " ";
 1341             new_text += m_current_original_file;
 1342         }
 1343 
 1344         sg->setText( new_text.c_str() );
 1345 
 1346         sg->redraw();
 1347 
 1348         m_completion_enabled = false;
 1349         return;
 1350     }
 1351 
 1352     if ( sg->getCursor() > 0 ) {
 1353 
 1354         std::string new_base = m_current_completions.front().second;
 1355 
 1356         std::string new_text( new_base );
 1357 
 1358         m_previous_sg_content = new_text;
 1359 
 1360         if ( sg->getCursor() < (int)m_previous_sg_content.length() ) {
 1361             m_previous_sg_content.resize( sg->getCursor() );
 1362         }
 1363 
 1364         if ( ! AGUIXUtils::ends_with( new_text, "}" ) ) {
 1365             new_text += " ";
 1366             new_text += m_current_original_file;
 1367         }
 1368 
 1369         sg->setText( new_text.c_str() );
 1370 
 1371         sg->setSelection( sg->getCursor(),
 1372                           new_text.length() );
 1373 
 1374         sg->redraw();
 1375     }
 1376 }
 1377 
 1378 void StartProgOp::updateSGFromRow( int row,
 1379                                    PersistentStringList &history,
 1380                                    std::shared_ptr< AJSON::JSONType > &filetype_history )
 1381 {
 1382     std::string t = m_completion_lv->getText( row, 0 );
 1383 
 1384     m_cmd_sg->setText( t.c_str() );
 1385     m_cmd_sg->setSelection( m_cmd_sg->getCursor(),
 1386                             t.length() );
 1387     m_cmd_sg->redraw();
 1388 
 1389     m_completion_enabled = false;
 1390 
 1391     updateSGFromComplete( m_cmd_sg, history, filetype_history, m_completion_lv );
 1392 }
 1393 
 1394 void StartProgOp::updateFiletypeHistory( std::shared_ptr< AJSON::JSONType > &filetype_history,
 1395                                          const std::string &base )
 1396 {
 1397     auto jobj = AJSON::as_object( filetype_history );
 1398 
 1399     if ( ! jobj ) return;
 1400 
 1401     auto jft = AJSON::as_object( jobj->get( "filetype" ) );
 1402 
 1403     if ( ! jft ) {
 1404         jft = AJSON::as_object( jobj->set( "filetype", AJSON::make_object() ) );
 1405 
 1406         if ( ! jft ) return;
 1407     }
 1408 
 1409     auto jold_commands = AJSON::as_array( jft->get( m_default_file_filetype ) );
 1410 
 1411     auto jnew_commands = AJSON::make_array();
 1412 
 1413     auto jnew_command = AJSON::make_object();
 1414     jnew_command->set( "command", AJSON::make_string( base ) );
 1415     jnew_commands->append( jnew_command );
 1416 
 1417     if ( jold_commands ) {
 1418         for ( size_t pos = 0; pos < jold_commands->size(); pos++ ) {
 1419             auto jold_command = AJSON::as_object( jold_commands->get( pos ) );
 1420 
 1421             if ( ! jold_command ) continue;
 1422 
 1423             auto jcmd = AJSON::as_string( jold_command->get( "command" ) );
 1424 
 1425             if ( ! jcmd ) continue;
 1426 
 1427             if ( jcmd->get_value() == base ) continue;
 1428 
 1429             jnew_commands->append( jold_command );
 1430         }
 1431     }
 1432 
 1433     jft->set( m_default_file_filetype, jnew_commands );
 1434 }