source: variable.c @ fc92e6e2

release-1.10release-1.4release-1.5release-1.6release-1.7release-1.8release-1.9
Last change on this file since fc92e6e2 was 8bce750, checked in by Nelson Elhage <nelhage@mit.edu>, 15 years ago
Move all regression tests into tester.c.
  • Property mode set to 100644
File size: 35.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 
190  OWLVAR_PATH( "zsigproc" /* %OwlVarStub:zsigproc */, NULL,
191               "name of a program to run that will generate zsigs",
192               "This program should produce a zsig on stdout when run.\n"
193               "Note that it is important that this program not block.\n\n"
194               "See the documentation for 'zsig' for more information about\n"
195               "how the outgoing zsig is chosen."
196               ),
197
198  OWLVAR_PATH( "newmsgproc" /* %OwlVarStub:newmsgproc */, NULL,
199               "name of a program to run when new messages are present",
200               "The named program will be run when owl recevies new.\n"
201               "messages.  It will not be run again until the first\n"
202               "instance exits"),
203
204  OWLVAR_STRING( "zsender" /* %OwlVarStub */, "",
205             "zephyr sender name",
206         "Allows you to customize the outgoing username in\n"
207         "zephyrs.  If this is unset, it will use your Kerberos\n"
208         "principal. Note that customizing the sender name will\n"
209         "cause your zephyrs to be sent unauthenticated."),
210
211  OWLVAR_STRING( "zsig" /* %OwlVarStub */, "",
212                 "zephyr signature",
213                 "The zsig to get on outgoing messages. If this variable is\n"
214                 "unset, 'zsigproc' will be run to generate a zsig. If that is\n"
215                 "also unset, the 'zwrite-signature' zephyr variable will be\n"
216                 "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(const owl_variable *v, const void *newval)
376{
377  if (newval == NULL) return(0);
378  else if (*(const int*)newval < 1) return(0);
379  else return (1);
380}
381
382int owl_variable_int_validate_positive(const owl_variable *v, const void *newval)
383{
384  if (newval == NULL) return(0);
385  else if (*(const int*)newval < 0) return(0);
386  else return (1);
387}
388
389/* typewinsize */
390int owl_variable_typewinsize_set(owl_variable *v, const 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, const void *newval)
400{
401  if (newval && (*(const int*)newval == 1 || *(const int*)newval == 0)) {
402    g.debug = *(const 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, const void *newval)
409{
410  if (newval) {
411    if (*(const int*)newval == 1) {
412      owl_aim_set_awaymsg(owl_global_get_aaway_msg(&g));
413    } else if (*(const 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, const void *newval)
421{
422  if (newval) {
423    if (*(const 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, const void *newval)
433{
434  if (newval && !owl_context_is_startup(owl_global_get_context(&g))) {
435    if (*(const int*)newval == 2) {
436      owl_function_command_norv("bindkey editmulti C-d command edit:delete-next-char");
437    } else if (*(const int*)newval == 1) {
438      owl_function_command_norv("bindkey editmulti C-d command edit:done-or-delete");
439    } else {
440      owl_function_command_norv("bindkey editmulti C-d command edit:done");
441    }
442  } 
443  return owl_variable_int_set_default(v, newval); 
444}
445
446int owl_variable_tty_set(owl_variable *v, const void *newval)
447{
448  owl_zephyr_set_locationinfo(owl_global_get_hostname(&g), newval);
449  return(owl_variable_string_set_default(v, newval));
450}
451
452
453/**************************************************************************/
454/****************************** GENERAL ***********************************/
455/**************************************************************************/
456
457int owl_variable_dict_setup(owl_vardict *vd) {
458  owl_variable *var, *cur;
459  if (owl_dict_create(vd)) return(-1);
460  for (var = variables_to_init; var->name != NULL; var++) {
461    cur = owl_malloc(sizeof(owl_variable));
462    memcpy(cur, var, sizeof(owl_variable));
463    switch (cur->type) {
464    case OWL_VARIABLE_OTHER:
465      cur->set_fn(cur, cur->pval_default);
466      break;
467    case OWL_VARIABLE_STRING:
468      if (!cur->validate_fn) 
469        cur->validate_fn = owl_variable_string_validate_default;
470      if (!cur->set_fn) 
471        cur->set_fn = owl_variable_string_set_default;
472      if (!cur->set_fromstring_fn) 
473        cur->set_fromstring_fn = owl_variable_string_set_fromstring_default;
474      if (!cur->get_fn) 
475        cur->get_fn = owl_variable_get_default;
476      if (!cur->get_tostring_fn) 
477        cur->get_tostring_fn = owl_variable_string_get_tostring_default;     
478      if (!cur->free_fn) 
479        cur->free_fn = owl_variable_free_default;
480      cur->set_fn(cur, cur->pval_default);
481      break;
482    case OWL_VARIABLE_BOOL:
483      if (!cur->validate_fn) 
484        cur->validate_fn = owl_variable_bool_validate_default;
485      if (!cur->set_fn) 
486        cur->set_fn = owl_variable_bool_set_default;
487      if (!cur->set_fromstring_fn) 
488        cur->set_fromstring_fn = owl_variable_bool_set_fromstring_default;
489      if (!cur->get_fn) 
490        cur->get_fn = owl_variable_get_default;
491      if (!cur->get_tostring_fn) 
492        cur->get_tostring_fn = owl_variable_bool_get_tostring_default;     
493      if (!cur->free_fn) 
494        cur->free_fn = owl_variable_free_default;
495      cur->val = owl_malloc(sizeof(int));
496      cur->set_fn(cur, &cur->ival_default);
497      break;
498    case OWL_VARIABLE_INT:
499      if (!cur->validate_fn) 
500        cur->validate_fn = owl_variable_int_validate_default;
501      if (!cur->set_fn) 
502        cur->set_fn = owl_variable_int_set_default;
503      if (!cur->set_fromstring_fn) 
504        cur->set_fromstring_fn = owl_variable_int_set_fromstring_default;
505      if (!cur->get_fn) 
506        cur->get_fn = owl_variable_get_default;
507      if (!cur->get_tostring_fn) 
508        cur->get_tostring_fn = owl_variable_int_get_tostring_default;     
509      if (!cur->free_fn) 
510        cur->free_fn = owl_variable_free_default;
511      cur->val = owl_malloc(sizeof(int));
512      cur->set_fn(cur, &cur->ival_default);
513      break;
514    default:
515      fprintf(stderr, "owl_variable_setup: invalid variable type\n");
516      return(-2);
517    }
518    owl_dict_insert_element(vd, cur->name, cur, NULL);
519  }
520  return 0;
521}
522
523void owl_variable_dict_add_variable(owl_vardict * vardict,
524                                    owl_variable * var) {
525  owl_dict_insert_element(vardict, var->name, var, (void(*)(void*))owl_variable_free);
526}
527
528owl_variable * owl_variable_newvar(const char *name, const char *summary, const char * description) {
529  owl_variable * var = owl_malloc(sizeof(owl_variable));
530  memset(var, 0, sizeof(owl_variable));
531  var->name = owl_strdup(name);
532  var->summary = owl_strdup(summary);
533  var->description = owl_strdup(description);
534  return var;
535}
536
537void owl_variable_update(owl_variable *var, const char *summary, const char *desc) {
538  if(var->summary) owl_free(var->summary);
539  var->summary = owl_strdup(summary);
540  if(var->description) owl_free(var->description);
541  var->description = owl_strdup(desc);
542}
543
544void owl_variable_dict_newvar_string(owl_vardict * vd, const char *name, const char *summ, const char * desc, const char * initval) {
545  owl_variable *old = owl_variable_get_var(vd, name, OWL_VARIABLE_STRING);
546  if(old) {
547    owl_variable_update(old, summ, desc);
548    if(old->pval_default) owl_free(old->pval_default);
549    old->pval_default = owl_strdup(initval);
550  } else {
551    owl_variable * var = owl_variable_newvar(name, summ, desc);
552    var->type = OWL_VARIABLE_STRING;
553    var->pval_default = owl_strdup(initval);
554    var->set_fn = owl_variable_string_set_default;
555    var->set_fromstring_fn = owl_variable_string_set_fromstring_default;
556    var->get_fn = owl_variable_get_default;
557    var->get_tostring_fn = owl_variable_string_get_tostring_default;
558    var->free_fn = owl_variable_free_default;
559    var->set_fn(var, initval);
560    owl_variable_dict_add_variable(vd, var);
561  }
562}
563
564void owl_variable_dict_newvar_int(owl_vardict * vd, const char *name, const char *summ, const char * desc, int initval) {
565  owl_variable *old = owl_variable_get_var(vd, name, OWL_VARIABLE_INT);
566  if(old) {
567    owl_variable_update(old, summ, desc);
568    old->ival_default = initval;
569  } else {
570    owl_variable * var = owl_variable_newvar(name, summ, desc);
571    var->type = OWL_VARIABLE_INT;
572    var->ival_default = initval;
573    var->validate_fn = owl_variable_int_validate_default;
574    var->set_fn = owl_variable_int_set_default;
575    var->set_fromstring_fn = owl_variable_int_set_fromstring_default;
576    var->get_fn = owl_variable_get_default;
577    var->get_tostring_fn = owl_variable_int_get_tostring_default;
578    var->free_fn = owl_variable_free_default;
579    var->val = owl_malloc(sizeof(int));
580    var->set_fn(var, &initval);
581    owl_variable_dict_add_variable(vd, var);
582  }
583}
584
585void owl_variable_dict_newvar_bool(owl_vardict * vd, const char *name, const char *summ, const char * desc, int initval) {
586  owl_variable *old = owl_variable_get_var(vd, name, OWL_VARIABLE_BOOL);
587  if(old) {
588    owl_variable_update(old, summ, desc);
589    old->ival_default = initval;
590  } else {
591    owl_variable * var = owl_variable_newvar(name, summ, desc);
592    var->type = OWL_VARIABLE_BOOL;
593    var->ival_default = initval;
594    var->validate_fn = owl_variable_bool_validate_default;
595    var->set_fn = owl_variable_bool_set_default;
596    var->set_fromstring_fn = owl_variable_bool_set_fromstring_default;
597    var->get_fn = owl_variable_get_default;
598    var->get_tostring_fn = owl_variable_bool_get_tostring_default;
599    var->free_fn = owl_variable_free_default;
600    var->val = owl_malloc(sizeof(int));
601    var->set_fn(var, &initval);
602    owl_variable_dict_add_variable(vd, var);
603  }
604}
605
606void owl_variable_dict_free(owl_vardict *d) {
607  owl_dict_free_all(d, (void(*)(void*))owl_variable_free);
608}
609
610/* free the list with owl_variable_dict_namelist_free */
611void owl_variable_dict_get_names(const owl_vardict *d, owl_list *l) {
612  owl_dict_get_keys(d, l);
613}
614
615void owl_variable_dict_namelist_free(owl_list *l) {
616  owl_list_free_all(l, owl_free);
617}
618
619void owl_variable_free(owl_variable *v) {
620  if (v->free_fn) v->free_fn(v);
621  owl_free(v);
622}
623
624
625const char *owl_variable_get_description(const owl_variable *v) {
626  return v->description;
627}
628
629const char *owl_variable_get_summary(const owl_variable *v) {
630  return v->summary;
631}
632
633const char *owl_variable_get_validsettings(const owl_variable *v) {
634  if (v->validsettings) {
635    return v->validsettings;
636  } else {
637    return "";
638  }
639}
640
641/* functions for getting and setting variable values */
642
643/* returns 0 on success, prints a status msg if msg is true */
644int owl_variable_set_fromstring(owl_vardict *d, const char *name, const char *value, int msg, int requirebool) {
645  owl_variable *v;
646  char buff2[1024];
647  if (!name) return(-1);
648  v = owl_dict_find_element(d, name);
649  if (v == NULL) {
650    if (msg) owl_function_error("Unknown variable %s", name);
651    return -1;
652  }
653  if (!v->set_fromstring_fn) {
654    if (msg) owl_function_error("Variable %s is read-only", name);
655    return -1;   
656  }
657  if (requirebool && v->type!=OWL_VARIABLE_BOOL) {
658    if (msg) owl_function_error("Variable %s is not a boolean", name);
659    return -1;   
660  }
661  if (0 != v->set_fromstring_fn(v, value)) {
662    if (msg) owl_function_error("Unable to set %s (must be %s)", name, 
663                                  owl_variable_get_validsettings(v));
664    return -1;
665  }
666  if (msg && v->get_tostring_fn) {
667    v->get_tostring_fn(v, buff2, 1024, v->val);
668    owl_function_makemsg("%s = '%s'", name, buff2);
669  }   
670  return 0;
671}
672 
673int owl_variable_set_string(owl_vardict *d, const char *name, const char *newval) {
674  owl_variable *v;
675  if (!name) return(-1);
676  v = owl_dict_find_element(d, name);
677  if (v == NULL || !v->set_fn) return(-1);
678  if (v->type!=OWL_VARIABLE_STRING) return(-1);
679  return v->set_fn(v, newval);
680}
681 
682int owl_variable_set_int(owl_vardict *d, const char *name, int newval) {
683  owl_variable *v;
684  if (!name) return(-1);
685  v = owl_dict_find_element(d, name);
686  if (v == NULL || !v->set_fn) return(-1);
687  if (v->type!=OWL_VARIABLE_INT && v->type!=OWL_VARIABLE_BOOL) return(-1);
688  return v->set_fn(v, &newval);
689}
690 
691int owl_variable_set_bool_on(owl_vardict *d, const char *name) {
692  return owl_variable_set_int(d,name,1);
693}
694
695int owl_variable_set_bool_off(owl_vardict *d, const char *name) {
696  return owl_variable_set_int(d,name,0);
697}
698
699int owl_variable_get_tostring(const owl_vardict *d, const char *name, char *buf, int bufsize) {
700  owl_variable *v;
701  if (!name) return(-1);
702  v = owl_dict_find_element(d, name);
703  if (v == NULL || !v->get_tostring_fn) return(-1);
704  return v->get_tostring_fn(v, buf, bufsize, v->val);
705}
706
707int owl_variable_get_default_tostring(const owl_vardict *d, const char *name, char *buf, int bufsize) {
708  owl_variable *v;
709  if (!name) return(-1);
710  v = owl_dict_find_element(d, name);
711  if (v == NULL || !v->get_tostring_fn) return(-1);
712  if (v->type == OWL_VARIABLE_INT || v->type == OWL_VARIABLE_BOOL) {
713    return v->get_tostring_fn(v, buf, bufsize, &(v->ival_default));
714  } else {
715    return v->get_tostring_fn(v, buf, bufsize, v->pval_default);
716  }
717}
718
719owl_variable *owl_variable_get_var(const owl_vardict *d, const char *name, int require_type) {
720  owl_variable *v;
721  if (!name) return(NULL);
722  v = owl_dict_find_element(d, name);
723  if (v == NULL || !v->get_fn || v->type != require_type) return(NULL);
724  return v;
725}
726
727/* returns a reference */
728const void *owl_variable_get(const owl_vardict *d, const char *name, int require_type) {
729  owl_variable *v = owl_variable_get_var(d, name, require_type);
730  if(v == NULL) return NULL;
731  return v->get_fn(v);
732}
733
734/* returns a reference */
735const char *owl_variable_get_string(const owl_vardict *d, const char *name) {
736  return owl_variable_get(d,name, OWL_VARIABLE_STRING);
737}
738
739/* returns a reference */
740const void *owl_variable_get_other(const owl_vardict *d, const char *name) {
741  return owl_variable_get(d,name, OWL_VARIABLE_OTHER);
742}
743
744int owl_variable_get_int(const owl_vardict *d, const char *name) {
745  const int *pi;
746  pi = owl_variable_get(d,name,OWL_VARIABLE_INT);
747  if (!pi) return(-1);
748  return(*pi);
749}
750
751int owl_variable_get_bool(const owl_vardict *d, const char *name) {
752  const int *pi;
753  pi = owl_variable_get(d,name,OWL_VARIABLE_BOOL);
754  if (!pi) return(-1);
755  return(*pi);
756}
757
758void owl_variable_describe(const owl_vardict *d, const char *name, owl_fmtext *fm) {
759  char defaultbuf[50];
760  char buf[1024];
761  int buflen = 1023;
762  owl_variable *v;
763
764  if (!name
765      || (v = owl_dict_find_element(d, name)) == NULL 
766      || !v->get_fn) {
767    snprintf(buf, buflen, "     No such variable '%s'\n", name);     
768    owl_fmtext_append_normal(fm, buf);
769    return;
770  }
771  if (v->type == OWL_VARIABLE_INT || v->type == OWL_VARIABLE_BOOL) {
772    v->get_tostring_fn(v, defaultbuf, 50, &(v->ival_default));
773  } else {
774    v->get_tostring_fn(v, defaultbuf, 50, v->pval_default);
775  }
776  snprintf(buf, buflen, OWL_TABSTR "%-20s - %s (default: '%s')\n", 
777                  v->name, 
778                  owl_variable_get_summary(v), defaultbuf);
779  owl_fmtext_append_normal(fm, buf);
780}
781
782void owl_variable_get_help(const owl_vardict *d, const char *name, owl_fmtext *fm) {
783  char buff[1024];
784  int bufflen = 1023;
785  owl_variable *v;
786
787  if (!name
788      || (v = owl_dict_find_element(d, name)) == NULL 
789      || !v->get_fn) {
790    owl_fmtext_append_normal(fm, "No such variable...\n");
791    return;
792  }
793
794  owl_fmtext_append_bold(fm, "OWL VARIABLE\n\n");
795  owl_fmtext_append_normal(fm, OWL_TABSTR);
796  owl_fmtext_append_normal(fm, name);
797  owl_fmtext_append_normal(fm, " - ");
798  owl_fmtext_append_normal(fm, v->summary);
799  owl_fmtext_append_normal(fm, "\n\n");
800
801  owl_fmtext_append_normal(fm, "Current:        ");
802  owl_variable_get_tostring(d, name, buff, bufflen);
803  owl_fmtext_append_normal(fm, buff);
804  owl_fmtext_append_normal(fm, "\n\n");
805
806
807  if (v->type == OWL_VARIABLE_INT || v->type == OWL_VARIABLE_BOOL) {
808    v->get_tostring_fn(v, buff, bufflen, &(v->ival_default));
809  } else {
810    v->get_tostring_fn(v, buff, bufflen, v->pval_default);
811  }
812  owl_fmtext_append_normal(fm, "Default:        ");
813  owl_fmtext_append_normal(fm, buff);
814  owl_fmtext_append_normal(fm, "\n\n");
815
816  owl_fmtext_append_normal(fm, "Valid Settings: ");
817  owl_fmtext_append_normal(fm, owl_variable_get_validsettings(v));
818  owl_fmtext_append_normal(fm, "\n\n");
819
820  if (v->description && *v->description) {
821    owl_fmtext_append_normal(fm, "Description:\n");
822    owl_fmtext_append_normal(fm, owl_variable_get_description(v));
823    owl_fmtext_append_normal(fm, "\n\n");
824  }
825}
826
827
828
829
830/**************************************************************************/
831/*********************** GENERAL TYPE-SPECIFIC ****************************/
832/**************************************************************************/
833
834/* default common functions */
835
836const void *owl_variable_get_default(const owl_variable *v) {
837  return v->val;
838}
839
840void owl_variable_free_default(owl_variable *v) {
841  if (v->val) owl_free(v->val);
842}
843
844/* default functions for booleans */
845
846int owl_variable_bool_validate_default(const owl_variable *v, const void *newval) {
847  if (newval == NULL) return(0);
848  else if (*(const int*)newval==1 || *(const int*)newval==0) return(1);
849  else return (0);
850}
851
852int owl_variable_bool_set_default(owl_variable *v, const void *newval) {
853  if (v->validate_fn) {
854    if (!v->validate_fn(v, newval)) return(-1);
855  }
856  *(int*)v->val = *(const int*)newval;
857  return(0);
858}
859
860int owl_variable_bool_set_fromstring_default(owl_variable *v, const char *newval) {
861  int i;
862  if (!strcmp(newval, "on")) i=1;
863  else if (!strcmp(newval, "off")) i=0;
864  else return(-1);
865  return (v->set_fn(v, &i));
866}
867
868int owl_variable_bool_get_tostring_default(const owl_variable *v, char* buf, int bufsize, const void *val) {
869  if (val == NULL) {
870    snprintf(buf, bufsize, "<null>");
871    return -1;
872  } else if (*(const int*)val == 0) {
873    snprintf(buf, bufsize, "off");
874    return 0;
875  } else if (*(const int*)val == 1) {
876    snprintf(buf, bufsize, "on");
877    return 0;
878  } else {
879    snprintf(buf, bufsize, "<invalid>");
880    return -1;
881  }
882}
883
884/* default functions for integers */
885
886int owl_variable_int_validate_default(const owl_variable *v, const void *newval) {
887  if (newval == NULL) return(0);
888  else return (1);
889}
890
891int owl_variable_int_set_default(owl_variable *v, const void *newval) {
892  if (v->validate_fn) {
893    if (!v->validate_fn(v, newval)) return(-1);
894  }
895  *(int*)v->val = *(const int*)newval;
896  return(0);
897}
898
899int owl_variable_int_set_fromstring_default(owl_variable *v, const char *newval) {
900  int i;
901  const char *ep = "x";
902  i = strtol(newval, (char **)&ep, 10);
903  if (*ep || ep==newval) return(-1);
904  return (v->set_fn(v, &i));
905}
906
907int owl_variable_int_get_tostring_default(const owl_variable *v, char* buf, int bufsize, const void *val) {
908  if (val == NULL) {
909    snprintf(buf, bufsize, "<null>");
910    return -1;
911  } else {
912    snprintf(buf, bufsize, "%d", *(const int*)val);
913    return 0;
914  } 
915}
916
917/* default functions for enums (a variant of integers) */
918
919int owl_variable_enum_validate(const owl_variable *v, const void *newval) { 
920  char **enums;
921  int nenums, val;
922  if (newval == NULL) return(0);
923  enums = atokenize(v->validsettings, ",", &nenums);
924  if (enums == NULL) return(0);
925  atokenize_free(enums, nenums);
926  val = *(const int*)newval;
927  if (val < 0 || val >= nenums) {
928    return(0);
929  }
930  return(1);
931}
932
933int owl_variable_enum_set_fromstring(owl_variable *v, const char *newval) {
934  char **enums;
935  int nenums, i, val=-1;
936  if (newval == NULL) return(-1);
937  enums = atokenize(v->validsettings, ",", &nenums);
938  if (enums == NULL) return(-1);
939  for (i=0; i<nenums; i++) {
940    if (0==strcmp(newval, enums[i])) {
941      val = i;
942    }
943  }
944  atokenize_free(enums, nenums);
945  if (val == -1) return(-1);
946  return (v->set_fn(v, &val));
947}
948
949int owl_variable_enum_get_tostring(const owl_variable *v, char* buf, int bufsize, const void *val) {
950  char **enums;
951  int nenums, i;
952
953  if (val == NULL) {
954    snprintf(buf, bufsize, "<null>");
955    return -1;
956  }
957  enums = atokenize(v->validsettings, ",", &nenums);
958  i = *(const int*)val;
959  if (i<0 || i>=nenums) {
960    snprintf(buf, bufsize, "<invalid:%d>",i);
961    atokenize_free(enums, nenums);
962    return(-1);
963  }
964  snprintf(buf, bufsize, "%s", enums[i]);
965  return 0;
966}
967
968/* default functions for stringeans */
969
970int owl_variable_string_validate_default(const struct _owl_variable *v, const void *newval) {
971  if (newval == NULL) return(0);
972  else return (1);
973}
974
975int owl_variable_string_set_default(owl_variable *v, const void *newval) {
976  if (v->validate_fn) {
977    if (!v->validate_fn(v, newval)) return(-1);
978  }
979  if (v->val) owl_free(v->val);
980  v->val = owl_strdup(newval);
981  return(0);
982}
983
984int owl_variable_string_set_fromstring_default(owl_variable *v, const char *newval) {
985  return (v->set_fn(v, newval));
986}
987
988int owl_variable_string_get_tostring_default(const owl_variable *v, char* buf, int bufsize, const void *val) {
989  if (val == NULL) {
990    snprintf(buf, bufsize, "<null>");
991    return -1;
992  } else {
993    snprintf(buf, bufsize, "%s", (const char*)val);
994    return 0;
995  }
996}
997
Note: See TracBrowser for help on using the repository browser.