source: variable.c @ b1299da

barnowl_perlaimdebianowlrelease-1.4release-1.5release-1.6release-1.7release-1.8release-1.9
Last change on this file since b1299da was b1299da, checked in by James M. Kretchmar <kretch@mit.edu>, 17 years ago
recalculate the topmsg after changing the style
  • Property mode set to 100644
File size: 32.4 KB
Line 
1#include <stdio.h>
2#include <stdlib.h>
3#include <string.h>
4#include <unistd.h>
5#include <ctype.h>
6#include "owl.h"
7
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( "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_BOOL( "colorztext" /* %OwlVarStub */, 1,
112               "allow @color() in zephyrs to change color",
113               "Note that only messages received after this variable\n"
114               "is set will be affected." ),
115
116  OWLVAR_BOOL( "zcrypt" /* %OwlVarStub */, 1,
117               "Do automatic zcrypt processing",
118               "" ),
119
120  OWLVAR_ENUM_FULL( "disable-ctrl-d" /* %OwlVarStub:lockout_ctrld */, 1,
121                    "don't send zephyrs on C-d",
122                    "If set to 'off', C-d won't send a zephyr from the edit\n"
123                    "window.  If set to 'on', C-d will always send a zephyr\n"
124                    "being composed in the edit window.  If set to 'middle',\n"
125                    "C-d will only ever send a zephyr if the cursor is at\n"
126                    "the end of the message being composed.\n\n"
127                    "Note that this works by changing the C-d keybinding\n"
128                    "in the editmulti keymap.\n",
129                    "off,middle,on",
130                    NULL, owl_variable_disable_ctrl_d_set, NULL),
131
132  OWLVAR_BOOL( "_burningears" /* %OwlVarStub:burningears */, 0,
133               "[NOT YET IMPLEMENTED] beep on messages matching patterns", "" ),
134
135  OWLVAR_BOOL( "_summarymode" /* %OwlVarStub:summarymode */, 0,
136               "[NOT YET IMPLEMENTED]", "" ),
137
138  OWLVAR_PATH( "logpath" /* %OwlVarStub */, "~/zlog/people",
139               "path for logging personal zephyrs", 
140               "Specifies a directory which must exist.\n"
141               "Files will be created in the directory for each sender.\n"),
142
143  OWLVAR_PATH( "classlogpath" /* %OwlVarStub:classlogpath */, "~/zlog/class",
144               "path for logging class zephyrs",
145               "Specifies a directory which must exist.\n"
146               "Files will be created in the directory for each class.\n"),
147
148  OWLVAR_PATH( "debug_file" /* %OwlVarStub */, OWL_DEBUG_FILE,
149               "path for logging debug messages when debugging is enabled",
150               "This file will be logged to if 'debug' is set to 'on'.\n"),
151 
152  OWLVAR_PATH( "zsigproc" /* %OwlVarStub:zsigproc */, NULL,
153               "name of a program to run that will generate zsigs",
154               "This program should produce a zsig on stdout when run.\n"
155               "Note that it is important that this program not block.\n" ),
156
157  OWLVAR_PATH( "newmsgproc" /* %OwlVarStub:newmsgproc */, NULL,
158               "name of a program to run when new messages are present",
159               "The named program will be run when owl recevies new.\n"
160               "messages.  It will not be run again until the first\n"
161               "instance exits"),
162
163  OWLVAR_STRING( "zsig" /* %OwlVarStub */, "",
164                 "zephyr signature", 
165                 "If 'zsigproc' is not set, this string will be used\n"
166                 "as a zsig.  If this is also unset, the 'zwrite-signature'\n"
167                 "zephyr variable will be used instead.\n"),
168
169  OWLVAR_STRING( "appendtosepbar" /* %OwlVarStub */, "",
170                 "string to append to the end of the sepbar",
171                 "The sepbar is the bar separating the top and bottom\n"
172                 "of the owl screen.  Any string specified here will\n"
173                 "be displayed on the right of the sepbar\n"),
174
175  OWLVAR_BOOL( "zaway" /* %OwlVarStub */, 0,
176               "turn zaway on or off", "" ),
177
178  OWLVAR_STRING( "zaway_msg" /* %OwlVarStub */, 
179                 OWL_DEFAULT_ZAWAYMSG,
180                 "zaway msg for responding to zephyrs when away", "" ),
181
182  OWLVAR_STRING( "zaway_msg_default" /* %OwlVarStub */, 
183                 OWL_DEFAULT_ZAWAYMSG,
184                 "default zaway message", "" ),
185
186  OWLVAR_STRING( "view_home" /* %OwlVarStub */, "all",
187                 "home view to switch to after 'X' and 'V'", 
188                 "SEE ALSO: view, filter\n" ),
189
190  OWLVAR_STRING( "alert_filter" /* %OwlVarStub */, "none",
191                 "filter on which to trigger alert actions",
192                 "" ),
193
194  OWLVAR_STRING( "alert_action" /* %OwlVarStub */, "nop",
195                 "filter on which to trigger alert actions",
196                 "" ),
197
198  OWLVAR_STRING_FULL( "tty" /* %OwlVarStub */, "", "tty name for zephyr location", "",
199                      NULL, owl_variable_tty_set, NULL),
200
201  OWLVAR_STRING_FULL( "style" /* %OwlVarStub */, "default", "name of the current formatting style",
202                      "This sets the current message formatting style. Possbile\n"
203                      "values include 'default' 'basic' 'oneline' and if\n"
204                      "available, 'perl'\n",
205                      NULL, owl_variable_style_set, NULL),
206
207  OWLVAR_STRING( "default_style" /* %OwlVarStub */, "default",
208                 "name of the default formatting style",
209                 "This sets the default message formatting style. Possbile\n"
210                 "values include 'default' 'basic' 'oneline' and if\n"
211                 "available, 'perl'\n" ),
212
213  OWLVAR_INT(    "edit:maxfillcols" /* %OwlVarStub:edit_maxfillcols */, 70,
214                 "maximum number of columns for M-q to fill text to",
215                 "This specifies the maximum number of columns for M-q\n"
216                 "to fill text to.  If set to 0, ther will be no maximum\n"
217                 "limit.  In all cases, the current width of the screen\n"
218                 "will also be taken into account.  It will be used instead\n"
219                 "if it is narrower than the maximum, or if this\n"
220                 "is set to 0.\n" ),
221
222  OWLVAR_INT(    "edit:maxwrapcols" /* %OwlVarStub:edit_maxwrapcols */, 0,
223                 "maximum number of columns for line-wrapping",
224                 "This specifies the maximum number of columns for\n"
225                 "auto-line-wrapping.  If set to 0, ther will be no maximum\n"
226                 "limit.  In all cases, the current width of the screen\n"
227                 "will also be taken into account.  It will be used instead\n"
228                 "if it is narrower than the maximum, or if this\n"
229                 "is set to 0.\n\n"
230                 "It is recommended that outgoing messages be no wider\n"
231                 "than 60 columns, as a courtesy to recipients.\n"),
232
233  OWLVAR_INT( "aim_ignorelogin_timer" /* %OwlVarStub */, 0,
234              "number of seconds after AIM login to ignore login messages",
235              "This specifies the number of seconds to wait after an\n"
236              "AIM login before allowing the recipt of AIM login notifications.\n"
237              "By default this is set to 0 and all login notifications are\n"
238              "viewed immediately.  If you dislike this behavior try setting\n"
239              "the value to 20 instead.\n"),
240
241             
242  OWLVAR_INT_FULL( "typewinsize" /* %OwlVarStub:typwin_lines */, 
243                   OWL_TYPWIN_SIZE,
244                  "number of lines in the typing window", 
245                   "This specifies the height of the window at the\n"
246                   "bottom of the screen where commands are entered\n"
247                   "and where messages are composed.\n",
248                   "int > 0",
249                   owl_variable_int_validate_gt0,
250                   owl_variable_typewinsize_set,
251                   NULL /* use default for get */
252                   ),
253
254  OWLVAR_ENUM( "scrollmode" /* %OwlVarStub */, OWL_SCROLLMODE_NORMAL,
255               "how to scroll up and down",
256               "This controls how the screen is scrolled as the\n"
257               "cursor moves between messages being displayed.\n"
258               "The following modes are supported:\n\n"
259               "   normal      - This is the owl default.  Scrolling happens\n"
260               "                 when it needs to, and an attempt is made to\n"
261               "                 keep the current message roughly near\n"
262               "                 the middle of the screen.\n"
263               "   top         - The current message will always be the\n"
264               "                 the top message displayed.\n"
265               "   neartop     - The current message will be one down\n"
266               "                 from the top message displayed,\n"
267               "                 where possible.\n"
268               "   center      - An attempt is made to keep the current\n"
269               "                 message near the center of the screen.\n"
270               "   paged       - The top message displayed only changes\n"
271               "                 when user moves the cursor to the top\n"
272               "                 or bottom of the screen.  When it moves,\n"
273               "                 the screen will be paged up or down and\n"
274               "                 the cursor will be near the top or\n"
275               "                 the bottom.\n"
276               "   pagedcenter - The top message displayed only changes\n"
277               "                 when user moves the cursor to the top\n"
278               "                 or bottom of the screen.  When it moves,\n"
279               "                 the screen will be paged up or down and\n"
280               "                 the cursor will be near the center.\n",
281               "normal,top,neartop,center,paged,pagedcenter" ),
282
283  OWLVAR_ENUM( "webbrowser" /* %OwlVarStub */, OWL_WEBBROWSER_NETSCAPE,
284               "web browser to use to launch URLs",
285               "When the 'w' key is pressed, this browser is used\n"
286               "to display the requested URL.\n",
287               "none,netscape,galeon,opera" ),
288
289
290  OWLVAR_BOOL( "_followlast" /* %OwlVarStub */, 0,
291               "enable automatic following of the last zephyr",
292               "If the cursor is at the last message, it will\n"
293               "continue to follow the last message if this is set.\n"
294               "Note that this is currently risky as you might accidentally\n"
295               "delete a message right as it came in.\n" ),
296
297  /* This MUST be last... */
298  { NULL, 0, NULL, 0, NULL, NULL, NULL, NULL,
299    NULL, NULL, NULL, NULL, NULL, NULL }
300
301};
302
303/**************************************************************************/
304/*********************** SPECIFIC TO VARIABLES ****************************/
305/**************************************************************************/
306
307
308/* commonly useful */
309
310int owl_variable_int_validate_gt0(owl_variable *v, void *newval) {
311  if (newval == NULL) return(0);
312  else if (*(int*)newval < 1) return(0);
313  else return (1);
314}
315
316int owl_variable_int_validate_positive(owl_variable *v, void *newval) {
317  if (newval == NULL) return(0);
318  else if (*(int*)newval < 0) return(0);
319  else return (1);
320}
321
322/* typewinsize */
323
324int owl_variable_typewinsize_set(owl_variable *v, void *newval) {
325  int rv;
326  rv = owl_variable_int_set_default(v, newval);
327  if (0 == rv) owl_function_resize();
328  return(rv);
329}
330
331/* debug (cache value in g->debug) */
332
333int owl_variable_debug_set(owl_variable *v, void *newval) {
334  if (newval && (*(int*)newval == 1 || *(int*)newval == 0)) {
335    g.debug = *(int*)newval;
336  }
337  return owl_variable_bool_set_default(v, newval);
338}
339
340/* note that changing the value of this will clobber
341 * any user setting of this */
342int owl_variable_disable_ctrl_d_set(owl_variable *v, void *newval) {
343
344  if (in_regtest) return owl_variable_int_set_default(v, newval);
345
346  if (newval && !owl_context_is_startup(owl_global_get_context(&g))) {
347    if (*(int*)newval == 2) {
348      owl_function_command_norv("bindkey editmulti C-d command edit:delete-next-char");
349    } else if (*(int*)newval == 1) {
350      owl_function_command_norv("bindkey editmulti C-d command editmulti:done-or-delete");
351    } else {
352      owl_function_command_norv("bindkey editmulti C-d command editmulti:done");
353    }
354  } 
355  return owl_variable_int_set_default(v, newval); 
356}
357
358int owl_variable_tty_set(owl_variable *v, void *newval) {
359  ZInitLocationInfo(owl_global_get_hostname(&g), newval);
360  return(owl_variable_string_set_default(v, newval));
361}
362
363int owl_variable_style_set(owl_variable *v, void *newval) {
364  /* Invalidate all message formats first */
365  int ret;
366  owl_style *s;
367
368  s=owl_global_get_style_by_name(&g, newval);
369  if (!s) {
370    /* this message won't get seen, we'll need to deal with that later */
371    owl_function_makemsg("No style named '%s' exists.", newval);
372    return(0);
373  }
374 
375  owl_messagelist_invalidate_formats(owl_global_get_msglist(&g));
376  ret=owl_variable_string_set_default(v, newval);
377  owl_function_calculate_topmsg(OWL_DIRECTION_DOWNWARDS);
378  owl_mainwin_redisplay(owl_global_get_mainwin(&g));
379  return(ret);
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_makemsg("Unknown variable %s", name);
495    return -1;
496  }
497  if (!v->set_fromstring_fn) {
498    if (msg) owl_function_makemsg("Variable %s is read-only", name);
499    return -1;   
500  }
501  if (requirebool && v->type!=OWL_VARIABLE_BOOL) {
502    if (msg) owl_function_makemsg("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_makemsg("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.