source: variable.c @ 73624b4

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