1 /* m-x.c -- Meta-x minibuffer reader.
2
3 Copyright 1993-2023 Free Software Foundation, Inc.
4
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 Originally written by Brian Fox. */
19
20 #include "info.h"
21 #include "display.h"
22 #include "session.h"
23 #include "echo-area.h"
24 #include "funs.h"
25
26 /* **************************************************************** */
27 /* */
28 /* Reading Named Commands */
29 /* */
30 /* **************************************************************** */
31
32 /* Read the name of an Info function in the echo area and return the
33 name. A return value of NULL indicates that no function name could
34 be read. */
35 char *
36 read_function_name (char *prompt, WINDOW *window)
37 {
38 register int i;
39 char *line;
40 REFERENCE **array = NULL;
41 size_t array_index = 0, array_slots = 0;
42
43 /* Make an array of REFERENCE which actually contains the names of
44 the functions available in Info. */
45 for (i = 0; function_doc_array[i].func; i++)
46 {
47 REFERENCE *entry;
48
49 entry = xmalloc (sizeof (REFERENCE));
50 entry->label = xstrdup (function_doc_array[i].func_name);
51 entry->nodename = NULL;
52 entry->filename = NULL;
53
54 add_pointer_to_array (entry, array_index, array, array_slots, 200);
55 }
56
57 line = info_read_completing_in_echo_area (prompt, array);
58 info_free_references (array);
59
60 return line;
61 }
62
63 DECLARE_INFO_COMMAND (describe_command,
64 _("Read the name of an Info command and describe it"))
65 {
66 char *line;
67
68 line = read_function_name (_("Describe command: "), window);
69
70 if (!line)
71 {
72 info_abort_key (active_window, count);
73 return;
74 }
75
76 if (*line)
77 {
78 InfoCommand *cmd = named_function (line);
79 if (cmd)
80 {
81 window_message_in_echo_area ("%s: %s.",
82 line, function_documentation (cmd));
83 }
84 }
85 free (line);
86 }
87
88 DECLARE_INFO_COMMAND (info_execute_command,
89 _("Read a command name in the echo area and execute it"))
90 {
91 char *line;
92 char *keys;
93 char *prompt;
94
95 keys = where_is (info_keymap, InfoCmd(info_execute_command));
96 /* If the where_is () function thinks that this command doesn't exist,
97 there's something very wrong! */
98 if (!keys)
99 abort();
100
101 if (info_explicit_arg || count != 1)
102 xasprintf (&prompt, "%d %s ", count, keys);
103 else
104 xasprintf (&prompt, "%s ", keys);
105
106 /* Ask the completer to read a reference for us. */
107 line = read_function_name (prompt, window);
108 free (prompt);
109
110 /* User aborted? */
111 if (!line)
112 {
113 info_abort_key (active_window, count);
114 return;
115 }
116
117 /* User accepted "default"? (There is none.) */
118 if (!*line)
119 {
120 free (line);
121 return;
122 }
123
124 /* User wants to execute a named command. Do it. */
125 {
126 InfoCommand *command;
127
128 if ((active_window != the_echo_area) &&
129 (strncmp (line, "echo-area-", 10) == 0))
130 {
131 free (line);
132 info_error (_("Cannot execute an 'echo-area' command here"));
133 return;
134 }
135
136 command = named_function (line);
137 free (line);
138
139 if (command && command->func)
140 (*command->func) (active_window, count, 0);
141 }
142 }
143
144 /* Okay, now that we have M-x, let the user set the screen height. */
145 DECLARE_INFO_COMMAND (set_screen_height,
146 _("Set the height of the displayed window"))
147 {
148 int new_height, old_height = screenheight;
149
150 if (info_explicit_arg || count != 1)
151 new_height = count;
152 else
153 {
154 char prompt[80];
155 char *line;
156
157 new_height = screenheight;
158
159 sprintf (prompt, _("Set screen height to (%d): "), new_height);
160
161 line = info_read_in_echo_area (prompt);
162
163 /* If the user aborted, do that now. */
164 if (!line)
165 {
166 info_abort_key (active_window, count);
167 return;
168 }
169
170 /* Find out what the new height is supposed to be. */
171 if (*line)
172 new_height = atoi (line);
173
174 free (line);
175 }
176
177 terminal_clear_screen ();
178 display_clear_display (the_display);
179 screenheight = new_height;
180 #ifdef SET_SCREEN_SIZE_HELPER
181 SET_SCREEN_SIZE_HELPER;
182 #endif
183 if (screenheight == old_height)
184 {
185 /* Display dimensions didn't actually change, so
186 window_new_screen_size won't do anything, but we've
187 already cleared the display above. Undo the damage. */
188 window_mark_chain (windows, W_UpdateWindow);
189 display_update_display ();
190 }
191 else
192 {
193 display_initialize_display (screenwidth, screenheight);
194 window_new_screen_size (screenwidth, screenheight);
195 }
196 }