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.
28 #include "global.h" /* home_dir */
32 #include "complete.h" /* completion constants */
33 #include "dialog.h" /* message () */
34 #include "dir.h" /* required by panel.h */
35 #include "panel.h" /* view_tree enum. Also, needed by main.h */
36 #include "main.h" /* do_cd */
37 #include "layout.h" /* for command_prompt variable */
38 #include "user.h" /* expand_format */
40 #include "tree.h" /* for tree_chdir */
42 #include "../vfs/vfs.h"
44 /* This holds the command line */
47 /*Tries variable substitution, and if a variable CDPATH
48 of the form e.g. CDPATH=".:~:/usr" exists, we try then all the paths which
49 are mentioned there. Also, we do not support such extraordinary things as
50 ${var:-value}, etc. Use the eval cd 'path' command instead.
51 Bugs: No quoting occurrs here, so ${VAR} and $VAR will be always
52 substituted. I think we can encourage users to use in such extreme
53 cases instead of >cd path< command a >eval cd 'path'< command, which works
54 as they might expect :)
55 FIXME: Perhaps we should do wildcard matching as well? */
56 static int examine_cd (char *path
)
60 char *q
, *r
, *s
, *t
, c
;
62 q
= g_malloc (MC_MAXPATHLEN
+ 10);
63 /* Variable expansion */
64 for (p
= path
, r
= q
; *p
&& r
< q
+ MC_MAXPATHLEN
; ) {
65 if (*p
!= '$' || (p
[1] == '[' || p
[1] == '('))
75 s
= strchr (p
, PATH_SEP
);
87 if (r
+ strlen (t
) < q
+ MC_MAXPATHLEN
) {
100 result
= do_cd (q
, cd_parse_command
);
102 /* CDPATH handling */
103 if (*q
!= PATH_SEP
&& !result
) {
104 p
= getenv ("CDPATH");
109 while (!result
&& c
== ':') {
116 r
= concat_dir_and_file (p
, q
);
117 result
= do_cd (r
, cd_parse_command
);
128 /* Execute the cd command on the command line */
129 void do_cd_command (char *cmd
)
133 /* Any final whitespace should be removed here
134 (to see why, try "cd fred "). */
135 /* NOTE: I think we should not remove the extra space,
136 that way, we can cd into hidden directories */
137 len
= strlen (cmd
) - 1;
139 (cmd
[len
] == ' ' || cmd
[len
] == '\t' || cmd
[len
] == '\n')){
147 if (get_current_type () == view_tree
){
149 sync_tree (home_dir
);
150 } else if (strcmp (cmd
+3, "..") == 0){
151 char *dir
= cpanel
->cwd
;
152 int len
= strlen (dir
);
153 while (len
&& dir
[--len
] != PATH_SEP
);
158 sync_tree (PATH_SEP_STR
);
159 } else if (cmd
[3] == PATH_SEP
){
162 char *old
= cpanel
->cwd
;
164 new = concat_dir_and_file (old
, cmd
+3);
169 if (!examine_cd (&cmd
[3])) {
170 message (1, MSG_ERROR
, _(" Can't chdir to '%s' \n %s "),
171 &cmd
[3], unix_error_string (errno
));
176 /* Returns 1 if the we could handle the enter, 0 if not */
177 static int enter (WCommand
*cmdline
)
181 if (command_prompt
&& strlen (input_w (cmdline
)->buffer
)){
184 /* Any initial whitespace should be removed at this point */
185 cmd
= input_w (cmdline
)->buffer
;
186 while (*cmd
== ' ' || *cmd
== '\t' || *cmd
== '\n')
189 if (strncmp (cmd
, "cd ", 3) == 0 || strcmp (cmd
, "cd") == 0){
191 new_input (input_w (cmdline
));
197 if (!vfs_current_is_local ()) {
198 message (1, MSG_ERROR
, _(" You can not execute commands on non-local filesystems"));
200 return MSG_NOT_HANDLED
;
202 command
= g_malloc (strlen (cmd
) + 1);
204 for (i
= j
= 0; i
< strlen (cmd
); i
++){
207 s
= expand_format (cmd
[i
], 1);
208 command
= g_realloc (command
, strlen (command
) + strlen (s
)
209 + strlen (cmd
) - i
+ 1);
212 j
= strlen (command
);
214 command
[j
] = cmd
[i
];
219 old_dlg
= current_dlg
;
221 new_input (input_w (cmdline
));
225 #ifdef HAVE_SUBSHELL_SUPPORT
226 if (quit
& SUBSHELL_EXIT
){
234 current_dlg
= old_dlg
;
240 static int command_callback (Dlg_head
*h
, WCommand
*cmd
, int msg
, int par
)
244 /* We refuse the focus always: needed not to unselect the panel */
245 return MSG_NOT_HANDLED
;
248 /* Special case: we handle the enter key */
253 return (*cmd
->old_callback
)(h
, cmd
, msg
, par
);
256 WCommand
*command_new (int y
, int x
, int cols
)
259 WCommand
*cmd
= g_new (WCommand
, 1);
261 in
= input_new (y
, x
, DEFAULT_COLOR
, cols
, "", "cmdline");
266 cmd
->old_callback
= (callback_fn
) cmd
->input
.widget
.callback
;
267 cmd
->input
.widget
.callback
= (int (*) (Dlg_head
*, void *, int, int))
270 cmd
->input
.completion_flags
|= INPUT_COMPLETE_COMMANDS
;