1/* variables.c -- how to manipulate user visible variables in Info.
2   $Id: variables.c,v 1.3 2004/04/11 17:56:46 karl 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. */
33static char *on_off_choices[] = { "Off", "On", (char *)NULL };
34
35VARIABLE_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
74DECLARE_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
99DECLARE_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. */
203VARIABLE_ALIST *
204read_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. */
249REFERENCE **
250make_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
274void
275set_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