source: variable.c @ 5d59c1e

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