xref: /openbsd/gnu/usr.bin/texinfo/info/variables.c (revision 73471bf0)
1 /* variables.c -- how to manipulate user visible variables in Info.
2    $Id: variables.c,v 1.5 2006/07/17 16:12:36 espie Exp $
3 
4    Copyright (C) 1993, 1997, 2001, 2002, 2004 Free Software Foundation, Inc.
5 
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2, or (at your option)
9    any later version.
10 
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15 
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
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", (char *)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   { "scroll-step",
64       N_("The number lines to scroll when the cursor moves out of the window"),
65       &window_scroll_step, (char **)NULL },
66 
67   { "ISO-Latin",
68       N_("When \"On\", Info accepts and displays ISO Latin characters"),
69       &ISO_Latin_p, (char **)on_off_choices },
70 
71   { (char *)NULL, (char *)NULL, (int *)NULL, (char **)NULL }
72 };
73 
74 DECLARE_INFO_COMMAND (describe_variable, _("Explain the use of a variable"))
75 {
76   VARIABLE_ALIST *var;
77   char *description;
78 
79   /* Get the variable's name. */
80   var = read_variable_name ((char *) _("Describe variable: "), window);
81 
82   if (!var)
83     return;
84 
85   description = (char *)xmalloc (20 + strlen (var->name)
86 				 + strlen (_(var->doc)));
87 
88   if (var->choices)
89     sprintf (description, "%s (%s): %s.",
90              var->name, var->choices[*(var->value)], _(var->doc));
91   else
92     sprintf (description, "%s (%d): %s.",
93 	     var->name, *(var->value), _(var->doc));
94 
95   window_message_in_echo_area ("%s", description, NULL);
96   free (description);
97 }
98 
99 DECLARE_INFO_COMMAND (set_variable, _("Set the value of an Info variable"))
100 {
101   VARIABLE_ALIST *var;
102   char *line;
103 
104   /* Get the variable's name and value. */
105   var = read_variable_name ((char *) _("Set variable: "), window);
106 
107   if (!var)
108     return;
109 
110   /* Read a new value for this variable. */
111   {
112     char prompt[100];
113 
114     if (!var->choices)
115       {
116         int potential_value;
117 
118         if (info_explicit_arg || count != 1)
119           potential_value = count;
120         else
121           potential_value = *(var->value);
122 
123         sprintf (prompt, _("Set %s to value (%d): "),
124                  var->name, potential_value);
125         line = info_read_in_echo_area (active_window, prompt);
126 
127         /* If no error was printed, clear the echo area. */
128         if (!info_error_was_printed)
129           window_clear_echo_area ();
130 
131         /* User aborted? */
132         if (!line)
133           return;
134 
135         /* If the user specified a value, get that, otherwise, we are done. */
136         canonicalize_whitespace (line);
137         if (*line)
138           *(var->value) = atoi (line);
139         else
140           *(var->value) = potential_value;
141 
142         free (line);
143       }
144     else
145       {
146         register int i;
147         REFERENCE **array = (REFERENCE **)NULL;
148         int array_index = 0;
149         int array_slots = 0;
150 
151         for (i = 0; var->choices[i]; i++)
152           {
153             REFERENCE *entry;
154 
155             entry = (REFERENCE *)xmalloc (sizeof (REFERENCE));
156             entry->label = xstrdup (var->choices[i]);
157             entry->nodename = (char *)NULL;
158             entry->filename = (char *)NULL;
159 
160             add_pointer_to_array
161               (entry, array_index, array, array_slots, 10, REFERENCE *);
162           }
163 
164         sprintf (prompt, _("Set %s to value (%s): "),
165                  var->name, var->choices[*(var->value)]);
166 
167         /* Ask the completer to read a variable value for us. */
168         line = info_read_completing_in_echo_area (window, prompt, array);
169 
170         info_free_references (array);
171 
172         if (!echo_area_is_active)
173           window_clear_echo_area ();
174 
175         /* User aborted? */
176         if (!line)
177           {
178             info_abort_key (active_window, 0, 0);
179             return;
180           }
181 
182         /* User accepted default choice?  If so, no change. */
183         if (!*line)
184           {
185             free (line);
186             return;
187           }
188 
189         /* Find the choice in our list of choices. */
190         for (i = 0; var->choices[i]; i++)
191           if (strcmp (var->choices[i], line) == 0)
192             break;
193 
194         if (var->choices[i])
195           *(var->value) = i;
196       }
197   }
198 }
199 
200 /* Read the name of an Info variable in the echo area and return the
201    address of a VARIABLE_ALIST member.  A return value of NULL indicates
202    that no variable could be read. */
203 VARIABLE_ALIST *
204 read_variable_name (char *prompt, WINDOW *window)
205 {
206   register int i;
207   char *line;
208   REFERENCE **variables;
209 
210   /* Get the completion array of variable names. */
211   variables = make_variable_completions_array ();
212 
213   /* Ask the completer to read a variable for us. */
214   line =
215     info_read_completing_in_echo_area (window, prompt, variables);
216 
217   info_free_references (variables);
218 
219   if (!echo_area_is_active)
220     window_clear_echo_area ();
221 
222   /* User aborted? */
223   if (!line)
224     {
225       info_abort_key (active_window, 0, 0);
226       return ((VARIABLE_ALIST *)NULL);
227     }
228 
229   /* User accepted "default"?  (There is none.) */
230   if (!*line)
231     {
232       free (line);
233       return ((VARIABLE_ALIST *)NULL);
234     }
235 
236   /* Find the variable in our list of variables. */
237   for (i = 0; info_variables[i].name; i++)
238     if (strcmp (info_variables[i].name, line) == 0)
239       break;
240 
241   if (!info_variables[i].name)
242     return ((VARIABLE_ALIST *)NULL);
243   else
244     return (&(info_variables[i]));
245 }
246 
247 /* Make an array of REFERENCE which actually contains the names of the
248    variables available in Info. */
249 REFERENCE **
250 make_variable_completions_array (void)
251 {
252   register int i;
253   REFERENCE **array = (REFERENCE **)NULL;
254   int array_index = 0, array_slots = 0;
255 
256   for (i = 0; info_variables[i].name; i++)
257     {
258       REFERENCE *entry;
259 
260       entry = (REFERENCE *) xmalloc (sizeof (REFERENCE));
261       entry->label = xstrdup (info_variables[i].name);
262       entry->nodename = (char *)NULL;
263       entry->filename = (char *)NULL;
264 
265       add_pointer_to_array
266         (entry, array_index, array, array_slots, 200, REFERENCE *);
267     }
268 
269   return (array);
270 }
271 
272 #if defined(INFOKEY)
273 
274 void
275 set_variable_to_value(char *name, char *value)
276 {
277 	register int i;
278 
279 	/* Find the variable in our list of variables. */
280 	for (i = 0; info_variables[i].name; i++)
281 		if (strcmp(info_variables[i].name, name) == 0)
282 			break;
283 
284 	if (!info_variables[i].name)
285 		return;
286 
287 	if (info_variables[i].choices)
288 	{
289 		register int j;
290 
291 		/* Find the choice in our list of choices. */
292 		for (j = 0; info_variables[i].choices[j]; j++)
293 			if (strcmp (info_variables[i].choices[j], value) == 0)
294 				break;
295 
296 		if (info_variables[i].choices[j])
297 			*info_variables[i].value = j;
298 	}
299 	else
300 	{
301 		*info_variables[i].value = atoi(value);
302 	}
303 }
304 
305 #endif /* INFOKEY */
306