source: variable.c @ 96134cb

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