source: variable.c @ 1db061d

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