source: variable.c @ 12c35df

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