source: variable.c @ 1cf3f8d3

barnowl_perlaimdebianrelease-1.4release-1.5release-1.6release-1.7release-1.8release-1.9
Last change on this file since 1cf3f8d3 was 1cf3f8d3, checked in by Nelson Elhage <nelhage@mit.edu>, 13 years ago
Make the built-in regression tests output TAP and add a perl wrapper to call it.
  • Property mode set to 100644
File size: 38.5 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( "zsig" /* %OwlVarStub */, "",
212                 "zephyr signature", 
213                 "If 'zsigproc' is not set, this string will be used\n"
214                 "as a zsig.  If this is also unset, the 'zwrite-signature'\n"
215                 "zephyr variable will be used instead.\n"),
216
217  OWLVAR_STRING( "appendtosepbar" /* %OwlVarStub */, "",
218                 "string to append to the end of the sepbar",
219                 "The sepbar is the bar separating the top and bottom\n"
220                 "of the owl screen.  Any string specified here will\n"
221                 "be displayed on the right of the sepbar\n"),
222
223  OWLVAR_BOOL( "zaway" /* %OwlVarStub */, 0,
224               "turn zaway on or off", "" ),
225
226  OWLVAR_STRING( "zaway_msg" /* %OwlVarStub */, 
227                 OWL_DEFAULT_ZAWAYMSG,
228                 "zaway msg for responding to zephyrs when away", "" ),
229
230  OWLVAR_STRING( "zaway_msg_default" /* %OwlVarStub */, 
231                 OWL_DEFAULT_ZAWAYMSG,
232                 "default zaway message", "" ),
233
234  OWLVAR_BOOL_FULL( "aaway" /* %OwlVarStub */, 0,
235                    "Set AIM away status",
236                    "",
237                    NULL, owl_variable_aaway_set, NULL),
238
239  OWLVAR_STRING( "aaway_msg" /* %OwlVarStub */, 
240                 OWL_DEFAULT_AAWAYMSG,
241                 "AIM away msg for responding when away", "" ),
242
243  OWLVAR_STRING( "aaway_msg_default" /* %OwlVarStub */, 
244                 OWL_DEFAULT_AAWAYMSG,
245                 "default AIM away message", "" ),
246
247  OWLVAR_STRING( "view_home" /* %OwlVarStub */, "all",
248                 "home view to switch to after 'X' and 'V'", 
249                 "SEE ALSO: view, filter\n" ),
250
251  OWLVAR_STRING( "alert_filter" /* %OwlVarStub */, "none",
252                 "filter on which to trigger alert actions",
253                 "" ),
254
255  OWLVAR_STRING( "alert_action" /* %OwlVarStub */, "nop",
256                 "owl command to execute for alert actions",
257                 "" ),
258
259  OWLVAR_STRING_FULL( "tty" /* %OwlVarStub */, "", "tty name for zephyr location", "",
260                      NULL, owl_variable_tty_set, NULL),
261
262  OWLVAR_STRING( "default_style" /* %OwlVarStub */, "__unspecified__",
263                 "name of the default formatting style",
264                 "This sets the default message formatting style.\n"
265                 "Styles may be created with the 'style' command.\n"
266                 "Some built-in styles include:\n"
267                 "   default  - the default owl formatting\n"
268                 "   basic    - simple 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_ENUM( "scrollmode" /* %OwlVarStub */, OWL_SCROLLMODE_NORMAL,
316               "how to scroll up and down",
317               "This controls how the screen is scrolled as the\n"
318               "cursor moves between messages being displayed.\n"
319               "The following modes are supported:\n\n"
320               "   normal      - This is the owl default.  Scrolling happens\n"
321               "                 when it needs to, and an attempt is made to\n"
322               "                 keep the current message roughly near\n"
323               "                 the middle of the screen.\n"
324               "   top         - The current message will always be the\n"
325               "                 the top message displayed.\n"
326               "   neartop     - The current message will be one down\n"
327               "                 from the top message displayed,\n"
328               "                 where possible.\n"
329               "   center      - An attempt is made to keep the current\n"
330               "                 message near the center of the screen.\n"
331               "   paged       - The top message displayed only changes\n"
332               "                 when user moves the cursor to the top\n"
333               "                 or bottom of the screen.  When it moves,\n"
334               "                 the screen will be paged up or down and\n"
335               "                 the cursor will be near the top or\n"
336               "                 the bottom.\n"
337               "   pagedcenter - The top message displayed only changes\n"
338               "                 when user moves the cursor to the top\n"
339               "                 or bottom of the screen.  When it moves,\n"
340               "                 the screen will be paged up or down and\n"
341               "                 the cursor will be near the center.\n",
342               "normal,top,neartop,center,paged,pagedcenter" ),
343
344  OWLVAR_ENUM( "webbrowser" /* %OwlVarStub */, OWL_WEBBROWSER_NETSCAPE,
345               "web browser to use to launch URLs",
346               "When the 'w' key is pressed, this browser is used\n"
347               "to display the requested URL.\n",
348               "none,netscape,galeon,opera" ),
349
350
351  OWLVAR_BOOL( "_followlast" /* %OwlVarStub */, 0,
352               "enable automatic following of the last zephyr",
353               "If the cursor is at the last message, it will\n"
354               "continue to follow the last message if this is set.\n"
355               "Note that this is currently risky as you might accidentally\n"
356               "delete a message right as it came in.\n" ),
357
358  /* This MUST be last... */
359  { NULL, 0, NULL, 0, NULL, NULL, NULL, NULL,
360    NULL, NULL, NULL, NULL, NULL, NULL }
361
362};
363
364/**************************************************************************/
365/*********************** SPECIFIC TO VARIABLES ****************************/
366/**************************************************************************/
367
368
369/* commonly useful */
370
371int owl_variable_int_validate_gt0(owl_variable *v, void *newval)
372{
373  if (newval == NULL) return(0);
374  else if (*(int*)newval < 1) return(0);
375  else return (1);
376}
377
378int owl_variable_int_validate_positive(owl_variable *v, void *newval)
379{
380  if (newval == NULL) return(0);
381  else if (*(int*)newval < 0) return(0);
382  else return (1);
383}
384
385/* typewinsize */
386int owl_variable_typewinsize_set(owl_variable *v, void *newval)
387{
388  int rv;
389  rv = owl_variable_int_set_default(v, newval);
390  if (0 == rv) owl_function_resize();
391  return(rv);
392}
393
394/* debug (cache value in g->debug) */
395int owl_variable_debug_set(owl_variable *v, void *newval)
396{
397  if (newval && (*(int*)newval == 1 || *(int*)newval == 0)) {
398    g.debug = *(int*)newval;
399  }
400  return owl_variable_bool_set_default(v, newval);
401}
402
403/* When 'aaway' is changed, need to notify the AIM server */
404int owl_variable_aaway_set(owl_variable *v, void *newval)
405{
406  if (newval) {
407    if (*(int*)newval == 1) {
408      owl_aim_set_awaymsg(owl_global_get_aaway_msg(&g));
409    } else if (*(int*)newval == 0) {
410      owl_aim_set_awaymsg("");
411    }
412  }
413  return owl_variable_bool_set_default(v, newval);
414}
415
416int owl_variable_pseudologins_set(owl_variable *v, void *newval)
417{
418  if (newval) {
419    if (*(int*)newval == 1) {
420      owl_function_zephyr_buddy_check(0);
421    }
422  }
423  return owl_variable_bool_set_default(v, newval);
424}
425
426/* note that changing the value of this will clobber
427 * any user setting of this */
428int owl_variable_disable_ctrl_d_set(owl_variable *v, void *newval)
429{
430
431  if (in_regtest) return owl_variable_int_set_default(v, newval);
432
433  if (newval && !owl_context_is_startup(owl_global_get_context(&g))) {
434    if (*(int*)newval == 2) {
435      owl_function_command_norv("bindkey editmulti C-d command edit:delete-next-char");
436    } else if (*(int*)newval == 1) {
437      owl_function_command_norv("bindkey editmulti C-d command editmulti:done-or-delete");
438    } else {
439      owl_function_command_norv("bindkey editmulti C-d command editmulti:done");
440    }
441  } 
442  return owl_variable_int_set_default(v, newval); 
443}
444
445int owl_variable_tty_set(owl_variable *v, void *newval)
446{
447  owl_zephyr_set_locationinfo(owl_global_get_hostname(&g), newval);
448  return(owl_variable_string_set_default(v, newval));
449}
450
451
452/**************************************************************************/
453/****************************** GENERAL ***********************************/
454/**************************************************************************/
455
456int owl_variable_dict_setup(owl_vardict *vd) {
457  owl_variable *cur;
458  if (owl_dict_create(vd)) return(-1);
459  for (cur = variables_to_init; cur->name != NULL; cur++) {
460    switch (cur->type) {
461    case OWL_VARIABLE_OTHER:
462      cur->set_fn(cur, cur->pval_default);
463      break;
464    case OWL_VARIABLE_STRING:
465      if (!cur->validate_fn) 
466        cur->validate_fn = owl_variable_string_validate_default;
467      if (!cur->set_fn) 
468        cur->set_fn = owl_variable_string_set_default;
469      if (!cur->set_fromstring_fn) 
470        cur->set_fromstring_fn = owl_variable_string_set_fromstring_default;
471      if (!cur->get_fn) 
472        cur->get_fn = owl_variable_get_default;
473      if (!cur->get_tostring_fn) 
474        cur->get_tostring_fn = owl_variable_string_get_tostring_default;     
475      if (!cur->free_fn) 
476        cur->free_fn = owl_variable_free_default;
477      cur->set_fn(cur, cur->pval_default);
478      break;
479    case OWL_VARIABLE_BOOL:
480      if (!cur->validate_fn) 
481        cur->validate_fn = owl_variable_bool_validate_default;
482      if (!cur->set_fn) 
483        cur->set_fn = owl_variable_bool_set_default;
484      if (!cur->set_fromstring_fn) 
485        cur->set_fromstring_fn = owl_variable_bool_set_fromstring_default;
486      if (!cur->get_fn) 
487        cur->get_fn = owl_variable_get_default;
488      if (!cur->get_tostring_fn) 
489        cur->get_tostring_fn = owl_variable_bool_get_tostring_default;     
490      if (!cur->free_fn) 
491        cur->free_fn = owl_variable_free_default;
492      cur->val = owl_malloc(sizeof(int));
493      cur->set_fn(cur, &cur->ival_default);
494      break;
495    case OWL_VARIABLE_INT:
496      if (!cur->validate_fn) 
497        cur->validate_fn = owl_variable_int_validate_default;
498      if (!cur->set_fn) 
499        cur->set_fn = owl_variable_int_set_default;
500      if (!cur->set_fromstring_fn) 
501        cur->set_fromstring_fn = owl_variable_int_set_fromstring_default;
502      if (!cur->get_fn) 
503        cur->get_fn = owl_variable_get_default;
504      if (!cur->get_tostring_fn) 
505        cur->get_tostring_fn = owl_variable_int_get_tostring_default;     
506      if (!cur->free_fn) 
507        cur->free_fn = owl_variable_free_default;
508      cur->val = owl_malloc(sizeof(int));
509      cur->set_fn(cur, &cur->ival_default);
510      break;
511    default:
512      fprintf(stderr, "owl_variable_setup: invalid variable type\n");
513      return(-2);
514    }
515    owl_dict_insert_element(vd, cur->name, (void*)cur, NULL);
516  }
517  return 0;
518}
519
520void owl_variable_dict_add_variable(owl_vardict * vardict,
521                                    owl_variable * var) {
522  owl_dict_insert_element(vardict, var->name, (void*)var, NULL);
523}
524
525owl_variable * owl_variable_newvar(char *name, char *summary, char * description) {
526  owl_variable * var = (owl_variable*)owl_malloc(sizeof(owl_variable));
527  memset(var, 0, sizeof(owl_variable));
528  var->name = owl_strdup(name);
529  var->summary = owl_strdup(summary);
530  var->description = owl_strdup(description);
531  return var;
532}
533
534void owl_variable_dict_newvar_string(owl_vardict * vd, char *name, char *summ, char * desc, char * initval) {
535  owl_variable * var = owl_variable_newvar(name, summ, desc);
536  var->type = OWL_VARIABLE_STRING;
537  var->pval_default = owl_strdup(initval);
538  var->set_fn = owl_variable_string_set_default;
539  var->set_fromstring_fn = owl_variable_string_set_fromstring_default;
540  var->get_fn = owl_variable_get_default;
541  var->get_tostring_fn = owl_variable_string_get_tostring_default;
542  var->free_fn = owl_variable_free_default;
543  var->set_fn(var, initval);
544  owl_variable_dict_add_variable(vd, var);
545}
546
547void owl_variable_dict_newvar_int(owl_vardict * vd, char *name, char *summ, char * desc, int initval) {
548  owl_variable * var = owl_variable_newvar(name, summ, desc);
549  var->type = OWL_VARIABLE_INT;
550  var->ival_default = initval;
551  var->validate_fn = owl_variable_int_validate_default;
552  var->set_fn = owl_variable_int_set_default;
553  var->set_fromstring_fn = owl_variable_int_set_fromstring_default;
554  var->get_fn = owl_variable_get_default;
555  var->get_tostring_fn = owl_variable_int_get_tostring_default;
556  var->free_fn = owl_variable_free_default;
557  var->val = owl_malloc(sizeof(int));
558  var->set_fn(var, &initval);
559  owl_variable_dict_add_variable(vd, var);
560}
561
562void owl_variable_dict_newvar_bool(owl_vardict * vd, char *name, char *summ, char * desc, int initval) {
563  owl_variable * var = owl_variable_newvar(name, summ, desc);
564  var->type = OWL_VARIABLE_BOOL;
565  var->ival_default = initval;
566  var->validate_fn = owl_variable_bool_validate_default;
567  var->set_fn = owl_variable_bool_set_default;
568  var->set_fromstring_fn = owl_variable_bool_set_fromstring_default;
569  var->get_fn = owl_variable_get_default;
570  var->get_tostring_fn = owl_variable_bool_get_tostring_default;
571  var->free_fn = owl_variable_free_default;
572  var->val = owl_malloc(sizeof(int));
573  var->set_fn(var, &initval);
574  owl_variable_dict_add_variable(vd, var);
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}
593
594
595char *owl_variable_get_description(owl_variable *v) {
596  return v->description;
597}
598
599char *owl_variable_get_summary(owl_variable *v) {
600  return v->summary;
601}
602
603char *owl_variable_get_validsettings(owl_variable *v) {
604  if (v->validsettings) {
605    return v->validsettings;
606  } else {
607    return "";
608  }
609}
610
611/* functions for getting and setting variable values */
612
613/* returns 0 on success, prints a status msg if msg is true */
614int owl_variable_set_fromstring(owl_vardict *d, char *name, char *value, int msg, int requirebool) {
615  owl_variable *v;
616  char buff2[1024];
617  if (!name) return(-1);
618  v = owl_dict_find_element(d, name);
619  if (v == NULL) {
620    if (msg) owl_function_error("Unknown variable %s", name);
621    return -1;
622  }
623  if (!v->set_fromstring_fn) {
624    if (msg) owl_function_error("Variable %s is read-only", name);
625    return -1;   
626  }
627  if (requirebool && v->type!=OWL_VARIABLE_BOOL) {
628    if (msg) owl_function_error("Variable %s is not a boolean", name);
629    return -1;   
630  }
631  if (0 != v->set_fromstring_fn(v, value)) {
632    if (msg) owl_function_error("Unable to set %s (must be %s)", name, 
633                                  owl_variable_get_validsettings(v));
634    return -1;
635  }
636  if (msg && v->get_tostring_fn) {
637    v->get_tostring_fn(v, buff2, 1024, v->val);
638    owl_function_makemsg("%s = '%s'", name, buff2);
639  }   
640  return 0;
641}
642 
643int owl_variable_set_string(owl_vardict *d, char *name, char *newval) {
644  owl_variable *v;
645  if (!name) return(-1);
646  v = owl_dict_find_element(d, name);
647  if (v == NULL || !v->set_fn) return(-1);
648  if (v->type!=OWL_VARIABLE_STRING) return(-1);
649  return v->set_fn(v, (void*)newval);
650}
651 
652int owl_variable_set_int(owl_vardict *d, char *name, int newval) {
653  owl_variable *v;
654  if (!name) return(-1);
655  v = owl_dict_find_element(d, name);
656  if (v == NULL || !v->set_fn) return(-1);
657  if (v->type!=OWL_VARIABLE_INT && v->type!=OWL_VARIABLE_BOOL) return(-1);
658  return v->set_fn(v, &newval);
659}
660 
661int owl_variable_set_bool_on(owl_vardict *d, char *name) {
662  return owl_variable_set_int(d,name,1);
663}
664
665int owl_variable_set_bool_off(owl_vardict *d, char *name) {
666  return owl_variable_set_int(d,name,0);
667}
668
669int owl_variable_get_tostring(owl_vardict *d, char *name, char *buf, int bufsize) {
670  owl_variable *v;
671  if (!name) return(-1);
672  v = owl_dict_find_element(d, name);
673  if (v == NULL || !v->get_tostring_fn) return(-1);
674  return v->get_tostring_fn(v, buf, bufsize, v->val);
675}
676
677int owl_variable_get_default_tostring(owl_vardict *d, char *name, char *buf, int bufsize) {
678  owl_variable *v;
679  if (!name) return(-1);
680  v = owl_dict_find_element(d, name);
681  if (v == NULL || !v->get_tostring_fn) return(-1);
682  if (v->type == OWL_VARIABLE_INT || v->type == OWL_VARIABLE_BOOL) {
683    return v->get_tostring_fn(v, buf, bufsize, &(v->ival_default));
684  } else {
685    return v->get_tostring_fn(v, buf, bufsize, v->pval_default);
686  }
687}
688
689/* returns a reference */
690void *owl_variable_get(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->get_fn(v);
696}
697
698/* returns a reference */
699char *owl_variable_get_string(owl_vardict *d, char *name) {
700  return (char*)owl_variable_get(d,name, OWL_VARIABLE_STRING);
701}
702
703/* returns a reference */
704void *owl_variable_get_other(owl_vardict *d, char *name) {
705  return (char*)owl_variable_get(d,name, OWL_VARIABLE_OTHER);
706}
707
708int owl_variable_get_int(owl_vardict *d, char *name) {
709  int *pi;
710  pi = (int*)owl_variable_get(d,name,OWL_VARIABLE_INT);
711  if (!pi) return(-1);
712  return(*pi);
713}
714
715int owl_variable_get_bool(owl_vardict *d, char *name) {
716  int *pi;
717  pi = (int*)owl_variable_get(d,name,OWL_VARIABLE_BOOL);
718  if (!pi) return(-1);
719  return(*pi);
720}
721
722void owl_variable_describe(owl_vardict *d, char *name, owl_fmtext *fm) {
723  char defaultbuf[50];
724  char buf[1024];
725  int buflen = 1023;
726  owl_variable *v;
727
728  if (!name
729      || (v = owl_dict_find_element(d, name)) == NULL 
730      || !v->get_fn) {
731    snprintf(buf, buflen, "     No such variable '%s'\n", name);     
732    owl_fmtext_append_normal(fm, buf);
733    return;
734  }
735  if (v->type == OWL_VARIABLE_INT || v->type == OWL_VARIABLE_BOOL) {
736    v->get_tostring_fn(v, defaultbuf, 50, &(v->ival_default));
737  } else {
738    v->get_tostring_fn(v, defaultbuf, 50, v->pval_default);
739  }
740  snprintf(buf, buflen, OWL_TABSTR "%-20s - %s (default: '%s')\n", 
741                  v->name, 
742                  owl_variable_get_summary(v), defaultbuf);
743  owl_fmtext_append_normal(fm, buf);
744}
745
746void owl_variable_get_help(owl_vardict *d, char *name, owl_fmtext *fm) {
747  char buff[1024];
748  int bufflen = 1023;
749  owl_variable *v;
750
751  if (!name
752      || (v = owl_dict_find_element(d, name)) == NULL 
753      || !v->get_fn) {
754    owl_fmtext_append_normal(fm, "No such variable...\n");
755    return;
756  }
757
758  owl_fmtext_append_bold(fm, "OWL VARIABLE\n\n");
759  owl_fmtext_append_normal(fm, OWL_TABSTR);
760  owl_fmtext_append_normal(fm, name);
761  owl_fmtext_append_normal(fm, " - ");
762  owl_fmtext_append_normal(fm, v->summary);
763  owl_fmtext_append_normal(fm, "\n\n");
764
765  owl_fmtext_append_normal(fm, "Current:        ");
766  owl_variable_get_tostring(d, name, buff, bufflen);
767  owl_fmtext_append_normal(fm, buff);
768  owl_fmtext_append_normal(fm, "\n\n");
769
770
771  if (v->type == OWL_VARIABLE_INT || v->type == OWL_VARIABLE_BOOL) {
772    v->get_tostring_fn(v, buff, bufflen, &(v->ival_default));
773  } else {
774    v->get_tostring_fn(v, buff, bufflen, v->pval_default);
775  }
776  owl_fmtext_append_normal(fm, "Default:        ");
777  owl_fmtext_append_normal(fm, buff);
778  owl_fmtext_append_normal(fm, "\n\n");
779
780  owl_fmtext_append_normal(fm, "Valid Settings: ");
781  owl_fmtext_append_normal(fm, owl_variable_get_validsettings(v));
782  owl_fmtext_append_normal(fm, "\n\n");
783
784  if (v->description && *v->description) {
785    owl_fmtext_append_normal(fm, "Description:\n");
786    owl_fmtext_append_normal(fm, owl_variable_get_description(v));
787    owl_fmtext_append_normal(fm, "\n\n");
788  }
789}
790
791
792
793
794/**************************************************************************/
795/*********************** GENERAL TYPE-SPECIFIC ****************************/
796/**************************************************************************/
797
798/* default common functions */
799
800void *owl_variable_get_default(owl_variable *v) {
801  return v->val;
802}
803
804void owl_variable_free_default(owl_variable *v) {
805  if (v->val) owl_free(v->val);
806}
807
808/* default functions for booleans */
809
810int owl_variable_bool_validate_default(owl_variable *v, void *newval) {
811  if (newval == NULL) return(0);
812  else if (*(int*)newval==1 || *(int*)newval==0) return(1);
813  else return (0);
814}
815
816int owl_variable_bool_set_default(owl_variable *v, void *newval) {
817  if (v->validate_fn) {
818    if (!v->validate_fn(v, newval)) return(-1);
819  }
820  *(int*)v->val = *(int*)newval;
821  return(0);
822}
823
824int owl_variable_bool_set_fromstring_default(owl_variable *v, char *newval) {
825  int i;
826  if (!strcmp(newval, "on")) i=1;
827  else if (!strcmp(newval, "off")) i=0;
828  else return(-1);
829  return (v->set_fn(v, &i));
830}
831
832int owl_variable_bool_get_tostring_default(owl_variable *v, char* buf, int bufsize, void *val) {
833  if (val == NULL) {
834    snprintf(buf, bufsize, "<null>");
835    return -1;
836  } else if (*(int*)val == 0) {
837    snprintf(buf, bufsize, "off");
838    return 0;
839  } else if (*(int*)val == 1) {
840    snprintf(buf, bufsize, "on");
841    return 0;
842  } else {
843    snprintf(buf, bufsize, "<invalid>");
844    return -1;
845  }
846}
847
848/* default functions for integers */
849
850int owl_variable_int_validate_default(owl_variable *v, void *newval) {
851  if (newval == NULL) return(0);
852  else return (1);
853}
854
855int owl_variable_int_set_default(owl_variable *v, void *newval) {
856  if (v->validate_fn) {
857    if (!v->validate_fn(v, newval)) return(-1);
858  }
859  *(int*)v->val = *(int*)newval;
860  return(0);
861}
862
863int owl_variable_int_set_fromstring_default(owl_variable *v, char *newval) {
864  int i;
865  char *ep = "x";
866  i = strtol(newval, &ep, 10);
867  if (*ep || ep==newval) return(-1);
868  return (v->set_fn(v, &i));
869}
870
871int owl_variable_int_get_tostring_default(owl_variable *v, char* buf, int bufsize, void *val) {
872  if (val == NULL) {
873    snprintf(buf, bufsize, "<null>");
874    return -1;
875  } else {
876    snprintf(buf, bufsize, "%d", *(int*)val);
877    return 0;
878  } 
879}
880
881/* default functions for enums (a variant of integers) */
882
883int owl_variable_enum_validate(owl_variable *v, void *newval) { 
884  char **enums;
885  int nenums, val;
886  if (newval == NULL) return(0);
887  enums = atokenize(v->validsettings, ",", &nenums);
888  if (enums == NULL) return(0);
889  atokenize_free(enums, nenums);
890  val = *(int*)newval;
891  if (val < 0 || val >= nenums) {
892    return(0);
893  }
894  return(1);
895}
896
897int owl_variable_enum_set_fromstring(owl_variable *v, char *newval) {
898  char **enums;
899  int nenums, i, val=-1;
900  if (newval == NULL) return(-1);
901  enums = atokenize(v->validsettings, ",", &nenums);
902  if (enums == NULL) return(-1);
903  for (i=0; i<nenums; i++) {
904    if (0==strcmp(newval, enums[i])) {
905      val = i;
906    }
907  }
908  atokenize_free(enums, nenums);
909  if (val == -1) return(-1);
910  return (v->set_fn(v, &val));
911}
912
913int owl_variable_enum_get_tostring(owl_variable *v, char* buf, int bufsize, void *val) {
914  char **enums;
915  int nenums, i;
916
917  if (val == NULL) {
918    snprintf(buf, bufsize, "<null>");
919    return -1;
920  }
921  enums = atokenize(v->validsettings, ",", &nenums);
922  i = *(int*)val;
923  if (i<0 || i>=nenums) {
924    snprintf(buf, bufsize, "<invalid:%d>",i);
925    atokenize_free(enums, nenums);
926    return(-1);
927  }
928  snprintf(buf, bufsize, "%s", enums[i]);
929  return 0;
930}
931
932/* default functions for stringeans */
933
934int owl_variable_string_validate_default(struct _owl_variable *v, void *newval) {
935  if (newval == NULL) return(0);
936  else return (1);
937}
938
939int owl_variable_string_set_default(owl_variable *v, void *newval) {
940  if (v->validate_fn) {
941    if (!v->validate_fn(v, newval)) return(-1);
942  }
943  if (v->val) owl_free(v->val);
944  v->val = owl_strdup(newval);
945  return(0);
946}
947
948int owl_variable_string_set_fromstring_default(owl_variable *v, char *newval) {
949  return (v->set_fn(v, newval));
950}
951
952int owl_variable_string_get_tostring_default(owl_variable *v, char* buf, int bufsize, void *val) {
953  if (val == NULL) {
954    snprintf(buf, bufsize, "<null>");
955    return -1;
956  } else {
957    snprintf(buf, bufsize, "%s", (char*)val);
958    return 0;
959  }
960}
961
962
963
964/**************************************************************************/
965/************************* REGRESSION TESTS *******************************/
966/**************************************************************************/
967
968#ifdef OWL_INCLUDE_REG_TESTS
969
970#include "test.h"
971
972int owl_variable_regtest(void) {
973  owl_vardict vd;
974  int numfailed=0;
975  char buf[1024];
976
977  in_regtest = 1;
978
979  printf("# BEGIN testing owl_variable\n");
980  FAIL_UNLESS("setup", 0==owl_variable_dict_setup(&vd));
981
982  FAIL_UNLESS("get bool", 0==owl_variable_get_bool(&vd,"rxping"));
983  FAIL_UNLESS("get bool (no such)", -1==owl_variable_get_bool(&vd,"mumble"));
984  FAIL_UNLESS("get bool as string 1", 0==owl_variable_get_tostring(&vd,"rxping", buf, 1024));
985  FAIL_UNLESS("get bool as string 2", 0==strcmp(buf,"off"));
986  FAIL_UNLESS("set bool 1", 0==owl_variable_set_bool_on(&vd,"rxping"));
987  FAIL_UNLESS("get bool 2", 1==owl_variable_get_bool(&vd,"rxping"));
988  FAIL_UNLESS("set bool 3", 0==owl_variable_set_fromstring(&vd,"rxping","off",0,0));
989  FAIL_UNLESS("get bool 4", 0==owl_variable_get_bool(&vd,"rxping"));
990  FAIL_UNLESS("set bool 5", -1==owl_variable_set_fromstring(&vd,"rxping","xxx",0,0));
991  FAIL_UNLESS("get bool 6", 0==owl_variable_get_bool(&vd,"rxping"));
992
993
994  FAIL_UNLESS("get string", 0==strcmp("~/zlog/people", owl_variable_get_string(&vd,"logpath")));
995  FAIL_UNLESS("set string 7", 0==owl_variable_set_string(&vd,"logpath","whee"));
996  FAIL_UNLESS("get string", 0==strcmp("whee", owl_variable_get_string(&vd,"logpath")));
997
998  FAIL_UNLESS("get int", 8==owl_variable_get_int(&vd,"typewinsize"));
999  FAIL_UNLESS("get int (no such)", -1==owl_variable_get_int(&vd,"mmble"));
1000  FAIL_UNLESS("get int as string 1", 0==owl_variable_get_tostring(&vd,"typewinsize", buf, 1024));
1001  FAIL_UNLESS("get int as string 2", 0==strcmp(buf,"8"));
1002  FAIL_UNLESS("set int 1", 0==owl_variable_set_int(&vd,"typewinsize",12));
1003  FAIL_UNLESS("get int 2", 12==owl_variable_get_int(&vd,"typewinsize"));
1004  FAIL_UNLESS("set int 1b", -1==owl_variable_set_int(&vd,"typewinsize",-3));
1005  FAIL_UNLESS("get int 2b", 12==owl_variable_get_int(&vd,"typewinsize"));
1006  FAIL_UNLESS("set int 3", 0==owl_variable_set_fromstring(&vd,"typewinsize","9",0,0));
1007  FAIL_UNLESS("get int 4", 9==owl_variable_get_int(&vd,"typewinsize"));
1008  FAIL_UNLESS("set int 5", -1==owl_variable_set_fromstring(&vd,"typewinsize","xxx",0,0));
1009  FAIL_UNLESS("set int 6", -1==owl_variable_set_fromstring(&vd,"typewinsize","",0,0));
1010  FAIL_UNLESS("get int 7", 9==owl_variable_get_int(&vd,"typewinsize"));
1011
1012  FAIL_UNLESS("get enum", OWL_WEBBROWSER_NETSCAPE==owl_variable_get_int(&vd,"webbrowser"));
1013  FAIL_UNLESS("get enum as string 1", 0==owl_variable_get_tostring(&vd,"webbrowser", buf, 1024));
1014  FAIL_UNLESS("get enum as string 2", 0==strcmp(buf,"netscape"));
1015  FAIL_UNLESS("set enum 1", 0==owl_variable_set_int(&vd,"webbrowser",OWL_WEBBROWSER_GALEON));
1016  FAIL_UNLESS("get enum 2", OWL_WEBBROWSER_GALEON==owl_variable_get_int(&vd,"webbrowser"));
1017  FAIL_UNLESS("set enum 1b", -1==owl_variable_set_int(&vd,"webbrowser",-3));
1018  FAIL_UNLESS("set enum 1b", -1==owl_variable_set_int(&vd,"webbrowser",209));
1019  FAIL_UNLESS("get enum 2b", OWL_WEBBROWSER_GALEON==owl_variable_get_int(&vd,"webbrowser"));
1020  FAIL_UNLESS("set enum 3", 0==owl_variable_set_fromstring(&vd,"webbrowser","none",0,0));
1021  FAIL_UNLESS("get enum 4", OWL_WEBBROWSER_NONE==owl_variable_get_int(&vd,"webbrowser"));
1022  FAIL_UNLESS("set enum 5", 0==owl_variable_set_fromstring(&vd,"webbrowser","netscape",0,0));
1023  FAIL_UNLESS("get enum 6", OWL_WEBBROWSER_NETSCAPE==owl_variable_get_int(&vd,"webbrowser"));
1024  FAIL_UNLESS("set enum 7", -1==owl_variable_set_fromstring(&vd,"webbrowser","xxx",0,0));
1025  FAIL_UNLESS("set enum 8", -1==owl_variable_set_fromstring(&vd,"webbrowser","",0,0));
1026  FAIL_UNLESS("set enum 9", -1==owl_variable_set_fromstring(&vd,"webbrowser","netscapey",0,0));
1027  FAIL_UNLESS("get enum 10", OWL_WEBBROWSER_NETSCAPE==owl_variable_get_int(&vd,"webbrowser"));
1028
1029  owl_variable * v;
1030 
1031  owl_variable_dict_newvar_string(&vd, "stringvar", "", "", "testval");
1032  FAIL_UNLESS("get new string var", NULL != (v = owl_variable_get(&vd, "stringvar", OWL_VARIABLE_STRING)));
1033  FAIL_UNLESS("get new string val", !strcmp("testval", owl_variable_get_string(&vd, "stringvar")));
1034  owl_variable_set_string(&vd, "stringvar", "new val");
1035  FAIL_UNLESS("update string val", !strcmp("new val", owl_variable_get_string(&vd, "stringvar")));
1036
1037  owl_variable_dict_newvar_int(&vd, "intvar", "", "", 47);
1038  FAIL_UNLESS("get new int var", NULL != (v = owl_variable_get(&vd, "intvar", OWL_VARIABLE_INT)));
1039  FAIL_UNLESS("get new int val", 47 == owl_variable_get_int(&vd, "intvar"));
1040  owl_variable_set_int(&vd, "intvar", 17);
1041  FAIL_UNLESS("update bool val", 17 == owl_variable_get_int(&vd, "intvar"));
1042
1043  owl_variable_dict_newvar_bool(&vd, "boolvar", "", "", 1);
1044  FAIL_UNLESS("get new bool var", NULL != (v = owl_variable_get(&vd, "boolvar", OWL_VARIABLE_BOOL)));
1045  FAIL_UNLESS("get new bool val", owl_variable_get_bool(&vd, "boolvar"));
1046  owl_variable_set_bool_off(&vd, "boolvar");
1047  FAIL_UNLESS("update string val", !owl_variable_get_bool(&vd, "boolvar"));
1048
1049  owl_variable_dict_free(&vd);
1050
1051  // if (numfailed) printf("*** WARNING: failures encountered with owl_variable\n");
1052  printf("# END testing owl_variable (%d failures)\n", numfailed);
1053  return(numfailed);
1054}
1055
1056
1057#endif /* OWL_INCLUDE_REG_TESTS */
Note: See TracBrowser for help on using the repository browser.