source: variable.c @ ecd5dc5

barnowl_perlaimdebianowlrelease-1.4release-1.5release-1.6release-1.7release-1.8release-1.9
Last change on this file since ecd5dc5 was ecd5dc5, checked in by James M. Kretchmar <kretch@mit.edu>, 18 years ago
M-p is bound to 'view personal' by default loadsubs and loadloginsubs only print messages if in interactive mode added the 'alert_filter' variable, defaults to 'none'. added the 'alert_action' variable, which is an owl command that will be executed when new messages arive that match the alert_filter added the 'term' command which takes the 'raise' and 'deiconify' options. It assumes xterm for now.
  • Property mode set to 100644
File size: 30.8 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_INT(    "edit:maxfillcols" /* %OwlVarStub:edit_maxfillcols */, 70,
202                 "maximum number of columns for M-q to fill text to",
203                 "This specifies the maximum number of columns for M-q\n"
204                 "to fill text to.  If set to 0, ther will be no maximum\n"
205                 "limit.  In all cases, the current width of the screen\n"
206                 "will also be taken into account.  It will be used instead\n"
207                 "if it is narrower than the maximum, or if this\n"
208                 "is set to 0.\n" ),
209
210  OWLVAR_INT(    "edit:maxwrapcols" /* %OwlVarStub:edit_maxwrapcols */, 0,
211                 "maximum number of columns for line-wrapping",
212                 "This specifies the maximum number of columns for\n"
213                 "auto-line-wrapping.  If set to 0, ther will be no maximum\n"
214                 "limit.  In all cases, the current width of the screen\n"
215                 "will also be taken into account.  It will be used instead\n"
216                 "if it is narrower than the maximum, or if this\n"
217                 "is set to 0.\n\n"
218                 "It is recommended that outgoing messages be no wider\n"
219                 "than 60 columns, as a courtesy to recipients.\n"),
220
221  OWLVAR_INT_FULL( "typewinsize" /* %OwlVarStub:typwin_lines */, 
222                   OWL_TYPWIN_SIZE,
223                  "number of lines in the typing window", 
224                   "This specifies the height of the window at the\n"
225                   "bottom of the screen where commands are entered\n"
226                   "and where messages are composed.\n",
227                   "int > 0",
228                   owl_variable_int_validate_gt0,
229                   owl_variable_typewinsize_set,
230                   NULL /* use default for get */
231                   ),
232
233  OWLVAR_ENUM( "scrollmode" /* %OwlVarStub */, OWL_SCROLLMODE_NORMAL,
234               "how to scroll up and down",
235               "This controls how the screen is scrolled as the\n"
236               "cursor moves between messages being displayed.\n"
237               "The following modes are supported:\n\n"
238               "   normal      - This is the owl default.  Scrolling happens\n"
239               "                 when it needs to, and an attempt is made to\n"
240               "                 keep the current message roughly near\n"
241               "                 the middle of the screen.\n"
242               "   top         - The current message will always be the\n"
243               "                 the top message displayed.\n"
244               "   neartop     - The current message will be one down\n"
245               "                 from the top message displayed,\n"
246               "                 where possible.\n"
247               "   center      - An attempt is made to keep the current\n"
248               "                 message near the center of the screen.\n"
249               "   paged       - The top message displayed only changes\n"
250               "                 when user moves the cursor to the top\n"
251               "                 or bottom of the screen.  When it moves,\n"
252               "                 the screen will be paged up or down and\n"
253               "                 the cursor will be near the top or\n"
254               "                 the bottom.\n"
255               "   pagedcenter - The top message displayed only changes\n"
256               "                 when user moves the cursor to the top\n"
257               "                 or bottom of the screen.  When it moves,\n"
258               "                 the screen will be paged up or down and\n"
259               "                 the cursor will be near the center.\n",
260               "normal,top,neartop,center,paged,pagedcenter" ),
261
262  OWLVAR_ENUM( "webbrowser" /* %OwlVarStub */, OWL_WEBBROWSER_NETSCAPE,
263               "web browser to use to launch URLs",
264               "When the 'w' key is pressed, this browser is used\n"
265               "to display the requested URL.\n",
266               "none,netscape,galeon,opera" ),
267
268
269  OWLVAR_BOOL( "_followlast" /* %OwlVarStub */, 0,
270               "enable automatic following of the last zephyr",
271               "If the cursor is at the last message, it will\n"
272               "continue to follow the last message if this is set.\n"
273               "Note that this is currently risky as you might accidentally\n"
274               "delete a message right as it came in.\n" ),
275
276  /* This MUST be last... */
277  { NULL, 0, NULL, 0, NULL, NULL, NULL, NULL,
278    NULL, NULL, NULL, NULL, NULL, NULL }
279
280};
281
282/**************************************************************************/
283/*********************** SPECIFIC TO VARIABLES ****************************/
284/**************************************************************************/
285
286
287/* commonly useful */
288
289int owl_variable_int_validate_gt0(owl_variable *v, void *newval) {
290  if (newval == NULL) return(0);
291  else if (*(int*)newval < 1) return(0);
292  else return (1);
293}
294
295int owl_variable_int_validate_positive(owl_variable *v, void *newval) {
296  if (newval == NULL) return(0);
297  else if (*(int*)newval < 0) return(0);
298  else return (1);
299}
300
301/* typewinsize */
302
303int owl_variable_typewinsize_set(owl_variable *v, void *newval) {
304  int rv;
305  rv = owl_variable_int_set_default(v, newval);
306  if (0 == rv) owl_function_resize();
307  return(rv);
308}
309
310/* debug (cache value in g->debug) */
311
312int owl_variable_debug_set(owl_variable *v, void *newval) {
313  if (newval && (*(int*)newval == 1 || *(int*)newval == 0)) {
314    g.debug = *(int*)newval;
315  }
316  return owl_variable_bool_set_default(v, newval);
317}
318
319/* note that changing the value of this will clobber
320 * any user setting of this */
321int owl_variable_disable_ctrl_d_set(owl_variable *v, void *newval) {
322
323  if (in_regtest) return owl_variable_int_set_default(v, newval);
324
325  if (newval && !owl_context_is_startup(owl_global_get_context(&g))) {
326    if (*(int*)newval == 2) {
327      owl_function_command_norv("bindkey editmulti C-d command edit:delete-next-char");
328    } else if (*(int*)newval == 1) {
329      owl_function_command_norv("bindkey editmulti C-d command editmulti:done-or-delete");
330    } else {
331      owl_function_command_norv("bindkey editmulti C-d command editmulti:done");
332    }
333  } 
334  return owl_variable_int_set_default(v, newval); 
335}
336
337int owl_variable_tty_set(owl_variable *v, void *newval) {
338  ZInitLocationInfo(owl_global_get_hostname(&g), newval);
339  return(owl_variable_string_set_default(v, newval));
340}
341
342
343/**************************************************************************/
344/****************************** GENERAL ***********************************/
345/**************************************************************************/
346
347int owl_variable_dict_setup(owl_vardict *vd) {
348  owl_variable *cur;
349  if (owl_dict_create(vd)) return(-1);
350  for (cur = variables_to_init; cur->name != NULL; cur++) {
351    switch (cur->type) {
352    case OWL_VARIABLE_OTHER:
353      cur->set_fn(cur, cur->pval_default);
354      break;
355    case OWL_VARIABLE_STRING:
356      if (!cur->validate_fn) 
357        cur->validate_fn = owl_variable_string_validate_default;
358      if (!cur->set_fn) 
359        cur->set_fn = owl_variable_string_set_default;
360      if (!cur->set_fromstring_fn) 
361        cur->set_fromstring_fn = owl_variable_string_set_fromstring_default;
362      if (!cur->get_fn) 
363        cur->get_fn = owl_variable_get_default;
364      if (!cur->get_tostring_fn) 
365        cur->get_tostring_fn = owl_variable_string_get_tostring_default;     
366      if (!cur->free_fn) 
367        cur->free_fn = owl_variable_free_default;
368      cur->set_fn(cur, cur->pval_default);
369      break;
370    case OWL_VARIABLE_BOOL:
371      if (!cur->validate_fn) 
372        cur->validate_fn = owl_variable_bool_validate_default;
373      if (!cur->set_fn) 
374        cur->set_fn = owl_variable_bool_set_default;
375      if (!cur->set_fromstring_fn) 
376        cur->set_fromstring_fn = owl_variable_bool_set_fromstring_default;
377      if (!cur->get_fn) 
378        cur->get_fn = owl_variable_get_default;
379      if (!cur->get_tostring_fn) 
380        cur->get_tostring_fn = owl_variable_bool_get_tostring_default;     
381      if (!cur->free_fn) 
382        cur->free_fn = owl_variable_free_default;
383      cur->val = owl_malloc(sizeof(int));
384      cur->set_fn(cur, &cur->ival_default);
385      break;
386    case OWL_VARIABLE_INT:
387      if (!cur->validate_fn) 
388        cur->validate_fn = owl_variable_int_validate_default;
389      if (!cur->set_fn) 
390        cur->set_fn = owl_variable_int_set_default;
391      if (!cur->set_fromstring_fn) 
392        cur->set_fromstring_fn = owl_variable_int_set_fromstring_default;
393      if (!cur->get_fn) 
394        cur->get_fn = owl_variable_get_default;
395      if (!cur->get_tostring_fn) 
396        cur->get_tostring_fn = owl_variable_int_get_tostring_default;     
397      if (!cur->free_fn) 
398        cur->free_fn = owl_variable_free_default;
399      cur->val = owl_malloc(sizeof(int));
400      cur->set_fn(cur, &cur->ival_default);
401      break;
402    default:
403      fprintf(stderr, "owl_variable_setup: invalid variable type\n");
404      return(-2);
405    }
406    owl_dict_insert_element(vd, cur->name, (void*)cur, NULL);
407  }
408  return 0;
409}
410
411void owl_variable_dict_free(owl_vardict *d) {
412  owl_dict_free_all(d, (void(*)(void*))owl_variable_free);
413}
414
415/* free the list with owl_variable_dict_namelist_free */
416void owl_variable_dict_get_names(owl_vardict *d, owl_list *l) {
417  owl_dict_get_keys(d, l);
418}
419
420void owl_variable_dict_namelist_free(owl_list *l) {
421  owl_list_free_all(l, owl_free);
422}
423
424void owl_variable_free(owl_variable *v) {
425  if (v->free_fn) v->free_fn(v);
426}
427
428
429char *owl_variable_get_description(owl_variable *v) {
430  return v->description;
431}
432
433char *owl_variable_get_summary(owl_variable *v) {
434  return v->summary;
435}
436
437char *owl_variable_get_validsettings(owl_variable *v) {
438  if (v->validsettings) {
439    return v->validsettings;
440  } else {
441    return "";
442  }
443}
444
445/* functions for getting and setting variable values */
446
447/* returns 0 on success, prints a status msg if msg is true */
448int owl_variable_set_fromstring(owl_vardict *d, char *name, char *value, int msg, int requirebool) {
449  owl_variable *v;
450  char buff2[1024];
451  if (!name) return(-1);
452  v = owl_dict_find_element(d, name);
453  if (v == NULL) {
454    if (msg) owl_function_makemsg("Unknown variable %s", name);
455    return -1;
456  }
457  if (!v->set_fromstring_fn) {
458    if (msg) owl_function_makemsg("Variable %s is read-only", name);
459    return -1;   
460  }
461  if (requirebool && v->type!=OWL_VARIABLE_BOOL) {
462    if (msg) owl_function_makemsg("Variable %s is not a boolean", name);
463    return -1;   
464  }
465  if (0 != v->set_fromstring_fn(v, value)) {
466    if (msg) owl_function_makemsg("Unable to set %s (must be %s)", name, 
467                                  owl_variable_get_validsettings(v));
468    return -1;
469  }
470  if (msg && v->get_tostring_fn) {
471    v->get_tostring_fn(v, buff2, 1024, v->val);
472    owl_function_makemsg("%s = '%s'", name, buff2);
473  }   
474  return 0;
475}
476 
477int owl_variable_set_string(owl_vardict *d, char *name, char *newval) {
478  owl_variable *v;
479  if (!name) return(-1);
480  v = owl_dict_find_element(d, name);
481  if (v == NULL || !v->set_fn) return(-1);
482  if (v->type!=OWL_VARIABLE_STRING) return(-1);
483  return v->set_fn(v, (void*)newval);
484}
485 
486int owl_variable_set_int(owl_vardict *d, char *name, int newval) {
487  owl_variable *v;
488  if (!name) return(-1);
489  v = owl_dict_find_element(d, name);
490  if (v == NULL || !v->set_fn) return(-1);
491  if (v->type!=OWL_VARIABLE_INT && v->type!=OWL_VARIABLE_BOOL) return(-1);
492  return v->set_fn(v, &newval);
493}
494 
495int owl_variable_set_bool_on(owl_vardict *d, char *name) {
496  return owl_variable_set_int(d,name,1);
497}
498
499int owl_variable_set_bool_off(owl_vardict *d, char *name) {
500  return owl_variable_set_int(d,name,0);
501}
502
503int owl_variable_get_tostring(owl_vardict *d, char *name, char *buf, int bufsize) {
504  owl_variable *v;
505  if (!name) return(-1);
506  v = owl_dict_find_element(d, name);
507  if (v == NULL || !v->get_tostring_fn) return(-1);
508  return v->get_tostring_fn(v, buf, bufsize, v->val);
509}
510
511int owl_variable_get_default_tostring(owl_vardict *d, char *name, char *buf, int bufsize) {
512  owl_variable *v;
513  if (!name) return(-1);
514  v = owl_dict_find_element(d, name);
515  if (v == NULL || !v->get_tostring_fn) return(-1);
516  if (v->type == OWL_VARIABLE_INT || v->type == OWL_VARIABLE_BOOL) {
517    return v->get_tostring_fn(v, buf, bufsize, &(v->ival_default));
518  } else {
519    return v->get_tostring_fn(v, buf, bufsize, v->pval_default);
520  }
521}
522
523/* returns a reference */
524void *owl_variable_get(owl_vardict *d, char *name, int require_type) {
525  owl_variable *v;
526  if (!name) return(NULL);
527  v = owl_dict_find_element(d, name);
528  if (v == NULL || !v->get_fn || v->type != require_type) return(NULL);
529  return v->get_fn(v);
530}
531
532/* returns a reference */
533char *owl_variable_get_string(owl_vardict *d, char *name) {
534  return (char*)owl_variable_get(d,name, OWL_VARIABLE_STRING);
535}
536
537/* returns a reference */
538void *owl_variable_get_other(owl_vardict *d, char *name) {
539  return (char*)owl_variable_get(d,name, OWL_VARIABLE_OTHER);
540}
541
542int owl_variable_get_int(owl_vardict *d, char *name) {
543  int *pi;
544  pi = (int*)owl_variable_get(d,name,OWL_VARIABLE_INT);
545  if (!pi) return(-1);
546  return(*pi);
547}
548
549int owl_variable_get_bool(owl_vardict *d, char *name) {
550  int *pi;
551  pi = (int*)owl_variable_get(d,name,OWL_VARIABLE_BOOL);
552  if (!pi) return(-1);
553  return(*pi);
554}
555
556void owl_variable_describe(owl_vardict *d, char *name, owl_fmtext *fm) {
557  char defaultbuf[50];
558  char buf[1024];
559  int buflen = 1023;
560  owl_variable *v;
561
562  if (!name
563      || (v = owl_dict_find_element(d, name)) == NULL 
564      || !v->get_fn) {
565    snprintf(buf, buflen, "     No such variable '%s'\n", name);     
566    owl_fmtext_append_normal(fm, buf);
567    return;
568  }
569  if (v->type == OWL_VARIABLE_INT || v->type == OWL_VARIABLE_BOOL) {
570    v->get_tostring_fn(v, defaultbuf, 50, &(v->ival_default));
571  } else {
572    v->get_tostring_fn(v, defaultbuf, 50, v->pval_default);
573  }
574  snprintf(buf, buflen, OWL_TABSTR "%-20s - %s (default: '%s')\n", 
575                  v->name, 
576                  owl_variable_get_summary(v), defaultbuf);
577  owl_fmtext_append_normal(fm, buf);
578}
579
580void owl_variable_get_help(owl_vardict *d, char *name, owl_fmtext *fm) {
581  char buff[1024];
582  int bufflen = 1023;
583  owl_variable *v;
584
585  if (!name
586      || (v = owl_dict_find_element(d, name)) == NULL 
587      || !v->get_fn) {
588    owl_fmtext_append_normal(fm, "No such variable...\n");
589    return;
590  }
591
592  owl_fmtext_append_bold(fm, "OWL VARIABLE\n\n");
593  owl_fmtext_append_normal(fm, OWL_TABSTR);
594  owl_fmtext_append_normal(fm, name);
595  owl_fmtext_append_normal(fm, " - ");
596  owl_fmtext_append_normal(fm, v->summary);
597  owl_fmtext_append_normal(fm, "\n\n");
598
599  owl_fmtext_append_normal(fm, "Current:        ");
600  owl_variable_get_tostring(d, name, buff, bufflen);
601  owl_fmtext_append_normal(fm, buff);
602  owl_fmtext_append_normal(fm, "\n\n");
603
604
605  if (v->type == OWL_VARIABLE_INT || v->type == OWL_VARIABLE_BOOL) {
606    v->get_tostring_fn(v, buff, bufflen, &(v->ival_default));
607  } else {
608    v->get_tostring_fn(v, buff, bufflen, v->pval_default);
609  }
610  owl_fmtext_append_normal(fm, "Default:        ");
611  owl_fmtext_append_normal(fm, buff);
612  owl_fmtext_append_normal(fm, "\n\n");
613
614  owl_fmtext_append_normal(fm, "Valid Settings: ");
615  owl_fmtext_append_normal(fm, owl_variable_get_validsettings(v));
616  owl_fmtext_append_normal(fm, "\n\n");
617
618  if (v->description && *v->description) {
619    owl_fmtext_append_normal(fm, "Description:\n");
620    owl_fmtext_append_normal(fm, owl_variable_get_description(v));
621    owl_fmtext_append_normal(fm, "\n\n");
622  }
623}
624
625
626
627
628/**************************************************************************/
629/*********************** GENERAL TYPE-SPECIFIC ****************************/
630/**************************************************************************/
631
632/* default common functions */
633
634void *owl_variable_get_default(owl_variable *v) {
635  return v->val;
636}
637
638void owl_variable_free_default(owl_variable *v) {
639  if (v->val) owl_free(v->val);
640}
641
642/* default functions for booleans */
643
644int owl_variable_bool_validate_default(owl_variable *v, void *newval) {
645  if (newval == NULL) return(0);
646  else if (*(int*)newval==1 || *(int*)newval==0) return(1);
647  else return (0);
648}
649
650int owl_variable_bool_set_default(owl_variable *v, void *newval) {
651  if (v->validate_fn) {
652    if (!v->validate_fn(v, newval)) return(-1);
653  }
654  *(int*)v->val = *(int*)newval;
655  return(0);
656}
657
658int owl_variable_bool_set_fromstring_default(owl_variable *v, char *newval) {
659  int i;
660  if (!strcmp(newval, "on")) i=1;
661  else if (!strcmp(newval, "off")) i=0;
662  else return(-1);
663  return (v->set_fn(v, &i));
664}
665
666int owl_variable_bool_get_tostring_default(owl_variable *v, char* buf, int bufsize, void *val) {
667  if (val == NULL) {
668    snprintf(buf, bufsize, "<null>");
669    return -1;
670  } else if (*(int*)val == 0) {
671    snprintf(buf, bufsize, "off");
672    return 0;
673  } else if (*(int*)val == 1) {
674    snprintf(buf, bufsize, "on");
675    return 0;
676  } else {
677    snprintf(buf, bufsize, "<invalid>");
678    return -1;
679  }
680}
681
682/* default functions for integers */
683
684int owl_variable_int_validate_default(owl_variable *v, void *newval) {
685  if (newval == NULL) return(0);
686  else return (1);
687}
688
689int owl_variable_int_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_int_set_fromstring_default(owl_variable *v, char *newval) {
698  int i;
699  char *ep = "x";
700  i = strtol(newval, &ep, 10);
701  if (*ep || ep==newval) return(-1);
702  return (v->set_fn(v, &i));
703}
704
705int owl_variable_int_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 {
710    snprintf(buf, bufsize, "%d", *(int*)val);
711    return 0;
712  } 
713}
714
715/* default functions for enums (a variant of integers) */
716
717int owl_variable_enum_validate(owl_variable *v, void *newval) { 
718  char **enums;
719  int nenums, val;
720  if (newval == NULL) return(0);
721  enums = atokenize(v->validsettings, ",", &nenums);
722  if (enums == NULL) return(0);
723  atokenize_free(enums, nenums);
724  val = *(int*)newval;
725  if (val < 0 || val >= nenums) {
726    return(0);
727  }
728  return(1);
729}
730
731int owl_variable_enum_set_fromstring(owl_variable *v, char *newval) {
732  char **enums;
733  int nenums, i, val=-1;
734  if (newval == NULL) return(-1);
735  enums = atokenize(v->validsettings, ",", &nenums);
736  if (enums == NULL) return(-1);
737  for (i=0; i<nenums; i++) {
738    if (0==strcmp(newval, enums[i])) {
739      val = i;
740    }
741  }
742  atokenize_free(enums, nenums);
743  if (val == -1) return(-1);
744  return (v->set_fn(v, &val));
745}
746
747int owl_variable_enum_get_tostring(owl_variable *v, char* buf, int bufsize, void *val) {
748  char **enums;
749  int nenums, i;
750
751  if (val == NULL) {
752    snprintf(buf, bufsize, "<null>");
753    return -1;
754  }
755  enums = atokenize(v->validsettings, ",", &nenums);
756  i = *(int*)val;
757  if (i<0 || i>=nenums) {
758    snprintf(buf, bufsize, "<invalid:%d>",i);
759    atokenize_free(enums, nenums);
760    return(-1);
761  }
762  snprintf(buf, bufsize, "%s", enums[i]);
763  return 0;
764}
765
766/* default functions for stringeans */
767
768int owl_variable_string_validate_default(struct _owl_variable *v, void *newval) {
769  if (newval == NULL) return(0);
770  else return (1);
771}
772
773int owl_variable_string_set_default(owl_variable *v, void *newval) {
774  if (v->validate_fn) {
775    if (!v->validate_fn(v, newval)) return(-1);
776  }
777  if (v->val) owl_free(v->val);
778  v->val = owl_strdup(newval);
779  return(0);
780}
781
782int owl_variable_string_set_fromstring_default(owl_variable *v, char *newval) {
783  return (v->set_fn(v, newval));
784}
785
786int owl_variable_string_get_tostring_default(owl_variable *v, char* buf, int bufsize, void *val) {
787  if (val == NULL) {
788    snprintf(buf, bufsize, "<null>");
789    return -1;
790  } else {
791    snprintf(buf, bufsize, "%s", (char*)val);
792    return 0;
793  }
794}
795
796
797
798/**************************************************************************/
799/************************* REGRESSION TESTS *******************************/
800/**************************************************************************/
801
802#ifdef OWL_INCLUDE_REG_TESTS
803
804#define FAIL_UNLESS(desc,pred) printf("\t%-4s: %s\n", (pred)?"ok":(numfailed++,"FAIL"), desc)
805
806int owl_variable_regtest(void) {
807  owl_vardict vd;
808  int numfailed=0;
809  char buf[1024];
810
811  in_regtest = 1;
812
813  printf("BEGIN testing owl_variable\n");
814  FAIL_UNLESS("setup", 0==owl_variable_dict_setup(&vd));
815
816  FAIL_UNLESS("get bool", 0==owl_variable_get_bool(&vd,"personalbell"));
817  FAIL_UNLESS("get bool (no such)", -1==owl_variable_get_bool(&vd,"mumble"));
818  FAIL_UNLESS("get bool as string 1", 0==owl_variable_get_tostring(&vd,"personalbell", buf, 1024));
819  FAIL_UNLESS("get bool as string 2", 0==strcmp(buf,"off"));
820  FAIL_UNLESS("set bool 1", 0==owl_variable_set_bool_on(&vd,"personalbell"));
821  FAIL_UNLESS("get bool 2", 1==owl_variable_get_bool(&vd,"personalbell"));
822  FAIL_UNLESS("set bool 3", 0==owl_variable_set_fromstring(&vd,"personalbell","off",0,0));
823  FAIL_UNLESS("get bool 4", 0==owl_variable_get_bool(&vd,"personalbell"));
824  FAIL_UNLESS("set bool 5", -1==owl_variable_set_fromstring(&vd,"personalbell","xxx",0,0));
825  FAIL_UNLESS("get bool 6", 0==owl_variable_get_bool(&vd,"personalbell"));
826
827
828  FAIL_UNLESS("get string", 0==strcmp("~/zlog/people", owl_variable_get_string(&vd,"logpath")));
829  FAIL_UNLESS("set string 7", 0==owl_variable_set_string(&vd,"logpath","whee"));
830  FAIL_UNLESS("get string", 0==strcmp("whee", owl_variable_get_string(&vd,"logpath")));
831
832  FAIL_UNLESS("get int", 8==owl_variable_get_int(&vd,"typewinsize"));
833  FAIL_UNLESS("get int (no such)", -1==owl_variable_get_int(&vd,"mmble"));
834  FAIL_UNLESS("get int as string 1", 0==owl_variable_get_tostring(&vd,"typewinsize", buf, 1024));
835  FAIL_UNLESS("get int as string 2", 0==strcmp(buf,"8"));
836  FAIL_UNLESS("set int 1", 0==owl_variable_set_int(&vd,"typewinsize",12));
837  FAIL_UNLESS("get int 2", 12==owl_variable_get_int(&vd,"typewinsize"));
838  FAIL_UNLESS("set int 1b", -1==owl_variable_set_int(&vd,"typewinsize",-3));
839  FAIL_UNLESS("get int 2b", 12==owl_variable_get_int(&vd,"typewinsize"));
840  FAIL_UNLESS("set int 3", 0==owl_variable_set_fromstring(&vd,"typewinsize","9",0,0));
841  FAIL_UNLESS("get int 4", 9==owl_variable_get_int(&vd,"typewinsize"));
842  FAIL_UNLESS("set int 5", -1==owl_variable_set_fromstring(&vd,"typewinsize","xxx",0,0));
843  FAIL_UNLESS("set int 6", -1==owl_variable_set_fromstring(&vd,"typewinsize","",0,0));
844  FAIL_UNLESS("get int 7", 9==owl_variable_get_int(&vd,"typewinsize"));
845
846  FAIL_UNLESS("get enum", OWL_WEBBROWSER_NETSCAPE==owl_variable_get_int(&vd,"webbrowser"));
847  FAIL_UNLESS("get enum as string 1", 0==owl_variable_get_tostring(&vd,"webbrowser", buf, 1024));
848  FAIL_UNLESS("get enum as string 2", 0==strcmp(buf,"netscape"));
849  FAIL_UNLESS("set enum 1", 0==owl_variable_set_int(&vd,"webbrowser",OWL_WEBBROWSER_GALEON));
850  FAIL_UNLESS("get enum 2", OWL_WEBBROWSER_GALEON==owl_variable_get_int(&vd,"webbrowser"));
851  FAIL_UNLESS("set enum 1b", -1==owl_variable_set_int(&vd,"webbrowser",-3));
852  FAIL_UNLESS("set enum 1b", -1==owl_variable_set_int(&vd,"webbrowser",209));
853  FAIL_UNLESS("get enum 2b", OWL_WEBBROWSER_GALEON==owl_variable_get_int(&vd,"webbrowser"));
854  FAIL_UNLESS("set enum 3", 0==owl_variable_set_fromstring(&vd,"webbrowser","none",0,0));
855  FAIL_UNLESS("get enum 4", OWL_WEBBROWSER_NONE==owl_variable_get_int(&vd,"webbrowser"));
856  FAIL_UNLESS("set enum 5", 0==owl_variable_set_fromstring(&vd,"webbrowser","netscape",0,0));
857  FAIL_UNLESS("get enum 6", OWL_WEBBROWSER_NETSCAPE==owl_variable_get_int(&vd,"webbrowser"));
858  FAIL_UNLESS("set enum 7", -1==owl_variable_set_fromstring(&vd,"webbrowser","xxx",0,0));
859  FAIL_UNLESS("set enum 8", -1==owl_variable_set_fromstring(&vd,"webbrowser","",0,0));
860  FAIL_UNLESS("set enum 9", -1==owl_variable_set_fromstring(&vd,"webbrowser","netscapey",0,0));
861  FAIL_UNLESS("get enum 10", OWL_WEBBROWSER_NETSCAPE==owl_variable_get_int(&vd,"webbrowser"));
862
863
864
865  owl_variable_dict_free(&vd);
866
867  if (numfailed) printf("*** WARNING: failures encountered with owl_variable\n");
868  printf("END testing owl_variable (%d failures)\n", numfailed);
869  return(numfailed);
870}
871
872
873#endif /* OWL_INCLUDE_REG_TESTS */
Note: See TracBrowser for help on using the repository browser.