source: variable.c @ d309eb3

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