source: variable.c @ aa2f33b3

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