1 /* Command line widget.
2 Copyright (C) 1995 Miguel de Icaza
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 This widget is derived from the WInput widget, it's used to cope
19 with all the magic of the command input line, we depend on some
20 help from the program's callback.
35 #include "complete.h" /* completion constants */
36 #include "global.h" /* home_dir */
37 #include "dialog.h" /* message () */
38 #include "dir.h" /* required by panel.h */
39 #include "panel.h" /* view_tree enum. Also, needed by main.h */
40 #include "main.h" /* do_cd */
41 #include "layout.h" /* for command_prompt variable */
42 #include "user.h" /* expand_format */
44 #include "tree.h" /* for tree_chdir */
46 #include "../vfs/vfs.h"
48 /* This holds the command line */
51 /*Tries variable substitution, and if a variable CDPATH
52 of the form e.g. CDPATH=".:~:/usr" exists, we try then all the paths which
53 are mentioned there. Also, we do not support such extraordinary things as
54 ${var:-value}, etc. Use the eval cd 'path' command instead.
55 Bugs: No quoting occurrs here, so ${VAR} and $VAR will be always
56 substituted. I think we can encourage users to use in such extreme
57 cases instead of >cd path< command a >eval cd 'path'< command, which works
58 as they might expect :)
59 FIXME: Perhaps we should do wildcard matching as well? */
60 static int examine_cd (char *path
)
64 char *q
= xmalloc (MC_MAXPATHLEN
+ 10, "examine_cd"), *r
, *s
, *t
, c
;
66 /* Variable expansion */
67 for (p
= path
, r
= q
; *p
&& r
< q
+ MC_MAXPATHLEN
; ) {
68 if (*p
!= '$' || (p
[1] == '[' || p
[1] == '('))
78 s
= strchr (p
, PATH_SEP
);
90 if (r
+ strlen (t
) < q
+ MC_MAXPATHLEN
) {
103 result
= do_cd (q
, cd_parse_command
);
105 /* CDPATH handling */
106 if (*q
!= PATH_SEP
&& !result
) {
107 p
= getenv ("CDPATH");
112 while (!result
&& c
== ':') {
119 r
= concat_dir_and_file (p
, q
);
120 result
= do_cd (r
, cd_parse_command
);
131 /* Execute the cd command on the command line */
132 void do_cd_command (char *cmd
)
136 /* Any final whitespace should be removed here
137 (to see why, try "cd fred "). */
138 /* NOTE: I think we should not remove the extra space,
139 that way, we can cd into hidden directories */
140 len
= strlen (cmd
) - 1;
142 (cmd
[len
] == ' ' || cmd
[len
] == '\t' || cmd
[len
] == '\n')){
150 if (get_current_type () == view_tree
){
152 tree_chdir (the_tree
, home_dir
);
153 } else if (strcmp (cmd
+3, "..") == 0){
154 char *dir
= cpanel
->cwd
;
155 int len
= strlen (dir
);
156 while (len
&& dir
[--len
] != PATH_SEP
);
159 tree_chdir (the_tree
, dir
);
161 tree_chdir (the_tree
, PATH_SEP_STR
);
162 } else if (cmd
[3] == PATH_SEP
){
163 tree_chdir (the_tree
, cmd
+3);
165 char *old
= cpanel
->cwd
;
167 new = concat_dir_and_file (old
, cmd
+3);
168 tree_chdir (the_tree
, new);
172 if (!examine_cd (&cmd
[3])) {
173 message (1, MSG_ERROR
, _(" Can't chdir to '%s' \n %s "),
174 &cmd
[3], unix_error_string (errno
));
179 /* Returns 1 if the we could handle the enter, 0 if not */
180 static int enter (WCommand
*cmdline
)
184 if (command_prompt
&& strlen (input_w (cmdline
)->buffer
)){
187 /* Any initial whitespace should be removed at this point */
188 cmd
= input_w (cmdline
)->buffer
;
189 while (*cmd
== ' ' || *cmd
== '\t' || *cmd
== '\n')
192 if (strncmp (cmd
, "cd ", 3) == 0 || strcmp (cmd
, "cd") == 0){
194 new_input (input_w (cmdline
));
198 else if ( (strncmp (cmd
, "set ", 4) == 0 || strncmp (cmd
, "Set ", 4) == 0 || strncmp (cmd
, "SET ", 4) == 0) && strchr(cmd
,'=') ){
200 while (*cmd
== ' ' || *cmd
== '\t' || *cmd
== '\n')
203 new_input (input_w (cmdline
));
211 if (!vfs_current_is_local ())
212 return MSG_NOT_HANDLED
;
213 command
= xmalloc (strlen (cmd
) + 1, "main, enter");
215 for (i
= j
= 0; i
< strlen (cmd
); i
++){
218 s
= expand_format (cmd
[i
], 1);
219 command
= realloc (command
, strlen (command
) + strlen (s
)
220 + strlen (cmd
) - i
+ 1);
223 j
= strlen (command
);
225 command
[j
] = cmd
[i
];
230 old_dlg
= current_dlg
;
232 new_input (input_w (cmdline
));
236 #ifdef HAVE_SUBSHELL_SUPPORT
237 if (quit
& SUBSHELL_EXIT
){
245 current_dlg
= old_dlg
;
251 static int command_callback (Dlg_head
*h
, WCommand
*cmd
, int msg
, int par
)
255 /* We refuse the focus always: needed not to unselect the panel */
256 return MSG_NOT_HANDLED
;
259 /* Special case: we handle the enter key */
264 return (*cmd
->old_callback
)(h
, cmd
, msg
, par
);
267 WCommand
*command_new (int y
, int x
, int cols
)
270 WCommand
*cmd
= xmalloc (sizeof (WCommand
), "command_new");
272 in
= input_new (y
, x
, DEFAULT_COLOR
, cols
, "", "cmdline");
277 cmd
->old_callback
= (callback_fn
) cmd
->input
.widget
.callback
;
278 cmd
->input
.widget
.callback
= (int (*) (Dlg_head
*, void *, int, int))
281 cmd
->input
.completion_flags
|= INPUT_COMPLETE_COMMANDS
;