source: variable.c @ 3dcccba

barnowl_perlaim
Last change on this file since 3dcccba was c453ada, checked in by Geoffrey Thomas <geofft@mit.edu>, 16 years ago
Remove aim.c. buddylist.c, buddy.c, libfaim, and everything that uses them.
  • Property mode set to 100644
File size: 38.8 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_STRING( "personalbell" /* %OwlVarStub */, "off",
60                 "ring the terminal bell when personal messages are received",
61                 "Can be set to 'on', 'off', or the name of a filter which\n"
62                 "messages need to match in order to ring the bell"),
63
64  OWLVAR_BOOL( "bell" /* %OwlVarStub */, 1,
65               "enable / disable the terminal bell", "" ),
66
67  OWLVAR_BOOL_FULL( "debug" /* %OwlVarStub */, OWL_DEBUG,
68                    "whether debugging is enabled",
69                    "If set to 'on', debugging messages are logged to the\n"
70                    "file specified by the debugfile variable.\n",
71                    NULL, owl_variable_debug_set, NULL),
72
73  OWLVAR_BOOL( "startuplogin" /* %OwlVarStub */, 1,
74               "send a login message when owl starts", "" ),
75
76  OWLVAR_BOOL( "shutdownlogout" /* %OwlVarStub */, 1,
77               "send a logout message when owl exits", "" ),
78
79  OWLVAR_BOOL( "rxping" /* %OwlVarStub */, 0,
80               "display received pings", "" ),
81
82  OWLVAR_BOOL( "txping" /* %OwlVarStub */, 1,
83               "send pings", "" ),
84
85  OWLVAR_BOOL( "sepbar_disable" /* %OwlVarStub */, 0,
86               "disable printing information in the seperator bar", "" ),
87
88  OWLVAR_BOOL( "smartstrip" /* %OwlVarStub */, 1,
89               "strip kerberos instance for reply", ""),
90
91  OWLVAR_BOOL( "newlinestrip" /* %OwlVarStub */, 1,
92               "strip leading and trailing newlines", ""),
93
94  OWLVAR_BOOL( "displayoutgoing" /* %OwlVarStub */, 1,
95               "display outgoing messages", "" ),
96
97  OWLVAR_BOOL( "loginsubs" /* %OwlVarStub */, 1,
98               "load logins from .anyone on startup", "" ),
99
100  OWLVAR_BOOL( "logging" /* %OwlVarStub */, 0,
101               "turn personal logging on or off", 
102               "If this is set to on, personal messages are\n"
103               "logged in the directory specified\n"
104               "by the 'logpath' variable.  The filename in that\n"
105               "directory is derived from the sender of the message.\n" ),
106
107  OWLVAR_BOOL( "classlogging" /* %OwlVarStub */, 0,
108               "turn class logging on or off",
109               "If this is set to on, class messages are\n"
110               "logged in the directory specified\n"
111               "by the 'classlogpath' variable.\n" 
112               "The filename in that directory is derived from\n"
113               "the name of the class to which the message was sent.\n" ),
114
115  OWLVAR_ENUM( "loggingdirection" /* %OwlVarStub */, OWL_LOGGING_DIRECTION_BOTH,
116               "specifices which kind of messages should be logged",
117               "Can be one of 'both', 'in', or 'out'.  If 'in' is\n"
118               "selected, only incoming messages are logged, if 'out'\n"
119               "is selected only outgoing messages are logged.  If 'both'\n"
120               "is selected both incoming and outgoing messages are\n"
121               "logged.",
122               "both,in,out"),
123
124  OWLVAR_BOOL( "colorztext" /* %OwlVarStub */, 1,
125               "allow @color() in zephyrs to change color",
126               "Note that only messages received after this variable\n"
127               "is set will be affected." ),
128
129  OWLVAR_BOOL( "fancylines" /* %OwlVarStub */, 1,
130               "Use 'nice' line drawing on the terminal.",
131               "If turned off, dashes, pipes and pluses will be used\n"
132               "to draw lines on the screen.  Useful when the terminal\n"
133               "is causing problems" ),
134
135  OWLVAR_BOOL( "zcrypt" /* %OwlVarStub */, 1,
136               "Do automatic zcrypt processing",
137               "" ),
138
139  OWLVAR_BOOL_FULL( "pseudologins" /* %OwlVarStub */, 0,
140                    "Enable zephyr pseudo logins",
141                    "When this is enabled, Owl will periodically check the zephyr\n"
142                    "location of users in your .anyone file.  If a user is present\n"
143                    "but sent no login message, or a user is not present that sent no\n"
144                    "logout message a pseudo login or logout message wil be created\n",
145                    NULL, owl_variable_pseudologins_set, NULL),
146
147  OWLVAR_BOOL( "ignorelogins" /* %OwlVarStub */, 0,
148               "Enable printing of login notifications",
149               "When this is enabled, Owl will print login and logout notifications\n"
150               "for AIM, zephyr, or other protocols.  If disabled Owl will not print\n"
151               "login or logout notifications.\n"),
152
153  OWLVAR_STRING( "logfilter" /* %OwlVarStub */, "",
154                 "name of a filter controlling which messages to log",
155
156                 "If non empty, any messages matching the given filter will be logged.\n"
157                 "This is a completely separate mechanisim from the other logging\n"
158                 "variables like logging, classlogging, loglogins, loggingdirection,\n"
159                 "etc.  If you want this variable to control all logging, make sure\n"
160                 "all other logging variables are in their default state.\n"),
161
162  OWLVAR_BOOL( "loglogins" /* %OwlVarStub */, 0,
163               "Enable logging of login notifications",
164               "When this is enabled, Owl will login login and logout notifications\n"
165               "for AIM, zephyr, or other protocols.  If disabled Owl will not print\n"
166               "login or logout notifications.\n"),
167
168  OWLVAR_ENUM_FULL( "disable-ctrl-d" /* %OwlVarStub:lockout_ctrld */, 1,
169                    "don't send zephyrs on C-d",
170                    "If set to 'off', C-d won't send a zephyr from the edit\n"
171                    "window.  If set to 'on', C-d will always send a zephyr\n"
172                    "being composed in the edit window.  If set to 'middle',\n"
173                    "C-d will only ever send a zephyr if the cursor is at\n"
174                    "the end of the message being composed.\n\n"
175                    "Note that this works by changing the C-d keybinding\n"
176                    "in the editmulti keymap.\n",
177                    "off,middle,on",
178                    NULL, owl_variable_disable_ctrl_d_set, NULL),
179
180  OWLVAR_BOOL( "_burningears" /* %OwlVarStub:burningears */, 0,
181               "[NOT YET IMPLEMENTED] beep on messages matching patterns", "" ),
182
183  OWLVAR_BOOL( "_summarymode" /* %OwlVarStub:summarymode */, 0,
184               "[NOT YET IMPLEMENTED]", "" ),
185
186  OWLVAR_PATH( "logpath" /* %OwlVarStub */, "~/zlog/people",
187               "path for logging personal zephyrs", 
188               "Specifies a directory which must exist.\n"
189               "Files will be created in the directory for each sender.\n"),
190
191  OWLVAR_PATH( "classlogpath" /* %OwlVarStub:classlogpath */, "~/zlog/class",
192               "path for logging class zephyrs",
193               "Specifies a directory which must exist.\n"
194               "Files will be created in the directory for each class.\n"),
195
196  OWLVAR_PATH( "debug_file" /* %OwlVarStub */, OWL_DEBUG_FILE,
197               "path for logging debug messages when debugging is enabled",
198               "This file will be logged to if 'debug' is set to 'on'.\n"),
199 
200  OWLVAR_PATH( "zsigproc" /* %OwlVarStub:zsigproc */, NULL,
201               "name of a program to run that will generate zsigs",
202               "This program should produce a zsig on stdout when run.\n"
203               "Note that it is important that this program not block.\n" ),
204
205  OWLVAR_PATH( "newmsgproc" /* %OwlVarStub:newmsgproc */, NULL,
206               "name of a program to run when new messages are present",
207               "The named program will be run when owl recevies new.\n"
208               "messages.  It will not be run again until the first\n"
209               "instance exits"),
210
211  OWLVAR_STRING( "zsender" /* %OwlVarStub */, "",
212             "zephyr sender name",
213         "Allows you to customize the outgoing username in\n"
214         "zephyrs.  If this is unset, it will use your Kerberos\n"
215         "principal. Note that customizing the sender name will\n"
216         "cause your zephyrs to be sent unauthenticated."),
217
218  OWLVAR_STRING( "zsig" /* %OwlVarStub */, "",
219                 "zephyr signature", 
220                 "If 'zsigproc' is not set, this string will be used\n"
221                 "as a zsig.  If this is also unset, the 'zwrite-signature'\n"
222                 "zephyr variable will be used instead.\n"),
223
224  OWLVAR_STRING( "appendtosepbar" /* %OwlVarStub */, "",
225                 "string to append to the end of the sepbar",
226                 "The sepbar is the bar separating the top and bottom\n"
227                 "of the owl screen.  Any string specified here will\n"
228                 "be displayed on the right of the sepbar\n"),
229
230  OWLVAR_BOOL( "zaway" /* %OwlVarStub */, 0,
231               "turn zaway on or off", "" ),
232
233  OWLVAR_STRING( "zaway_msg" /* %OwlVarStub */, 
234                 OWL_DEFAULT_ZAWAYMSG,
235                 "zaway msg for responding to zephyrs when away", "" ),
236
237  OWLVAR_STRING( "zaway_msg_default" /* %OwlVarStub */, 
238                 OWL_DEFAULT_ZAWAYMSG,
239                 "default zaway message", "" ),
240
241  OWLVAR_STRING( "view_home" /* %OwlVarStub */, "all",
242                 "home view to switch to after 'X' and 'V'", 
243                 "SEE ALSO: view, filter\n" ),
244
245  OWLVAR_STRING( "alert_filter" /* %OwlVarStub */, "none",
246                 "filter on which to trigger alert actions",
247                 "" ),
248
249  OWLVAR_STRING( "alert_action" /* %OwlVarStub */, "nop",
250                 "owl command to execute for alert actions",
251                 "" ),
252
253  OWLVAR_STRING_FULL( "tty" /* %OwlVarStub */, "", "tty name for zephyr location", "",
254                      NULL, owl_variable_tty_set, NULL),
255
256  OWLVAR_STRING( "default_style" /* %OwlVarStub */, "__unspecified__",
257                 "name of the default formatting style",
258                 "This sets the default message formatting style.\n"
259                 "Styles may be created with the 'style' command.\n"
260                 "Some built-in styles include:\n"
261                 "   default  - the default owl formatting\n"
262                 "   oneline  - one line per-message\n"
263                 "   perl     - legacy perl interface\n"
264                 "\nSEE ALSO: style, show styles, view -s <style>\n"
265                 ),
266
267
268  OWLVAR_INT(    "edit:maxfillcols" /* %OwlVarStub:edit_maxfillcols */, 70,
269                 "maximum number of columns for M-q to fill text to",
270                 "This specifies the maximum number of columns for M-q\n"
271                 "to fill text to.  If set to 0, ther will be no maximum\n"
272                 "limit.  In all cases, the current width of the screen\n"
273                 "will also be taken into account.  It will be used instead\n"
274                 "if it is narrower than the maximum, or if this\n"
275                 "is set to 0.\n" ),
276
277  OWLVAR_INT(    "edit:maxwrapcols" /* %OwlVarStub:edit_maxwrapcols */, 0,
278                 "maximum number of columns for line-wrapping",
279                 "This specifies the maximum number of columns for\n"
280                 "auto-line-wrapping.  If set to 0, ther will be no maximum\n"
281                 "limit.  In all cases, the current width of the screen\n"
282                 "will also be taken into account.  It will be used instead\n"
283                 "if it is narrower than the maximum, or if this\n"
284                 "is set to 0.\n\n"
285                 "It is recommended that outgoing messages be no wider\n"
286                 "than 60 columns, as a courtesy to recipients.\n"),
287
288  OWLVAR_INT_FULL( "typewinsize" /* %OwlVarStub:typwin_lines */, 
289                   OWL_TYPWIN_SIZE,
290                  "number of lines in the typing window", 
291                   "This specifies the height of the window at the\n"
292                   "bottom of the screen where commands are entered\n"
293                   "and where messages are composed.\n",
294                   "int > 0",
295                   owl_variable_int_validate_gt0,
296                   owl_variable_typewinsize_set,
297                   NULL /* use default for get */
298                   ),
299
300  OWLVAR_ENUM( "scrollmode" /* %OwlVarStub */, OWL_SCROLLMODE_NORMAL,
301               "how to scroll up and down",
302               "This controls how the screen is scrolled as the\n"
303               "cursor moves between messages being displayed.\n"
304               "The following modes are supported:\n\n"
305               "   normal      - This is the owl default.  Scrolling happens\n"
306               "                 when it needs to, and an attempt is made to\n"
307               "                 keep the current message roughly near\n"
308               "                 the middle of the screen.\n"
309               "   top         - The current message will always be the\n"
310               "                 the top message displayed.\n"
311               "   neartop     - The current message will be one down\n"
312               "                 from the top message displayed,\n"
313               "                 where possible.\n"
314               "   center      - An attempt is made to keep the current\n"
315               "                 message near the center of the screen.\n"
316               "   paged       - The top message displayed only changes\n"
317               "                 when user moves the cursor to the top\n"
318               "                 or bottom of the screen.  When it moves,\n"
319               "                 the screen will be paged up or down and\n"
320               "                 the cursor will be near the top or\n"
321               "                 the bottom.\n"
322               "   pagedcenter - The top message displayed only changes\n"
323               "                 when user moves the cursor to the top\n"
324               "                 or bottom of the screen.  When it moves,\n"
325               "                 the screen will be paged up or down and\n"
326               "                 the cursor will be near the center.\n",
327               "normal,top,neartop,center,paged,pagedcenter" ),
328
329  OWLVAR_ENUM( "webbrowser" /* %OwlVarStub */, OWL_WEBBROWSER_NETSCAPE,
330               "web browser to use to launch URLs",
331               "When the 'w' key is pressed, this browser is used\n"
332               "to display the requested URL.\n",
333               "none,netscape,galeon,opera" ),
334
335
336  OWLVAR_BOOL( "_followlast" /* %OwlVarStub */, 0,
337               "enable automatic following of the last zephyr",
338               "If the cursor is at the last message, it will\n"
339               "continue to follow the last message if this is set.\n"
340               "Note that this is currently risky as you might accidentally\n"
341               "delete a message right as it came in.\n" ),
342
343  /* This MUST be last... */
344  { NULL, 0, NULL, 0, NULL, NULL, NULL, NULL,
345    NULL, NULL, NULL, NULL, NULL, NULL }
346
347};
348
349/**************************************************************************/
350/*********************** SPECIFIC TO VARIABLES ****************************/
351/**************************************************************************/
352
353
354/* commonly useful */
355
356int owl_variable_int_validate_gt0(owl_variable *v, void *newval)
357{
358  if (newval == NULL) return(0);
359  else if (*(int*)newval < 1) return(0);
360  else return (1);
361}
362
363int owl_variable_int_validate_positive(owl_variable *v, void *newval)
364{
365  if (newval == NULL) return(0);
366  else if (*(int*)newval < 0) return(0);
367  else return (1);
368}
369
370/* typewinsize */
371int owl_variable_typewinsize_set(owl_variable *v, void *newval)
372{
373  int rv;
374  rv = owl_variable_int_set_default(v, newval);
375  if (0 == rv) owl_function_resize();
376  return(rv);
377}
378
379/* debug (cache value in g->debug) */
380int owl_variable_debug_set(owl_variable *v, void *newval)
381{
382  if (newval && (*(int*)newval == 1 || *(int*)newval == 0)) {
383    g.debug = *(int*)newval;
384  }
385  return owl_variable_bool_set_default(v, newval);
386}
387
388int owl_variable_pseudologins_set(owl_variable *v, void *newval)
389{
390  if (newval) {
391    if (*(int*)newval == 1) {
392      owl_function_zephyr_buddy_check(0);
393    }
394  }
395  return owl_variable_bool_set_default(v, newval);
396}
397
398/* note that changing the value of this will clobber
399 * any user setting of this */
400int owl_variable_disable_ctrl_d_set(owl_variable *v, void *newval)
401{
402
403  if (in_regtest) return owl_variable_int_set_default(v, newval);
404
405  if (newval && !owl_context_is_startup(owl_global_get_context(&g))) {
406    if (*(int*)newval == 2) {
407      owl_function_command_norv("bindkey editmulti C-d command edit:delete-next-char");
408    } else if (*(int*)newval == 1) {
409      owl_function_command_norv("bindkey editmulti C-d command editmulti:done-or-delete");
410    } else {
411      owl_function_command_norv("bindkey editmulti C-d command editmulti:done");
412    }
413  } 
414  return owl_variable_int_set_default(v, newval); 
415}
416
417int owl_variable_tty_set(owl_variable *v, void *newval)
418{
419  owl_zephyr_set_locationinfo(owl_global_get_hostname(&g), newval);
420  return(owl_variable_string_set_default(v, newval));
421}
422
423
424/**************************************************************************/
425/****************************** GENERAL ***********************************/
426/**************************************************************************/
427
428int owl_variable_dict_setup(owl_vardict *vd) {
429  owl_variable *var, *cur;
430  if (owl_dict_create(vd)) return(-1);
431  for (var = variables_to_init; var->name != NULL; var++) {
432    cur = owl_malloc(sizeof(owl_variable));
433    memcpy(cur, var, sizeof(owl_variable));
434    switch (cur->type) {
435    case OWL_VARIABLE_OTHER:
436      cur->set_fn(cur, cur->pval_default);
437      break;
438    case OWL_VARIABLE_STRING:
439      if (!cur->validate_fn) 
440        cur->validate_fn = owl_variable_string_validate_default;
441      if (!cur->set_fn) 
442        cur->set_fn = owl_variable_string_set_default;
443      if (!cur->set_fromstring_fn) 
444        cur->set_fromstring_fn = owl_variable_string_set_fromstring_default;
445      if (!cur->get_fn) 
446        cur->get_fn = owl_variable_get_default;
447      if (!cur->get_tostring_fn) 
448        cur->get_tostring_fn = owl_variable_string_get_tostring_default;     
449      if (!cur->free_fn) 
450        cur->free_fn = owl_variable_free_default;
451      cur->set_fn(cur, cur->pval_default);
452      break;
453    case OWL_VARIABLE_BOOL:
454      if (!cur->validate_fn) 
455        cur->validate_fn = owl_variable_bool_validate_default;
456      if (!cur->set_fn) 
457        cur->set_fn = owl_variable_bool_set_default;
458      if (!cur->set_fromstring_fn) 
459        cur->set_fromstring_fn = owl_variable_bool_set_fromstring_default;
460      if (!cur->get_fn) 
461        cur->get_fn = owl_variable_get_default;
462      if (!cur->get_tostring_fn) 
463        cur->get_tostring_fn = owl_variable_bool_get_tostring_default;     
464      if (!cur->free_fn) 
465        cur->free_fn = owl_variable_free_default;
466      cur->val = owl_malloc(sizeof(int));
467      cur->set_fn(cur, &cur->ival_default);
468      break;
469    case OWL_VARIABLE_INT:
470      if (!cur->validate_fn) 
471        cur->validate_fn = owl_variable_int_validate_default;
472      if (!cur->set_fn) 
473        cur->set_fn = owl_variable_int_set_default;
474      if (!cur->set_fromstring_fn) 
475        cur->set_fromstring_fn = owl_variable_int_set_fromstring_default;
476      if (!cur->get_fn) 
477        cur->get_fn = owl_variable_get_default;
478      if (!cur->get_tostring_fn) 
479        cur->get_tostring_fn = owl_variable_int_get_tostring_default;     
480      if (!cur->free_fn) 
481        cur->free_fn = owl_variable_free_default;
482      cur->val = owl_malloc(sizeof(int));
483      cur->set_fn(cur, &cur->ival_default);
484      break;
485    default:
486      fprintf(stderr, "owl_variable_setup: invalid variable type\n");
487      return(-2);
488    }
489    owl_dict_insert_element(vd, cur->name, (void*)cur, NULL);
490  }
491  return 0;
492}
493
494void owl_variable_dict_add_variable(owl_vardict * vardict,
495                                    owl_variable * var) {
496  owl_dict_insert_element(vardict, var->name, (void*)var, (void(*)(void*))owl_variable_free);
497}
498
499owl_variable * owl_variable_newvar(char *name, char *summary, char * description) {
500  owl_variable * var = (owl_variable*)owl_malloc(sizeof(owl_variable));
501  memset(var, 0, sizeof(owl_variable));
502  var->name = owl_strdup(name);
503  var->summary = owl_strdup(summary);
504  var->description = owl_strdup(description);
505  return var;
506}
507
508void owl_variable_update(owl_variable *var, char *summary, char *desc) {
509  if(var->summary) owl_free(var->summary);
510  var->summary = owl_strdup(summary);
511  if(var->description) owl_free(var->description);
512  var->description = owl_strdup(desc);
513}
514
515void owl_variable_dict_newvar_string(owl_vardict * vd, char *name, char *summ, char * desc, char * initval) {
516  owl_variable *old = owl_variable_get_var(vd, name, OWL_VARIABLE_STRING);
517  if(old) {
518    owl_variable_update(old, summ, desc);
519    if(old->pval_default) owl_free(old->pval_default);
520    old->pval_default = owl_strdup(initval);
521  } else {
522    owl_variable * var = owl_variable_newvar(name, summ, desc);
523    var->type = OWL_VARIABLE_STRING;
524    var->pval_default = owl_strdup(initval);
525    var->set_fn = owl_variable_string_set_default;
526    var->set_fromstring_fn = owl_variable_string_set_fromstring_default;
527    var->get_fn = owl_variable_get_default;
528    var->get_tostring_fn = owl_variable_string_get_tostring_default;
529    var->free_fn = owl_variable_free_default;
530    var->set_fn(var, initval);
531    owl_variable_dict_add_variable(vd, var);
532  }
533}
534
535void owl_variable_dict_newvar_int(owl_vardict * vd, char *name, char *summ, char * desc, int initval) {
536  owl_variable *old = owl_variable_get_var(vd, name, OWL_VARIABLE_INT);
537  if(old) {
538    owl_variable_update(old, summ, desc);
539    old->ival_default = initval;
540  } else {
541    owl_variable * var = owl_variable_newvar(name, summ, desc);
542    var->type = OWL_VARIABLE_INT;
543    var->ival_default = initval;
544    var->validate_fn = owl_variable_int_validate_default;
545    var->set_fn = owl_variable_int_set_default;
546    var->set_fromstring_fn = owl_variable_int_set_fromstring_default;
547    var->get_fn = owl_variable_get_default;
548    var->get_tostring_fn = owl_variable_int_get_tostring_default;
549    var->free_fn = owl_variable_free_default;
550    var->val = owl_malloc(sizeof(int));
551    var->set_fn(var, &initval);
552    owl_variable_dict_add_variable(vd, var);
553  }
554}
555
556void owl_variable_dict_newvar_bool(owl_vardict * vd, char *name, char *summ, char * desc, int initval) {
557  owl_variable *old = owl_variable_get_var(vd, name, OWL_VARIABLE_BOOL);
558  if(old) {
559    owl_variable_update(old, summ, desc);
560    old->ival_default = initval;
561  } else {
562    owl_variable * var = owl_variable_newvar(name, summ, desc);
563    var->type = OWL_VARIABLE_BOOL;
564    var->ival_default = initval;
565    var->validate_fn = owl_variable_bool_validate_default;
566    var->set_fn = owl_variable_bool_set_default;
567    var->set_fromstring_fn = owl_variable_bool_set_fromstring_default;
568    var->get_fn = owl_variable_get_default;
569    var->get_tostring_fn = owl_variable_bool_get_tostring_default;
570    var->free_fn = owl_variable_free_default;
571    var->val = owl_malloc(sizeof(int));
572    var->set_fn(var, &initval);
573    owl_variable_dict_add_variable(vd, var);
574  }
575}
576
577void owl_variable_dict_free(owl_vardict *d) {
578  owl_dict_free_all(d, (void(*)(void*))owl_variable_free);
579}
580
581/* free the list with owl_variable_dict_namelist_free */
582void owl_variable_dict_get_names(owl_vardict *d, owl_list *l) {
583  owl_dict_get_keys(d, l);
584}
585
586void owl_variable_dict_namelist_free(owl_list *l) {
587  owl_list_free_all(l, owl_free);
588}
589
590void owl_variable_free(owl_variable *v) {
591  if (v->free_fn) v->free_fn(v);
592  owl_free(v);
593}
594
595
596char *owl_variable_get_description(owl_variable *v) {
597  return v->description;
598}
599
600char *owl_variable_get_summary(owl_variable *v) {
601  return v->summary;
602}
603
604char *owl_variable_get_validsettings(owl_variable *v) {
605  if (v->validsettings) {
606    return v->validsettings;
607  } else {
608    return "";
609  }
610}
611
612/* functions for getting and setting variable values */
613
614/* returns 0 on success, prints a status msg if msg is true */
615int owl_variable_set_fromstring(owl_vardict *d, char *name, char *value, int msg, int requirebool) {
616  owl_variable *v;
617  char buff2[1024];
618  if (!name) return(-1);
619  v = owl_dict_find_element(d, name);
620  if (v == NULL) {
621    if (msg) owl_function_error("Unknown variable %s", name);
622    return -1;
623  }
624  if (!v->set_fromstring_fn) {
625    if (msg) owl_function_error("Variable %s is read-only", name);
626    return -1;   
627  }
628  if (requirebool && v->type!=OWL_VARIABLE_BOOL) {
629    if (msg) owl_function_error("Variable %s is not a boolean", name);
630    return -1;   
631  }
632  if (0 != v->set_fromstring_fn(v, value)) {
633    if (msg) owl_function_error("Unable to set %s (must be %s)", name, 
634                                  owl_variable_get_validsettings(v));
635    return -1;
636  }
637  if (msg && v->get_tostring_fn) {
638    v->get_tostring_fn(v, buff2, 1024, v->val);
639    owl_function_makemsg("%s = '%s'", name, buff2);
640  }   
641  return 0;
642}
643 
644int owl_variable_set_string(owl_vardict *d, char *name, char *newval) {
645  owl_variable *v;
646  if (!name) return(-1);
647  v = owl_dict_find_element(d, name);
648  if (v == NULL || !v->set_fn) return(-1);
649  if (v->type!=OWL_VARIABLE_STRING) return(-1);
650  return v->set_fn(v, (void*)newval);
651}
652 
653int owl_variable_set_int(owl_vardict *d, char *name, int newval) {
654  owl_variable *v;
655  if (!name) return(-1);
656  v = owl_dict_find_element(d, name);
657  if (v == NULL || !v->set_fn) return(-1);
658  if (v->type!=OWL_VARIABLE_INT && v->type!=OWL_VARIABLE_BOOL) return(-1);
659  return v->set_fn(v, &newval);
660}
661 
662int owl_variable_set_bool_on(owl_vardict *d, char *name) {
663  return owl_variable_set_int(d,name,1);
664}
665
666int owl_variable_set_bool_off(owl_vardict *d, char *name) {
667  return owl_variable_set_int(d,name,0);
668}
669
670int owl_variable_get_tostring(owl_vardict *d, char *name, char *buf, int bufsize) {
671  owl_variable *v;
672  if (!name) return(-1);
673  v = owl_dict_find_element(d, name);
674  if (v == NULL || !v->get_tostring_fn) return(-1);
675  return v->get_tostring_fn(v, buf, bufsize, v->val);
676}
677
678int owl_variable_get_default_tostring(owl_vardict *d, char *name, char *buf, int bufsize) {
679  owl_variable *v;
680  if (!name) return(-1);
681  v = owl_dict_find_element(d, name);
682  if (v == NULL || !v->get_tostring_fn) return(-1);
683  if (v->type == OWL_VARIABLE_INT || v->type == OWL_VARIABLE_BOOL) {
684    return v->get_tostring_fn(v, buf, bufsize, &(v->ival_default));
685  } else {
686    return v->get_tostring_fn(v, buf, bufsize, v->pval_default);
687  }
688}
689
690owl_variable *owl_variable_get_var(owl_vardict *d, char *name, int require_type) {
691  owl_variable *v;
692  if (!name) return(NULL);
693  v = owl_dict_find_element(d, name);
694  if (v == NULL || !v->get_fn || v->type != require_type) return(NULL);
695  return v;
696}
697
698/* returns a reference */
699void *owl_variable_get(owl_vardict *d, char *name, int require_type) {
700  owl_variable *v = owl_variable_get_var(d, name, require_type);
701  if(v == NULL) return NULL;
702  return v->get_fn(v);
703}
704
705/* returns a reference */
706char *owl_variable_get_string(owl_vardict *d, char *name) {
707  return (char*)owl_variable_get(d,name, OWL_VARIABLE_STRING);
708}
709
710/* returns a reference */
711void *owl_variable_get_other(owl_vardict *d, char *name) {
712  return (char*)owl_variable_get(d,name, OWL_VARIABLE_OTHER);
713}
714
715int owl_variable_get_int(owl_vardict *d, char *name) {
716  int *pi;
717  pi = (int*)owl_variable_get(d,name,OWL_VARIABLE_INT);
718  if (!pi) return(-1);
719  return(*pi);
720}
721
722int owl_variable_get_bool(owl_vardict *d, char *name) {
723  int *pi;
724  pi = (int*)owl_variable_get(d,name,OWL_VARIABLE_BOOL);
725  if (!pi) return(-1);
726  return(*pi);
727}
728
729void owl_variable_describe(owl_vardict *d, char *name, owl_fmtext *fm) {
730  char defaultbuf[50];
731  char buf[1024];
732  int buflen = 1023;
733  owl_variable *v;
734
735  if (!name
736      || (v = owl_dict_find_element(d, name)) == NULL 
737      || !v->get_fn) {
738    snprintf(buf, buflen, "     No such variable '%s'\n", name);     
739    owl_fmtext_append_normal(fm, buf);
740    return;
741  }
742  if (v->type == OWL_VARIABLE_INT || v->type == OWL_VARIABLE_BOOL) {
743    v->get_tostring_fn(v, defaultbuf, 50, &(v->ival_default));
744  } else {
745    v->get_tostring_fn(v, defaultbuf, 50, v->pval_default);
746  }
747  snprintf(buf, buflen, OWL_TABSTR "%-20s - %s (default: '%s')\n", 
748                  v->name, 
749                  owl_variable_get_summary(v), defaultbuf);
750  owl_fmtext_append_normal(fm, buf);
751}
752
753void owl_variable_get_help(owl_vardict *d, char *name, owl_fmtext *fm) {
754  char buff[1024];
755  int bufflen = 1023;
756  owl_variable *v;
757
758  if (!name
759      || (v = owl_dict_find_element(d, name)) == NULL 
760      || !v->get_fn) {
761    owl_fmtext_append_normal(fm, "No such variable...\n");
762    return;
763  }
764
765  owl_fmtext_append_bold(fm, "OWL VARIABLE\n\n");
766  owl_fmtext_append_normal(fm, OWL_TABSTR);
767  owl_fmtext_append_normal(fm, name);
768  owl_fmtext_append_normal(fm, " - ");
769  owl_fmtext_append_normal(fm, v->summary);
770  owl_fmtext_append_normal(fm, "\n\n");
771
772  owl_fmtext_append_normal(fm, "Current:        ");
773  owl_variable_get_tostring(d, name, buff, bufflen);
774  owl_fmtext_append_normal(fm, buff);
775  owl_fmtext_append_normal(fm, "\n\n");
776
777
778  if (v->type == OWL_VARIABLE_INT || v->type == OWL_VARIABLE_BOOL) {
779    v->get_tostring_fn(v, buff, bufflen, &(v->ival_default));
780  } else {
781    v->get_tostring_fn(v, buff, bufflen, v->pval_default);
782  }
783  owl_fmtext_append_normal(fm, "Default:        ");
784  owl_fmtext_append_normal(fm, buff);
785  owl_fmtext_append_normal(fm, "\n\n");
786
787  owl_fmtext_append_normal(fm, "Valid Settings: ");
788  owl_fmtext_append_normal(fm, owl_variable_get_validsettings(v));
789  owl_fmtext_append_normal(fm, "\n\n");
790
791  if (v->description && *v->description) {
792    owl_fmtext_append_normal(fm, "Description:\n");
793    owl_fmtext_append_normal(fm, owl_variable_get_description(v));
794    owl_fmtext_append_normal(fm, "\n\n");
795  }
796}
797
798
799
800
801/**************************************************************************/
802/*********************** GENERAL TYPE-SPECIFIC ****************************/
803/**************************************************************************/
804
805/* default common functions */
806
807void *owl_variable_get_default(owl_variable *v) {
808  return v->val;
809}
810
811void owl_variable_free_default(owl_variable *v) {
812  if (v->val) owl_free(v->val);
813}
814
815/* default functions for booleans */
816
817int owl_variable_bool_validate_default(owl_variable *v, void *newval) {
818  if (newval == NULL) return(0);
819  else if (*(int*)newval==1 || *(int*)newval==0) return(1);
820  else return (0);
821}
822
823int owl_variable_bool_set_default(owl_variable *v, void *newval) {
824  if (v->validate_fn) {
825    if (!v->validate_fn(v, newval)) return(-1);
826  }
827  *(int*)v->val = *(int*)newval;
828  return(0);
829}
830
831int owl_variable_bool_set_fromstring_default(owl_variable *v, char *newval) {
832  int i;
833  if (!strcmp(newval, "on")) i=1;
834  else if (!strcmp(newval, "off")) i=0;
835  else return(-1);
836  return (v->set_fn(v, &i));
837}
838
839int owl_variable_bool_get_tostring_default(owl_variable *v, char* buf, int bufsize, void *val) {
840  if (val == NULL) {
841    snprintf(buf, bufsize, "<null>");
842    return -1;
843  } else if (*(int*)val == 0) {
844    snprintf(buf, bufsize, "off");
845    return 0;
846  } else if (*(int*)val == 1) {
847    snprintf(buf, bufsize, "on");
848    return 0;
849  } else {
850    snprintf(buf, bufsize, "<invalid>");
851    return -1;
852  }
853}
854
855/* default functions for integers */
856
857int owl_variable_int_validate_default(owl_variable *v, void *newval) {
858  if (newval == NULL) return(0);
859  else return (1);
860}
861
862int owl_variable_int_set_default(owl_variable *v, void *newval) {
863  if (v->validate_fn) {
864    if (!v->validate_fn(v, newval)) return(-1);
865  }
866  *(int*)v->val = *(int*)newval;
867  return(0);
868}
869
870int owl_variable_int_set_fromstring_default(owl_variable *v, char *newval) {
871  int i;
872  char *ep = "x";
873  i = strtol(newval, &ep, 10);
874  if (*ep || ep==newval) return(-1);
875  return (v->set_fn(v, &i));
876}
877
878int owl_variable_int_get_tostring_default(owl_variable *v, char* buf, int bufsize, void *val) {
879  if (val == NULL) {
880    snprintf(buf, bufsize, "<null>");
881    return -1;
882  } else {
883    snprintf(buf, bufsize, "%d", *(int*)val);
884    return 0;
885  } 
886}
887
888/* default functions for enums (a variant of integers) */
889
890int owl_variable_enum_validate(owl_variable *v, void *newval) { 
891  char **enums;
892  int nenums, val;
893  if (newval == NULL) return(0);
894  enums = atokenize(v->validsettings, ",", &nenums);
895  if (enums == NULL) return(0);
896  atokenize_free(enums, nenums);
897  val = *(int*)newval;
898  if (val < 0 || val >= nenums) {
899    return(0);
900  }
901  return(1);
902}
903
904int owl_variable_enum_set_fromstring(owl_variable *v, char *newval) {
905  char **enums;
906  int nenums, i, val=-1;
907  if (newval == NULL) return(-1);
908  enums = atokenize(v->validsettings, ",", &nenums);
909  if (enums == NULL) return(-1);
910  for (i=0; i<nenums; i++) {
911    if (0==strcmp(newval, enums[i])) {
912      val = i;
913    }
914  }
915  atokenize_free(enums, nenums);
916  if (val == -1) return(-1);
917  return (v->set_fn(v, &val));
918}
919
920int owl_variable_enum_get_tostring(owl_variable *v, char* buf, int bufsize, void *val) {
921  char **enums;
922  int nenums, i;
923
924  if (val == NULL) {
925    snprintf(buf, bufsize, "<null>");
926    return -1;
927  }
928  enums = atokenize(v->validsettings, ",", &nenums);
929  i = *(int*)val;
930  if (i<0 || i>=nenums) {
931    snprintf(buf, bufsize, "<invalid:%d>",i);
932    atokenize_free(enums, nenums);
933    return(-1);
934  }
935  snprintf(buf, bufsize, "%s", enums[i]);
936  return 0;
937}
938
939/* default functions for stringeans */
940
941int owl_variable_string_validate_default(struct _owl_variable *v, void *newval) {
942  if (newval == NULL) return(0);
943  else return (1);
944}
945
946int owl_variable_string_set_default(owl_variable *v, void *newval) {
947  if (v->validate_fn) {
948    if (!v->validate_fn(v, newval)) return(-1);
949  }
950  if (v->val) owl_free(v->val);
951  v->val = owl_strdup(newval);
952  return(0);
953}
954
955int owl_variable_string_set_fromstring_default(owl_variable *v, char *newval) {
956  return (v->set_fn(v, newval));
957}
958
959int owl_variable_string_get_tostring_default(owl_variable *v, char* buf, int bufsize, void *val) {
960  if (val == NULL) {
961    snprintf(buf, bufsize, "<null>");
962    return -1;
963  } else {
964    snprintf(buf, bufsize, "%s", (char*)val);
965    return 0;
966  }
967}
968
969
970
971/**************************************************************************/
972/************************* REGRESSION TESTS *******************************/
973/**************************************************************************/
974
975#ifdef OWL_INCLUDE_REG_TESTS
976
977#include "test.h"
978
979int owl_variable_regtest(void) {
980  owl_vardict vd;
981  int numfailed=0;
982  char buf[1024];
983  owl_variable * v;
984
985  in_regtest = 1;
986
987  printf("# BEGIN testing owl_variable\n");
988  FAIL_UNLESS("setup", 0==owl_variable_dict_setup(&vd));
989
990  FAIL_UNLESS("get bool", 0==owl_variable_get_bool(&vd,"rxping"));
991  FAIL_UNLESS("get bool (no such)", -1==owl_variable_get_bool(&vd,"mumble"));
992  FAIL_UNLESS("get bool as string 1", 0==owl_variable_get_tostring(&vd,"rxping", buf, 1024));
993  FAIL_UNLESS("get bool as string 2", 0==strcmp(buf,"off"));
994  FAIL_UNLESS("set bool 1", 0==owl_variable_set_bool_on(&vd,"rxping"));
995  FAIL_UNLESS("get bool 2", 1==owl_variable_get_bool(&vd,"rxping"));
996  FAIL_UNLESS("set bool 3", 0==owl_variable_set_fromstring(&vd,"rxping","off",0,0));
997  FAIL_UNLESS("get bool 4", 0==owl_variable_get_bool(&vd,"rxping"));
998  FAIL_UNLESS("set bool 5", -1==owl_variable_set_fromstring(&vd,"rxping","xxx",0,0));
999  FAIL_UNLESS("get bool 6", 0==owl_variable_get_bool(&vd,"rxping"));
1000
1001
1002  FAIL_UNLESS("get string", 0==strcmp("~/zlog/people", owl_variable_get_string(&vd,"logpath")));
1003  FAIL_UNLESS("set string 7", 0==owl_variable_set_string(&vd,"logpath","whee"));
1004  FAIL_UNLESS("get string", 0==strcmp("whee", owl_variable_get_string(&vd,"logpath")));
1005
1006  FAIL_UNLESS("get int", 8==owl_variable_get_int(&vd,"typewinsize"));
1007  FAIL_UNLESS("get int (no such)", -1==owl_variable_get_int(&vd,"mmble"));
1008  FAIL_UNLESS("get int as string 1", 0==owl_variable_get_tostring(&vd,"typewinsize", buf, 1024));
1009  FAIL_UNLESS("get int as string 2", 0==strcmp(buf,"8"));
1010  FAIL_UNLESS("set int 1", 0==owl_variable_set_int(&vd,"typewinsize",12));
1011  FAIL_UNLESS("get int 2", 12==owl_variable_get_int(&vd,"typewinsize"));
1012  FAIL_UNLESS("set int 1b", -1==owl_variable_set_int(&vd,"typewinsize",-3));
1013  FAIL_UNLESS("get int 2b", 12==owl_variable_get_int(&vd,"typewinsize"));
1014  FAIL_UNLESS("set int 3", 0==owl_variable_set_fromstring(&vd,"typewinsize","9",0,0));
1015  FAIL_UNLESS("get int 4", 9==owl_variable_get_int(&vd,"typewinsize"));
1016  FAIL_UNLESS("set int 5", -1==owl_variable_set_fromstring(&vd,"typewinsize","xxx",0,0));
1017  FAIL_UNLESS("set int 6", -1==owl_variable_set_fromstring(&vd,"typewinsize","",0,0));
1018  FAIL_UNLESS("get int 7", 9==owl_variable_get_int(&vd,"typewinsize"));
1019
1020  FAIL_UNLESS("get enum", OWL_WEBBROWSER_NETSCAPE==owl_variable_get_int(&vd,"webbrowser"));
1021  FAIL_UNLESS("get enum as string 1", 0==owl_variable_get_tostring(&vd,"webbrowser", buf, 1024));
1022  FAIL_UNLESS("get enum as string 2", 0==strcmp(buf,"netscape"));
1023  FAIL_UNLESS("set enum 1", 0==owl_variable_set_int(&vd,"webbrowser",OWL_WEBBROWSER_GALEON));
1024  FAIL_UNLESS("get enum 2", OWL_WEBBROWSER_GALEON==owl_variable_get_int(&vd,"webbrowser"));
1025  FAIL_UNLESS("set enum 1b", -1==owl_variable_set_int(&vd,"webbrowser",-3));
1026  FAIL_UNLESS("set enum 1b", -1==owl_variable_set_int(&vd,"webbrowser",209));
1027  FAIL_UNLESS("get enum 2b", OWL_WEBBROWSER_GALEON==owl_variable_get_int(&vd,"webbrowser"));
1028  FAIL_UNLESS("set enum 3", 0==owl_variable_set_fromstring(&vd,"webbrowser","none",0,0));
1029  FAIL_UNLESS("get enum 4", OWL_WEBBROWSER_NONE==owl_variable_get_int(&vd,"webbrowser"));
1030  FAIL_UNLESS("set enum 5", 0==owl_variable_set_fromstring(&vd,"webbrowser","netscape",0,0));
1031  FAIL_UNLESS("get enum 6", OWL_WEBBROWSER_NETSCAPE==owl_variable_get_int(&vd,"webbrowser"));
1032  FAIL_UNLESS("set enum 7", -1==owl_variable_set_fromstring(&vd,"webbrowser","xxx",0,0));
1033  FAIL_UNLESS("set enum 8", -1==owl_variable_set_fromstring(&vd,"webbrowser","",0,0));
1034  FAIL_UNLESS("set enum 9", -1==owl_variable_set_fromstring(&vd,"webbrowser","netscapey",0,0));
1035  FAIL_UNLESS("get enum 10", OWL_WEBBROWSER_NETSCAPE==owl_variable_get_int(&vd,"webbrowser"));
1036
1037  owl_variable_dict_newvar_string(&vd, "stringvar", "", "", "testval");
1038  FAIL_UNLESS("get new string var", NULL != (v = owl_variable_get(&vd, "stringvar", OWL_VARIABLE_STRING)));
1039  FAIL_UNLESS("get new string val", !strcmp("testval", owl_variable_get_string(&vd, "stringvar")));
1040  owl_variable_set_string(&vd, "stringvar", "new val");
1041  FAIL_UNLESS("update string val", !strcmp("new val", owl_variable_get_string(&vd, "stringvar")));
1042
1043  owl_variable_dict_newvar_int(&vd, "intvar", "", "", 47);
1044  FAIL_UNLESS("get new int var", NULL != (v = owl_variable_get(&vd, "intvar", OWL_VARIABLE_INT)));
1045  FAIL_UNLESS("get new int val", 47 == owl_variable_get_int(&vd, "intvar"));
1046  owl_variable_set_int(&vd, "intvar", 17);
1047  FAIL_UNLESS("update bool val", 17 == owl_variable_get_int(&vd, "intvar"));
1048
1049  owl_variable_dict_newvar_bool(&vd, "boolvar", "", "", 1);
1050  FAIL_UNLESS("get new bool var", NULL != (v = owl_variable_get(&vd, "boolvar", OWL_VARIABLE_BOOL)));
1051  FAIL_UNLESS("get new bool val", owl_variable_get_bool(&vd, "boolvar"));
1052  owl_variable_set_bool_off(&vd, "boolvar");
1053  FAIL_UNLESS("update string val", !owl_variable_get_bool(&vd, "boolvar"));
1054
1055  owl_variable_dict_free(&vd);
1056
1057  /* if (numfailed) printf("*** WARNING: failures encountered with owl_variable\n"); */
1058  printf("# END testing owl_variable (%d failures)\n", numfailed);
1059  return(numfailed);
1060}
1061
1062
1063#endif /* OWL_INCLUDE_REG_TESTS */
Note: See TracBrowser for help on using the repository browser.