source: variable.c @ 9854278

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