source: variable.c @ 8b32593

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