1 /* Zile variables handling functions
2
3 Copyright (c) 1997-2011 Free Software Foundation, Inc.
4
5 This file is part of GNU Zile.
6
7 GNU Zile is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
10 any later version.
11
12 GNU Zile is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GNU Zile; see the file COPYING. If not, write to the
19 Free Software Foundation, Fifth Floor, 51 Franklin Street, Boston,
20 MA 02111-1301, USA. */
21
22 #include <config.h>
23
24 #include <assert.h>
25 #include <stdarg.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include "hash.h"
29
30 #include "main.h"
31 #include "extern.h"
32
33 /*
34 * Variable type.
35 */
36 struct var_entry
37 {
38 char *var; /* Variable name. */
39 char *defval; /* Default value. */
40 char *val; /* Current value, if any. */
41 bool local; /* If true, becomes local when set. */
42 const char *doc; /* Documentation */
43 };
44 typedef struct var_entry *var_entry;
45
46 static Hash_table *main_vars;
47
48 static size_t
var_hash(const void * v,size_t n)49 var_hash (const void *v, size_t n)
50 {
51 return hash_string (((var_entry) v)->var, n);
52 }
53
54 static bool
var_cmp(const void * v,const void * w)55 var_cmp (const void *v, const void *w)
56 {
57 return STREQ (((var_entry) v)->var, ((var_entry) w)->var);
58 }
59
60 static void
init_builtin_var(const char * var,const char * defval,bool local,const char * doc)61 init_builtin_var (const char *var, const char *defval, bool local, const char *doc)
62 {
63 var_entry p = XZALLOC (struct var_entry);
64 p->var = xstrdup (var);
65 p->defval = xstrdup (defval);
66 p->val = xstrdup (defval);
67 p->local = local;
68 p->doc = doc;
69 assert (hash_insert (main_vars, p));
70 }
71
72 static Hash_table *
new_varlist(void)73 new_varlist (void)
74 {
75 /* Initial size is big enough for default variables and some more */
76 return hash_initialize (32, NULL, var_hash, var_cmp, NULL);
77 }
78
79 void
init_variables(void)80 init_variables (void)
81 {
82 main_vars = new_varlist ();
83 #define X(var, defval, local, doc) \
84 init_builtin_var (var, defval, local, doc);
85 #include "tbl_vars.h"
86 #undef X
87 }
88
89 void
set_variable(const char * var,const char * val)90 set_variable (const char *var, const char *val)
91 {
92 Hash_table *var_list;
93 var_entry ent, key = XZALLOC (struct var_entry);
94 var_entry p = XZALLOC (struct var_entry), q;
95
96 /* Find whether variable is buffer-local when set, and if needed
97 create a buffer-local variable list. */
98 key->var = xstrdup (var);
99 ent = hash_lookup (main_vars, key);
100 if (ent && ent->local && get_buffer_vars (cur_bp) == NULL)
101 set_buffer_vars (cur_bp, new_varlist ());
102 var_list = (ent && ent->local) ? get_buffer_vars (cur_bp) : main_vars;
103
104 /* Insert variable if it doesn't already exist. */
105 p->var = xstrdup (var);
106 q = hash_insert (var_list, p);
107
108 /* Update value */
109 q->val = xstrdup (val);
110
111 /* If variable is new, initialise other fields. */
112 if (q == p)
113 {
114 if (var_list == main_vars)
115 {
116 p->defval = xstrdup (val);
117 p->local = false;
118 p->doc = "";
119 }
120 }
121 }
122
123 static var_entry
get_variable_entry(Buffer bp,const char * var)124 get_variable_entry (Buffer bp, const char *var)
125 {
126 var_entry p = NULL, key = XZALLOC (struct var_entry);
127
128 key->var = xstrdup (var);
129
130 if (bp && get_buffer_vars (bp))
131 p = hash_lookup (get_buffer_vars (bp), key);
132
133 return p ? p : hash_lookup (main_vars, key);
134 }
135
136 const char *
get_variable_doc(const char * var,const char ** defval)137 get_variable_doc (const char *var, const char **defval)
138 {
139 var_entry p = get_variable_entry (NULL, var);
140 if (p == NULL)
141 return NULL;
142
143 *defval = p->defval;
144 return p->doc;
145 }
146
147 const char *
get_variable_bp(Buffer bp,const char * var)148 get_variable_bp (Buffer bp, const char *var)
149 {
150 var_entry p = get_variable_entry (bp, var);
151 return p ? p->val : NULL;
152 }
153
154 const char *
get_variable(const char * var)155 get_variable (const char *var)
156 {
157 return get_variable_bp (cur_bp, var);
158 }
159
160 bool
get_variable_bool(const char * var)161 get_variable_bool (const char *var)
162 {
163 const char *p = get_variable (var);
164 if (p != NULL)
165 return !STREQ (p, "nil");
166
167 return false;
168 }
169
170 const_astr
minibuf_read_variable_name(const char * fmt,...)171 minibuf_read_variable_name (const char *fmt, ...)
172 {
173 Completion cp = completion_new (false);
174
175 for (var_entry p = hash_get_first (main_vars);
176 p != NULL;
177 p = hash_get_next (main_vars, p))
178 {
179 gl_sortedlist_add (get_completion_completions (cp), completion_strcmp,
180 xstrdup (p->var));
181 }
182
183 va_list ap;
184 va_start (ap, fmt);
185 const_astr ms = minibuf_vread_completion (fmt, "", cp, NULL,
186 "No variable name given",
187 minibuf_test_in_completions,
188 "Undefined variable name `%s'", ap);
189 va_end (ap);
190
191 return ms;
192 }
193
194 DEFUN_ARGS ("set-variable", set_variable,
195 STR_ARG (var)
196 STR_ARG (val))
197 /*+
198 Set a variable value to the user-specified value.
199 +*/
200 {
201 STR_INIT (var)
202 else
203 var = minibuf_read_variable_name ("Set variable: ");
204 if (var == NULL)
205 return leNIL;
206 STR_INIT (val)
207 else
208 val = minibuf_read ("Set %s to value: ", "", astr_cstr (var));
209 if (val == NULL)
210 ok = FUNCALL (keyboard_quit);
211
212 if (ok == leT)
213 set_variable (astr_cstr (var), astr_cstr (val));
214 }
215 END_DEFUN
216