Upgrade Texinfo from 4.8 to 4.13 on the vendor branch
[dragonfly.git] / contrib / texinfo / info / variables.c
1 /* variables.c -- how to manipulate user visible variables in Info.
2    $Id: variables.c,v 1.10 2008/06/11 09:55:43 gray Exp $
3
4    Copyright (C) 1993, 1997, 2001, 2002, 2004, 2007, 2008
5    Free Software Foundation, Inc.
6
7    This program is free software: you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation, either version 3 of the License, or
10    (at your option) any later version.
11
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with this program.  If not, see <http://www.gnu.org/licenses/>.
19
20    Written by Brian Fox (bfox@ai.mit.edu). */
21
22 #include "info.h"
23 #include "variables.h"
24
25 /* **************************************************************** */
26 /*                                                                  */
27 /*                  User Visible Variables in Info                  */
28 /*                                                                  */
29 /* **************************************************************** */
30
31 /* Choices used by the completer when reading a zero/non-zero value for
32    a variable. */
33 static char *on_off_choices[] = { "Off", "On", NULL };
34
35 VARIABLE_ALIST info_variables[] = {
36   { "automatic-footnotes",
37       N_("When \"On\", footnotes appear and disappear automatically"),
38       &auto_footnotes_p, (char **)on_off_choices },
39
40   { "automatic-tiling",
41       N_("When \"On\", creating or deleting a window resizes other windows"),
42       &auto_tiling_p, (char **)on_off_choices },
43
44   { "visible-bell",
45       N_("When \"On\", flash the screen instead of ringing the bell"),
46       &terminal_use_visible_bell_p, (char **)on_off_choices },
47
48   { "errors-ring-bell",
49       N_("When \"On\", errors cause the bell to ring"),
50       &info_error_rings_bell_p, (char **)on_off_choices },
51
52   { "gc-compressed-files",
53       N_("When \"On\", Info garbage collects files which had to be uncompressed"),
54       &gc_compressed_files, (char **)on_off_choices },
55   { "show-index-match",
56       N_("When \"On\", the portion of the matched search string is highlighted"),
57       &show_index_match, (char **)on_off_choices },
58
59   { "scroll-behaviour",
60       N_("Controls what happens when scrolling is requested at the end of a node"),
61       &info_scroll_behaviour, (char **)info_scroll_choices },
62
63   /* Alternate spelling */
64   { "scroll-behavior",
65       N_("Same as scroll-behaviour"),
66       &info_scroll_behaviour, (char **)info_scroll_choices },
67
68   { "scroll-step",
69       N_("The number lines to scroll when the cursor moves out of the window"),
70       &window_scroll_step, NULL },
71
72   { "cursor-movement-scrolls",
73     N_("Controls whether scroll-behavior affects cursor movement commands"),
74     &cursor_movement_scrolls_p, (char **)on_off_choices },
75   
76   { "ISO-Latin",
77       N_("When \"On\", Info accepts and displays ISO Latin characters"),
78       &ISO_Latin_p, (char **)on_off_choices },
79
80   { "scroll-last-node",
81     N_("What to do when a scrolling command is issued at the end of the "
82        "last node"),
83     &scroll_last_node, (char**)scroll_last_node_choices },
84   
85   { NULL }
86 };
87
88 DECLARE_INFO_COMMAND (describe_variable, _("Explain the use of a variable"))
89 {
90   VARIABLE_ALIST *var;
91   char *description;
92
93   /* Get the variable's name. */
94   var = read_variable_name (_("Describe variable: "), window);
95
96   if (!var)
97     return;
98
99   description = xmalloc (20 + strlen (var->name)
100                          + strlen (_(var->doc)));
101
102   if (var->choices)
103     sprintf (description, "%s (%s): %s.",
104              var->name, var->choices[*(var->value)], _(var->doc));
105   else
106     sprintf (description, "%s (%d): %s.",
107              var->name, *(var->value), _(var->doc));
108
109   window_message_in_echo_area ("%s", description, NULL);
110   free (description);
111 }
112
113 DECLARE_INFO_COMMAND (set_variable, _("Set the value of an Info variable"))
114 {
115   VARIABLE_ALIST *var;
116   char *line;
117
118   /* Get the variable's name and value. */
119   var = read_variable_name (_("Set variable: "), window);
120
121   if (!var)
122     return;
123
124   /* Read a new value for this variable. */
125   {
126     char prompt[100];
127
128     if (!var->choices)
129       {
130         int potential_value;
131
132         if (info_explicit_arg || count != 1)
133           potential_value = count;
134         else
135           potential_value = *(var->value);
136
137         sprintf (prompt, _("Set %s to value (%d): "),
138                  var->name, potential_value);
139         line = info_read_in_echo_area (active_window, prompt);
140
141         /* If no error was printed, clear the echo area. */
142         if (!info_error_was_printed)
143           window_clear_echo_area ();
144
145         /* User aborted? */
146         if (!line)
147           return;
148
149         /* If the user specified a value, get that, otherwise, we are done. */
150         canonicalize_whitespace (line);
151         if (*line)
152           *(var->value) = atoi (line);
153         else
154           *(var->value) = potential_value;
155
156         free (line);
157       }
158     else
159       {
160         register int i;
161         REFERENCE **array = NULL;
162         int array_index = 0;
163         int array_slots = 0;
164
165         for (i = 0; var->choices[i]; i++)
166           {
167             REFERENCE *entry;
168
169             entry = xmalloc (sizeof (REFERENCE));
170             entry->label = xstrdup (var->choices[i]);
171             entry->nodename = NULL;
172             entry->filename = NULL;
173
174             add_pointer_to_array
175               (entry, array_index, array, array_slots, 10, REFERENCE *);
176           }
177
178         sprintf (prompt, _("Set %s to value (%s): "),
179                  var->name, var->choices[*(var->value)]);
180
181         /* Ask the completer to read a variable value for us. */
182         line = info_read_completing_in_echo_area (window, prompt, array);
183
184         info_free_references (array);
185
186         if (!echo_area_is_active)
187           window_clear_echo_area ();
188
189         /* User aborted? */
190         if (!line)
191           {
192             info_abort_key (active_window, 0, 0);
193             return;
194           }
195
196         /* User accepted default choice?  If so, no change. */
197         if (!*line)
198           {
199             free (line);
200             return;
201           }
202
203         /* Find the choice in our list of choices. */
204         for (i = 0; var->choices[i]; i++)
205           if (strcmp (var->choices[i], line) == 0)
206             break;
207
208         if (var->choices[i])
209           *(var->value) = i;
210       }
211   }
212 }
213
214 /* Read the name of an Info variable in the echo area and return the
215    address of a VARIABLE_ALIST member.  A return value of NULL indicates
216    that no variable could be read. */
217 VARIABLE_ALIST *
218 read_variable_name (const char *prompt, WINDOW *window)
219 {
220   register int i;
221   char *line;
222   REFERENCE **variables;
223
224   /* Get the completion array of variable names. */
225   variables = make_variable_completions_array ();
226
227   /* Ask the completer to read a variable for us. */
228   line =
229     info_read_completing_in_echo_area (window, prompt, variables);
230
231   info_free_references (variables);
232
233   if (!echo_area_is_active)
234     window_clear_echo_area ();
235
236   /* User aborted? */
237   if (!line)
238     {
239       info_abort_key (active_window, 0, 0);
240       return NULL;
241     }
242
243   /* User accepted "default"?  (There is none.) */
244   if (!*line)
245     {
246       free (line);
247       return NULL;
248     }
249
250   /* Find the variable in our list of variables. */
251   for (i = 0; info_variables[i].name; i++)
252     if (strcmp (info_variables[i].name, line) == 0)
253       break;
254
255   if (!info_variables[i].name)
256     return NULL;
257   else
258     return &info_variables[i];
259 }
260
261 /* Make an array of REFERENCE which actually contains the names of the
262    variables available in Info. */
263 REFERENCE **
264 make_variable_completions_array (void)
265 {
266   register int i;
267   REFERENCE **array = NULL;
268   int array_index = 0, array_slots = 0;
269
270   for (i = 0; info_variables[i].name; i++)
271     {
272       REFERENCE *entry;
273
274       entry = xmalloc (sizeof (REFERENCE));
275       entry->label = xstrdup (info_variables[i].name);
276       entry->nodename = NULL;
277       entry->filename = NULL;
278
279       add_pointer_to_array
280         (entry, array_index, array, array_slots, 200, REFERENCE *);
281     }
282
283   return array;
284 }
285
286 #if defined(INFOKEY)
287
288 void
289 set_variable_to_value(char *name, char *value)
290 {
291         register int i;
292
293         /* Find the variable in our list of variables. */
294         for (i = 0; info_variables[i].name; i++)
295                 if (strcmp(info_variables[i].name, name) == 0)
296                         break;
297
298         if (!info_variables[i].name)
299                 return;
300
301         if (info_variables[i].choices)
302         {
303                 register int j;
304
305                 /* Find the choice in our list of choices. */
306                 for (j = 0; info_variables[i].choices[j]; j++)
307                         if (strcmp (info_variables[i].choices[j], value) == 0)
308                                 break;
309
310                 if (info_variables[i].choices[j])
311                         *info_variables[i].value = j;
312         }
313         else
314         {
315                 *info_variables[i].value = atoi(value);
316         }
317 }
318
319 #endif /* INFOKEY */