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