source: variable.c @ 937ac795

release-1.6
Last change on this file since 937ac795 was 937ac795, checked in by Nelson Elhage <nelhage@mit.edu>, 10 years ago
Set edit:maxwrapcols to 70 by default. New BarnOwl users may not be aware that sending wide zephyrs will make 80-column terminal users annoyed. Let’s enable 70-column wrapping by default, regardless of the sender’s terminal size. Users that know they need to send longer lines can easily disable it. Also, update the documentation for edit:maxwrapcols to suggest 70 instead of 60 as the recommended maximum. Signed-off-by: Anders Kaseorg <andersk@mit.edu>
  • Property mode set to 100644
File size: 36.3 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( "zsigfunc" /* %OwlVarStub */, "BarnOwl::default_zephyr_signature()",
212                 "zsig perl function",
213                 "Called every time you start a zephyrgram without an\n"
214                 "explicit zsig.  The default setting implements the policy\n"
215                 "descripted in the documentation for the 'zsig' variable.\n"),
216
217  OWLVAR_STRING( "zsig" /* %OwlVarStub */, "",
218                 "zephyr signature",
219                 "The zsig to get on outgoing messages. If this variable is\n"
220                 "unset, 'zsigproc' will be run to generate a zsig. If that is\n"
221                 "also unset, the 'zwrite-signature' zephyr variable will be\n"
222                 "used instead.\n"),
223
224  OWLVAR_STRING( "appendtosepbar" /* %OwlVarStub */, "",
225                 "string to append to the end of the sepbar",
226                 "The sepbar is the bar separating the top and bottom\n"
227                 "of the owl screen.  Any string specified here will\n"
228                 "be displayed on the right of the sepbar\n"),
229
230  OWLVAR_BOOL( "zaway" /* %OwlVarStub */, 0,
231               "turn zaway on or off", "" ),
232
233  OWLVAR_STRING( "zaway_msg" /* %OwlVarStub */, 
234                 OWL_DEFAULT_ZAWAYMSG,
235                 "zaway msg for responding to zephyrs when away", "" ),
236
237  OWLVAR_STRING( "zaway_msg_default" /* %OwlVarStub */, 
238                 OWL_DEFAULT_ZAWAYMSG,
239                 "default zaway message", "" ),
240
241  OWLVAR_BOOL_FULL( "aaway" /* %OwlVarStub */, 0,
242                    "Set AIM away status",
243                    "",
244                    NULL, owl_variable_aaway_set, NULL),
245
246  OWLVAR_STRING( "aaway_msg" /* %OwlVarStub */, 
247                 OWL_DEFAULT_AAWAYMSG,
248                 "AIM away msg for responding when away", "" ),
249
250  OWLVAR_STRING( "aaway_msg_default" /* %OwlVarStub */, 
251                 OWL_DEFAULT_AAWAYMSG,
252                 "default AIM away message", "" ),
253
254  OWLVAR_STRING( "view_home" /* %OwlVarStub */, "all",
255                 "home view to switch to after 'X' and 'V'", 
256                 "SEE ALSO: view, filter\n" ),
257
258  OWLVAR_STRING( "alert_filter" /* %OwlVarStub */, "none",
259                 "filter on which to trigger alert actions",
260                 "" ),
261
262  OWLVAR_STRING( "alert_action" /* %OwlVarStub */, "nop",
263                 "owl command to execute for alert actions",
264                 "" ),
265
266  OWLVAR_STRING_FULL( "tty" /* %OwlVarStub */, "", "tty name for zephyr location", "",
267                      NULL, owl_variable_tty_set, NULL),
268
269  OWLVAR_STRING( "default_style" /* %OwlVarStub */, "__unspecified__",
270                 "name of the default formatting style",
271                 "This sets the default message formatting style.\n"
272                 "Styles may be created with the 'style' command.\n"
273                 "Some built-in styles include:\n"
274                 "   default  - the default owl formatting\n"
275                 "   oneline  - one line per-message\n"
276                 "   perl     - legacy perl interface\n"
277                 "\nSEE ALSO: style, show styles, view -s <style>\n"
278                 ),
279
280
281  OWLVAR_INT(    "edit:maxfillcols" /* %OwlVarStub:edit_maxfillcols */, 70,
282                 "maximum number of columns for M-q to fill text to",
283                 "This specifies the maximum number of columns for M-q\n"
284                 "to fill text to.  If set to 0, ther will be no maximum\n"
285                 "limit.  In all cases, the current width of the screen\n"
286                 "will also be taken into account.  It will be used instead\n"
287                 "if it is narrower than the maximum, or if this\n"
288                 "is set to 0.\n" ),
289
290  OWLVAR_INT(    "edit:maxwrapcols" /* %OwlVarStub:edit_maxwrapcols */, 70,
291                 "maximum number of columns for line-wrapping",
292                 "This specifies the maximum number of columns for\n"
293                 "auto-line-wrapping.  If set to 0, ther will be no maximum\n"
294                 "limit.  In all cases, the current width of the screen\n"
295                 "will also be taken into account.  It will be used instead\n"
296                 "if it is narrower than the maximum, or if this\n"
297                 "is set to 0.\n\n"
298                 "It is recommended that outgoing messages be no wider\n"
299                 "than 70 columns, as a courtesy to recipients.\n"),
300
301  OWLVAR_INT( "aim_ignorelogin_timer" /* %OwlVarStub */, 15,
302              "number of seconds after AIM login to ignore login messages",
303              "This specifies the number of seconds to wait after an\n"
304              "AIM login before allowing the recipt of AIM login notifications.\n"
305              "By default this is set to 15.  If you would like to view login\n"
306              "notifications of buddies as soon as you login, set it to 0 instead."),
307
308             
309  OWLVAR_INT_FULL( "typewinsize" /* %OwlVarStub:typwin_lines */, 
310                   OWL_TYPWIN_SIZE,
311                  "number of lines in the typing window", 
312                   "This specifies the height of the window at the\n"
313                   "bottom of the screen where commands are entered\n"
314                   "and where messages are composed.\n",
315                   "int > 0",
316                   owl_variable_int_validate_gt0,
317                   owl_variable_typewinsize_set,
318                   NULL /* use default for get */
319                   ),
320
321  OWLVAR_INT( "typewindelta" /* %OwlVarStub */, 0,
322                  "number of lines to add to the typing window when in use",
323                   "On small screens you may want the typing window to\n"
324                   "auto-hide when not entering a command or message.\n"
325                   "This variable is the number of lines to add to the\n"
326           "typing window when it is in use; you can then set\n"
327           "typewinsize to 1.\n\n"
328           "This works a lot better with a non-default scrollmode;\n"
329           "try :set scrollmode pagedcenter.\n"),
330
331  OWLVAR_ENUM( "scrollmode" /* %OwlVarStub */, OWL_SCROLLMODE_NORMAL,
332               "how to scroll up and down",
333               "This controls how the screen is scrolled as the\n"
334               "cursor moves between messages being displayed.\n"
335               "The following modes are supported:\n\n"
336               "   normal      - This is the owl default.  Scrolling happens\n"
337               "                 when it needs to, and an attempt is made to\n"
338               "                 keep the current message roughly near\n"
339               "                 the middle of the screen.\n"
340               "   top         - The current message will always be the\n"
341               "                 the top message displayed.\n"
342               "   neartop     - The current message will be one down\n"
343               "                 from the top message displayed,\n"
344               "                 where possible.\n"
345               "   center      - An attempt is made to keep the current\n"
346               "                 message near the center of the screen.\n"
347               "   paged       - 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 top or\n"
352               "                 the bottom.\n"
353               "   pagedcenter - The top message displayed only changes\n"
354               "                 when user moves the cursor to the top\n"
355               "                 or bottom of the screen.  When it moves,\n"
356               "                 the screen will be paged up or down and\n"
357               "                 the cursor will be near the center.\n",
358               "normal,top,neartop,center,paged,pagedcenter" ),
359
360  OWLVAR_BOOL( "narrow-related" /* %OwlVarStub:narrow_related */, 1,
361               "Make smartnarrow use broader filters",
362               "Causes smartfiler to narrow to messages \"related\" to \n"
363               "the current message, as well as ones to the same place.\n\n"
364               "for Zephyr, this controls whether to narrow to e.g. class-help or\n"
365               "class-help.d alone, or to related-class-help, which includes\n"
366               "help, unhelp, help.d, etc.\n\nDefault is true (include unclasses, etc.).\n" ),
367
368  OWLVAR_BOOL( "_followlast" /* %OwlVarStub */, 0,
369               "enable automatic following of the last zephyr",
370               "If the cursor is at the last message, it will\n"
371               "continue to follow the last message if this is set.\n"
372               "Note that this is currently risky as you might accidentally\n"
373               "delete a message right as it came in.\n" ),
374
375  /* This MUST be last... */
376  { NULL, 0, NULL, 0, NULL, NULL, NULL, NULL,
377    NULL, NULL, NULL, NULL, NULL, NULL }
378
379};
380
381/**************************************************************************/
382/*********************** SPECIFIC TO VARIABLES ****************************/
383/**************************************************************************/
384
385
386/* commonly useful */
387
388int owl_variable_int_validate_gt0(const owl_variable *v, const void *newval)
389{
390  if (newval == NULL) return(0);
391  else if (*(const int*)newval < 1) return(0);
392  else return (1);
393}
394
395int owl_variable_int_validate_positive(const owl_variable *v, const void *newval)
396{
397  if (newval == NULL) return(0);
398  else if (*(const int*)newval < 0) return(0);
399  else return (1);
400}
401
402/* typewinsize */
403int owl_variable_typewinsize_set(owl_variable *v, const void *newval)
404{
405  int rv;
406  rv = owl_variable_int_set_default(v, newval);
407  if (0 == rv) owl_function_resize();
408  return(rv);
409}
410
411/* debug (cache value in g->debug) */
412int owl_variable_debug_set(owl_variable *v, const void *newval)
413{
414  if (newval && (*(const int*)newval == 1 || *(const int*)newval == 0)) {
415    g.debug = *(const int*)newval;
416  }
417  return owl_variable_bool_set_default(v, newval);
418}
419
420/* When 'aaway' is changed, need to notify the AIM server */
421int owl_variable_aaway_set(owl_variable *v, const void *newval)
422{
423  if (newval) {
424    if (*(const int*)newval == 1) {
425      owl_aim_set_awaymsg(owl_global_get_aaway_msg(&g));
426    } else if (*(const int*)newval == 0) {
427      owl_aim_set_awaymsg("");
428    }
429  }
430  return owl_variable_bool_set_default(v, newval);
431}
432
433int owl_variable_pseudologins_set(owl_variable *v, const void *newval)
434{
435  if (newval) {
436    if (*(const int*)newval == 1) {
437      owl_function_zephyr_buddy_check(0);
438    }
439  }
440  return owl_variable_bool_set_default(v, newval);
441}
442
443/* note that changing the value of this will clobber
444 * any user setting of this */
445int owl_variable_disable_ctrl_d_set(owl_variable *v, const void *newval)
446{
447  if (newval && !owl_context_is_startup(owl_global_get_context(&g))) {
448    if (*(const int*)newval == 2) {
449      owl_function_command_norv("bindkey editmulti C-d command edit:delete-next-char");
450    } else if (*(const int*)newval == 1) {
451      owl_function_command_norv("bindkey editmulti C-d command edit:done-or-delete");
452    } else {
453      owl_function_command_norv("bindkey editmulti C-d command edit:done");
454    }
455  } 
456  return owl_variable_int_set_default(v, newval); 
457}
458
459int owl_variable_tty_set(owl_variable *v, const void *newval)
460{
461  owl_zephyr_set_locationinfo(owl_global_get_hostname(&g), newval);
462  return(owl_variable_string_set_default(v, newval));
463}
464
465
466/**************************************************************************/
467/****************************** GENERAL ***********************************/
468/**************************************************************************/
469
470int owl_variable_dict_setup(owl_vardict *vd) {
471  owl_variable *var, *cur;
472  if (owl_dict_create(vd)) return(-1);
473  for (var = variables_to_init; var->name != NULL; var++) {
474    cur = owl_malloc(sizeof(owl_variable));
475    *cur = *var;
476    switch (cur->type) {
477    case OWL_VARIABLE_OTHER:
478      cur->set_fn(cur, cur->pval_default);
479      break;
480    case OWL_VARIABLE_STRING:
481      if (!cur->validate_fn) 
482        cur->validate_fn = owl_variable_string_validate_default;
483      if (!cur->set_fn) 
484        cur->set_fn = owl_variable_string_set_default;
485      if (!cur->set_fromstring_fn) 
486        cur->set_fromstring_fn = owl_variable_string_set_fromstring_default;
487      if (!cur->get_fn) 
488        cur->get_fn = owl_variable_get_default;
489      if (!cur->get_tostring_fn) 
490        cur->get_tostring_fn = owl_variable_string_get_tostring_default;     
491      if (!cur->delete_fn)
492        cur->delete_fn = owl_variable_delete_default;
493      cur->set_fn(cur, cur->pval_default);
494      break;
495    case OWL_VARIABLE_BOOL:
496      if (!cur->validate_fn) 
497        cur->validate_fn = owl_variable_bool_validate_default;
498      if (!cur->set_fn) 
499        cur->set_fn = owl_variable_bool_set_default;
500      if (!cur->set_fromstring_fn) 
501        cur->set_fromstring_fn = owl_variable_bool_set_fromstring_default;
502      if (!cur->get_fn) 
503        cur->get_fn = owl_variable_get_default;
504      if (!cur->get_tostring_fn) 
505        cur->get_tostring_fn = owl_variable_bool_get_tostring_default;     
506      if (!cur->delete_fn)
507        cur->delete_fn = owl_variable_delete_default;
508      cur->val = owl_malloc(sizeof(int));
509      cur->set_fn(cur, &cur->ival_default);
510      break;
511    case OWL_VARIABLE_INT:
512      if (!cur->validate_fn) 
513        cur->validate_fn = owl_variable_int_validate_default;
514      if (!cur->set_fn) 
515        cur->set_fn = owl_variable_int_set_default;
516      if (!cur->set_fromstring_fn) 
517        cur->set_fromstring_fn = owl_variable_int_set_fromstring_default;
518      if (!cur->get_fn) 
519        cur->get_fn = owl_variable_get_default;
520      if (!cur->get_tostring_fn) 
521        cur->get_tostring_fn = owl_variable_int_get_tostring_default;     
522      if (!cur->delete_fn)
523        cur->delete_fn = owl_variable_delete_default;
524      cur->val = owl_malloc(sizeof(int));
525      cur->set_fn(cur, &cur->ival_default);
526      break;
527    default:
528      fprintf(stderr, "owl_variable_setup: invalid variable type\n");
529      return(-2);
530    }
531    owl_dict_insert_element(vd, cur->name, cur, NULL);
532  }
533  return 0;
534}
535
536void owl_variable_dict_add_variable(owl_vardict * vardict,
537                                    owl_variable * var) {
538  owl_dict_insert_element(vardict, var->name, var, (void (*)(void *))owl_variable_delete);
539}
540
541owl_variable * owl_variable_newvar(const char *name, const char *summary, const char * description) {
542  owl_variable * var = owl_malloc(sizeof(owl_variable));
543  memset(var, 0, sizeof(owl_variable));
544  var->name = owl_strdup(name);
545  var->summary = owl_strdup(summary);
546  var->description = owl_strdup(description);
547  return var;
548}
549
550void owl_variable_update(owl_variable *var, const char *summary, const char *desc) {
551  if(var->summary) owl_free(var->summary);
552  var->summary = owl_strdup(summary);
553  if(var->description) owl_free(var->description);
554  var->description = owl_strdup(desc);
555}
556
557void owl_variable_dict_newvar_string(owl_vardict * vd, const char *name, const char *summ, const char * desc, const char * initval) {
558  owl_variable *old = owl_variable_get_var(vd, name, OWL_VARIABLE_STRING);
559  if(old) {
560    owl_variable_update(old, summ, desc);
561    if(old->pval_default) owl_free(old->pval_default);
562    old->pval_default = owl_strdup(initval);
563  } else {
564    owl_variable * var = owl_variable_newvar(name, summ, desc);
565    var->type = OWL_VARIABLE_STRING;
566    var->pval_default = owl_strdup(initval);
567    var->set_fn = owl_variable_string_set_default;
568    var->set_fromstring_fn = owl_variable_string_set_fromstring_default;
569    var->get_fn = owl_variable_get_default;
570    var->get_tostring_fn = owl_variable_string_get_tostring_default;
571    var->delete_fn = owl_variable_delete_default;
572    var->set_fn(var, initval);
573    owl_variable_dict_add_variable(vd, var);
574  }
575}
576
577void owl_variable_dict_newvar_int(owl_vardict * vd, const char *name, const char *summ, const char * desc, int initval) {
578  owl_variable *old = owl_variable_get_var(vd, name, OWL_VARIABLE_INT);
579  if(old) {
580    owl_variable_update(old, summ, desc);
581    old->ival_default = initval;
582  } else {
583    owl_variable * var = owl_variable_newvar(name, summ, desc);
584    var->type = OWL_VARIABLE_INT;
585    var->ival_default = initval;
586    var->validate_fn = owl_variable_int_validate_default;
587    var->set_fn = owl_variable_int_set_default;
588    var->set_fromstring_fn = owl_variable_int_set_fromstring_default;
589    var->get_fn = owl_variable_get_default;
590    var->get_tostring_fn = owl_variable_int_get_tostring_default;
591    var->delete_fn = owl_variable_delete_default;
592    var->val = owl_malloc(sizeof(int));
593    var->set_fn(var, &initval);
594    owl_variable_dict_add_variable(vd, var);
595  }
596}
597
598void owl_variable_dict_newvar_bool(owl_vardict * vd, const char *name, const char *summ, const char * desc, int initval) {
599  owl_variable *old = owl_variable_get_var(vd, name, OWL_VARIABLE_BOOL);
600  if(old) {
601    owl_variable_update(old, summ, desc);
602    old->ival_default = initval;
603  } else {
604    owl_variable * var = owl_variable_newvar(name, summ, desc);
605    var->type = OWL_VARIABLE_BOOL;
606    var->ival_default = initval;
607    var->validate_fn = owl_variable_bool_validate_default;
608    var->set_fn = owl_variable_bool_set_default;
609    var->set_fromstring_fn = owl_variable_bool_set_fromstring_default;
610    var->get_fn = owl_variable_get_default;
611    var->get_tostring_fn = owl_variable_bool_get_tostring_default;
612    var->delete_fn = owl_variable_delete_default;
613    var->val = owl_malloc(sizeof(int));
614    var->set_fn(var, &initval);
615    owl_variable_dict_add_variable(vd, var);
616  }
617}
618
619void owl_variable_dict_cleanup(owl_vardict *d)
620{
621  owl_dict_cleanup(d, (void (*)(void *))owl_variable_delete);
622}
623
624/* free the list with owl_variable_dict_namelist_cleanup */
625void owl_variable_dict_get_names(const owl_vardict *d, owl_list *l) {
626  owl_dict_get_keys(d, l);
627}
628
629void owl_variable_dict_namelist_cleanup(owl_list *l)
630{
631  owl_list_cleanup(l, owl_free);
632}
633
634void owl_variable_delete(owl_variable *v)
635{
636  if (v->delete_fn) v->delete_fn(v);
637  owl_free(v);
638}
639
640
641const char *owl_variable_get_description(const owl_variable *v) {
642  return v->description;
643}
644
645const char *owl_variable_get_summary(const owl_variable *v) {
646  return v->summary;
647}
648
649const char *owl_variable_get_validsettings(const owl_variable *v) {
650  if (v->validsettings) {
651    return v->validsettings;
652  } else {
653    return "";
654  }
655}
656
657/* functions for getting and setting variable values */
658
659/* returns 0 on success, prints a status msg if msg is true */
660int owl_variable_set_fromstring(owl_vardict *d, const char *name, const char *value, int msg, int requirebool) {
661  owl_variable *v;
662  char buff2[1024];
663  if (!name) return(-1);
664  v = owl_dict_find_element(d, name);
665  if (v == NULL) {
666    if (msg) owl_function_error("Unknown variable %s", name);
667    return -1;
668  }
669  if (!v->set_fromstring_fn) {
670    if (msg) owl_function_error("Variable %s is read-only", name);
671    return -1;   
672  }
673  if (requirebool && v->type!=OWL_VARIABLE_BOOL) {
674    if (msg) owl_function_error("Variable %s is not a boolean", name);
675    return -1;   
676  }
677  if (0 != v->set_fromstring_fn(v, value)) {
678    if (msg) owl_function_error("Unable to set %s (must be %s)", name, 
679                                  owl_variable_get_validsettings(v));
680    return -1;
681  }
682  if (msg && v->get_tostring_fn) {
683    v->get_tostring_fn(v, buff2, 1024, v->val);
684    owl_function_makemsg("%s = '%s'", name, buff2);
685  }   
686  return 0;
687}
688 
689int owl_variable_set_string(owl_vardict *d, const char *name, const char *newval) {
690  owl_variable *v;
691  if (!name) return(-1);
692  v = owl_dict_find_element(d, name);
693  if (v == NULL || !v->set_fn) return(-1);
694  if (v->type!=OWL_VARIABLE_STRING) return(-1);
695  return v->set_fn(v, newval);
696}
697 
698int owl_variable_set_int(owl_vardict *d, const char *name, int newval) {
699  owl_variable *v;
700  if (!name) return(-1);
701  v = owl_dict_find_element(d, name);
702  if (v == NULL || !v->set_fn) return(-1);
703  if (v->type!=OWL_VARIABLE_INT && v->type!=OWL_VARIABLE_BOOL) return(-1);
704  return v->set_fn(v, &newval);
705}
706 
707int owl_variable_set_bool_on(owl_vardict *d, const char *name) {
708  return owl_variable_set_int(d,name,1);
709}
710
711int owl_variable_set_bool_off(owl_vardict *d, const char *name) {
712  return owl_variable_set_int(d,name,0);
713}
714
715int owl_variable_get_tostring(const owl_vardict *d, const char *name, char *buf, int bufsize) {
716  owl_variable *v;
717  if (!name) return(-1);
718  v = owl_dict_find_element(d, name);
719  if (v == NULL || !v->get_tostring_fn) return(-1);
720  return v->get_tostring_fn(v, buf, bufsize, v->val);
721}
722
723int owl_variable_get_default_tostring(const owl_vardict *d, const char *name, char *buf, int bufsize) {
724  owl_variable *v;
725  if (!name) return(-1);
726  v = owl_dict_find_element(d, name);
727  if (v == NULL || !v->get_tostring_fn) return(-1);
728  if (v->type == OWL_VARIABLE_INT || v->type == OWL_VARIABLE_BOOL) {
729    return v->get_tostring_fn(v, buf, bufsize, &(v->ival_default));
730  } else {
731    return v->get_tostring_fn(v, buf, bufsize, v->pval_default);
732  }
733}
734
735owl_variable *owl_variable_get_var(const owl_vardict *d, const char *name, int require_type) {
736  owl_variable *v;
737  if (!name) return(NULL);
738  v = owl_dict_find_element(d, name);
739  if (v == NULL || !v->get_fn || v->type != require_type) return(NULL);
740  return v;
741}
742
743/* returns a reference */
744const void *owl_variable_get(const owl_vardict *d, const char *name, int require_type) {
745  owl_variable *v = owl_variable_get_var(d, name, require_type);
746  if(v == NULL) return NULL;
747  return v->get_fn(v);
748}
749
750/* returns a reference */
751const char *owl_variable_get_string(const owl_vardict *d, const char *name) {
752  return owl_variable_get(d,name, OWL_VARIABLE_STRING);
753}
754
755/* returns a reference */
756const void *owl_variable_get_other(const owl_vardict *d, const char *name) {
757  return owl_variable_get(d,name, OWL_VARIABLE_OTHER);
758}
759
760int owl_variable_get_int(const owl_vardict *d, const char *name) {
761  const int *pi;
762  pi = owl_variable_get(d,name,OWL_VARIABLE_INT);
763  if (!pi) return(-1);
764  return(*pi);
765}
766
767int owl_variable_get_bool(const owl_vardict *d, const char *name) {
768  const int *pi;
769  pi = owl_variable_get(d,name,OWL_VARIABLE_BOOL);
770  if (!pi) return(-1);
771  return(*pi);
772}
773
774void owl_variable_describe(const owl_vardict *d, const char *name, owl_fmtext *fm) {
775  char defaultbuf[50];
776  char buf[1024];
777  int buflen = 1023;
778  owl_variable *v;
779
780  if (!name
781      || (v = owl_dict_find_element(d, name)) == NULL 
782      || !v->get_fn) {
783    snprintf(buf, buflen, "     No such variable '%s'\n", name);     
784    owl_fmtext_append_normal(fm, buf);
785    return;
786  }
787  if (v->type == OWL_VARIABLE_INT || v->type == OWL_VARIABLE_BOOL) {
788    v->get_tostring_fn(v, defaultbuf, 50, &(v->ival_default));
789  } else {
790    v->get_tostring_fn(v, defaultbuf, 50, v->pval_default);
791  }
792  snprintf(buf, buflen, OWL_TABSTR "%-20s - %s (default: '%s')\n", 
793                  v->name, 
794                  owl_variable_get_summary(v), defaultbuf);
795  owl_fmtext_append_normal(fm, buf);
796}
797
798void owl_variable_get_help(const owl_vardict *d, const char *name, owl_fmtext *fm) {
799  char buff[1024];
800  int bufflen = 1023;
801  owl_variable *v;
802
803  if (!name
804      || (v = owl_dict_find_element(d, name)) == NULL 
805      || !v->get_fn) {
806    owl_fmtext_append_normal(fm, "No such variable...\n");
807    return;
808  }
809
810  owl_fmtext_append_bold(fm, "OWL VARIABLE\n\n");
811  owl_fmtext_append_normal(fm, OWL_TABSTR);
812  owl_fmtext_append_normal(fm, name);
813  owl_fmtext_append_normal(fm, " - ");
814  owl_fmtext_append_normal(fm, v->summary);
815  owl_fmtext_append_normal(fm, "\n\n");
816
817  owl_fmtext_append_normal(fm, "Current:        ");
818  owl_variable_get_tostring(d, name, buff, bufflen);
819  owl_fmtext_append_normal(fm, buff);
820  owl_fmtext_append_normal(fm, "\n\n");
821
822
823  if (v->type == OWL_VARIABLE_INT || v->type == OWL_VARIABLE_BOOL) {
824    v->get_tostring_fn(v, buff, bufflen, &(v->ival_default));
825  } else {
826    v->get_tostring_fn(v, buff, bufflen, v->pval_default);
827  }
828  owl_fmtext_append_normal(fm, "Default:        ");
829  owl_fmtext_append_normal(fm, buff);
830  owl_fmtext_append_normal(fm, "\n\n");
831
832  owl_fmtext_append_normal(fm, "Valid Settings: ");
833  owl_fmtext_append_normal(fm, owl_variable_get_validsettings(v));
834  owl_fmtext_append_normal(fm, "\n\n");
835
836  if (v->description && *v->description) {
837    owl_fmtext_append_normal(fm, "Description:\n");
838    owl_fmtext_append_normal(fm, owl_variable_get_description(v));
839    owl_fmtext_append_normal(fm, "\n\n");
840  }
841}
842
843
844
845
846/**************************************************************************/
847/*********************** GENERAL TYPE-SPECIFIC ****************************/
848/**************************************************************************/
849
850/* default common functions */
851
852const void *owl_variable_get_default(const owl_variable *v) {
853  return v->val;
854}
855
856void owl_variable_delete_default(owl_variable *v)
857{
858  if (v->val) owl_free(v->val);
859}
860
861/* default functions for booleans */
862
863int owl_variable_bool_validate_default(const owl_variable *v, const void *newval) {
864  if (newval == NULL) return(0);
865  else if (*(const int*)newval==1 || *(const int*)newval==0) return(1);
866  else return (0);
867}
868
869int owl_variable_bool_set_default(owl_variable *v, const void *newval) {
870  if (v->validate_fn) {
871    if (!v->validate_fn(v, newval)) return(-1);
872  }
873  *(int*)v->val = *(const int*)newval;
874  return(0);
875}
876
877int owl_variable_bool_set_fromstring_default(owl_variable *v, const char *newval) {
878  int i;
879  if (!strcmp(newval, "on")) i=1;
880  else if (!strcmp(newval, "off")) i=0;
881  else return(-1);
882  return (v->set_fn(v, &i));
883}
884
885int owl_variable_bool_get_tostring_default(const owl_variable *v, char* buf, int bufsize, const void *val) {
886  if (val == NULL) {
887    snprintf(buf, bufsize, "<null>");
888    return -1;
889  } else if (*(const int*)val == 0) {
890    snprintf(buf, bufsize, "off");
891    return 0;
892  } else if (*(const int*)val == 1) {
893    snprintf(buf, bufsize, "on");
894    return 0;
895  } else {
896    snprintf(buf, bufsize, "<invalid>");
897    return -1;
898  }
899}
900
901/* default functions for integers */
902
903int owl_variable_int_validate_default(const owl_variable *v, const void *newval) {
904  if (newval == NULL) return(0);
905  else return (1);
906}
907
908int owl_variable_int_set_default(owl_variable *v, const void *newval) {
909  if (v->validate_fn) {
910    if (!v->validate_fn(v, newval)) return(-1);
911  }
912  *(int*)v->val = *(const int*)newval;
913  return(0);
914}
915
916int owl_variable_int_set_fromstring_default(owl_variable *v, const char *newval) {
917  int i;
918  char *ep;
919  i = strtol(newval, &ep, 10);
920  if (*ep || ep==newval) return(-1);
921  return (v->set_fn(v, &i));
922}
923
924int owl_variable_int_get_tostring_default(const owl_variable *v, char* buf, int bufsize, const void *val) {
925  if (val == NULL) {
926    snprintf(buf, bufsize, "<null>");
927    return -1;
928  } else {
929    snprintf(buf, bufsize, "%d", *(const int*)val);
930    return 0;
931  } 
932}
933
934/* default functions for enums (a variant of integers) */
935
936int owl_variable_enum_validate(const owl_variable *v, const void *newval) { 
937  char **enums;
938  int nenums, val;
939  if (newval == NULL) return(0);
940  enums = atokenize(v->validsettings, ",", &nenums);
941  if (enums == NULL) return(0);
942  atokenize_delete(enums, nenums);
943  val = *(const int*)newval;
944  if (val < 0 || val >= nenums) {
945    return(0);
946  }
947  return(1);
948}
949
950int owl_variable_enum_set_fromstring(owl_variable *v, const char *newval) {
951  char **enums;
952  int nenums, i, val=-1;
953  if (newval == NULL) return(-1);
954  enums = atokenize(v->validsettings, ",", &nenums);
955  if (enums == NULL) return(-1);
956  for (i=0; i<nenums; i++) {
957    if (0==strcmp(newval, enums[i])) {
958      val = i;
959    }
960  }
961  atokenize_delete(enums, nenums);
962  if (val == -1) return(-1);
963  return (v->set_fn(v, &val));
964}
965
966int owl_variable_enum_get_tostring(const owl_variable *v, char* buf, int bufsize, const void *val) {
967  char **enums;
968  int nenums, i;
969
970  if (val == NULL) {
971    snprintf(buf, bufsize, "<null>");
972    return -1;
973  }
974  enums = atokenize(v->validsettings, ",", &nenums);
975  i = *(const int*)val;
976  if (i<0 || i>=nenums) {
977    snprintf(buf, bufsize, "<invalid:%d>",i);
978    atokenize_delete(enums, nenums);
979    return(-1);
980  }
981  snprintf(buf, bufsize, "%s", enums[i]);
982  atokenize_delete(enums, nenums);
983  return 0;
984}
985
986/* default functions for stringeans */
987
988int owl_variable_string_validate_default(const struct _owl_variable *v, const void *newval) {
989  if (newval == NULL) return(0);
990  else return (1);
991}
992
993int owl_variable_string_set_default(owl_variable *v, const void *newval) {
994  if (v->validate_fn) {
995    if (!v->validate_fn(v, newval)) return(-1);
996  }
997  if (v->val) owl_free(v->val);
998  v->val = owl_strdup(newval);
999  return(0);
1000}
1001
1002int owl_variable_string_set_fromstring_default(owl_variable *v, const char *newval) {
1003  return (v->set_fn(v, newval));
1004}
1005
1006int owl_variable_string_get_tostring_default(const owl_variable *v, char* buf, int bufsize, const void *val) {
1007  if (val == NULL) {
1008    snprintf(buf, bufsize, "<null>");
1009    return -1;
1010  } else {
1011    snprintf(buf, bufsize, "%s", (const char*)val);
1012    return 0;
1013  }
1014}
1015
Note: See TracBrowser for help on using the repository browser.