source: variable.c @ c3ab155

barnowl_perlaimdebianowlrelease-1.10release-1.4release-1.5release-1.6release-1.7release-1.8release-1.9
Last change on this file since c3ab155 was c3ab155, checked in by James M. Kretchmar <kretch@mit.edu>, 21 years ago
Really use just one view now, named 'main' and recalculate messages when its filter is changed. This is in preperation for other design changes Added the 'default_style' variable Added the 'toggle-oneline' command the 'o' key is bound to 'toggle-oneline'
  • Property mode set to 100644
File size: 32.3 KB
Line 
1#include <stdio.h>
2#include <stdlib.h>
3#include <string.h>
4#include <unistd.h>
5#include <ctype.h>
6#include "owl.h"
7
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_mainwin_redisplay(owl_global_get_mainwin(&g));
378  return(ret);
379}
380
381
382/**************************************************************************/
383/****************************** GENERAL ***********************************/
384/**************************************************************************/
385
386int owl_variable_dict_setup(owl_vardict *vd) {
387  owl_variable *cur;
388  if (owl_dict_create(vd)) return(-1);
389  for (cur = variables_to_init; cur->name != NULL; cur++) {
390    switch (cur->type) {
391    case OWL_VARIABLE_OTHER:
392      cur->set_fn(cur, cur->pval_default);
393      break;
394    case OWL_VARIABLE_STRING:
395      if (!cur->validate_fn) 
396        cur->validate_fn = owl_variable_string_validate_default;
397      if (!cur->set_fn) 
398        cur->set_fn = owl_variable_string_set_default;
399      if (!cur->set_fromstring_fn) 
400        cur->set_fromstring_fn = owl_variable_string_set_fromstring_default;
401      if (!cur->get_fn) 
402        cur->get_fn = owl_variable_get_default;
403      if (!cur->get_tostring_fn) 
404        cur->get_tostring_fn = owl_variable_string_get_tostring_default;     
405      if (!cur->free_fn) 
406        cur->free_fn = owl_variable_free_default;
407      cur->set_fn(cur, cur->pval_default);
408      break;
409    case OWL_VARIABLE_BOOL:
410      if (!cur->validate_fn) 
411        cur->validate_fn = owl_variable_bool_validate_default;
412      if (!cur->set_fn) 
413        cur->set_fn = owl_variable_bool_set_default;
414      if (!cur->set_fromstring_fn) 
415        cur->set_fromstring_fn = owl_variable_bool_set_fromstring_default;
416      if (!cur->get_fn) 
417        cur->get_fn = owl_variable_get_default;
418      if (!cur->get_tostring_fn) 
419        cur->get_tostring_fn = owl_variable_bool_get_tostring_default;     
420      if (!cur->free_fn) 
421        cur->free_fn = owl_variable_free_default;
422      cur->val = owl_malloc(sizeof(int));
423      cur->set_fn(cur, &cur->ival_default);
424      break;
425    case OWL_VARIABLE_INT:
426      if (!cur->validate_fn) 
427        cur->validate_fn = owl_variable_int_validate_default;
428      if (!cur->set_fn) 
429        cur->set_fn = owl_variable_int_set_default;
430      if (!cur->set_fromstring_fn) 
431        cur->set_fromstring_fn = owl_variable_int_set_fromstring_default;
432      if (!cur->get_fn) 
433        cur->get_fn = owl_variable_get_default;
434      if (!cur->get_tostring_fn) 
435        cur->get_tostring_fn = owl_variable_int_get_tostring_default;     
436      if (!cur->free_fn) 
437        cur->free_fn = owl_variable_free_default;
438      cur->val = owl_malloc(sizeof(int));
439      cur->set_fn(cur, &cur->ival_default);
440      break;
441    default:
442      fprintf(stderr, "owl_variable_setup: invalid variable type\n");
443      return(-2);
444    }
445    owl_dict_insert_element(vd, cur->name, (void*)cur, NULL);
446  }
447  return 0;
448}
449
450void owl_variable_dict_free(owl_vardict *d) {
451  owl_dict_free_all(d, (void(*)(void*))owl_variable_free);
452}
453
454/* free the list with owl_variable_dict_namelist_free */
455void owl_variable_dict_get_names(owl_vardict *d, owl_list *l) {
456  owl_dict_get_keys(d, l);
457}
458
459void owl_variable_dict_namelist_free(owl_list *l) {
460  owl_list_free_all(l, owl_free);
461}
462
463void owl_variable_free(owl_variable *v) {
464  if (v->free_fn) v->free_fn(v);
465}
466
467
468char *owl_variable_get_description(owl_variable *v) {
469  return v->description;
470}
471
472char *owl_variable_get_summary(owl_variable *v) {
473  return v->summary;
474}
475
476char *owl_variable_get_validsettings(owl_variable *v) {
477  if (v->validsettings) {
478    return v->validsettings;
479  } else {
480    return "";
481  }
482}
483
484/* functions for getting and setting variable values */
485
486/* returns 0 on success, prints a status msg if msg is true */
487int owl_variable_set_fromstring(owl_vardict *d, char *name, char *value, int msg, int requirebool) {
488  owl_variable *v;
489  char buff2[1024];
490  if (!name) return(-1);
491  v = owl_dict_find_element(d, name);
492  if (v == NULL) {
493    if (msg) owl_function_makemsg("Unknown variable %s", name);
494    return -1;
495  }
496  if (!v->set_fromstring_fn) {
497    if (msg) owl_function_makemsg("Variable %s is read-only", name);
498    return -1;   
499  }
500  if (requirebool && v->type!=OWL_VARIABLE_BOOL) {
501    if (msg) owl_function_makemsg("Variable %s is not a boolean", name);
502    return -1;   
503  }
504  if (0 != v->set_fromstring_fn(v, value)) {
505    if (msg) owl_function_makemsg("Unable to set %s (must be %s)", name, 
506                                  owl_variable_get_validsettings(v));
507    return -1;
508  }
509  if (msg && v->get_tostring_fn) {
510    v->get_tostring_fn(v, buff2, 1024, v->val);
511    owl_function_makemsg("%s = '%s'", name, buff2);
512  }   
513  return 0;
514}
515 
516int owl_variable_set_string(owl_vardict *d, char *name, char *newval) {
517  owl_variable *v;
518  if (!name) return(-1);
519  v = owl_dict_find_element(d, name);
520  if (v == NULL || !v->set_fn) return(-1);
521  if (v->type!=OWL_VARIABLE_STRING) return(-1);
522  return v->set_fn(v, (void*)newval);
523}
524 
525int owl_variable_set_int(owl_vardict *d, char *name, int newval) {
526  owl_variable *v;
527  if (!name) return(-1);
528  v = owl_dict_find_element(d, name);
529  if (v == NULL || !v->set_fn) return(-1);
530  if (v->type!=OWL_VARIABLE_INT && v->type!=OWL_VARIABLE_BOOL) return(-1);
531  return v->set_fn(v, &newval);
532}
533 
534int owl_variable_set_bool_on(owl_vardict *d, char *name) {
535  return owl_variable_set_int(d,name,1);
536}
537
538int owl_variable_set_bool_off(owl_vardict *d, char *name) {
539  return owl_variable_set_int(d,name,0);
540}
541
542int owl_variable_get_tostring(owl_vardict *d, char *name, char *buf, int bufsize) {
543  owl_variable *v;
544  if (!name) return(-1);
545  v = owl_dict_find_element(d, name);
546  if (v == NULL || !v->get_tostring_fn) return(-1);
547  return v->get_tostring_fn(v, buf, bufsize, v->val);
548}
549
550int owl_variable_get_default_tostring(owl_vardict *d, char *name, char *buf, int bufsize) {
551  owl_variable *v;
552  if (!name) return(-1);
553  v = owl_dict_find_element(d, name);
554  if (v == NULL || !v->get_tostring_fn) return(-1);
555  if (v->type == OWL_VARIABLE_INT || v->type == OWL_VARIABLE_BOOL) {
556    return v->get_tostring_fn(v, buf, bufsize, &(v->ival_default));
557  } else {
558    return v->get_tostring_fn(v, buf, bufsize, v->pval_default);
559  }
560}
561
562/* returns a reference */
563void *owl_variable_get(owl_vardict *d, char *name, int require_type) {
564  owl_variable *v;
565  if (!name) return(NULL);
566  v = owl_dict_find_element(d, name);
567  if (v == NULL || !v->get_fn || v->type != require_type) return(NULL);
568  return v->get_fn(v);
569}
570
571/* returns a reference */
572char *owl_variable_get_string(owl_vardict *d, char *name) {
573  return (char*)owl_variable_get(d,name, OWL_VARIABLE_STRING);
574}
575
576/* returns a reference */
577void *owl_variable_get_other(owl_vardict *d, char *name) {
578  return (char*)owl_variable_get(d,name, OWL_VARIABLE_OTHER);
579}
580
581int owl_variable_get_int(owl_vardict *d, char *name) {
582  int *pi;
583  pi = (int*)owl_variable_get(d,name,OWL_VARIABLE_INT);
584  if (!pi) return(-1);
585  return(*pi);
586}
587
588int owl_variable_get_bool(owl_vardict *d, char *name) {
589  int *pi;
590  pi = (int*)owl_variable_get(d,name,OWL_VARIABLE_BOOL);
591  if (!pi) return(-1);
592  return(*pi);
593}
594
595void owl_variable_describe(owl_vardict *d, char *name, owl_fmtext *fm) {
596  char defaultbuf[50];
597  char buf[1024];
598  int buflen = 1023;
599  owl_variable *v;
600
601  if (!name
602      || (v = owl_dict_find_element(d, name)) == NULL 
603      || !v->get_fn) {
604    snprintf(buf, buflen, "     No such variable '%s'\n", name);     
605    owl_fmtext_append_normal(fm, buf);
606    return;
607  }
608  if (v->type == OWL_VARIABLE_INT || v->type == OWL_VARIABLE_BOOL) {
609    v->get_tostring_fn(v, defaultbuf, 50, &(v->ival_default));
610  } else {
611    v->get_tostring_fn(v, defaultbuf, 50, v->pval_default);
612  }
613  snprintf(buf, buflen, OWL_TABSTR "%-20s - %s (default: '%s')\n", 
614                  v->name, 
615                  owl_variable_get_summary(v), defaultbuf);
616  owl_fmtext_append_normal(fm, buf);
617}
618
619void owl_variable_get_help(owl_vardict *d, char *name, owl_fmtext *fm) {
620  char buff[1024];
621  int bufflen = 1023;
622  owl_variable *v;
623
624  if (!name
625      || (v = owl_dict_find_element(d, name)) == NULL 
626      || !v->get_fn) {
627    owl_fmtext_append_normal(fm, "No such variable...\n");
628    return;
629  }
630
631  owl_fmtext_append_bold(fm, "OWL VARIABLE\n\n");
632  owl_fmtext_append_normal(fm, OWL_TABSTR);
633  owl_fmtext_append_normal(fm, name);
634  owl_fmtext_append_normal(fm, " - ");
635  owl_fmtext_append_normal(fm, v->summary);
636  owl_fmtext_append_normal(fm, "\n\n");
637
638  owl_fmtext_append_normal(fm, "Current:        ");
639  owl_variable_get_tostring(d, name, buff, bufflen);
640  owl_fmtext_append_normal(fm, buff);
641  owl_fmtext_append_normal(fm, "\n\n");
642
643
644  if (v->type == OWL_VARIABLE_INT || v->type == OWL_VARIABLE_BOOL) {
645    v->get_tostring_fn(v, buff, bufflen, &(v->ival_default));
646  } else {
647    v->get_tostring_fn(v, buff, bufflen, v->pval_default);
648  }
649  owl_fmtext_append_normal(fm, "Default:        ");
650  owl_fmtext_append_normal(fm, buff);
651  owl_fmtext_append_normal(fm, "\n\n");
652
653  owl_fmtext_append_normal(fm, "Valid Settings: ");
654  owl_fmtext_append_normal(fm, owl_variable_get_validsettings(v));
655  owl_fmtext_append_normal(fm, "\n\n");
656
657  if (v->description && *v->description) {
658    owl_fmtext_append_normal(fm, "Description:\n");
659    owl_fmtext_append_normal(fm, owl_variable_get_description(v));
660    owl_fmtext_append_normal(fm, "\n\n");
661  }
662}
663
664
665
666
667/**************************************************************************/
668/*********************** GENERAL TYPE-SPECIFIC ****************************/
669/**************************************************************************/
670
671/* default common functions */
672
673void *owl_variable_get_default(owl_variable *v) {
674  return v->val;
675}
676
677void owl_variable_free_default(owl_variable *v) {
678  if (v->val) owl_free(v->val);
679}
680
681/* default functions for booleans */
682
683int owl_variable_bool_validate_default(owl_variable *v, void *newval) {
684  if (newval == NULL) return(0);
685  else if (*(int*)newval==1 || *(int*)newval==0) return(1);
686  else return (0);
687}
688
689int owl_variable_bool_set_default(owl_variable *v, void *newval) {
690  if (v->validate_fn) {
691    if (!v->validate_fn(v, newval)) return(-1);
692  }
693  *(int*)v->val = *(int*)newval;
694  return(0);
695}
696
697int owl_variable_bool_set_fromstring_default(owl_variable *v, char *newval) {
698  int i;
699  if (!strcmp(newval, "on")) i=1;
700  else if (!strcmp(newval, "off")) i=0;
701  else return(-1);
702  return (v->set_fn(v, &i));
703}
704
705int owl_variable_bool_get_tostring_default(owl_variable *v, char* buf, int bufsize, void *val) {
706  if (val == NULL) {
707    snprintf(buf, bufsize, "<null>");
708    return -1;
709  } else if (*(int*)val == 0) {
710    snprintf(buf, bufsize, "off");
711    return 0;
712  } else if (*(int*)val == 1) {
713    snprintf(buf, bufsize, "on");
714    return 0;
715  } else {
716    snprintf(buf, bufsize, "<invalid>");
717    return -1;
718  }
719}
720
721/* default functions for integers */
722
723int owl_variable_int_validate_default(owl_variable *v, void *newval) {
724  if (newval == NULL) return(0);
725  else return (1);
726}
727
728int owl_variable_int_set_default(owl_variable *v, void *newval) {
729  if (v->validate_fn) {
730    if (!v->validate_fn(v, newval)) return(-1);
731  }
732  *(int*)v->val = *(int*)newval;
733  return(0);
734}
735
736int owl_variable_int_set_fromstring_default(owl_variable *v, char *newval) {
737  int i;
738  char *ep = "x";
739  i = strtol(newval, &ep, 10);
740  if (*ep || ep==newval) return(-1);
741  return (v->set_fn(v, &i));
742}
743
744int owl_variable_int_get_tostring_default(owl_variable *v, char* buf, int bufsize, void *val) {
745  if (val == NULL) {
746    snprintf(buf, bufsize, "<null>");
747    return -1;
748  } else {
749    snprintf(buf, bufsize, "%d", *(int*)val);
750    return 0;
751  } 
752}
753
754/* default functions for enums (a variant of integers) */
755
756int owl_variable_enum_validate(owl_variable *v, void *newval) { 
757  char **enums;
758  int nenums, val;
759  if (newval == NULL) return(0);
760  enums = atokenize(v->validsettings, ",", &nenums);
761  if (enums == NULL) return(0);
762  atokenize_free(enums, nenums);
763  val = *(int*)newval;
764  if (val < 0 || val >= nenums) {
765    return(0);
766  }
767  return(1);
768}
769
770int owl_variable_enum_set_fromstring(owl_variable *v, char *newval) {
771  char **enums;
772  int nenums, i, val=-1;
773  if (newval == NULL) return(-1);
774  enums = atokenize(v->validsettings, ",", &nenums);
775  if (enums == NULL) return(-1);
776  for (i=0; i<nenums; i++) {
777    if (0==strcmp(newval, enums[i])) {
778      val = i;
779    }
780  }
781  atokenize_free(enums, nenums);
782  if (val == -1) return(-1);
783  return (v->set_fn(v, &val));
784}
785
786int owl_variable_enum_get_tostring(owl_variable *v, char* buf, int bufsize, void *val) {
787  char **enums;
788  int nenums, i;
789
790  if (val == NULL) {
791    snprintf(buf, bufsize, "<null>");
792    return -1;
793  }
794  enums = atokenize(v->validsettings, ",", &nenums);
795  i = *(int*)val;
796  if (i<0 || i>=nenums) {
797    snprintf(buf, bufsize, "<invalid:%d>",i);
798    atokenize_free(enums, nenums);
799    return(-1);
800  }
801  snprintf(buf, bufsize, "%s", enums[i]);
802  return 0;
803}
804
805/* default functions for stringeans */
806
807int owl_variable_string_validate_default(struct _owl_variable *v, void *newval) {
808  if (newval == NULL) return(0);
809  else return (1);
810}
811
812int owl_variable_string_set_default(owl_variable *v, void *newval) {
813  if (v->validate_fn) {
814    if (!v->validate_fn(v, newval)) return(-1);
815  }
816  if (v->val) owl_free(v->val);
817  v->val = owl_strdup(newval);
818  return(0);
819}
820
821int owl_variable_string_set_fromstring_default(owl_variable *v, char *newval) {
822  return (v->set_fn(v, newval));
823}
824
825int owl_variable_string_get_tostring_default(owl_variable *v, char* buf, int bufsize, void *val) {
826  if (val == NULL) {
827    snprintf(buf, bufsize, "<null>");
828    return -1;
829  } else {
830    snprintf(buf, bufsize, "%s", (char*)val);
831    return 0;
832  }
833}
834
835
836
837/**************************************************************************/
838/************************* REGRESSION TESTS *******************************/
839/**************************************************************************/
840
841#ifdef OWL_INCLUDE_REG_TESTS
842
843#define FAIL_UNLESS(desc,pred) printf("\t%-4s: %s\n", (pred)?"ok":(numfailed++,"FAIL"), desc)
844
845int owl_variable_regtest(void) {
846  owl_vardict vd;
847  int numfailed=0;
848  char buf[1024];
849
850  in_regtest = 1;
851
852  printf("BEGIN testing owl_variable\n");
853  FAIL_UNLESS("setup", 0==owl_variable_dict_setup(&vd));
854
855  FAIL_UNLESS("get bool", 0==owl_variable_get_bool(&vd,"personalbell"));
856  FAIL_UNLESS("get bool (no such)", -1==owl_variable_get_bool(&vd,"mumble"));
857  FAIL_UNLESS("get bool as string 1", 0==owl_variable_get_tostring(&vd,"personalbell", buf, 1024));
858  FAIL_UNLESS("get bool as string 2", 0==strcmp(buf,"off"));
859  FAIL_UNLESS("set bool 1", 0==owl_variable_set_bool_on(&vd,"personalbell"));
860  FAIL_UNLESS("get bool 2", 1==owl_variable_get_bool(&vd,"personalbell"));
861  FAIL_UNLESS("set bool 3", 0==owl_variable_set_fromstring(&vd,"personalbell","off",0,0));
862  FAIL_UNLESS("get bool 4", 0==owl_variable_get_bool(&vd,"personalbell"));
863  FAIL_UNLESS("set bool 5", -1==owl_variable_set_fromstring(&vd,"personalbell","xxx",0,0));
864  FAIL_UNLESS("get bool 6", 0==owl_variable_get_bool(&vd,"personalbell"));
865
866
867  FAIL_UNLESS("get string", 0==strcmp("~/zlog/people", owl_variable_get_string(&vd,"logpath")));
868  FAIL_UNLESS("set string 7", 0==owl_variable_set_string(&vd,"logpath","whee"));
869  FAIL_UNLESS("get string", 0==strcmp("whee", owl_variable_get_string(&vd,"logpath")));
870
871  FAIL_UNLESS("get int", 8==owl_variable_get_int(&vd,"typewinsize"));
872  FAIL_UNLESS("get int (no such)", -1==owl_variable_get_int(&vd,"mmble"));
873  FAIL_UNLESS("get int as string 1", 0==owl_variable_get_tostring(&vd,"typewinsize", buf, 1024));
874  FAIL_UNLESS("get int as string 2", 0==strcmp(buf,"8"));
875  FAIL_UNLESS("set int 1", 0==owl_variable_set_int(&vd,"typewinsize",12));
876  FAIL_UNLESS("get int 2", 12==owl_variable_get_int(&vd,"typewinsize"));
877  FAIL_UNLESS("set int 1b", -1==owl_variable_set_int(&vd,"typewinsize",-3));
878  FAIL_UNLESS("get int 2b", 12==owl_variable_get_int(&vd,"typewinsize"));
879  FAIL_UNLESS("set int 3", 0==owl_variable_set_fromstring(&vd,"typewinsize","9",0,0));
880  FAIL_UNLESS("get int 4", 9==owl_variable_get_int(&vd,"typewinsize"));
881  FAIL_UNLESS("set int 5", -1==owl_variable_set_fromstring(&vd,"typewinsize","xxx",0,0));
882  FAIL_UNLESS("set int 6", -1==owl_variable_set_fromstring(&vd,"typewinsize","",0,0));
883  FAIL_UNLESS("get int 7", 9==owl_variable_get_int(&vd,"typewinsize"));
884
885  FAIL_UNLESS("get enum", OWL_WEBBROWSER_NETSCAPE==owl_variable_get_int(&vd,"webbrowser"));
886  FAIL_UNLESS("get enum as string 1", 0==owl_variable_get_tostring(&vd,"webbrowser", buf, 1024));
887  FAIL_UNLESS("get enum as string 2", 0==strcmp(buf,"netscape"));
888  FAIL_UNLESS("set enum 1", 0==owl_variable_set_int(&vd,"webbrowser",OWL_WEBBROWSER_GALEON));
889  FAIL_UNLESS("get enum 2", OWL_WEBBROWSER_GALEON==owl_variable_get_int(&vd,"webbrowser"));
890  FAIL_UNLESS("set enum 1b", -1==owl_variable_set_int(&vd,"webbrowser",-3));
891  FAIL_UNLESS("set enum 1b", -1==owl_variable_set_int(&vd,"webbrowser",209));
892  FAIL_UNLESS("get enum 2b", OWL_WEBBROWSER_GALEON==owl_variable_get_int(&vd,"webbrowser"));
893  FAIL_UNLESS("set enum 3", 0==owl_variable_set_fromstring(&vd,"webbrowser","none",0,0));
894  FAIL_UNLESS("get enum 4", OWL_WEBBROWSER_NONE==owl_variable_get_int(&vd,"webbrowser"));
895  FAIL_UNLESS("set enum 5", 0==owl_variable_set_fromstring(&vd,"webbrowser","netscape",0,0));
896  FAIL_UNLESS("get enum 6", OWL_WEBBROWSER_NETSCAPE==owl_variable_get_int(&vd,"webbrowser"));
897  FAIL_UNLESS("set enum 7", -1==owl_variable_set_fromstring(&vd,"webbrowser","xxx",0,0));
898  FAIL_UNLESS("set enum 8", -1==owl_variable_set_fromstring(&vd,"webbrowser","",0,0));
899  FAIL_UNLESS("set enum 9", -1==owl_variable_set_fromstring(&vd,"webbrowser","netscapey",0,0));
900  FAIL_UNLESS("get enum 10", OWL_WEBBROWSER_NETSCAPE==owl_variable_get_int(&vd,"webbrowser"));
901
902
903
904  owl_variable_dict_free(&vd);
905
906  if (numfailed) printf("*** WARNING: failures encountered with owl_variable\n");
907  printf("END testing owl_variable (%d failures)\n", numfailed);
908  return(numfailed);
909}
910
911
912#endif /* OWL_INCLUDE_REG_TESTS */
Note: See TracBrowser for help on using the repository browser.