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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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.
27 #include "global.h" /* home_dir */
29 #include "widget.h" /* WInput */
31 #include "complete.h" /* completion constants */
32 #include "wtools.h" /* message () */
33 #include "panel.h" /* view_tree enum. Also, needed by main.h */
34 #include "main.h" /* do_cd */
35 #include "layout.h" /* for command_prompt variable */
36 #include "user.h" /* expand_format */
37 #include "subshell.h" /* SUBSHELL_EXIT */
38 #include "tree.h" /* for tree_chdir */
39 #include "color.h" /* DEFAULT_COLOR */
41 /* This holds the command line */
44 /*Tries variable substitution, and if a variable CDPATH
45 of the form e.g. CDPATH=".:~:/usr" exists, we try then all the paths which
46 are mentioned there. Also, we do not support such extraordinary things as
47 ${var:-value}, etc. Use the eval cd 'path' command instead.
48 Bugs: No quoting occurrs here, so ${VAR} and $VAR will be always
49 substituted. I think we can encourage users to use in such extreme
50 cases instead of >cd path< command a >eval cd 'path'< command, which works
51 as they might expect :)
52 FIXME: Perhaps we should do wildcard matching as well? */
53 static int examine_cd (char *path
)
57 char *q
, *r
, *s
, *t
, c
;
59 q
= g_malloc (MC_MAXPATHLEN
+ 10);
60 /* Variable expansion */
61 for (p
= path
, r
= q
; *p
&& r
< q
+ MC_MAXPATHLEN
; ) {
62 if (*p
!= '$' || (p
[1] == '[' || p
[1] == '('))
72 s
= strchr (p
, PATH_SEP
);
84 if (r
+ strlen (t
) < q
+ MC_MAXPATHLEN
) {
97 result
= do_cd (q
, cd_parse_command
);
100 if (*q
!= PATH_SEP
&& !result
) {
101 p
= getenv ("CDPATH");
106 while (!result
&& c
== ':') {
113 r
= concat_dir_and_file (p
, q
);
114 result
= do_cd (r
, cd_parse_command
);
125 /* Execute the cd command on the command line */
126 void do_cd_command (char *cmd
)
130 /* Any final whitespace should be removed here
131 (to see why, try "cd fred "). */
132 /* NOTE: I think we should not remove the extra space,
133 that way, we can cd into hidden directories */
134 len
= strlen (cmd
) - 1;
136 (cmd
[len
] == ' ' || cmd
[len
] == '\t' || cmd
[len
] == '\n')){
144 if (get_current_type () == view_tree
){
146 sync_tree (home_dir
);
147 } else if (strcmp (cmd
+3, "..") == 0){
148 char *dir
= cpanel
->cwd
;
149 int len
= strlen (dir
);
150 while (len
&& dir
[--len
] != PATH_SEP
);
155 sync_tree (PATH_SEP_STR
);
156 } else if (cmd
[3] == PATH_SEP
){
159 char *old
= cpanel
->cwd
;
161 new = concat_dir_and_file (old
, cmd
+3);
166 if (!examine_cd (&cmd
[3])) {
167 message (1, MSG_ERROR
, _(" Cannot chdir to \"%s\" \n %s "),
168 &cmd
[3], unix_error_string (errno
));
173 /* Returns 1 if the we could handle the enter, 0 if not */
175 enter (WInput
* cmdline
)
179 if (command_prompt
&& strlen (cmdline
->buffer
)) {
182 /* Any initial whitespace should be removed at this point */
183 cmd
= cmdline
->buffer
;
184 while (*cmd
== ' ' || *cmd
== '\t' || *cmd
== '\n')
187 if (strncmp (cmd
, "cd ", 3) == 0 || strcmp (cmd
, "cd") == 0) {
195 if (!vfs_current_is_local ()) {
196 message (1, MSG_ERROR
,
198 (" Cannot 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 (NULL
, cmd
[i
], 1);
209 g_realloc (command
, strlen (command
) + strlen (s
)
210 + strlen (cmd
) - i
+ 1);
213 j
= strlen (command
);
220 old_dlg
= current_dlg
;
226 #ifdef HAVE_SUBSHELL_SUPPORT
227 if (quit
& SUBSHELL_EXIT
) {
235 current_dlg
= old_dlg
;
242 command_callback (WInput
*cmd
, int msg
, int par
)
246 /* Never accept focus, otherwise panels will be unselected */
247 return MSG_NOT_HANDLED
;
250 /* Special case: we handle the enter key */
255 return input_callback (cmd
, msg
, par
);
259 command_new (int y
, int x
, int cols
)
261 WInput
*cmd
= g_new (WInput
, 1);
263 cmd
= input_new (y
, x
, DEFAULT_COLOR
, cols
, "", "cmdline");
266 cmd
->widget
.callback
= (callback_fn
) command_callback
;
267 cmd
->completion_flags
|= INPUT_COMPLETE_COMMANDS
;
273 * Insert quoted text in input line. The function is meant for the
274 * command line, so the percent sign is quoted as well.
277 command_insert (WInput
* in
, char *text
, int insert_extra_space
)
281 quoted_text
= name_quote (text
, 1);
282 stuff (in
, quoted_text
, insert_extra_space
);
283 g_free (quoted_text
);