source: variable.c @ d536e72

barnowl_perlaimdebianrelease-1.10release-1.4release-1.5release-1.6release-1.7release-1.8release-1.9
Last change on this file since d536e72 was d536e72, checked in by Nelson Elhage <nelhage@mit.edu>, 16 years ago
Handle recreation of an existing variable better. Copy over the default and docstrings, but preserve the old value.
  • Property mode set to 100644
File size: 39.7 KB
Line 
1#include <stdio.h>
2#include <stdlib.h>
3#include <string.h>
4#include <unistd.h>
5#include <ctype.h>
6#include "owl.h"
7
8static const char fileIdent[] = "$Id$";
9
10static int in_regtest = 0;
11
12#define OWLVAR_BOOL(name,default,summary,description) \
13        { name, OWL_VARIABLE_BOOL, NULL, default, "on,off", summary,description, NULL, \
14        NULL, NULL, NULL, NULL, NULL }
15
16#define OWLVAR_BOOL_FULL(name,default,summary,description,validate,set,get) \
17        { name, OWL_VARIABLE_BOOL, NULL, default, "on,off", summary,description, NULL, \
18        validate, set, NULL, get, NULL }
19
20#define OWLVAR_INT(name,default,summary,description) \
21        { name, OWL_VARIABLE_INT, NULL, default, "<int>", summary,description, NULL, \
22        NULL, NULL, NULL, NULL, NULL, NULL }
23
24#define OWLVAR_INT_FULL(name,default,summary,description,validset,validate,set,get) \
25        { name, OWL_VARIABLE_INT, NULL, default, validset, summary,description, NULL, \
26        validate, set, NULL, get, NULL, NULL }
27
28#define OWLVAR_PATH(name,default,summary,description) \
29        { name, OWL_VARIABLE_STRING, default, 0, "<path>", summary,description,  NULL, \
30        NULL, NULL, NULL, NULL, NULL, NULL }
31
32#define OWLVAR_STRING(name,default,summary,description) \
33        { name, OWL_VARIABLE_STRING, default, 0, "<string>", summary,description, NULL, \
34        NULL, NULL, NULL, NULL, NULL, NULL }
35
36#define OWLVAR_STRING_FULL(name,default,summary,description,validate,set,get) \
37        { name, OWL_VARIABLE_STRING, default, 0, "<string>", summary,description, NULL, \
38        validate, set, NULL, get, NULL, NULL }
39
40/* enums are really integers, but where validset is a comma-separated
41 * list of strings which can be specified.  The tokens, starting at 0,
42 * correspond to the values that may be specified. */
43#define OWLVAR_ENUM(name,default,summary,description,validset) \
44        { name, OWL_VARIABLE_INT, NULL, default, validset, summary,description, NULL, \
45        owl_variable_enum_validate, \
46        NULL, owl_variable_enum_set_fromstring, \
47        NULL, owl_variable_enum_get_tostring, \
48        NULL }
49
50#define OWLVAR_ENUM_FULL(name,default,summary,description,validset,validate, set, get) \
51        { name, OWL_VARIABLE_INT, NULL, default, validset, summary,description, NULL, \
52        validate, \
53        set, owl_variable_enum_set_fromstring, \
54        get, owl_variable_enum_get_tostring, \
55        NULL }
56
57static owl_variable variables_to_init[] = {
58
59  OWLVAR_STRING( "personalbell" /* %OwlVarStub */, "off",
60                 "ring the terminal bell when personal messages are received",
61                 "Can be set to 'on', 'off', or the name of a filter which\n"
62                 "messages need to match in order to ring the bell"),
63
64  OWLVAR_BOOL( "bell" /* %OwlVarStub */, 1,
65               "enable / disable the terminal bell", "" ),
66
67  OWLVAR_BOOL_FULL( "debug" /* %OwlVarStub */, OWL_DEBUG,
68                    "whether debugging is enabled",
69                    "If set to 'on', debugging messages are logged to the\n"
70                    "file specified by the debugfile variable.\n",
71                    NULL, owl_variable_debug_set, NULL),
72
73  OWLVAR_BOOL( "startuplogin" /* %OwlVarStub */, 1,
74               "send a login message when owl starts", "" ),
75
76  OWLVAR_BOOL( "shutdownlogout" /* %OwlVarStub */, 1,
77               "send a logout message when owl exits", "" ),
78
79  OWLVAR_BOOL( "rxping" /* %OwlVarStub */, 0,
80               "display received pings", "" ),
81
82  OWLVAR_BOOL( "txping" /* %OwlVarStub */, 1,
83               "send pings", "" ),
84
85  OWLVAR_BOOL( "sepbar_disable" /* %OwlVarStub */, 0,
86               "disable printing information in the seperator bar", "" ),
87
88  OWLVAR_BOOL( "smartstrip" /* %OwlVarStub */, 1,
89               "strip kerberos instance for reply", ""),
90
91  OWLVAR_BOOL( "newlinestrip" /* %OwlVarStub */, 1,
92               "strip leading and trailing newlines", ""),
93
94  OWLVAR_BOOL( "displayoutgoing" /* %OwlVarStub */, 1,
95               "display outgoing messages", "" ),
96
97  OWLVAR_BOOL( "loginsubs" /* %OwlVarStub */, 1,
98               "load logins from .anyone on startup", "" ),
99
100  OWLVAR_BOOL( "logging" /* %OwlVarStub */, 0,
101               "turn personal logging on or off", 
102               "If this is set to on, personal messages are\n"
103               "logged in the directory specified\n"
104               "by the 'logpath' variable.  The filename in that\n"
105               "directory is derived from the sender of the message.\n" ),
106
107  OWLVAR_BOOL( "classlogging" /* %OwlVarStub */, 0,
108               "turn class logging on or off",
109               "If this is set to on, class messages are\n"
110               "logged in the directory specified\n"
111               "by the 'classlogpath' variable.\n" 
112               "The filename in that directory is derived from\n"
113               "the name of the class to which the message was sent.\n" ),
114
115  OWLVAR_ENUM( "loggingdirection" /* %OwlVarStub */, OWL_LOGGING_DIRECTION_BOTH,
116               "specifices which kind of messages should be logged",
117               "Can be one of 'both', 'in', or 'out'.  If 'in' is\n"
118               "selected, only incoming messages are logged, if 'out'\n"
119               "is selected only outgoing messages are logged.  If 'both'\n"
120               "is selected both incoming and outgoing messages are\n"
121               "logged.",
122               "both,in,out"),
123
124  OWLVAR_BOOL( "colorztext" /* %OwlVarStub */, 1,
125               "allow @color() in zephyrs to change color",
126               "Note that only messages received after this variable\n"
127               "is set will be affected." ),
128
129  OWLVAR_BOOL( "fancylines" /* %OwlVarStub */, 1,
130               "Use 'nice' line drawing on the terminal.",
131               "If turned off, dashes, pipes and pluses will be used\n"
132               "to draw lines on the screen.  Useful when the terminal\n"
133               "is causing problems" ),
134
135  OWLVAR_BOOL( "zcrypt" /* %OwlVarStub */, 1,
136               "Do automatic zcrypt processing",
137               "" ),
138
139  OWLVAR_BOOL_FULL( "pseudologins" /* %OwlVarStub */, 0,
140                    "Enable zephyr pseudo logins",
141                    "When this is enabled, Owl will periodically check the zephyr\n"
142                    "location of users in your .anyone file.  If a user is present\n"
143                    "but sent no login message, or a user is not present that sent no\n"
144                    "logout message a pseudo login or logout message wil be created\n",
145                    NULL, owl_variable_pseudologins_set, NULL),
146
147  OWLVAR_BOOL( "ignorelogins" /* %OwlVarStub */, 0,
148               "Enable printing of login notifications",
149               "When this is enabled, Owl will print login and logout notifications\n"
150               "for AIM, zephyr, or other protocols.  If disabled Owl will not print\n"
151               "login or logout notifications.\n"),
152
153  OWLVAR_STRING( "logfilter" /* %OwlVarStub */, "",
154                 "name of a filter controlling which messages to log",
155
156                 "If non empty, any messages matching the given filter will be logged.\n"
157                 "This is a completely separate mechanisim from the other logging\n"
158                 "variables like logging, classlogging, loglogins, loggingdirection,\n"
159                 "etc.  If you want this variable to control all logging, make sure\n"
160                 "all other logging variables are in their default state.\n"),
161
162  OWLVAR_BOOL( "loglogins" /* %OwlVarStub */, 0,
163               "Enable logging of login notifications",
164               "When this is enabled, Owl will login login and logout notifications\n"
165               "for AIM, zephyr, or other protocols.  If disabled Owl will not print\n"
166               "login or logout notifications.\n"),
167
168  OWLVAR_ENUM_FULL( "disable-ctrl-d" /* %OwlVarStub:lockout_ctrld */, 1,
169                    "don't send zephyrs on C-d",
170                    "If set to 'off', C-d won't send a zephyr from the edit\n"
171                    "window.  If set to 'on', C-d will always send a zephyr\n"
172                    "being composed in the edit window.  If set to 'middle',\n"
173                    "C-d will only ever send a zephyr if the cursor is at\n"
174                    "the end of the message being composed.\n\n"
175                    "Note that this works by changing the C-d keybinding\n"
176                    "in the editmulti keymap.\n",
177                    "off,middle,on",
178                    NULL, owl_variable_disable_ctrl_d_set, NULL),
179
180  OWLVAR_BOOL( "_burningears" /* %OwlVarStub:burningears */, 0,
181               "[NOT YET IMPLEMENTED] beep on messages matching patterns", "" ),
182
183  OWLVAR_BOOL( "_summarymode" /* %OwlVarStub:summarymode */, 0,
184               "[NOT YET IMPLEMENTED]", "" ),
185
186  OWLVAR_PATH( "logpath" /* %OwlVarStub */, "~/zlog/people",
187               "path for logging personal zephyrs", 
188               "Specifies a directory which must exist.\n"
189               "Files will be created in the directory for each sender.\n"),
190
191  OWLVAR_PATH( "classlogpath" /* %OwlVarStub:classlogpath */, "~/zlog/class",
192               "path for logging class zephyrs",
193               "Specifies a directory which must exist.\n"
194               "Files will be created in the directory for each class.\n"),
195
196  OWLVAR_PATH( "debug_file" /* %OwlVarStub */, OWL_DEBUG_FILE,
197               "path for logging debug messages when debugging is enabled",
198               "This file will be logged to if 'debug' is set to 'on'.\n"),
199 
200  OWLVAR_PATH( "zsigproc" /* %OwlVarStub:zsigproc */, NULL,
201               "name of a program to run that will generate zsigs",
202               "This program should produce a zsig on stdout when run.\n"
203               "Note that it is important that this program not block.\n" ),
204
205  OWLVAR_PATH( "newmsgproc" /* %OwlVarStub:newmsgproc */, NULL,
206               "name of a program to run when new messages are present",
207               "The named program will be run when owl recevies new.\n"
208               "messages.  It will not be run again until the first\n"
209               "instance exits"),
210
211  OWLVAR_STRING( "zsig" /* %OwlVarStub */, "",
212                 "zephyr signature", 
213                 "If 'zsigproc' is not set, this string will be used\n"
214                 "as a zsig.  If this is also unset, the 'zwrite-signature'\n"
215                 "zephyr variable will be used instead.\n"),
216
217  OWLVAR_STRING( "appendtosepbar" /* %OwlVarStub */, "",
218                 "string to append to the end of the sepbar",
219                 "The sepbar is the bar separating the top and bottom\n"
220                 "of the owl screen.  Any string specified here will\n"
221                 "be displayed on the right of the sepbar\n"),
222
223  OWLVAR_BOOL( "zaway" /* %OwlVarStub */, 0,
224               "turn zaway on or off", "" ),
225
226  OWLVAR_STRING( "zaway_msg" /* %OwlVarStub */, 
227                 OWL_DEFAULT_ZAWAYMSG,
228                 "zaway msg for responding to zephyrs when away", "" ),
229
230  OWLVAR_STRING( "zaway_msg_default" /* %OwlVarStub */, 
231                 OWL_DEFAULT_ZAWAYMSG,
232                 "default zaway message", "" ),
233
234  OWLVAR_BOOL_FULL( "aaway" /* %OwlVarStub */, 0,
235                    "Set AIM away status",
236                    "",
237                    NULL, owl_variable_aaway_set, NULL),
238
239  OWLVAR_STRING( "aaway_msg" /* %OwlVarStub */, 
240                 OWL_DEFAULT_AAWAYMSG,
241                 "AIM away msg for responding when away", "" ),
242
243  OWLVAR_STRING( "aaway_msg_default" /* %OwlVarStub */, 
244                 OWL_DEFAULT_AAWAYMSG,
245                 "default AIM away message", "" ),
246
247  OWLVAR_STRING( "view_home" /* %OwlVarStub */, "all",
248                 "home view to switch to after 'X' and 'V'", 
249                 "SEE ALSO: view, filter\n" ),
250
251  OWLVAR_STRING( "alert_filter" /* %OwlVarStub */, "none",
252                 "filter on which to trigger alert actions",
253                 "" ),
254
255  OWLVAR_STRING( "alert_action" /* %OwlVarStub */, "nop",
256                 "owl command to execute for alert actions",
257                 "" ),
258
259  OWLVAR_STRING_FULL( "tty" /* %OwlVarStub */, "", "tty name for zephyr location", "",
260                      NULL, owl_variable_tty_set, NULL),
261
262  OWLVAR_STRING( "default_style" /* %OwlVarStub */, "__unspecified__",
263                 "name of the default formatting style",
264                 "This sets the default message formatting style.\n"
265                 "Styles may be created with the 'style' command.\n"
266                 "Some built-in styles include:\n"
267                 "   default  - the default owl formatting\n"
268                 "   basic    - simple formatting\n"
269                 "   oneline  - one line per-message\n"
270                 "   perl     - legacy perl interface\n"
271                 "\nSEE ALSO: style, show styles, view -s <style>\n"
272                 ),
273
274
275  OWLVAR_INT(    "edit:maxfillcols" /* %OwlVarStub:edit_maxfillcols */, 70,
276                 "maximum number of columns for M-q to fill text to",
277                 "This specifies the maximum number of columns for M-q\n"
278                 "to fill text to.  If set to 0, ther will be no maximum\n"
279                 "limit.  In all cases, the current width of the screen\n"
280                 "will also be taken into account.  It will be used instead\n"
281                 "if it is narrower than the maximum, or if this\n"
282                 "is set to 0.\n" ),
283
284  OWLVAR_INT(    "edit:maxwrapcols" /* %OwlVarStub:edit_maxwrapcols */, 0,
285                 "maximum number of columns for line-wrapping",
286                 "This specifies the maximum number of columns for\n"
287                 "auto-line-wrapping.  If set to 0, ther will be no maximum\n"
288                 "limit.  In all cases, the current width of the screen\n"
289                 "will also be taken into account.  It will be used instead\n"
290                 "if it is narrower than the maximum, or if this\n"
291                 "is set to 0.\n\n"
292                 "It is recommended that outgoing messages be no wider\n"
293                 "than 60 columns, as a courtesy to recipients.\n"),
294
295  OWLVAR_INT( "aim_ignorelogin_timer" /* %OwlVarStub */, 15,
296              "number of seconds after AIM login to ignore login messages",
297              "This specifies the number of seconds to wait after an\n"
298              "AIM login before allowing the recipt of AIM login notifications.\n"
299              "By default this is set to 15.  If you would like to view login\n"
300              "notifications of buddies as soon as you login, set it to 0 instead."),
301
302             
303  OWLVAR_INT_FULL( "typewinsize" /* %OwlVarStub:typwin_lines */, 
304                   OWL_TYPWIN_SIZE,
305                  "number of lines in the typing window", 
306                   "This specifies the height of the window at the\n"
307                   "bottom of the screen where commands are entered\n"
308                   "and where messages are composed.\n",
309                   "int > 0",
310                   owl_variable_int_validate_gt0,
311                   owl_variable_typewinsize_set,
312                   NULL /* use default for get */
313                   ),
314
315  OWLVAR_ENUM( "scrollmode" /* %OwlVarStub */, OWL_SCROLLMODE_NORMAL,
316               "how to scroll up and down",
317               "This controls how the screen is scrolled as the\n"
318               "cursor moves between messages being displayed.\n"
319               "The following modes are supported:\n\n"
320               "   normal      - This is the owl default.  Scrolling happens\n"
321               "                 when it needs to, and an attempt is made to\n"
322               "                 keep the current message roughly near\n"
323               "                 the middle of the screen.\n"
324               "   top         - The current message will always be the\n"
325               "                 the top message displayed.\n"
326               "   neartop     - The current message will be one down\n"
327               "                 from the top message displayed,\n"
328               "                 where possible.\n"
329               "   center      - An attempt is made to keep the current\n"
330               "                 message near the center of the screen.\n"
331               "   paged       - The top message displayed only changes\n"
332               "                 when user moves the cursor to the top\n"
333               "                 or bottom of the screen.  When it moves,\n"
334               "                 the screen will be paged up or down and\n"
335               "                 the cursor will be near the top or\n"
336               "                 the bottom.\n"
337               "   pagedcenter - The top message displayed only changes\n"
338               "                 when user moves the cursor to the top\n"
339               "                 or bottom of the screen.  When it moves,\n"
340               "                 the screen will be paged up or down and\n"
341               "                 the cursor will be near the center.\n",
342               "normal,top,neartop,center,paged,pagedcenter" ),
343
344  OWLVAR_ENUM( "webbrowser" /* %OwlVarStub */, OWL_WEBBROWSER_NETSCAPE,
345               "web browser to use to launch URLs",
346               "When the 'w' key is pressed, this browser is used\n"
347               "to display the requested URL.\n",
348               "none,netscape,galeon,opera" ),
349
350
351  OWLVAR_BOOL( "_followlast" /* %OwlVarStub */, 0,
352               "enable automatic following of the last zephyr",
353               "If the cursor is at the last message, it will\n"
354               "continue to follow the last message if this is set.\n"
355               "Note that this is currently risky as you might accidentally\n"
356               "delete a message right as it came in.\n" ),
357
358  /* This MUST be last... */
359  { NULL, 0, NULL, 0, NULL, NULL, NULL, NULL,
360    NULL, NULL, NULL, NULL, NULL, NULL }
361
362};
363
364/**************************************************************************/
365/*********************** SPECIFIC TO VARIABLES ****************************/
366/**************************************************************************/
367
368
369/* commonly useful */
370
371int owl_variable_int_validate_gt0(owl_variable *v, void *newval)
372{
373  if (newval == NULL) return(0);
374  else if (*(int*)newval < 1) return(0);
375  else return (1);
376}
377
378int owl_variable_int_validate_positive(owl_variable *v, void *newval)
379{
380  if (newval == NULL) return(0);
381  else if (*(int*)newval < 0) return(0);
382  else return (1);
383}
384
385/* typewinsize */
386int owl_variable_typewinsize_set(owl_variable *v, void *newval)
387{
388  int rv;
389  rv = owl_variable_int_set_default(v, newval);
390  if (0 == rv) owl_function_resize();
391  return(rv);
392}
393
394/* debug (cache value in g->debug) */
395int owl_variable_debug_set(owl_variable *v, void *newval)
396{
397  if (newval && (*(int*)newval == 1 || *(int*)newval == 0)) {
398    g.debug = *(int*)newval;
399  }
400  return owl_variable_bool_set_default(v, newval);
401}
402
403/* When 'aaway' is changed, need to notify the AIM server */
404int owl_variable_aaway_set(owl_variable *v, void *newval)
405{
406  if (newval) {
407    if (*(int*)newval == 1) {
408      owl_aim_set_awaymsg(owl_global_get_aaway_msg(&g));
409    } else if (*(int*)newval == 0) {
410      owl_aim_set_awaymsg("");
411    }
412  }
413  return owl_variable_bool_set_default(v, newval);
414}
415
416int owl_variable_pseudologins_set(owl_variable *v, void *newval)
417{
418  if (newval) {
419    if (*(int*)newval == 1) {
420      owl_function_zephyr_buddy_check(0);
421    }
422  }
423  return owl_variable_bool_set_default(v, newval);
424}
425
426/* note that changing the value of this will clobber
427 * any user setting of this */
428int owl_variable_disable_ctrl_d_set(owl_variable *v, void *newval)
429{
430
431  if (in_regtest) return owl_variable_int_set_default(v, newval);
432
433  if (newval && !owl_context_is_startup(owl_global_get_context(&g))) {
434    if (*(int*)newval == 2) {
435      owl_function_command_norv("bindkey editmulti C-d command edit:delete-next-char");
436    } else if (*(int*)newval == 1) {
437      owl_function_command_norv("bindkey editmulti C-d command editmulti:done-or-delete");
438    } else {
439      owl_function_command_norv("bindkey editmulti C-d command editmulti:done");
440    }
441  } 
442  return owl_variable_int_set_default(v, newval); 
443}
444
445int owl_variable_tty_set(owl_variable *v, void *newval)
446{
447  owl_zephyr_set_locationinfo(owl_global_get_hostname(&g), newval);
448  return(owl_variable_string_set_default(v, newval));
449}
450
451
452/**************************************************************************/
453/****************************** GENERAL ***********************************/
454/**************************************************************************/
455
456int owl_variable_dict_setup(owl_vardict *vd) {
457  owl_variable *var, *cur;
458  if (owl_dict_create(vd)) return(-1);
459  for (var = variables_to_init; var->name != NULL; var++) {
460    cur = owl_malloc(sizeof(owl_variable));
461    memcpy(cur, var, sizeof(owl_variable));
462    switch (cur->type) {
463    case OWL_VARIABLE_OTHER:
464      cur->set_fn(cur, cur->pval_default);
465      break;
466    case OWL_VARIABLE_STRING:
467      if (!cur->validate_fn) 
468        cur->validate_fn = owl_variable_string_validate_default;
469      if (!cur->set_fn) 
470        cur->set_fn = owl_variable_string_set_default;
471      if (!cur->set_fromstring_fn) 
472        cur->set_fromstring_fn = owl_variable_string_set_fromstring_default;
473      if (!cur->get_fn) 
474        cur->get_fn = owl_variable_get_default;
475      if (!cur->get_tostring_fn) 
476        cur->get_tostring_fn = owl_variable_string_get_tostring_default;     
477      if (!cur->free_fn) 
478        cur->free_fn = owl_variable_free_default;
479      cur->set_fn(cur, cur->pval_default);
480      break;
481    case OWL_VARIABLE_BOOL:
482      if (!cur->validate_fn) 
483        cur->validate_fn = owl_variable_bool_validate_default;
484      if (!cur->set_fn) 
485        cur->set_fn = owl_variable_bool_set_default;
486      if (!cur->set_fromstring_fn) 
487        cur->set_fromstring_fn = owl_variable_bool_set_fromstring_default;
488      if (!cur->get_fn) 
489        cur->get_fn = owl_variable_get_default;
490      if (!cur->get_tostring_fn) 
491        cur->get_tostring_fn = owl_variable_bool_get_tostring_default;     
492      if (!cur->free_fn) 
493        cur->free_fn = owl_variable_free_default;
494      cur->val = owl_malloc(sizeof(int));
495      cur->set_fn(cur, &cur->ival_default);
496      break;
497    case OWL_VARIABLE_INT:
498      if (!cur->validate_fn) 
499        cur->validate_fn = owl_variable_int_validate_default;
500      if (!cur->set_fn) 
501        cur->set_fn = owl_variable_int_set_default;
502      if (!cur->set_fromstring_fn) 
503        cur->set_fromstring_fn = owl_variable_int_set_fromstring_default;
504      if (!cur->get_fn) 
505        cur->get_fn = owl_variable_get_default;
506      if (!cur->get_tostring_fn) 
507        cur->get_tostring_fn = owl_variable_int_get_tostring_default;     
508      if (!cur->free_fn) 
509        cur->free_fn = owl_variable_free_default;
510      cur->val = owl_malloc(sizeof(int));
511      cur->set_fn(cur, &cur->ival_default);
512      break;
513    default:
514      fprintf(stderr, "owl_variable_setup: invalid variable type\n");
515      return(-2);
516    }
517    owl_dict_insert_element(vd, cur->name, (void*)cur, NULL);
518  }
519  return 0;
520}
521
522void owl_variable_dict_add_variable(owl_vardict * vardict,
523                                    owl_variable * var) {
524  owl_dict_insert_element(vardict, var->name, (void*)var, (void(*)(void*))owl_variable_free);
525}
526
527owl_variable * owl_variable_newvar(char *name, char *summary, char * description) {
528  owl_variable * var = (owl_variable*)owl_malloc(sizeof(owl_variable));
529  memset(var, 0, sizeof(owl_variable));
530  var->name = owl_strdup(name);
531  var->summary = owl_strdup(summary);
532  var->description = owl_strdup(description);
533  return var;
534}
535
536void owl_variable_update(owl_variable *var, char *summary, char *desc) {
537  if(var->summary) owl_free(var->summary);
538  var->summary = owl_strdup(summary);
539  if(var->description) owl_free(var->description);
540  var->description = owl_strdup(desc);
541}
542
543void owl_variable_dict_newvar_string(owl_vardict * vd, char *name, char *summ, char * desc, char * initval) {
544  owl_variable *old = owl_variable_get_var(vd, name, OWL_VARIABLE_STRING);
545  if(old) {
546    owl_variable_update(old, summ, desc);
547    if(old->pval_default) owl_free(old->pval_default);
548    old->pval_default = owl_strdup(initval);
549  } else {
550    owl_variable * var = owl_variable_newvar(name, summ, desc);
551    var->type = OWL_VARIABLE_STRING;
552    var->pval_default = owl_strdup(initval);
553    var->set_fn = owl_variable_string_set_default;
554    var->set_fromstring_fn = owl_variable_string_set_fromstring_default;
555    var->get_fn = owl_variable_get_default;
556    var->get_tostring_fn = owl_variable_string_get_tostring_default;
557    var->free_fn = owl_variable_free_default;
558    var->set_fn(var, initval);
559    owl_variable_dict_add_variable(vd, var);
560  }
561}
562
563void owl_variable_dict_newvar_int(owl_vardict * vd, char *name, char *summ, char * desc, int initval) {
564  owl_variable *old = owl_variable_get_var(vd, name, OWL_VARIABLE_INT);
565  if(old) {
566    owl_variable_update(old, summ, desc);
567    old->ival_default = initval;
568  } else {
569    owl_variable * var = owl_variable_newvar(name, summ, desc);
570    var->type = OWL_VARIABLE_INT;
571    var->ival_default = initval;
572    var->validate_fn = owl_variable_int_validate_default;
573    var->set_fn = owl_variable_int_set_default;
574    var->set_fromstring_fn = owl_variable_int_set_fromstring_default;
575    var->get_fn = owl_variable_get_default;
576    var->get_tostring_fn = owl_variable_int_get_tostring_default;
577    var->free_fn = owl_variable_free_default;
578    var->val = owl_malloc(sizeof(int));
579    var->set_fn(var, &initval);
580    owl_variable_dict_add_variable(vd, var);
581  }
582}
583
584void owl_variable_dict_newvar_bool(owl_vardict * vd, char *name, char *summ, char * desc, int initval) {
585  owl_variable *old = owl_variable_get_var(vd, name, OWL_VARIABLE_BOOL);
586  if(old) {
587    owl_variable_update(old, summ, desc);
588    old->ival_default = initval;
589  } else {
590    owl_variable * var = owl_variable_newvar(name, summ, desc);
591    var->type = OWL_VARIABLE_BOOL;
592    var->ival_default = initval;
593    var->validate_fn = owl_variable_bool_validate_default;
594    var->set_fn = owl_variable_bool_set_default;
595    var->set_fromstring_fn = owl_variable_bool_set_fromstring_default;
596    var->get_fn = owl_variable_get_default;
597    var->get_tostring_fn = owl_variable_bool_get_tostring_default;
598    var->free_fn = owl_variable_free_default;
599    var->val = owl_malloc(sizeof(int));
600    var->set_fn(var, &initval);
601    owl_variable_dict_add_variable(vd, var);
602  }
603}
604
605void owl_variable_dict_free(owl_vardict *d) {
606  owl_dict_free_all(d, (void(*)(void*))owl_variable_free);
607}
608
609/* free the list with owl_variable_dict_namelist_free */
610void owl_variable_dict_get_names(owl_vardict *d, owl_list *l) {
611  owl_dict_get_keys(d, l);
612}
613
614void owl_variable_dict_namelist_free(owl_list *l) {
615  owl_list_free_all(l, owl_free);
616}
617
618void owl_variable_free(owl_variable *v) {
619  if (v->free_fn) v->free_fn(v);
620  owl_free(v);
621}
622
623
624char *owl_variable_get_description(owl_variable *v) {
625  return v->description;
626}
627
628char *owl_variable_get_summary(owl_variable *v) {
629  return v->summary;
630}
631
632char *owl_variable_get_validsettings(owl_variable *v) {
633  if (v->validsettings) {
634    return v->validsettings;
635  } else {
636    return "";
637  }
638}
639
640/* functions for getting and setting variable values */
641
642/* returns 0 on success, prints a status msg if msg is true */
643int owl_variable_set_fromstring(owl_vardict *d, char *name, char *value, int msg, int requirebool) {
644  owl_variable *v;
645  char buff2[1024];
646  if (!name) return(-1);
647  v = owl_dict_find_element(d, name);
648  if (v == NULL) {
649    if (msg) owl_function_error("Unknown variable %s", name);
650    return -1;
651  }
652  if (!v->set_fromstring_fn) {
653    if (msg) owl_function_error("Variable %s is read-only", name);
654    return -1;   
655  }
656  if (requirebool && v->type!=OWL_VARIABLE_BOOL) {
657    if (msg) owl_function_error("Variable %s is not a boolean", name);
658    return -1;   
659  }
660  if (0 != v->set_fromstring_fn(v, value)) {
661    if (msg) owl_function_error("Unable to set %s (must be %s)", name, 
662                                  owl_variable_get_validsettings(v));
663    return -1;
664  }
665  if (msg && v->get_tostring_fn) {
666    v->get_tostring_fn(v, buff2, 1024, v->val);
667    owl_function_makemsg("%s = '%s'", name, buff2);
668  }   
669  return 0;
670}
671 
672int owl_variable_set_string(owl_vardict *d, char *name, char *newval) {
673  owl_variable *v;
674  if (!name) return(-1);
675  v = owl_dict_find_element(d, name);
676  if (v == NULL || !v->set_fn) return(-1);
677  if (v->type!=OWL_VARIABLE_STRING) return(-1);
678  return v->set_fn(v, (void*)newval);
679}
680 
681int owl_variable_set_int(owl_vardict *d, char *name, int newval) {
682  owl_variable *v;
683  if (!name) return(-1);
684  v = owl_dict_find_element(d, name);
685  if (v == NULL || !v->set_fn) return(-1);
686  if (v->type!=OWL_VARIABLE_INT && v->type!=OWL_VARIABLE_BOOL) return(-1);
687  return v->set_fn(v, &newval);
688}
689 
690int owl_variable_set_bool_on(owl_vardict *d, char *name) {
691  return owl_variable_set_int(d,name,1);
692}
693
694int owl_variable_set_bool_off(owl_vardict *d, char *name) {
695  return owl_variable_set_int(d,name,0);
696}
697
698int owl_variable_get_tostring(owl_vardict *d, char *name, char *buf, int bufsize) {
699  owl_variable *v;
700  if (!name) return(-1);
701  v = owl_dict_find_element(d, name);
702  if (v == NULL || !v->get_tostring_fn) return(-1);
703  return v->get_tostring_fn(v, buf, bufsize, v->val);
704}
705
706int owl_variable_get_default_tostring(owl_vardict *d, char *name, char *buf, int bufsize) {
707  owl_variable *v;
708  if (!name) return(-1);
709  v = owl_dict_find_element(d, name);
710  if (v == NULL || !v->get_tostring_fn) return(-1);
711  if (v->type == OWL_VARIABLE_INT || v->type == OWL_VARIABLE_BOOL) {
712    return v->get_tostring_fn(v, buf, bufsize, &(v->ival_default));
713  } else {
714    return v->get_tostring_fn(v, buf, bufsize, v->pval_default);
715  }
716}
717
718owl_variable *owl_variable_get_var(owl_vardict *d, char *name, int require_type) {
719  owl_variable *v;
720  if (!name) return(NULL);
721  v = owl_dict_find_element(d, name);
722  if (v == NULL || !v->get_fn || v->type != require_type) return(NULL);
723  return v;
724}
725
726/* returns a reference */
727void *owl_variable_get(owl_vardict *d, char *name, int require_type) {
728  owl_variable *v = owl_variable_get_var(d, name, require_type);
729  if(v == NULL) return NULL;
730  return v->get_fn(v);
731}
732
733/* returns a reference */
734char *owl_variable_get_string(owl_vardict *d, char *name) {
735  return (char*)owl_variable_get(d,name, OWL_VARIABLE_STRING);
736}
737
738/* returns a reference */
739void *owl_variable_get_other(owl_vardict *d, char *name) {
740  return (char*)owl_variable_get(d,name, OWL_VARIABLE_OTHER);
741}
742
743int owl_variable_get_int(owl_vardict *d, char *name) {
744  int *pi;
745  pi = (int*)owl_variable_get(d,name,OWL_VARIABLE_INT);
746  if (!pi) return(-1);
747  return(*pi);
748}
749
750int owl_variable_get_bool(owl_vardict *d, char *name) {
751  int *pi;
752  pi = (int*)owl_variable_get(d,name,OWL_VARIABLE_BOOL);
753  if (!pi) return(-1);
754  return(*pi);
755}
756
757void owl_variable_describe(owl_vardict *d, char *name, owl_fmtext *fm) {
758  char defaultbuf[50];
759  char buf[1024];
760  int buflen = 1023;
761  owl_variable *v;
762
763  if (!name
764      || (v = owl_dict_find_element(d, name)) == NULL 
765      || !v->get_fn) {
766    snprintf(buf, buflen, "     No such variable '%s'\n", name);     
767    owl_fmtext_append_normal(fm, buf);
768    return;
769  }
770  if (v->type == OWL_VARIABLE_INT || v->type == OWL_VARIABLE_BOOL) {
771    v->get_tostring_fn(v, defaultbuf, 50, &(v->ival_default));
772  } else {
773    v->get_tostring_fn(v, defaultbuf, 50, v->pval_default);
774  }
775  snprintf(buf, buflen, OWL_TABSTR "%-20s - %s (default: '%s')\n", 
776                  v->name, 
777                  owl_variable_get_summary(v), defaultbuf);
778  owl_fmtext_append_normal(fm, buf);
779}
780
781void owl_variable_get_help(owl_vardict *d, char *name, owl_fmtext *fm) {
782  char buff[1024];
783  int bufflen = 1023;
784  owl_variable *v;
785
786  if (!name
787      || (v = owl_dict_find_element(d, name)) == NULL 
788      || !v->get_fn) {
789    owl_fmtext_append_normal(fm, "No such variable...\n");
790    return;
791  }
792
793  owl_fmtext_append_bold(fm, "OWL VARIABLE\n\n");
794  owl_fmtext_append_normal(fm, OWL_TABSTR);
795  owl_fmtext_append_normal(fm, name);
796  owl_fmtext_append_normal(fm, " - ");
797  owl_fmtext_append_normal(fm, v->summary);
798  owl_fmtext_append_normal(fm, "\n\n");
799
800  owl_fmtext_append_normal(fm, "Current:        ");
801  owl_variable_get_tostring(d, name, buff, bufflen);
802  owl_fmtext_append_normal(fm, buff);
803  owl_fmtext_append_normal(fm, "\n\n");
804
805
806  if (v->type == OWL_VARIABLE_INT || v->type == OWL_VARIABLE_BOOL) {
807    v->get_tostring_fn(v, buff, bufflen, &(v->ival_default));
808  } else {
809    v->get_tostring_fn(v, buff, bufflen, v->pval_default);
810  }
811  owl_fmtext_append_normal(fm, "Default:        ");
812  owl_fmtext_append_normal(fm, buff);
813  owl_fmtext_append_normal(fm, "\n\n");
814
815  owl_fmtext_append_normal(fm, "Valid Settings: ");
816  owl_fmtext_append_normal(fm, owl_variable_get_validsettings(v));
817  owl_fmtext_append_normal(fm, "\n\n");
818
819  if (v->description && *v->description) {
820    owl_fmtext_append_normal(fm, "Description:\n");
821    owl_fmtext_append_normal(fm, owl_variable_get_description(v));
822    owl_fmtext_append_normal(fm, "\n\n");
823  }
824}
825
826
827
828
829/**************************************************************************/
830/*********************** GENERAL TYPE-SPECIFIC ****************************/
831/**************************************************************************/
832
833/* default common functions */
834
835void *owl_variable_get_default(owl_variable *v) {
836  return v->val;
837}
838
839void owl_variable_free_default(owl_variable *v) {
840  if (v->val) owl_free(v->val);
841}
842
843/* default functions for booleans */
844
845int owl_variable_bool_validate_default(owl_variable *v, void *newval) {
846  if (newval == NULL) return(0);
847  else if (*(int*)newval==1 || *(int*)newval==0) return(1);
848  else return (0);
849}
850
851int owl_variable_bool_set_default(owl_variable *v, void *newval) {
852  if (v->validate_fn) {
853    if (!v->validate_fn(v, newval)) return(-1);
854  }
855  *(int*)v->val = *(int*)newval;
856  return(0);
857}
858
859int owl_variable_bool_set_fromstring_default(owl_variable *v, char *newval) {
860  int i;
861  if (!strcmp(newval, "on")) i=1;
862  else if (!strcmp(newval, "off")) i=0;
863  else return(-1);
864  return (v->set_fn(v, &i));
865}
866
867int owl_variable_bool_get_tostring_default(owl_variable *v, char* buf, int bufsize, void *val) {
868  if (val == NULL) {
869    snprintf(buf, bufsize, "<null>");
870    return -1;
871  } else if (*(int*)val == 0) {
872    snprintf(buf, bufsize, "off");
873    return 0;
874  } else if (*(int*)val == 1) {
875    snprintf(buf, bufsize, "on");
876    return 0;
877  } else {
878    snprintf(buf, bufsize, "<invalid>");
879    return -1;
880  }
881}
882
883/* default functions for integers */
884
885int owl_variable_int_validate_default(owl_variable *v, void *newval) {
886  if (newval == NULL) return(0);
887  else return (1);
888}
889
890int owl_variable_int_set_default(owl_variable *v, void *newval) {
891  if (v->validate_fn) {
892    if (!v->validate_fn(v, newval)) return(-1);
893  }
894  *(int*)v->val = *(int*)newval;
895  return(0);
896}
897
898int owl_variable_int_set_fromstring_default(owl_variable *v, char *newval) {
899  int i;
900  char *ep = "x";
901  i = strtol(newval, &ep, 10);
902  if (*ep || ep==newval) return(-1);
903  return (v->set_fn(v, &i));
904}
905
906int owl_variable_int_get_tostring_default(owl_variable *v, char* buf, int bufsize, void *val) {
907  if (val == NULL) {
908    snprintf(buf, bufsize, "<null>");
909    return -1;
910  } else {
911    snprintf(buf, bufsize, "%d", *(int*)val);
912    return 0;
913  } 
914}
915
916/* default functions for enums (a variant of integers) */
917
918int owl_variable_enum_validate(owl_variable *v, void *newval) { 
919  char **enums;
920  int nenums, val;
921  if (newval == NULL) return(0);
922  enums = atokenize(v->validsettings, ",", &nenums);
923  if (enums == NULL) return(0);
924  atokenize_free(enums, nenums);
925  val = *(int*)newval;
926  if (val < 0 || val >= nenums) {
927    return(0);
928  }
929  return(1);
930}
931
932int owl_variable_enum_set_fromstring(owl_variable *v, char *newval) {
933  char **enums;
934  int nenums, i, val=-1;
935  if (newval == NULL) return(-1);
936  enums = atokenize(v->validsettings, ",", &nenums);
937  if (enums == NULL) return(-1);
938  for (i=0; i<nenums; i++) {
939    if (0==strcmp(newval, enums[i])) {
940      val = i;
941    }
942  }
943  atokenize_free(enums, nenums);
944  if (val == -1) return(-1);
945  return (v->set_fn(v, &val));
946}
947
948int owl_variable_enum_get_tostring(owl_variable *v, char* buf, int bufsize, void *val) {
949  char **enums;
950  int nenums, i;
951
952  if (val == NULL) {
953    snprintf(buf, bufsize, "<null>");
954    return -1;
955  }
956  enums = atokenize(v->validsettings, ",", &nenums);
957  i = *(int*)val;
958  if (i<0 || i>=nenums) {
959    snprintf(buf, bufsize, "<invalid:%d>",i);
960    atokenize_free(enums, nenums);
961    return(-1);
962  }
963  snprintf(buf, bufsize, "%s", enums[i]);
964  return 0;
965}
966
967/* default functions for stringeans */
968
969int owl_variable_string_validate_default(struct _owl_variable *v, void *newval) {
970  if (newval == NULL) return(0);
971  else return (1);
972}
973
974int owl_variable_string_set_default(owl_variable *v, void *newval) {
975  if (v->validate_fn) {
976    if (!v->validate_fn(v, newval)) return(-1);
977  }
978  if (v->val) owl_free(v->val);
979  v->val = owl_strdup(newval);
980  return(0);
981}
982
983int owl_variable_string_set_fromstring_default(owl_variable *v, char *newval) {
984  return (v->set_fn(v, newval));
985}
986
987int owl_variable_string_get_tostring_default(owl_variable *v, char* buf, int bufsize, void *val) {
988  if (val == NULL) {
989    snprintf(buf, bufsize, "<null>");
990    return -1;
991  } else {
992    snprintf(buf, bufsize, "%s", (char*)val);
993    return 0;
994  }
995}
996
997
998
999/**************************************************************************/
1000/************************* REGRESSION TESTS *******************************/
1001/**************************************************************************/
1002
1003#ifdef OWL_INCLUDE_REG_TESTS
1004
1005#include "test.h"
1006
1007int owl_variable_regtest(void) {
1008  owl_vardict vd;
1009  int numfailed=0;
1010  char buf[1024];
1011  owl_variable * v;
1012
1013  in_regtest = 1;
1014
1015  printf("# BEGIN testing owl_variable\n");
1016  FAIL_UNLESS("setup", 0==owl_variable_dict_setup(&vd));
1017
1018  FAIL_UNLESS("get bool", 0==owl_variable_get_bool(&vd,"rxping"));
1019  FAIL_UNLESS("get bool (no such)", -1==owl_variable_get_bool(&vd,"mumble"));
1020  FAIL_UNLESS("get bool as string 1", 0==owl_variable_get_tostring(&vd,"rxping", buf, 1024));
1021  FAIL_UNLESS("get bool as string 2", 0==strcmp(buf,"off"));
1022  FAIL_UNLESS("set bool 1", 0==owl_variable_set_bool_on(&vd,"rxping"));
1023  FAIL_UNLESS("get bool 2", 1==owl_variable_get_bool(&vd,"rxping"));
1024  FAIL_UNLESS("set bool 3", 0==owl_variable_set_fromstring(&vd,"rxping","off",0,0));
1025  FAIL_UNLESS("get bool 4", 0==owl_variable_get_bool(&vd,"rxping"));
1026  FAIL_UNLESS("set bool 5", -1==owl_variable_set_fromstring(&vd,"rxping","xxx",0,0));
1027  FAIL_UNLESS("get bool 6", 0==owl_variable_get_bool(&vd,"rxping"));
1028
1029
1030  FAIL_UNLESS("get string", 0==strcmp("~/zlog/people", owl_variable_get_string(&vd,"logpath")));
1031  FAIL_UNLESS("set string 7", 0==owl_variable_set_string(&vd,"logpath","whee"));
1032  FAIL_UNLESS("get string", 0==strcmp("whee", owl_variable_get_string(&vd,"logpath")));
1033
1034  FAIL_UNLESS("get int", 8==owl_variable_get_int(&vd,"typewinsize"));
1035  FAIL_UNLESS("get int (no such)", -1==owl_variable_get_int(&vd,"mmble"));
1036  FAIL_UNLESS("get int as string 1", 0==owl_variable_get_tostring(&vd,"typewinsize", buf, 1024));
1037  FAIL_UNLESS("get int as string 2", 0==strcmp(buf,"8"));
1038  FAIL_UNLESS("set int 1", 0==owl_variable_set_int(&vd,"typewinsize",12));
1039  FAIL_UNLESS("get int 2", 12==owl_variable_get_int(&vd,"typewinsize"));
1040  FAIL_UNLESS("set int 1b", -1==owl_variable_set_int(&vd,"typewinsize",-3));
1041  FAIL_UNLESS("get int 2b", 12==owl_variable_get_int(&vd,"typewinsize"));
1042  FAIL_UNLESS("set int 3", 0==owl_variable_set_fromstring(&vd,"typewinsize","9",0,0));
1043  FAIL_UNLESS("get int 4", 9==owl_variable_get_int(&vd,"typewinsize"));
1044  FAIL_UNLESS("set int 5", -1==owl_variable_set_fromstring(&vd,"typewinsize","xxx",0,0));
1045  FAIL_UNLESS("set int 6", -1==owl_variable_set_fromstring(&vd,"typewinsize","",0,0));
1046  FAIL_UNLESS("get int 7", 9==owl_variable_get_int(&vd,"typewinsize"));
1047
1048  FAIL_UNLESS("get enum", OWL_WEBBROWSER_NETSCAPE==owl_variable_get_int(&vd,"webbrowser"));
1049  FAIL_UNLESS("get enum as string 1", 0==owl_variable_get_tostring(&vd,"webbrowser", buf, 1024));
1050  FAIL_UNLESS("get enum as string 2", 0==strcmp(buf,"netscape"));
1051  FAIL_UNLESS("set enum 1", 0==owl_variable_set_int(&vd,"webbrowser",OWL_WEBBROWSER_GALEON));
1052  FAIL_UNLESS("get enum 2", OWL_WEBBROWSER_GALEON==owl_variable_get_int(&vd,"webbrowser"));
1053  FAIL_UNLESS("set enum 1b", -1==owl_variable_set_int(&vd,"webbrowser",-3));
1054  FAIL_UNLESS("set enum 1b", -1==owl_variable_set_int(&vd,"webbrowser",209));
1055  FAIL_UNLESS("get enum 2b", OWL_WEBBROWSER_GALEON==owl_variable_get_int(&vd,"webbrowser"));
1056  FAIL_UNLESS("set enum 3", 0==owl_variable_set_fromstring(&vd,"webbrowser","none",0,0));
1057  FAIL_UNLESS("get enum 4", OWL_WEBBROWSER_NONE==owl_variable_get_int(&vd,"webbrowser"));
1058  FAIL_UNLESS("set enum 5", 0==owl_variable_set_fromstring(&vd,"webbrowser","netscape",0,0));
1059  FAIL_UNLESS("get enum 6", OWL_WEBBROWSER_NETSCAPE==owl_variable_get_int(&vd,"webbrowser"));
1060  FAIL_UNLESS("set enum 7", -1==owl_variable_set_fromstring(&vd,"webbrowser","xxx",0,0));
1061  FAIL_UNLESS("set enum 8", -1==owl_variable_set_fromstring(&vd,"webbrowser","",0,0));
1062  FAIL_UNLESS("set enum 9", -1==owl_variable_set_fromstring(&vd,"webbrowser","netscapey",0,0));
1063  FAIL_UNLESS("get enum 10", OWL_WEBBROWSER_NETSCAPE==owl_variable_get_int(&vd,"webbrowser"));
1064
1065  owl_variable_dict_newvar_string(&vd, "stringvar", "", "", "testval");
1066  FAIL_UNLESS("get new string var", NULL != (v = owl_variable_get(&vd, "stringvar", OWL_VARIABLE_STRING)));
1067  FAIL_UNLESS("get new string val", !strcmp("testval", owl_variable_get_string(&vd, "stringvar")));
1068  owl_variable_set_string(&vd, "stringvar", "new val");
1069  FAIL_UNLESS("update string val", !strcmp("new val", owl_variable_get_string(&vd, "stringvar")));
1070
1071  owl_variable_dict_newvar_int(&vd, "intvar", "", "", 47);
1072  FAIL_UNLESS("get new int var", NULL != (v = owl_variable_get(&vd, "intvar", OWL_VARIABLE_INT)));
1073  FAIL_UNLESS("get new int val", 47 == owl_variable_get_int(&vd, "intvar"));
1074  owl_variable_set_int(&vd, "intvar", 17);
1075  FAIL_UNLESS("update bool val", 17 == owl_variable_get_int(&vd, "intvar"));
1076
1077  owl_variable_dict_newvar_bool(&vd, "boolvar", "", "", 1);
1078  FAIL_UNLESS("get new bool var", NULL != (v = owl_variable_get(&vd, "boolvar", OWL_VARIABLE_BOOL)));
1079  FAIL_UNLESS("get new bool val", owl_variable_get_bool(&vd, "boolvar"));
1080  owl_variable_set_bool_off(&vd, "boolvar");
1081  FAIL_UNLESS("update string val", !owl_variable_get_bool(&vd, "boolvar"));
1082
1083  owl_variable_dict_free(&vd);
1084
1085  // if (numfailed) printf("*** WARNING: failures encountered with owl_variable\n");
1086  printf("# END testing owl_variable (%d failures)\n", numfailed);
1087  return(numfailed);
1088}
1089
1090
1091#endif /* OWL_INCLUDE_REG_TESTS */
Note: See TracBrowser for help on using the repository browser.