source: variable.c @ 9e5c9f3

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