source: variable.c @ debb15d

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