source: variable.c @ 4357be8

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