source: variable.c @ af16ad3

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