source: variable.c @ f1e629d

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