source: variable.c @ 700dc91

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