1 /*
2 *
3 * CLEX File Manager
4 *
5 * Copyright (C) 2001-2018 Vlado Potisk <vlado_potisk@clex.sk>
6 *
7 * CLEX is free software without warranty of any kind; see the
8 * GNU General Public License as set out in the "COPYING" document
9 * which accompanies the CLEX File Manager package.
10 *
11 * CLEX can be downloaded from http://www.clex.sk
12 *
13 */
14
15 #include "clexheaders.h"
16
17 #include <sys/stat.h> /* umask() */
18 #include <stdarg.h> /* log.h */
19 #include <stdio.h> /* puts() */
20 #include <stdlib.h> /* setenv() */
21 #include <string.h> /* strcmp() */
22 #include <unistd.h> /* getpid() */
23 #include "curses.h" /* NCURSES_MOUSE_VERSION */
24
25 #include "bookmarks.h" /* bm_initialize() */
26 #include "cfg.h" /* cfg_initialize() */
27 #include "completion.h" /* compl_initialize() */
28 #include "control.h" /* control_loop() */
29 #include "directory.h" /* dir_initialize() */
30 #include "exec.h" /* exec_initialize() */
31 #include "filepanel.h" /* files_initialize() */
32 #include "help.h" /* help_initialize() */
33 #include "history.h" /* hist_initialize() */
34 #include "inout.h" /* curses_initialize() */
35 #include "inschar.h" /* inschar_initialize() */
36 #include "lang.h" /* locale_initialize() */
37 #include "list.h" /* list_initialize() */
38 #include "mouse.h" /* mouse_initialize() */
39 #include "opt.h" /* opt_initialize() */
40 #include "log.h" /* logfile_open() */
41 #include "signals.h" /* signal_initialize() */
42 #include "tty.h" /* tty_initialize() */
43 #include "userdata.h" /* userdata_initialize() */
44 #include "util.h" /* base_name() */
45 #include "xterm_title.h" /* xterm_title_initialize() */
46
47 /*
48 * NOTE: ANSI/ISO C requires that all global and static variables
49 * are initialized to zero. CLEX relies on it.
50 */
51 static INPUTLINE log_filt = { L"",0,0,0 }, help_filt = { L"",0,0,0 }, shared_filt = { L"",0,0,0 };
52
53 static EXTRA_LINE el_exit[1] = {
54 { 0,0,MODE_SPECIAL_RETURN,0 }
55 };
56 static EXTRA_LINE el_bm[2] = {
57 { 0,L"Changes will be saved",0,cx_bm_save },
58 { L"Cancel",L"Changes will be discarded",0,cx_bm_revert }
59 };
60 static EXTRA_LINE el_cfg[3] = {
61 { L"Cancel",L"Revert to the original state",MODE_SPECIAL_RETURN,0 },
62 { L"Apply",L"Use the new configuration in this session",
63 MODE_SPECIAL_RETURN,cx_cfg_apply },
64 { L"Apply+Save",L"Save the configuration to disk",
65 MODE_SPECIAL_RETURN,cx_cfg_apply_save }
66 };
67 static EXTRA_LINE el_dir[2] = {
68 { 0,0,MODE_SPECIAL_RETURN,cx_dir_enter },
69 { L"Bookmarks",0,MODE_BM,cx_dir_enter },
70 };
71 static EXTRA_LINE el_dir_split[1] = {
72 { 0,0,MODE_SPECIAL_RETURN,cx_dir_enter }
73 };
74 static EXTRA_LINE el_group[2] = {
75 { 0,0,MODE_SPECIAL_RETURN,0 },
76 { L"Switch to user data (alt-U)",0,MODE_USER,0 }
77 };
78 static EXTRA_LINE el_user[2] = {
79 { 0,0,MODE_SPECIAL_RETURN,0 },
80 { L"Switch to group data (alt-G)",0,MODE_GROUP,0 }
81 };
82 #define EL_EXIT (-1 * ARRAY_SIZE(el_exit))
83
84 /*
85 * PANEL_DESC initialization:
86 * cnt, top, curs, min, type, norev, extra, filter, drawfn
87 * implicit null: help, filtering
88 */
89 static PANEL_DESC pd_bm = { 0,0,0,
90 -1 * ARRAY_SIZE(el_bm),PANEL_TYPE_BM,0,el_bm,&shared_filt,draw_line_bm };
91 static PANEL_DESC pd_bm_edit = { 2,0,0,
92 EL_EXIT,PANEL_TYPE_BM,0,el_exit,0,draw_line_bm_edit };
93 static PANEL_DESC pd_cfg = { CFG_TOTAL_,0,0,
94 -1 * ARRAY_SIZE(el_cfg),PANEL_TYPE_CFG,0,el_cfg,0,draw_line_cfg };
95 static PANEL_DESC pd_cfg_menu = { 0,0,0,
96 0,PANEL_TYPE_CFG_MENU,0,0,0,draw_line_cfg_menu };
97 static PANEL_DESC pd_cmp = { 1 + CMP_TOTAL_,0,0,
98 EL_EXIT,PANEL_TYPE_CMP,0,el_exit,0,draw_line_cmp };
99 static PANEL_DESC pd_cmp_sum = { 0,0,0,
100 EL_EXIT,PANEL_TYPE_CMP_SUM,0,el_exit,0,draw_line_cmp_sum };
101 static PANEL_DESC pd_compl = { 0,0,0,
102 EL_EXIT,PANEL_TYPE_COMPL,0,el_exit,&shared_filt,draw_line_compl };
103 static PANEL_DESC pd_dir = { 0,0,0,
104 -1 * ARRAY_SIZE(el_dir),PANEL_TYPE_DIR,0,el_dir,&shared_filt,draw_line_dir };
105 static PANEL_DESC pd_dir_split = { 0,0,0,
106 -1 * ARRAY_SIZE(el_dir_split),PANEL_TYPE_DIR_SPLIT,0,el_dir_split,0,draw_line_dir_split };
107 static PANEL_DESC pd_fopt = { FOPT_TOTAL_,0,0,
108 EL_EXIT,PANEL_TYPE_FOPT,0,el_exit,0,draw_line_fopt };
109 static PANEL_DESC pd_grp = { 0,0,0,
110 -1 * ARRAY_SIZE(el_group),PANEL_TYPE_GROUP,0,el_group,&shared_filt,draw_line_group };
111 static PANEL_DESC pd_help = { 0,0,0,
112 0,PANEL_TYPE_HELP,1,0,&help_filt,draw_line_help };
113 static PANEL_DESC pd_hist = { 0,0,0,
114 EL_EXIT,PANEL_TYPE_HIST,0,el_exit,&shared_filt,draw_line_hist };
115 static PANEL_DESC pd_log = { 0,0,0,
116 EL_EXIT,PANEL_TYPE_LOG,0,el_exit,&log_filt,draw_line_log };
117 static PANEL_DESC pd_mainmenu = /* 22 items in this menu */ { 22,EL_EXIT,EL_EXIT,
118 EL_EXIT,PANEL_TYPE_MAINMENU,0,el_exit,0,draw_line_mainmenu };
119 static PANEL_DESC pd_notif = { NOTIF_TOTAL_,0,0,
120 EL_EXIT,PANEL_TYPE_NOTIF,0,el_exit,0,draw_line_notif };
121 static PANEL_DESC pd_paste = /* 15 items in this menu */ { 15,EL_EXIT,EL_EXIT,
122 EL_EXIT,PANEL_TYPE_PASTE,0,el_exit,0,draw_line_paste };
123 static PANEL_DESC pd_preview = /* 15 items in this menu */ { 0,0,0,
124 0,PANEL_TYPE_PREVIEW,0,0,0,draw_line_preview };
125 static PANEL_DESC pd_sort = /* 18 items in this menu */ { 18,0,0,
126 EL_EXIT,PANEL_TYPE_SORT,0,el_exit,0,draw_line_sort };
127 static PANEL_DESC pd_usr = { 0,0,0,
128 -1 * ARRAY_SIZE(el_user),PANEL_TYPE_USER,0,el_user,&shared_filt,draw_line_user };
129 PANEL_DESC *panel = 0;
130 PANEL_BM panel_bm = { &pd_bm };
131 PANEL_BM_EDIT panel_bm_edit = { &pd_bm_edit };
132 PANEL_COMPL panel_compl = { &pd_compl };
133 PANEL_CFG panel_cfg = { &pd_cfg };
134 PANEL_CFG_MENU panel_cfg_menu = { &pd_cfg_menu };
135 PANEL_CMP panel_cmp = { &pd_cmp };
136 PANEL_CMP_SUM panel_cmp_sum = { &pd_cmp_sum };
137 PANEL_DIR panel_dir = { &pd_dir };
138 PANEL_DIR_SPLIT panel_dir_split = { &pd_dir_split };
139 PANEL_FOPT panel_fopt = { &pd_fopt };
140 PANEL_GROUP panel_group = { &pd_grp };
141 PANEL_HELP panel_help = { &pd_help };
142 PANEL_HIST panel_hist = { &pd_hist };
143 PANEL_LOG panel_log = { &pd_log };
144 PANEL_MENU panel_mainmenu = { &pd_mainmenu };
145 PANEL_NOTIF panel_notif = { &pd_notif };
146 PANEL_PASTE panel_paste = { &pd_paste };
147 PANEL_PREVIEW panel_preview = { &pd_preview };
148 PANEL_SORT panel_sort = { &pd_sort, GROUP_DSP, SORT_NAME_NUM, HIDE_NEVER };
149 PANEL_USER panel_user = { &pd_usr };
150 PANEL_FILE *ppanel_file;
151
152 DISP_DATA disp_data;
153 LANG_DATA lang_data;
154 USER_DATA user_data;
155 CLEX_DATA clex_data;
156
157 MOUSE_INPUT minp;
158 KBD_INPUT kinp;
159
160 TEXTLINE *textline = 0, line_cmd, line_tmp, line_dir, line_inschar;
161 CODE next_mode;
162 volatile FLAG ctrlc_flag;
163 const void *pcfg[CFG_TOTAL_];
164
165 int
main(int argc,char * argv[])166 main(int argc, char *argv[])
167 {
168 FLAG help = 0, version = 0;
169 int i;
170 const char *arg;
171
172 locale_initialize(); /* before writing the first text message */
173
174 /* check command line arguments */
175 for (i = 1; i < argc; i++) {
176 arg = argv[i];
177 if (strcmp(arg,"--help") == 0)
178 help = 1;
179 else if (strcmp(arg,"--version") == 0)
180 version = 1;
181 else if (strcmp(arg,"--log") == 0) {
182 if (++i == argc)
183 err_exit("--log option requires an argument (filename)");
184 logfile_open(argv[i]);
185 }
186 else {
187 msgout(MSG_W,"Unrecognized option '%s'",arg);
188 msgout(MSG_i,"Try '%s --help' for more information",base_name(argv[0]));
189 err_exit("Incorrect usage");
190 }
191 }
192 if (version)
193 puts(
194 "\nCLEX File Manager " VERSION "\n"
195 " compiled with POSIX job control: "
196 #ifdef _POSIX_JOB_CONTROL
197 "yes\n"
198 #else
199 "no\n"
200 #endif
201 " mouse interface: "
202 #if NCURSES_MOUSE_VERSION >= 2
203 "ncurses\n"
204 #else
205 "xterm\n"
206 #endif
207 "\nCopyright (C) 2001-2018 Vlado Potisk <vlado_potisk@clex.sk>"
208 "\n\n"
209 "This is free software distributed without any warranty.\n"
210 "See the GNU General Public License for more details.\n"
211 "\n"
212 "Project homepage is http://www.clex.sk");
213 if (help)
214 printf(
215 "\nUsage: %s [OPTIONS]\n\n"
216 " --version display program version and exit\n"
217 " --help display this help and exit\n"
218 " --log logfile append log information to logfile\n",
219 base_name(argv[0]));
220 if (help || version)
221 exit(EXIT_SUCCESS); /* no cleanup necessary at this stage */
222
223 /* real start */
224 puts("\n\n\nStarting CLEX " VERSION "\n");
225
226 /* initialize program data */
227 clex_data.umask = umask(0777);
228 umask(clex_data.umask);
229 clex_data.pid = getpid();
230 sprintf(clex_data.pidstr,"%d",(int)clex_data.pid);
231 #ifdef HAVE_SETENV
232 setenv("CLEX",clex_data.pidstr,1); /* let's have $CLEX (just so) */
233 #endif
234
235 /* low-level stuff except jc_initialize() */
236 tty_initialize();
237 signal_initialize();
238
239 /* read the configuration and options asap */
240 userdata_initialize(); /* required by cfg_initialize */
241 cfg_initialize();
242 opt_initialize();
243 bm_initialize();
244
245 /* initialize the rest, the order is not important (except when noted) */
246 compl_initialize();
247 dir_initialize();
248 files_initialize();
249 exec_initialize(); /* after files_initialize (if PROMPT contains $w) */
250 help_initialize();
251 hist_initialize();
252 inschar_initialize();
253 list_initialize();
254
255 /* user interface */
256 curses_initialize();
257 xterm_title_initialize(); /* after curses_initialize */
258 mouse_initialize(); /* after curses_initialize */
259 cx_version();
260
261 /* job control initialization is done last in order to provide enough time
262 for the parent process to finish its job control tasks */
263 jc_initialize();
264 control_loop(MODE_FILE);
265
266 /* NOTREACHED */
267 return 0;
268 }
269