1 /* worker.h
2  * This file belongs to Worker, a file manager for UN*X/X11.
3  * Copyright (C) 2001-2021 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 #ifndef WORKER_H
23 #define WORKER_H
24 
25 #include "wdefines.h"
26 #include "functionproto.h"
27 #include <string>
28 #include "generic_callback.hh"
29 #include "layoutsettings.hh"
30 #include "timedtext.hh"
31 #include "processhandler.hh"
32 #include <map>
33 #include "aguix/message.h"
34 #include "hw_volume_manager.hh"
35 #include <memory>
36 #include "event_callbacks.hh"
37 #include "temporaryfilecache.hh"
38 #include "deeppathstore.hh"
39 #include <set>
40 #include "kvpstore.hh"
41 #include <future>
42 #include "worker_types.h"
43 #include "existence_test.hh"
44 #include "wconfig_initial_command.hh"
45 #include "file_command_log.hh"
46 
47 class ListerMode;
48 class Lister;
49 class BookmarkDBProxy;
50 class PopUpMenu;
51 class HWVolume;
52 class WaitThread;
53 class TimeoutStore;
54 class EventQueue;
55 class Requester;
56 class Button;
57 class AWindow;
58 class AContainer;
59 class WCHotkey;
60 class WCButton;
61 class WCPath;
62 class PartSpace;
63 class CopyfileProgressCallback;
64 class PersDeepPathStore;
65 class HintDB;
66 class PathnameWatcher;
67 class Slider;
68 class MenuTreeUI;
69 class MenuTreeNode;
70 class WConfig;
71 class PersistentKVP;
72 class PrefixDB;
73 
74 class worker_version
75 {
76 public:
worker_version()77     worker_version() : m_major( 0 ),
78                        m_minor( 0 ),
79                        m_patch( 0 )
80     {}
81 
worker_version(int major,int minor,int patch)82     worker_version( int major ,
83                     int minor,
84                     int patch ) : m_major( major ),
85                                   m_minor( minor ),
86                                   m_patch( patch )
87     {}
88 
89     bool operator<( const worker_version &rhs ) const
90     {
91         if ( m_major < rhs.m_major ) return true;
92 
93         if ( m_major > rhs.m_major ) return false;
94 
95         if ( m_minor < rhs.m_minor ) return true;
96 
97         if ( m_minor > rhs.m_minor ) return false;
98 
99         if ( m_patch < rhs.m_patch ) return true;
100 
101         return false;
102     }
103 
104     bool operator<=( const worker_version &rhs ) const
105     {
106         return ! ( rhs < *this );
107     }
108 
109     bool operator>( const worker_version &rhs ) const
110     {
111         return rhs < *this;
112     }
113 
114     int m_major;
115     int m_minor;
116     int m_patch;
117 };
118 
119 class Worker
120 {
121 public:
122   Worker( int argc, char **argv, int optind = -1 );
123   ~Worker();
124   Worker( const Worker &other );
125   Worker &operator=( const Worker &other );
126 
127   void run();
128   static AGUIX *getAGUIX();
129   static int getMaxModeNr();
130   static int getID4Mode(ListerMode*);
131   static const char *getNameOfMode( int nr );
132   static const char *getLocaleNameOfMode( int nr );
133   static int getID4Name( const char *str );
134   ListerMode *getMode4ID(int,Lister *);
135   AWindow *getMainWin();
136   void setStatebarText(const char*);
137   static int getNrOfCommands();
138   static std::shared_ptr< FunctionProto > getCommand4ID(int);
139   static int getID4Command(FunctionProto*);
140   Lister *getOtherLister(Lister*);
141   int getSide(Lister*);
142   Lister *getLister(int);
143   Lister *getActiveLister();
144   int interpret( const command_list_t &,ActionMessage *);
145   AWindow *getListerWin( Lister *l );
146 
147   int quit(int mode);
148   void checkfirststart( char **setlang );
149   void setTitle(const char *add_infos);
150 
151   static Requester *getRequester();
152   void activateShortkeyFromList();
153 
154   int PS_readSpace( const char*name );
155 
156   loff_t PS_getBlocksize();
157   loff_t PS_getFreeSpace();
158   loff_t PS_getSpace();
159 
160   std::string PS_getFreeSpaceH() const;
161   std::string PS_getSpaceH() const;
162   void PS_setLifetime( double t );
163   void setWaitCursor();
164   void unsetWaitCursor();
165   static const std::string getDataDir();
166 
167   int runCommand( const char *exestr,
168 		  const char *tmpname,
169 		  const char *tmpoutput,
170 		  bool inbackground,
171                   RefCount< GenericCallbackArg< void, int > > pea );
172 
173   static std::string getWorkerConfigDir();
174 
175   void openWorkerMenu();
176     void handleHelp();
177 
178   int getStatebarWidth();
179 
180   static BookmarkDBProxy &getBookmarkDBInstance();
181 
182   void registerPopUpCallback( RefCount<GenericCallbackArg<void, AGMessage*> > cb,
183                               const PopUpMenu *menu );
184   void unregisterPopUpCallback( RefCount<GenericCallbackArg<void, AGMessage*> > cb );
185 
186   LayoutSettings getCustomLayout() const;
187   bool getUseCustomLayout() const;
188   void setCustomLayout( const LayoutSettings &nv );
189   void unsetCustomLayout();
190 
191     void pushStatebarText( const TimedText &text );
192     void updateStatebarText( const TimedText &text );
193     void removeStatebarText( const TimedText &text );
194 
195     HWVolumeManager &getVolumeManager();
196     void clearNewVolumesInfo();
197 
198     void registerTimeout( loff_t timeout_ms );
199     void unregisterTimeout( loff_t timeout_ms );
200     void wakeupMainLoop();
201 
202     void showCommandFailed( int status );
203 
204     void setIgnoreKey( KeySym key, bool state );
205     bool isIgnoredKey( KeySym key ) const;
206 
207     void shuffleButton( int dir );
208     void switchToButtonBank( int nr );
209 
210     EventCallbacks &getEventHandler();
211     TemporaryFileCache::TemporaryFileCacheEntry getTempCopy( const std::string &filename,
212                                                              CopyfileProgressCallback *progress_callback = NULL );
213 
214     DeepPathStore &getPathStore();
215 
216     bool storePathPers( const std::string &path, time_t ts );
217     bool storePathPers( const std::string &path,
218                         const std::string &command_str,
219                         time_t ts );
220     bool storePathPersArchive( const std::string &path, time_t ts );
221     void removePathPers( const std::string &path );
222     void removePathPersArchive( const std::string &path );
223     void removePathProgramPers( const std::string &program );
224     DeepPathStore getPathsPers();
225     DeepPathStore getPathsPersArchive();
226     std::map< std::string, DeepPathStore > getPathProgramsPers();
227     loff_t getSizeOfPersPaths() const;
228     loff_t getSizeOfPersPathsArchive() const;
229     loff_t getSizeOfPersPathPrograms() const;
230     void relocateEntriesPers( const std::string &dest,
231                               const std::string &source,
232                               time_t ts,
233                               bool move );
234 
235     bool storePathPersIfInProgress( const std::string &path );
236     void setPathJumpInProgress( bool nv = true );
237     void setPathJumpInProgress( const std::string last_filter );
238 
239     void copyToClipboard( const std::string &str );
240 
241     void showNextHint();
242 
243     RefCount< PathnameWatcher > getPathnameWatcher();
244 
245     bool checkEnterDir( const std::string &dir );
246 
247     static mode_t getUMask();
248 
249     void openCommandMenu( bool show_recently_used );
250 
251     worker_version getLastRunningVersion();
252     void checkForUpdates( const worker_version &last_running_version,
253                           WConfig *conf );
254 
255     void setOverrideXIM( bool nv );
256 
257     static PersistentKVP &getPersKVPStore();
258 
259     PrefixDB &getDirHistPrefixDB();
260 
261     bool getKeyChainCandidateActive() const;
262 
263     static KVPStore &getKVPStore();
264 
265     void enqueueFuture( std::future< ExistenceTest::existence_state_t > f );
266 
267     std::list< WorkerTypes::reg_command_info_t > getListOfCommandsWithoutArgs() const;
268     WorkerTypes::reg_command_info_t getCommandInfo( const std::string &command, bool args ) const;
269 
270     static std::string getTerminalCommand( const std::string &cmdfile,
271                                            const std::string &outfile,
272                                            bool &remove_after_exec );
273 
274     void issueConfigOpen( const std::string &panel );
275     void issueConfigOpen( const std::string &panel, const WConfigInitialCommand &cmd );
276 
277     std::shared_ptr< WPUContext > getCurrentWPU();
278 
279     static void pushCommandLog( const std::string &command,
280                                 const std::string &path,
281                                 const std::string &description );
282 
283     std::list< FileCommandLog::Entry > getCommandLog() const;
284     void clearCommandLog();
285 protected:
286   void createMainWin();
287   void setupMainWin();
288   void closeMainWin();
289   void shufflePath();
290   void shuffleButton( int dir, bool nocycle );
291   void about();
292   bool configure( const std::string &panel = "" );
293   void showPathBank();
294   void showButtonBank();
295   void setPath(int);
296   void setPath( WCPath *);
297   int activateShortkey(AGMessage*);
298   void activateButton(int,int,int);
299     void activateButton( int pos );
300     void activateHotkey( int pos );
301     void activateCommandByID( int id, bool interactive = false );
302   int saveListerState();
303   int initListerState();
304   void updateTime();
305 
306   static AGUIX *aguix;
307   static int workerInstances;
308   Lister *lister[2];
309   AWindow *mainwin;
310   Button *aboutb,*configureb,*clockbar;
311   Button *statebar;
312   Button **pathbs;
313   Button **buttons;
314   Slider *button_bank_slider;
315   AWindow *listerwin[2];
316   AContainer *maincont;
317 
318   int m_main_window_width, m_main_window_height;
319     int m_main_window_last_absolute_x;
320     int m_main_window_last_absolute_y;
321     bool m_main_window_last_maximized_x;
322     bool m_main_window_last_maximized_y;
323 
324   unsigned int curRows,curColumns;
325   int pbanknr,bbanknr;
326 
327   enum {WORKER_NORMAL,WORKER_QUIT};
328   int runningmode;
329   static int argc;
330   static char **argv;
331   static int m_optind;
332   static std::string startcwd;
333   time_t lasttimep;
334 
335   DNDMsg *dm;
336 
337   static Requester *req_static;
338 
339     static int shortkeysort( void *p1, void *p2, int sortmode );
340   struct shortkeylisttype {WCHotkey *h;
341                            WCButton *b;
342                            WCPath *p;};
343   PartSpace *freesp;
344   bool isRoot;
345 
346   KeySym lastkey;
347   unsigned int lastmod;
348   Time lastkey_time;
349 
350   typedef struct _keyhash {
351     WCButton *b;
352     WCHotkey *h;
353     WCPath *p;
354     struct _keyhash *next;
355   } keyhash;
356   keyhash **keyhashtable;
357   int keyhashtable_size;
358   void buildtable();
359   void deletetable();
360   unsigned int keyhashfunc( KeySym k, unsigned int m );
361   void insertkey( KeySym k, unsigned int m, WCButton *b, WCHotkey *h, WCPath *p );
362   int findkey( KeySym k, unsigned int m, WCButton **b, WCHotkey **h, WCPath **p );
363   int findkey( KeySym k1, unsigned int m1, KeySym k2, unsigned int m2, WCButton **b, WCHotkey **h, WCPath **p );
364   bool isKeyChainPrefix( KeySym k, unsigned int m );
365   int waitcursorcount;
366 
367   int getMaxButtonsWidth();
368 
369   std::string m_statebar_text;
370 
371   std::string queryLanguage();
372 
373   void createWorkerMenu();
374   PopUpMenu *m_worker_menu;
375   void startMenuAction( AGMessage *msg );
376   void saveWorkerState();
377 
378   int m_interpret_recursion_depth;
379   static const int m_interpret_max_recursion = 1000;
380 
381   static std::unique_ptr<BookmarkDBProxy> m_bookmarkproxy;
382 
383   std::map<const PopUpMenu *, std::list< RefCount<GenericCallbackArg<void, AGMessage*> > > > m_popup_callbacks;
384 
385   void handlePopUps( AGMessage *msg );
386 
387   bool m_use_custom_layout;
388   LayoutSettings m_custom_layout;
389 
390     typedef enum {
391         RS_RECONFIG,
392         RS_RELAYOUT,
393         RS_NONE
394     } restart_t;
395     restart_t restart;
396 
397     std::list< TimedText > m_statebar_texts;
398     bool getValidStatebarText( TimedText &return_text );
399     bool getNextValidStatebarText( TimedText &return_text );
400     void updateStatebar();
401 
402     TimedText m_key_message;
403     std::string getNamesOfKeyChainCompletions( KeySym k, unsigned int m,
404                                                std::list< WCButton * > *buttons,
405                                                std::list< WCHotkey * > *hotkeys,
406                                                std::list< WCPath * > *paths );
407 
408     HWVolumeManager m_volume_manager;
409     void checkNewVolumes();
410     std::list< HWVolume > m_known_volumes;
411     TimedText m_new_volumes_infotext;
412 
413     void updateVolumeManagerConfig();
414     void initVolumeManagerStuff();
415 
416     void queryNewVolumeAction( const std::list< HWVolume > &l );
417 
418     void initWaitThread();
419     void shutdownWaitThread();
420 
421     RefCount< EventQueue > m_eventqueue;
422     std::shared_ptr< TimeoutStore > m_timeouts;
423     RefCount< WaitThread > m_waitthread;
424 
425     loff_t m_current_clock_update_ms;
426     void setClockUpdate( loff_t time_ms );
427 
428     loff_t m_current_dbus_update_ms;
429     void setDbusUpdate( loff_t time_ms );
430 
431     loff_t m_current_statebar_update_ms;
432     void setStatebarUpdate( loff_t time_ms );
433 
434     TemporaryFileCache m_temp_file_cache;
435     ProcessHandler m_process_handler;
436     void waitForEvent();
437 
438     struct worker_event_store {
worker_event_storeworker_event_store439         worker_event_store() : check_children( false ) {}
440         bool check_children;
441     } m_event_store;
442 
443     int buildShortkeyLV( FieldListView *lv,
444                          List *sklist );
445 
446     std::map< KeySym, int > m_ignored_keys;
447 
448     void updateSettingsFromWConfig();
449 
450     EventCallbacks m_event_handler;
451     std::map< EventCallbacks::event_callback_type_t, bool > m_events_seen;
452     void fireSeenEvents();
453 
454     void updateHintDB();
455 
456     void prepareMenuTree( MenuTreeUI &menuui );
457     void initWorkerTextMenu( MenuTreeNode *menu );
458     bool checkCommandListForCommand( const command_list_t &list, const std::string &name );
459 
460     void updateRunningVersion();
461 
462     bool importUpdate( WConfig *baseconfig,
463                        const std::pair< worker_version, std::string > &config_entry );
464 
465     void switchCurrentMode( int mode );
466     void configureCurrentMode();
467 
468     std::string getOverrideXIMPath() const;
469 
470     void setKeyChainCandidateActive( bool nv );
471 
472     void showButtonCommandHelp( int i, int j, int state );
473 
474     void loadWindowGeometry();
475 
476     void cleanFutures();
477     void checkFutures();
478 
479     void disableHelp();
480     void showHelp( KeySym lastkey,
481                    unsigned int lastmod,
482                    const std::list< WCButton * > &button_list,
483                    const std::list< WCHotkey * > &hotkey_list,
484                    const std::list< WCPath * > &path_list );
485 
486     std::string getButtonHelpText( int relative_pos_in_bank ) const;
487 
488     void setCurrentWPU( std::shared_ptr< WPUContext > wpu );
489 
490     DeepPathStore m_path_store;
491     std::unique_ptr< PersDeepPathStore > m_pers_path_store;
492     std::unique_ptr< PersDeepPathStore > m_pers_path_store_archive;
493 
494     std::string m_current_hint;
495     time_t m_hint_time;
496     RefCount< HintDB > m_hint_db;
497     RefCount< PathnameWatcher > m_pathname_watcher;
498     std::set< std::string > m_changed_paths;
499 
500     enum ssh_allow_t { SSH_ASK, SSH_NEVER, SSH_ALWAYS } m_ssh_allow;
501 
502     static mode_t m_process_umask;
503 
504     RefCount< MenuTreeUI > m_menu_ui;
505     bool m_menu_active;
506 
507     int m_commandmenu_original_button_banknr;
508     int m_commandmenu_original_path_banknr;
509 
510     static std::unique_ptr< PersistentKVP > m_pers_kvp_store;
511     static KVPStore m_kvp_store;
512 
513     bool m_path_jump_in_progress;
514     std::string m_path_jump_last_filter;
515 
516     std::unique_ptr< PrefixDB > m_pdb;
517 
518     bool m_key_chain_cand_active;
519 
520     TimedText m_button_help_text;
521 
522     std::list< std::future< ExistenceTest::existence_state_t > > m_existence_futures;
523 
524     std::string m_pending_config_open;
525     WConfigInitialCommand m_pending_config_command;
526 
527     TimedText m_help_message;
528     bool m_help_active = false;
529 
530     std::weak_ptr< WPUContext > m_current_wpu;
531 
532     static std::unique_ptr< FileCommandLog > m_command_log;
533     static std::mutex m_command_log_mutex;
534 };
535 
536 #endif
537 
538 /* Local Variables: */
539 /* mode:c++ */
540 /* End: */
541