source: variable.c @ bd3f232

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