source: variable.c @ a352335c

barnowl_perlaimdebianowlrelease-1.10release-1.4release-1.5release-1.6release-1.7release-1.8release-1.9
Last change on this file since a352335c was 09489b89, checked in by James M. Kretchmar <kretch@mit.edu>, 21 years ago
First pass at making owl build without zephyr
  • Property mode set to 100644
File size: 32.2 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_BOOL( "personalbell" /* %OwlVarStub */, 0,
60               "ring the terminal bell when personal messages are received",
61               "" ),
62
63  OWLVAR_BOOL( "bell" /* %OwlVarStub */, 1,
64               "enable / disable the terminal bell", "" ),
65
66  OWLVAR_BOOL_FULL( "debug" /* %OwlVarStub */, OWL_DEBUG,
67                    "whether debugging is enabled",
68                    "If set to 'on', debugging messages are logged to the\n"
69                    "file specified by the debugfile variable.\n",
70                    NULL, owl_variable_debug_set, NULL),
71
72  OWLVAR_BOOL( "startuplogin" /* %OwlVarStub */, 1,
73               "send a login message when owl starts", "" ),
74
75  OWLVAR_BOOL( "shutdownlogout" /* %OwlVarStub */, 1,
76               "send a logout message when owl exits", "" ),
77
78  OWLVAR_BOOL( "rxping" /* %OwlVarStub */, 0,
79               "display received pings", "" ),
80
81  OWLVAR_BOOL( "txping" /* %OwlVarStub */, 1,
82               "send pings", "" ),
83
84  OWLVAR_BOOL( "sepbar_disable" /* %OwlVarStub */, 0,
85               "disable printing information in the seperator bar", "" ),
86
87  OWLVAR_BOOL( "smartstrip" /* %OwlVarStub */, 1,
88               "strip kerberos instance for reply", ""),
89
90  OWLVAR_BOOL( "newlinestrip" /* %OwlVarStub */, 1,
91               "strip leading and trailing newlines", ""),
92
93  OWLVAR_BOOL( "displayoutgoing" /* %OwlVarStub */, 1,
94               "display outgoing messages", "" ),
95
96  OWLVAR_BOOL( "loginsubs" /* %OwlVarStub */, 1,
97               "load logins from .anyone on startup", "" ),
98
99  OWLVAR_BOOL( "logging" /* %OwlVarStub */, 0,
100               "turn personal logging on or off", 
101               "If this is set to on, personal messages are\n"
102               "logged in the directory specified\n"
103               "by the 'logpath' variable.  The filename in that\n"
104               "directory is derived from the sender of the message.\n" ),
105
106  OWLVAR_BOOL( "classlogging" /* %OwlVarStub */, 0,
107               "turn class logging on or off",
108               "If this is set to on, class messages are\n"
109               "logged in the directory specified\n"
110               "by the 'classlogpath' variable.\n" 
111               "The filename in that directory is derived from\n"
112               "the name of the class to which the message was sent.\n" ),
113
114  OWLVAR_BOOL( "colorztext" /* %OwlVarStub */, 1,
115               "allow @color() in zephyrs to change color",
116               "Note that only messages received after this variable\n"
117               "is set will be affected." ),
118
119  OWLVAR_BOOL( "zcrypt" /* %OwlVarStub */, 1,
120               "Do automatic zcrypt processing",
121               "" ),
122
123  OWLVAR_ENUM_FULL( "disable-ctrl-d" /* %OwlVarStub:lockout_ctrld */, 1,
124                    "don't send zephyrs on C-d",
125                    "If set to 'off', C-d won't send a zephyr from the edit\n"
126                    "window.  If set to 'on', C-d will always send a zephyr\n"
127                    "being composed in the edit window.  If set to 'middle',\n"
128                    "C-d will only ever send a zephyr if the cursor is at\n"
129                    "the end of the message being composed.\n\n"
130                    "Note that this works by changing the C-d keybinding\n"
131                    "in the editmulti keymap.\n",
132                    "off,middle,on",
133                    NULL, owl_variable_disable_ctrl_d_set, NULL),
134
135  OWLVAR_BOOL( "_burningears" /* %OwlVarStub:burningears */, 0,
136               "[NOT YET IMPLEMENTED] beep on messages matching patterns", "" ),
137
138  OWLVAR_BOOL( "_summarymode" /* %OwlVarStub:summarymode */, 0,
139               "[NOT YET IMPLEMENTED]", "" ),
140
141  OWLVAR_PATH( "logpath" /* %OwlVarStub */, "~/zlog/people",
142               "path for logging personal zephyrs", 
143               "Specifies a directory which must exist.\n"
144               "Files will be created in the directory for each sender.\n"),
145
146  OWLVAR_PATH( "classlogpath" /* %OwlVarStub:classlogpath */, "~/zlog/class",
147               "path for logging class zephyrs",
148               "Specifies a directory which must exist.\n"
149               "Files will be created in the directory for each class.\n"),
150
151  OWLVAR_PATH( "debug_file" /* %OwlVarStub */, OWL_DEBUG_FILE,
152               "path for logging debug messages when debugging is enabled",
153               "This file will be logged to if 'debug' is set to 'on'.\n"),
154 
155  OWLVAR_PATH( "zsigproc" /* %OwlVarStub:zsigproc */, NULL,
156               "name of a program to run that will generate zsigs",
157               "This program should produce a zsig on stdout when run.\n"
158               "Note that it is important that this program not block.\n" ),
159
160  OWLVAR_PATH( "newmsgproc" /* %OwlVarStub:newmsgproc */, NULL,
161               "name of a program to run when new messages are present",
162               "The named program will be run when owl recevies new.\n"
163               "messages.  It will not be run again until the first\n"
164               "instance exits"),
165
166  OWLVAR_STRING( "zsig" /* %OwlVarStub */, "",
167                 "zephyr signature", 
168                 "If 'zsigproc' is not set, this string will be used\n"
169                 "as a zsig.  If this is also unset, the 'zwrite-signature'\n"
170                 "zephyr variable will be used instead.\n"),
171
172  OWLVAR_STRING( "appendtosepbar" /* %OwlVarStub */, "",
173                 "string to append to the end of the sepbar",
174                 "The sepbar is the bar separating the top and bottom\n"
175                 "of the owl screen.  Any string specified here will\n"
176                 "be displayed on the right of the sepbar\n"),
177
178  OWLVAR_BOOL( "zaway" /* %OwlVarStub */, 0,
179               "turn zaway on or off", "" ),
180
181  OWLVAR_STRING( "zaway_msg" /* %OwlVarStub */, 
182                 OWL_DEFAULT_ZAWAYMSG,
183                 "zaway msg for responding to zephyrs when away", "" ),
184
185  OWLVAR_STRING( "zaway_msg_default" /* %OwlVarStub */, 
186                 OWL_DEFAULT_ZAWAYMSG,
187                 "default zaway message", "" ),
188
189  OWLVAR_STRING( "view_home" /* %OwlVarStub */, "all",
190                 "home view to switch to after 'X' and 'V'", 
191                 "SEE ALSO: view, filter\n" ),
192
193  OWLVAR_STRING( "alert_filter" /* %OwlVarStub */, "none",
194                 "filter on which to trigger alert actions",
195                 "" ),
196
197  OWLVAR_STRING( "alert_action" /* %OwlVarStub */, "nop",
198                 "owl command to execute for alert actions",
199                 "" ),
200
201  OWLVAR_STRING_FULL( "tty" /* %OwlVarStub */, "", "tty name for zephyr location", "",
202                      NULL, owl_variable_tty_set, NULL),
203
204  OWLVAR_STRING( "default_style" /* %OwlVarStub */, "default",
205                 "name of the default formatting style",
206                 "This sets the default message formatting style. Possbile\n"
207                 "values include 'default' 'basic' 'oneline' and if\n"
208                 "available, 'perl'\n" ),
209
210  OWLVAR_INT(    "edit:maxfillcols" /* %OwlVarStub:edit_maxfillcols */, 70,
211                 "maximum number of columns for M-q to fill text to",
212                 "This specifies the maximum number of columns for M-q\n"
213                 "to fill text to.  If set to 0, ther will be no maximum\n"
214                 "limit.  In all cases, the current width of the screen\n"
215                 "will also be taken into account.  It will be used instead\n"
216                 "if it is narrower than the maximum, or if this\n"
217                 "is set to 0.\n" ),
218
219  OWLVAR_INT(    "edit:maxwrapcols" /* %OwlVarStub:edit_maxwrapcols */, 0,
220                 "maximum number of columns for line-wrapping",
221                 "This specifies the maximum number of columns for\n"
222                 "auto-line-wrapping.  If set to 0, ther will be no maximum\n"
223                 "limit.  In all cases, the current width of the screen\n"
224                 "will also be taken into account.  It will be used instead\n"
225                 "if it is narrower than the maximum, or if this\n"
226                 "is set to 0.\n\n"
227                 "It is recommended that outgoing messages be no wider\n"
228                 "than 60 columns, as a courtesy to recipients.\n"),
229
230  OWLVAR_INT( "aim_ignorelogin_timer" /* %OwlVarStub */, 0,
231              "number of seconds after AIM login to ignore login messages",
232              "This specifies the number of seconds to wait after an\n"
233              "AIM login before allowing the recipt of AIM login notifications.\n"
234              "By default this is set to 0 and all login notifications are\n"
235              "viewed immediately.  If you dislike this behavior try setting\n"
236              "the value to 20 instead.\n"),
237
238             
239  OWLVAR_INT_FULL( "typewinsize" /* %OwlVarStub:typwin_lines */, 
240                   OWL_TYPWIN_SIZE,
241                  "number of lines in the typing window", 
242                   "This specifies the height of the window at the\n"
243                   "bottom of the screen where commands are entered\n"
244                   "and where messages are composed.\n",
245                   "int > 0",
246                   owl_variable_int_validate_gt0,
247                   owl_variable_typewinsize_set,
248                   NULL /* use default for get */
249                   ),
250
251  OWLVAR_ENUM( "scrollmode" /* %OwlVarStub */, OWL_SCROLLMODE_NORMAL,
252               "how to scroll up and down",
253               "This controls how the screen is scrolled as the\n"
254               "cursor moves between messages being displayed.\n"
255               "The following modes are supported:\n\n"
256               "   normal      - This is the owl default.  Scrolling happens\n"
257               "                 when it needs to, and an attempt is made to\n"
258               "                 keep the current message roughly near\n"
259               "                 the middle of the screen.\n"
260               "   top         - The current message will always be the\n"
261               "                 the top message displayed.\n"
262               "   neartop     - The current message will be one down\n"
263               "                 from the top message displayed,\n"
264               "                 where possible.\n"
265               "   center      - An attempt is made to keep the current\n"
266               "                 message near the center of the screen.\n"
267               "   paged       - The top message displayed only changes\n"
268               "                 when user moves the cursor to the top\n"
269               "                 or bottom of the screen.  When it moves,\n"
270               "                 the screen will be paged up or down and\n"
271               "                 the cursor will be near the top or\n"
272               "                 the bottom.\n"
273               "   pagedcenter - The top message displayed only changes\n"
274               "                 when user moves the cursor to the top\n"
275               "                 or bottom of the screen.  When it moves,\n"
276               "                 the screen will be paged up or down and\n"
277               "                 the cursor will be near the center.\n",
278               "normal,top,neartop,center,paged,pagedcenter" ),
279
280  OWLVAR_ENUM( "webbrowser" /* %OwlVarStub */, OWL_WEBBROWSER_NETSCAPE,
281               "web browser to use to launch URLs",
282               "When the 'w' key is pressed, this browser is used\n"
283               "to display the requested URL.\n",
284               "none,netscape,galeon,opera" ),
285
286
287  OWLVAR_BOOL( "_followlast" /* %OwlVarStub */, 0,
288               "enable automatic following of the last zephyr",
289               "If the cursor is at the last message, it will\n"
290               "continue to follow the last message if this is set.\n"
291               "Note that this is currently risky as you might accidentally\n"
292               "delete a message right as it came in.\n" ),
293
294  /* This MUST be last... */
295  { NULL, 0, NULL, 0, NULL, NULL, NULL, NULL,
296    NULL, NULL, NULL, NULL, NULL, NULL }
297
298};
299
300/**************************************************************************/
301/*********************** SPECIFIC TO VARIABLES ****************************/
302/**************************************************************************/
303
304
305/* commonly useful */
306
307int owl_variable_int_validate_gt0(owl_variable *v, void *newval) {
308  if (newval == NULL) return(0);
309  else if (*(int*)newval < 1) return(0);
310  else return (1);
311}
312
313int owl_variable_int_validate_positive(owl_variable *v, void *newval) {
314  if (newval == NULL) return(0);
315  else if (*(int*)newval < 0) return(0);
316  else return (1);
317}
318
319/* typewinsize */
320
321int owl_variable_typewinsize_set(owl_variable *v, void *newval) {
322  int rv;
323  rv = owl_variable_int_set_default(v, newval);
324  if (0 == rv) owl_function_resize();
325  return(rv);
326}
327
328/* debug (cache value in g->debug) */
329
330int owl_variable_debug_set(owl_variable *v, void *newval) {
331  if (newval && (*(int*)newval == 1 || *(int*)newval == 0)) {
332    g.debug = *(int*)newval;
333  }
334  return owl_variable_bool_set_default(v, newval);
335}
336
337/* note that changing the value of this will clobber
338 * any user setting of this */
339int owl_variable_disable_ctrl_d_set(owl_variable *v, void *newval) {
340
341  if (in_regtest) return owl_variable_int_set_default(v, newval);
342
343  if (newval && !owl_context_is_startup(owl_global_get_context(&g))) {
344    if (*(int*)newval == 2) {
345      owl_function_command_norv("bindkey editmulti C-d command edit:delete-next-char");
346    } else if (*(int*)newval == 1) {
347      owl_function_command_norv("bindkey editmulti C-d command editmulti:done-or-delete");
348    } else {
349      owl_function_command_norv("bindkey editmulti C-d command editmulti:done");
350    }
351  } 
352  return owl_variable_int_set_default(v, newval); 
353}
354
355int owl_variable_tty_set(owl_variable *v, void *newval) {
356  owl_zephyr_set_locationinfo(owl_global_get_hostname(&g), newval);
357  return(owl_variable_string_set_default(v, newval));
358}
359
360int owl_variable_style_set(owl_variable *v, void *newval) {
361  /* Invalidate all message formats first */
362  int ret;
363  owl_style *s;
364
365  s=owl_global_get_style_by_name(&g, newval);
366  if (!s) {
367    /* this message won't get seen, we'll need to deal with that later */
368    owl_function_makemsg("No style named '%s' exists.", newval);
369    return(0);
370  }
371 
372  owl_messagelist_invalidate_formats(owl_global_get_msglist(&g));
373  ret=owl_variable_string_set_default(v, newval);
374  owl_function_calculate_topmsg(OWL_DIRECTION_DOWNWARDS);
375  owl_mainwin_redisplay(owl_global_get_mainwin(&g));
376  return(ret);
377}
378
379
380/**************************************************************************/
381/****************************** GENERAL ***********************************/
382/**************************************************************************/
383
384int owl_variable_dict_setup(owl_vardict *vd) {
385  owl_variable *cur;
386  if (owl_dict_create(vd)) return(-1);
387  for (cur = variables_to_init; cur->name != NULL; cur++) {
388    switch (cur->type) {
389    case OWL_VARIABLE_OTHER:
390      cur->set_fn(cur, cur->pval_default);
391      break;
392    case OWL_VARIABLE_STRING:
393      if (!cur->validate_fn) 
394        cur->validate_fn = owl_variable_string_validate_default;
395      if (!cur->set_fn) 
396        cur->set_fn = owl_variable_string_set_default;
397      if (!cur->set_fromstring_fn) 
398        cur->set_fromstring_fn = owl_variable_string_set_fromstring_default;
399      if (!cur->get_fn) 
400        cur->get_fn = owl_variable_get_default;
401      if (!cur->get_tostring_fn) 
402        cur->get_tostring_fn = owl_variable_string_get_tostring_default;     
403      if (!cur->free_fn) 
404        cur->free_fn = owl_variable_free_default;
405      cur->set_fn(cur, cur->pval_default);
406      break;
407    case OWL_VARIABLE_BOOL:
408      if (!cur->validate_fn) 
409        cur->validate_fn = owl_variable_bool_validate_default;
410      if (!cur->set_fn) 
411        cur->set_fn = owl_variable_bool_set_default;
412      if (!cur->set_fromstring_fn) 
413        cur->set_fromstring_fn = owl_variable_bool_set_fromstring_default;
414      if (!cur->get_fn) 
415        cur->get_fn = owl_variable_get_default;
416      if (!cur->get_tostring_fn) 
417        cur->get_tostring_fn = owl_variable_bool_get_tostring_default;     
418      if (!cur->free_fn) 
419        cur->free_fn = owl_variable_free_default;
420      cur->val = owl_malloc(sizeof(int));
421      cur->set_fn(cur, &cur->ival_default);
422      break;
423    case OWL_VARIABLE_INT:
424      if (!cur->validate_fn) 
425        cur->validate_fn = owl_variable_int_validate_default;
426      if (!cur->set_fn) 
427        cur->set_fn = owl_variable_int_set_default;
428      if (!cur->set_fromstring_fn) 
429        cur->set_fromstring_fn = owl_variable_int_set_fromstring_default;
430      if (!cur->get_fn) 
431        cur->get_fn = owl_variable_get_default;
432      if (!cur->get_tostring_fn) 
433        cur->get_tostring_fn = owl_variable_int_get_tostring_default;     
434      if (!cur->free_fn) 
435        cur->free_fn = owl_variable_free_default;
436      cur->val = owl_malloc(sizeof(int));
437      cur->set_fn(cur, &cur->ival_default);
438      break;
439    default:
440      fprintf(stderr, "owl_variable_setup: invalid variable type\n");
441      return(-2);
442    }
443    owl_dict_insert_element(vd, cur->name, (void*)cur, NULL);
444  }
445  return 0;
446}
447
448void owl_variable_dict_free(owl_vardict *d) {
449  owl_dict_free_all(d, (void(*)(void*))owl_variable_free);
450}
451
452/* free the list with owl_variable_dict_namelist_free */
453void owl_variable_dict_get_names(owl_vardict *d, owl_list *l) {
454  owl_dict_get_keys(d, l);
455}
456
457void owl_variable_dict_namelist_free(owl_list *l) {
458  owl_list_free_all(l, owl_free);
459}
460
461void owl_variable_free(owl_variable *v) {
462  if (v->free_fn) v->free_fn(v);
463}
464
465
466char *owl_variable_get_description(owl_variable *v) {
467  return v->description;
468}
469
470char *owl_variable_get_summary(owl_variable *v) {
471  return v->summary;
472}
473
474char *owl_variable_get_validsettings(owl_variable *v) {
475  if (v->validsettings) {
476    return v->validsettings;
477  } else {
478    return "";
479  }
480}
481
482/* functions for getting and setting variable values */
483
484/* returns 0 on success, prints a status msg if msg is true */
485int owl_variable_set_fromstring(owl_vardict *d, char *name, char *value, int msg, int requirebool) {
486  owl_variable *v;
487  char buff2[1024];
488  if (!name) return(-1);
489  v = owl_dict_find_element(d, name);
490  if (v == NULL) {
491    if (msg) owl_function_makemsg("Unknown variable %s", name);
492    return -1;
493  }
494  if (!v->set_fromstring_fn) {
495    if (msg) owl_function_makemsg("Variable %s is read-only", name);
496    return -1;   
497  }
498  if (requirebool && v->type!=OWL_VARIABLE_BOOL) {
499    if (msg) owl_function_makemsg("Variable %s is not a boolean", name);
500    return -1;   
501  }
502  if (0 != v->set_fromstring_fn(v, value)) {
503    if (msg) owl_function_makemsg("Unable to set %s (must be %s)", name, 
504                                  owl_variable_get_validsettings(v));
505    return -1;
506  }
507  if (msg && v->get_tostring_fn) {
508    v->get_tostring_fn(v, buff2, 1024, v->val);
509    owl_function_makemsg("%s = '%s'", name, buff2);
510  }   
511  return 0;
512}
513 
514int owl_variable_set_string(owl_vardict *d, char *name, char *newval) {
515  owl_variable *v;
516  if (!name) return(-1);
517  v = owl_dict_find_element(d, name);
518  if (v == NULL || !v->set_fn) return(-1);
519  if (v->type!=OWL_VARIABLE_STRING) return(-1);
520  return v->set_fn(v, (void*)newval);
521}
522 
523int owl_variable_set_int(owl_vardict *d, char *name, int newval) {
524  owl_variable *v;
525  if (!name) return(-1);
526  v = owl_dict_find_element(d, name);
527  if (v == NULL || !v->set_fn) return(-1);
528  if (v->type!=OWL_VARIABLE_INT && v->type!=OWL_VARIABLE_BOOL) return(-1);
529  return v->set_fn(v, &newval);
530}
531 
532int owl_variable_set_bool_on(owl_vardict *d, char *name) {
533  return owl_variable_set_int(d,name,1);
534}
535
536int owl_variable_set_bool_off(owl_vardict *d, char *name) {
537  return owl_variable_set_int(d,name,0);
538}
539
540int owl_variable_get_tostring(owl_vardict *d, char *name, char *buf, int bufsize) {
541  owl_variable *v;
542  if (!name) return(-1);
543  v = owl_dict_find_element(d, name);
544  if (v == NULL || !v->get_tostring_fn) return(-1);
545  return v->get_tostring_fn(v, buf, bufsize, v->val);
546}
547
548int owl_variable_get_default_tostring(owl_vardict *d, char *name, char *buf, int bufsize) {
549  owl_variable *v;
550  if (!name) return(-1);
551  v = owl_dict_find_element(d, name);
552  if (v == NULL || !v->get_tostring_fn) return(-1);
553  if (v->type == OWL_VARIABLE_INT || v->type == OWL_VARIABLE_BOOL) {
554    return v->get_tostring_fn(v, buf, bufsize, &(v->ival_default));
555  } else {
556    return v->get_tostring_fn(v, buf, bufsize, v->pval_default);
557  }
558}
559
560/* returns a reference */
561void *owl_variable_get(owl_vardict *d, char *name, int require_type) {
562  owl_variable *v;
563  if (!name) return(NULL);
564  v = owl_dict_find_element(d, name);
565  if (v == NULL || !v->get_fn || v->type != require_type) return(NULL);
566  return v->get_fn(v);
567}
568
569/* returns a reference */
570char *owl_variable_get_string(owl_vardict *d, char *name) {
571  return (char*)owl_variable_get(d,name, OWL_VARIABLE_STRING);
572}
573
574/* returns a reference */
575void *owl_variable_get_other(owl_vardict *d, char *name) {
576  return (char*)owl_variable_get(d,name, OWL_VARIABLE_OTHER);
577}
578
579int owl_variable_get_int(owl_vardict *d, char *name) {
580  int *pi;
581  pi = (int*)owl_variable_get(d,name,OWL_VARIABLE_INT);
582  if (!pi) return(-1);
583  return(*pi);
584}
585
586int owl_variable_get_bool(owl_vardict *d, char *name) {
587  int *pi;
588  pi = (int*)owl_variable_get(d,name,OWL_VARIABLE_BOOL);
589  if (!pi) return(-1);
590  return(*pi);
591}
592
593void owl_variable_describe(owl_vardict *d, char *name, owl_fmtext *fm) {
594  char defaultbuf[50];
595  char buf[1024];
596  int buflen = 1023;
597  owl_variable *v;
598
599  if (!name
600      || (v = owl_dict_find_element(d, name)) == NULL 
601      || !v->get_fn) {
602    snprintf(buf, buflen, "     No such variable '%s'\n", name);     
603    owl_fmtext_append_normal(fm, buf);
604    return;
605  }
606  if (v->type == OWL_VARIABLE_INT || v->type == OWL_VARIABLE_BOOL) {
607    v->get_tostring_fn(v, defaultbuf, 50, &(v->ival_default));
608  } else {
609    v->get_tostring_fn(v, defaultbuf, 50, v->pval_default);
610  }
611  snprintf(buf, buflen, OWL_TABSTR "%-20s - %s (default: '%s')\n", 
612                  v->name, 
613                  owl_variable_get_summary(v), defaultbuf);
614  owl_fmtext_append_normal(fm, buf);
615}
616
617void owl_variable_get_help(owl_vardict *d, char *name, owl_fmtext *fm) {
618  char buff[1024];
619  int bufflen = 1023;
620  owl_variable *v;
621
622  if (!name
623      || (v = owl_dict_find_element(d, name)) == NULL 
624      || !v->get_fn) {
625    owl_fmtext_append_normal(fm, "No such variable...\n");
626    return;
627  }
628
629  owl_fmtext_append_bold(fm, "OWL VARIABLE\n\n");
630  owl_fmtext_append_normal(fm, OWL_TABSTR);
631  owl_fmtext_append_normal(fm, name);
632  owl_fmtext_append_normal(fm, " - ");
633  owl_fmtext_append_normal(fm, v->summary);
634  owl_fmtext_append_normal(fm, "\n\n");
635
636  owl_fmtext_append_normal(fm, "Current:        ");
637  owl_variable_get_tostring(d, name, buff, bufflen);
638  owl_fmtext_append_normal(fm, buff);
639  owl_fmtext_append_normal(fm, "\n\n");
640
641
642  if (v->type == OWL_VARIABLE_INT || v->type == OWL_VARIABLE_BOOL) {
643    v->get_tostring_fn(v, buff, bufflen, &(v->ival_default));
644  } else {
645    v->get_tostring_fn(v, buff, bufflen, v->pval_default);
646  }
647  owl_fmtext_append_normal(fm, "Default:        ");
648  owl_fmtext_append_normal(fm, buff);
649  owl_fmtext_append_normal(fm, "\n\n");
650
651  owl_fmtext_append_normal(fm, "Valid Settings: ");
652  owl_fmtext_append_normal(fm, owl_variable_get_validsettings(v));
653  owl_fmtext_append_normal(fm, "\n\n");
654
655  if (v->description && *v->description) {
656    owl_fmtext_append_normal(fm, "Description:\n");
657    owl_fmtext_append_normal(fm, owl_variable_get_description(v));
658    owl_fmtext_append_normal(fm, "\n\n");
659  }
660}
661
662
663
664
665/**************************************************************************/
666/*********************** GENERAL TYPE-SPECIFIC ****************************/
667/**************************************************************************/
668
669/* default common functions */
670
671void *owl_variable_get_default(owl_variable *v) {
672  return v->val;
673}
674
675void owl_variable_free_default(owl_variable *v) {
676  if (v->val) owl_free(v->val);
677}
678
679/* default functions for booleans */
680
681int owl_variable_bool_validate_default(owl_variable *v, void *newval) {
682  if (newval == NULL) return(0);
683  else if (*(int*)newval==1 || *(int*)newval==0) return(1);
684  else return (0);
685}
686
687int owl_variable_bool_set_default(owl_variable *v, void *newval) {
688  if (v->validate_fn) {
689    if (!v->validate_fn(v, newval)) return(-1);
690  }
691  *(int*)v->val = *(int*)newval;
692  return(0);
693}
694
695int owl_variable_bool_set_fromstring_default(owl_variable *v, char *newval) {
696  int i;
697  if (!strcmp(newval, "on")) i=1;
698  else if (!strcmp(newval, "off")) i=0;
699  else return(-1);
700  return (v->set_fn(v, &i));
701}
702
703int owl_variable_bool_get_tostring_default(owl_variable *v, char* buf, int bufsize, void *val) {
704  if (val == NULL) {
705    snprintf(buf, bufsize, "<null>");
706    return -1;
707  } else if (*(int*)val == 0) {
708    snprintf(buf, bufsize, "off");
709    return 0;
710  } else if (*(int*)val == 1) {
711    snprintf(buf, bufsize, "on");
712    return 0;
713  } else {
714    snprintf(buf, bufsize, "<invalid>");
715    return -1;
716  }
717}
718
719/* default functions for integers */
720
721int owl_variable_int_validate_default(owl_variable *v, void *newval) {
722  if (newval == NULL) return(0);
723  else return (1);
724}
725
726int owl_variable_int_set_default(owl_variable *v, void *newval) {
727  if (v->validate_fn) {
728    if (!v->validate_fn(v, newval)) return(-1);
729  }
730  *(int*)v->val = *(int*)newval;
731  return(0);
732}
733
734int owl_variable_int_set_fromstring_default(owl_variable *v, char *newval) {
735  int i;
736  char *ep = "x";
737  i = strtol(newval, &ep, 10);
738  if (*ep || ep==newval) return(-1);
739  return (v->set_fn(v, &i));
740}
741
742int owl_variable_int_get_tostring_default(owl_variable *v, char* buf, int bufsize, void *val) {
743  if (val == NULL) {
744    snprintf(buf, bufsize, "<null>");
745    return -1;
746  } else {
747    snprintf(buf, bufsize, "%d", *(int*)val);
748    return 0;
749  } 
750}
751
752/* default functions for enums (a variant of integers) */
753
754int owl_variable_enum_validate(owl_variable *v, void *newval) { 
755  char **enums;
756  int nenums, val;
757  if (newval == NULL) return(0);
758  enums = atokenize(v->validsettings, ",", &nenums);
759  if (enums == NULL) return(0);
760  atokenize_free(enums, nenums);
761  val = *(int*)newval;
762  if (val < 0 || val >= nenums) {
763    return(0);
764  }
765  return(1);
766}
767
768int owl_variable_enum_set_fromstring(owl_variable *v, char *newval) {
769  char **enums;
770  int nenums, i, val=-1;
771  if (newval == NULL) return(-1);
772  enums = atokenize(v->validsettings, ",", &nenums);
773  if (enums == NULL) return(-1);
774  for (i=0; i<nenums; i++) {
775    if (0==strcmp(newval, enums[i])) {
776      val = i;
777    }
778  }
779  atokenize_free(enums, nenums);
780  if (val == -1) return(-1);
781  return (v->set_fn(v, &val));
782}
783
784int owl_variable_enum_get_tostring(owl_variable *v, char* buf, int bufsize, void *val) {
785  char **enums;
786  int nenums, i;
787
788  if (val == NULL) {
789    snprintf(buf, bufsize, "<null>");
790    return -1;
791  }
792  enums = atokenize(v->validsettings, ",", &nenums);
793  i = *(int*)val;
794  if (i<0 || i>=nenums) {
795    snprintf(buf, bufsize, "<invalid:%d>",i);
796    atokenize_free(enums, nenums);
797    return(-1);
798  }
799  snprintf(buf, bufsize, "%s", enums[i]);
800  return 0;
801}
802
803/* default functions for stringeans */
804
805int owl_variable_string_validate_default(struct _owl_variable *v, void *newval) {
806  if (newval == NULL) return(0);
807  else return (1);
808}
809
810int owl_variable_string_set_default(owl_variable *v, void *newval) {
811  if (v->validate_fn) {
812    if (!v->validate_fn(v, newval)) return(-1);
813  }
814  if (v->val) owl_free(v->val);
815  v->val = owl_strdup(newval);
816  return(0);
817}
818
819int owl_variable_string_set_fromstring_default(owl_variable *v, char *newval) {
820  return (v->set_fn(v, newval));
821}
822
823int owl_variable_string_get_tostring_default(owl_variable *v, char* buf, int bufsize, void *val) {
824  if (val == NULL) {
825    snprintf(buf, bufsize, "<null>");
826    return -1;
827  } else {
828    snprintf(buf, bufsize, "%s", (char*)val);
829    return 0;
830  }
831}
832
833
834
835/**************************************************************************/
836/************************* REGRESSION TESTS *******************************/
837/**************************************************************************/
838
839#ifdef OWL_INCLUDE_REG_TESTS
840
841#define FAIL_UNLESS(desc,pred) printf("\t%-4s: %s\n", (pred)?"ok":(numfailed++,"FAIL"), desc)
842
843int owl_variable_regtest(void) {
844  owl_vardict vd;
845  int numfailed=0;
846  char buf[1024];
847
848  in_regtest = 1;
849
850  printf("BEGIN testing owl_variable\n");
851  FAIL_UNLESS("setup", 0==owl_variable_dict_setup(&vd));
852
853  FAIL_UNLESS("get bool", 0==owl_variable_get_bool(&vd,"personalbell"));
854  FAIL_UNLESS("get bool (no such)", -1==owl_variable_get_bool(&vd,"mumble"));
855  FAIL_UNLESS("get bool as string 1", 0==owl_variable_get_tostring(&vd,"personalbell", buf, 1024));
856  FAIL_UNLESS("get bool as string 2", 0==strcmp(buf,"off"));
857  FAIL_UNLESS("set bool 1", 0==owl_variable_set_bool_on(&vd,"personalbell"));
858  FAIL_UNLESS("get bool 2", 1==owl_variable_get_bool(&vd,"personalbell"));
859  FAIL_UNLESS("set bool 3", 0==owl_variable_set_fromstring(&vd,"personalbell","off",0,0));
860  FAIL_UNLESS("get bool 4", 0==owl_variable_get_bool(&vd,"personalbell"));
861  FAIL_UNLESS("set bool 5", -1==owl_variable_set_fromstring(&vd,"personalbell","xxx",0,0));
862  FAIL_UNLESS("get bool 6", 0==owl_variable_get_bool(&vd,"personalbell"));
863
864
865  FAIL_UNLESS("get string", 0==strcmp("~/zlog/people", owl_variable_get_string(&vd,"logpath")));
866  FAIL_UNLESS("set string 7", 0==owl_variable_set_string(&vd,"logpath","whee"));
867  FAIL_UNLESS("get string", 0==strcmp("whee", owl_variable_get_string(&vd,"logpath")));
868
869  FAIL_UNLESS("get int", 8==owl_variable_get_int(&vd,"typewinsize"));
870  FAIL_UNLESS("get int (no such)", -1==owl_variable_get_int(&vd,"mmble"));
871  FAIL_UNLESS("get int as string 1", 0==owl_variable_get_tostring(&vd,"typewinsize", buf, 1024));
872  FAIL_UNLESS("get int as string 2", 0==strcmp(buf,"8"));
873  FAIL_UNLESS("set int 1", 0==owl_variable_set_int(&vd,"typewinsize",12));
874  FAIL_UNLESS("get int 2", 12==owl_variable_get_int(&vd,"typewinsize"));
875  FAIL_UNLESS("set int 1b", -1==owl_variable_set_int(&vd,"typewinsize",-3));
876  FAIL_UNLESS("get int 2b", 12==owl_variable_get_int(&vd,"typewinsize"));
877  FAIL_UNLESS("set int 3", 0==owl_variable_set_fromstring(&vd,"typewinsize","9",0,0));
878  FAIL_UNLESS("get int 4", 9==owl_variable_get_int(&vd,"typewinsize"));
879  FAIL_UNLESS("set int 5", -1==owl_variable_set_fromstring(&vd,"typewinsize","xxx",0,0));
880  FAIL_UNLESS("set int 6", -1==owl_variable_set_fromstring(&vd,"typewinsize","",0,0));
881  FAIL_UNLESS("get int 7", 9==owl_variable_get_int(&vd,"typewinsize"));
882
883  FAIL_UNLESS("get enum", OWL_WEBBROWSER_NETSCAPE==owl_variable_get_int(&vd,"webbrowser"));
884  FAIL_UNLESS("get enum as string 1", 0==owl_variable_get_tostring(&vd,"webbrowser", buf, 1024));
885  FAIL_UNLESS("get enum as string 2", 0==strcmp(buf,"netscape"));
886  FAIL_UNLESS("set enum 1", 0==owl_variable_set_int(&vd,"webbrowser",OWL_WEBBROWSER_GALEON));
887  FAIL_UNLESS("get enum 2", OWL_WEBBROWSER_GALEON==owl_variable_get_int(&vd,"webbrowser"));
888  FAIL_UNLESS("set enum 1b", -1==owl_variable_set_int(&vd,"webbrowser",-3));
889  FAIL_UNLESS("set enum 1b", -1==owl_variable_set_int(&vd,"webbrowser",209));
890  FAIL_UNLESS("get enum 2b", OWL_WEBBROWSER_GALEON==owl_variable_get_int(&vd,"webbrowser"));
891  FAIL_UNLESS("set enum 3", 0==owl_variable_set_fromstring(&vd,"webbrowser","none",0,0));
892  FAIL_UNLESS("get enum 4", OWL_WEBBROWSER_NONE==owl_variable_get_int(&vd,"webbrowser"));
893  FAIL_UNLESS("set enum 5", 0==owl_variable_set_fromstring(&vd,"webbrowser","netscape",0,0));
894  FAIL_UNLESS("get enum 6", OWL_WEBBROWSER_NETSCAPE==owl_variable_get_int(&vd,"webbrowser"));
895  FAIL_UNLESS("set enum 7", -1==owl_variable_set_fromstring(&vd,"webbrowser","xxx",0,0));
896  FAIL_UNLESS("set enum 8", -1==owl_variable_set_fromstring(&vd,"webbrowser","",0,0));
897  FAIL_UNLESS("set enum 9", -1==owl_variable_set_fromstring(&vd,"webbrowser","netscapey",0,0));
898  FAIL_UNLESS("get enum 10", OWL_WEBBROWSER_NETSCAPE==owl_variable_get_int(&vd,"webbrowser"));
899
900
901
902  owl_variable_dict_free(&vd);
903
904  if (numfailed) printf("*** WARNING: failures encountered with owl_variable\n");
905  printf("END testing owl_variable (%d failures)\n", numfailed);
906  return(numfailed);
907}
908
909
910#endif /* OWL_INCLUDE_REG_TESTS */
Note: See TracBrowser for help on using the repository browser.