source: variable.c @ c15bbfb

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