source: variable.c @ aecf3e6

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