source: variable.c @ 52a0f14

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