source: variable.c @ 4fd3c04

Last change on this file since 4fd3c04 was 4fd3c04, checked in by Anders Kaseorg <andersk@mit.edu>, 7 years ago
Remove AIM support This code has received almost no security attention, and anyway, AIM is shutting down on December 15, 2017. https://aimemories.tumblr.com/post/166091776077/aimemories Signed-off-by: Anders Kaseorg <andersk@mit.edu>
  • Property mode set to 100644
File size: 42.6 KB
Line 
1#include "owl.h"
2#include <stdio.h>
3#include "gmarshal_funcs.h"
4
5/* TODO(davidben): When we can require 2.30 and up, remove this. */
6#ifndef G_VALUE_INIT
7#define G_VALUE_INIT { 0, { { 0 } } }
8#endif
9
10typedef const char *(*get_string_t)(const owl_variable *);
11typedef int (*get_int_t)(const owl_variable *);
12typedef bool (*get_bool_t)(const owl_variable *);
13
14typedef int (*set_string_t)(owl_variable *, const char *);
15typedef int (*set_int_t)(owl_variable *, int);
16typedef int (*set_bool_t)(owl_variable *, bool);
17
18typedef int (*validate_string_t)(const owl_variable *, const char *);
19typedef int (*validate_int_t)(const owl_variable *, int);
20typedef int (*validate_bool_t)(const owl_variable *, bool);
21
22static void owl_variable_dict_newvar_bool_full(owl_vardict *vd,
23                                               const char *name,
24                                               bool default_val,
25                                               const char *summary,
26                                               const char *description,
27                                               validate_bool_t validate_fn,
28                                               set_bool_t set_fn,
29                                               get_bool_t get_fn);
30
31static void owl_variable_dict_newvar_string_full(owl_vardict *vd,
32                                                 const char *name,
33                                                 const char *default_val,
34                                                 const char *summary,
35                                                 const char *description,
36                                                 const char *validsettings,
37                                                 validate_string_t validate_fn,
38                                                 set_string_t set_fn,
39                                                 get_string_t get_fn);
40
41static void owl_variable_dict_newvar_int_full(owl_vardict *vd,
42                                              const char *name,
43                                              int default_val,
44                                              const char *summary,
45                                              const char *description,
46                                              const char *validsettings,
47                                              validate_int_t validate_fn,
48                                              set_int_t set_fn,
49                                              get_int_t get_fn);
50
51static void owl_variable_dict_newvar_enum_full(owl_vardict *vd,
52                                               const char *name,
53                                               int default_val,
54                                               const char *summary,
55                                               const char *description,
56                                               const char *validsettings,
57                                               validate_int_t validate_fn,
58                                               set_int_t set_fn,
59                                               get_int_t get_fn);
60
61#define OWLVAR_BOOL(name, default, summary, description) \
62        owl_variable_dict_newvar_bool(vd, name, default, summary, description)
63
64#define OWLVAR_BOOL_FULL(name, default, summary, description, validate, set, get) \
65        owl_variable_dict_newvar_bool_full(vd, name, default, summary, description, \
66                                           validate, set, get)
67
68#define OWLVAR_INT(name, default, summary, description) \
69        owl_variable_dict_newvar_int(vd, name, default, summary, description)
70
71#define OWLVAR_INT_FULL(name,default,summary,description,validset,validate,set,get) \
72        owl_variable_dict_newvar_int_full(vd, name, default, summary, description, \
73                                          validset, validate, set, get)
74
75#define OWLVAR_PATH(name, default, summary, description) \
76        owl_variable_dict_newvar_path(vd, name, default, summary, description)
77
78#define OWLVAR_STRING(name, default, summary, description) \
79        owl_variable_dict_newvar_string(vd, name, default, summary, description)
80
81#define OWLVAR_STRING_FULL(name, default, validset, summary, description, validate, set, get) \
82        owl_variable_dict_newvar_string_full(vd, name, default, summary, description, \
83                                             validset, validate, set, get)
84
85/* enums are really integers, but where validset is a comma-separated
86 * list of strings which can be specified.  The tokens, starting at 0,
87 * correspond to the values that may be specified. */
88#define OWLVAR_ENUM(name, default, summary, description, validset) \
89        owl_variable_dict_newvar_enum(vd, name, default, summary, description, validset)
90
91#define OWLVAR_ENUM_FULL(name,default,summary,description,validset,validate, set, get) \
92        owl_variable_dict_newvar_enum_full(vd, name, default, summary, description, \
93                                           validset, validate, set, get)
94
95void owl_variable_add_defaults(owl_vardict *vd)
96{
97  OWLVAR_STRING( "personalbell" /* %OwlVarStub */, "off",
98                 "ring the terminal bell when personal messages are received",
99                 "Can be set to 'on', 'off', or the name of a filter which\n"
100                 "messages need to match in order to ring the bell");
101
102  OWLVAR_BOOL( "bell" /* %OwlVarStub */, 1,
103               "enable / disable the terminal bell", "" );
104
105  OWLVAR_BOOL_FULL( "debug" /* %OwlVarStub */, OWL_DEBUG,
106                    "whether debugging is enabled",
107                    "If set to 'on', debugging messages are logged to the\n"
108                    "file specified by the debugfile variable.\n",
109                    NULL, owl_variable_debug_set, NULL);
110
111  OWLVAR_BOOL( "startuplogin" /* %OwlVarStub */, 1,
112               "send a login message when BarnOwl starts", "" );
113
114  OWLVAR_BOOL( "shutdownlogout" /* %OwlVarStub */, 1,
115               "send a logout message when BarnOwl exits", "" );
116
117  OWLVAR_BOOL( "rxping" /* %OwlVarStub */, 0,
118               "display received pings", "" );
119
120  OWLVAR_BOOL( "txping" /* %OwlVarStub */, 1,
121               "send pings", "" );
122
123  OWLVAR_BOOL( "sepbar_disable" /* %OwlVarStub */, 0,
124               "disable printing information in the separator bar", "" );
125
126  OWLVAR_BOOL( "smartstrip" /* %OwlVarStub */, 1,
127               "strip kerberos instance for reply", "");
128
129  OWLVAR_BOOL( "newlinestrip" /* %OwlVarStub */, 1,
130               "strip leading and trailing newlines", "");
131
132  OWLVAR_BOOL( "displayoutgoing" /* %OwlVarStub */, 1,
133               "display outgoing messages", "" );
134
135  OWLVAR_BOOL( "loginsubs" /* %OwlVarStub */, 1,
136               "load logins from .anyone on startup", "" );
137
138  OWLVAR_BOOL_FULL( "colorztext" /* %OwlVarStub */, 1,
139                    "allow @color() in zephyrs to change color",
140                    "", NULL, owl_variable_colorztext_set, NULL);
141
142  OWLVAR_BOOL( "fancylines" /* %OwlVarStub */, 1,
143               "Use 'nice' line drawing on the terminal.",
144               "If turned off, dashes, pipes and pluses will be used\n"
145               "to draw lines on the screen.  Useful when the terminal\n"
146               "is causing problems" );
147
148  OWLVAR_BOOL( "zcrypt" /* %OwlVarStub */, 1,
149               "Do automatic zcrypt processing",
150               "" );
151
152  OWLVAR_BOOL_FULL( "pseudologins" /* %OwlVarStub */, 0,
153                    "Enable zephyr pseudo logins",
154                    "When this is enabled, BarnOwl will periodically check the zephyr\n"
155                    "location of users in your .anyone file.  If a user is present\n"
156                    "but sent no login message, or a user is not present that sent no\n"
157                    "logout message, a pseudo login or logout message will be created\n",
158                    NULL, owl_variable_pseudologins_set, NULL);
159
160  OWLVAR_BOOL( "ignorelogins" /* %OwlVarStub */, 0,
161               "Enable printing of login notifications",
162               "When this is enabled, BarnOwl will print login and logout notifications\n"
163               "for zephyr or other protocols.  If disabled BarnOwl will not print\n"
164               "login or logout notifications.\n");
165
166  OWLVAR_ENUM_FULL( "disable-ctrl-d" /* %OwlVarStub:lockout_ctrld */, 1,
167                    "don't send zephyrs on C-d",
168                    "If set to 'on', C-d won't send a zephyr from the edit\n"
169                    "window.  If set to 'off', C-d will always send a zephyr\n"
170                    "being composed in the edit window.  If set to 'middle',\n"
171                    "C-d will only ever send a zephyr if the cursor is at\n"
172                    "the end of the message being composed.\n\n"
173                    "Note that this works by changing the C-d keybinding\n"
174                    "in the editmulti keymap.\n",
175                    "off,middle,on",
176                    NULL, owl_variable_disable_ctrl_d_set, NULL);
177
178  OWLVAR_PATH( "debug_file" /* %OwlVarStub */, OWL_DEBUG_FILE,
179               "path for logging debug messages when debugging is enabled",
180               "This file will be logged to if 'debug' is set to 'on'.\n"
181               "BarnOwl will append a dot and the current process's pid to the filename.");
182 
183  OWLVAR_PATH( "zsigproc" /* %OwlVarStub:zsigproc */, NULL,
184               "name of a program to run that will generate zsigs",
185               "This program should produce a zsig on stdout when run.\n"
186               "Note that it is important that this program not block.\n\n"
187               "See the documentation for 'zsig' for more information about\n"
188               "how the outgoing zsig is chosen."
189               );
190
191  OWLVAR_PATH( "newmsgproc" /* %OwlVarStub:newmsgproc */, NULL,
192               "name of a program to run when new messages are present",
193               "The named program will be run when BarnOwl receives new\n"
194               "messages.  It will not be run again until the first\n"
195               "instance exits");
196
197  OWLVAR_STRING( "zsender" /* %OwlVarStub */, "",
198             "zephyr sender name",
199         "Allows you to customize the outgoing username in\n"
200         "zephyrs.  If this is unset, it will use your Kerberos\n"
201         "principal. Note that customizing the sender name will\n"
202         "cause your zephyrs to be sent unauthenticated.");
203
204  OWLVAR_STRING( "zsigfunc" /* %OwlVarStub */, "BarnOwl::default_zephyr_signature()",
205                 "zsig perl function",
206                 "Called every time you start a zephyrgram without an\n"
207                 "explicit zsig.  The default setting implements the policy\n"
208                 "described in the documentation for the 'zsig' variable.\n"
209                 "See also BarnOwl::random_zephyr_signature().\n");
210
211  OWLVAR_STRING( "zsig" /* %OwlVarStub */, "",
212                 "zephyr signature",
213                 "The zsig to get on outgoing messages. If this variable is\n"
214                 "unset, 'zsigproc' will be run to generate a zsig. If that is\n"
215                 "also unset, the 'zwrite-signature' zephyr variable will be\n"
216                 "used instead.\n");
217
218  OWLVAR_STRING( "appendtosepbar" /* %OwlVarStub */, "",
219                 "string to append to the end of the sepbar",
220                 "The sepbar is the bar separating the top and bottom\n"
221                 "of the BarnOwl screen.  Any string specified here will\n"
222                 "be displayed on the right of the sepbar\n");
223
224  OWLVAR_BOOL( "zaway" /* %OwlVarStub */, 0,
225               "turn zaway on or off", "" );
226
227  OWLVAR_STRING( "zaway_msg" /* %OwlVarStub */, 
228                 OWL_DEFAULT_ZAWAYMSG,
229                 "zaway msg for responding to zephyrs when away", "" );
230
231  OWLVAR_STRING( "zaway_msg_default" /* %OwlVarStub */, 
232                 OWL_DEFAULT_ZAWAYMSG,
233                 "default zaway message", "" );
234
235  OWLVAR_STRING( "view_home" /* %OwlVarStub */, "all",
236                 "home view to switch to after 'X' and 'V'", 
237                 "SEE ALSO: view, filter\n" );
238
239  OWLVAR_STRING( "alert_filter" /* %OwlVarStub */, "none",
240                 "filter on which to trigger alert actions",
241                 "" );
242
243  OWLVAR_STRING( "alert_action" /* %OwlVarStub */, "nop",
244                 "BarnOwl command to execute for alert actions",
245                 "" );
246
247  OWLVAR_STRING_FULL( "tty" /* %OwlVarStub */, "", "<string>", "tty name for zephyr location", "",
248                      NULL, owl_variable_tty_set, NULL);
249
250  OWLVAR_STRING( "default_style" /* %OwlVarStub */, "default",
251                 "name of the default formatting style",
252                 "This sets the default message formatting style.\n"
253                 "Styles may be created with the 'style' command.\n"
254                 "Some built-in styles include:\n"
255                 "   default  - the default BarnOwl formatting\n"
256                 "   oneline  - one line per-message\n"
257                 "   perl     - legacy perl interface\n"
258                 "\nSEE ALSO: style, show styles, view -s <style>\n"
259                 );
260
261
262  OWLVAR_INT(    "edit:maxfillcols" /* %OwlVarStub:edit_maxfillcols */, 70,
263                 "maximum number of columns for M-q (edit:fill-paragraph) to fill text to",
264                 "This specifies the maximum number of columns for M-q to fill text\n"
265                 "to.  If set to 0, M-q will wrap to the width of the window, and\n"
266                 "values less than 0 disable M-q entirely.\n");
267
268  OWLVAR_INT(    "edit:maxwrapcols" /* %OwlVarStub:edit_maxwrapcols */, 70,
269                 "maximum number of columns for line-wrapping",
270                 "This specifies the maximum number of columns for\n"
271                 "auto-line-wrapping.  If set to 0, text will be wrapped at the\n"
272                 "window width. Values less than 0 disable automatic wrapping.\n"
273                 "\n"
274                 "As a courtesy to recipients, it is recommended that outgoing\n"
275                 "Zephyr messages be no wider than 70 columns.\n");
276
277  OWLVAR_INT_FULL( "typewinsize" /* %OwlVarStub:typwin_lines */, 
278                   OWL_TYPWIN_SIZE,
279                  "number of lines in the typing window", 
280                   "This specifies the height of the window at the\n"
281                   "bottom of the screen where commands are entered\n"
282                   "and where messages are composed.\n",
283                   "int > 0",
284                   owl_variable_int_validate_gt0,
285                   owl_variable_typewinsize_set,
286                   NULL /* use default for get */
287                   );
288
289  OWLVAR_INT( "typewindelta" /* %OwlVarStub */, 0,
290                  "number of lines to add to the typing window when in use",
291                   "On small screens you may want the typing window to\n"
292                   "auto-hide when not entering a command or message.\n"
293                   "This variable is the number of lines to add to the\n"
294           "typing window when it is in use; you can then set\n"
295           "typewinsize to 1.\n\n"
296           "This works a lot better with a non-default scrollmode;\n"
297           "try :set scrollmode pagedcenter.\n");
298
299  OWLVAR_ENUM( "scrollmode" /* %OwlVarStub */, OWL_SCROLLMODE_NORMAL,
300               "how to scroll up and down",
301               "This controls how the screen is scrolled as the\n"
302               "cursor moves between messages being displayed.\n"
303               "The following modes are supported:\n\n"
304               "   normal      - This is the BarnOwl default.  Scrolling happens\n"
305               "                 when it needs to, and an attempt is made to\n"
306               "                 keep the current message roughly near\n"
307               "                 the middle of the screen.\n"
308               "   top         - The current message will always be the\n"
309               "                 the top message displayed.\n"
310               "   neartop     - The current message will be one down\n"
311               "                 from the top message displayed,\n"
312               "                 where possible.\n"
313               "   center      - An attempt is made to keep the current\n"
314               "                 message near the center of the screen.\n"
315               "   paged       - The top message displayed only changes\n"
316               "                 when user moves the cursor to the top\n"
317               "                 or bottom of the screen.  When it moves,\n"
318               "                 the screen will be paged up or down and\n"
319               "                 the cursor will be near the top or\n"
320               "                 the bottom.\n"
321               "   pagedcenter - The top message displayed only changes\n"
322               "                 when user moves the cursor to the top\n"
323               "                 or bottom of the screen.  When it moves,\n"
324               "                 the screen will be paged up or down and\n"
325               "                 the cursor will be near the center.\n",
326               "normal,top,neartop,center,paged,pagedcenter" );
327
328  OWLVAR_BOOL( "narrow-related" /* %OwlVarStub:narrow_related */, 1,
329               "Make smartnarrow use broader filters",
330               "Causes smartfilter to narrow to messages \"related\" to \n"
331               "the current message, as well as ones to the same place.\n\n"
332               "for Zephyr, this controls whether to narrow to e.g. class-help or\n"
333               "class-help.d alone, or to related-class-help, which includes\n"
334               "help, unhelp, help.d, etc.\n\nDefault is true (include unclasses, etc.).\n" );
335
336  OWLVAR_BOOL( "_followlast" /* %OwlVarStub */, 0,
337               "enable automatic following of the last zephyr",
338               "If the cursor is at the last message, it will\n"
339               "continue to follow the last message if this is set.\n"
340               "Note that this is currently risky as you might accidentally\n"
341               "delete a message right as it came in.\n" );
342
343  OWLVAR_STRING_FULL( "default_exposure" /* %OwlVarStub */, "",
344                      "none,opstaff,realm-visible,realm-announced,net-visible,net-announced",
345                      "controls the persistent value for exposure",
346                      "The default exposure level corresponds to the Zephyr exposure value\n"
347                      "in ~/.zephyr.vars.  Defaults to realm-visible if there is no value in\n"
348                      "~/.zephyr.vars.\n"
349                      "See the description of exposure for the values this can be.",
350                      NULL, owl_variable_default_exposure_set, owl_variable_default_exposure_get );
351
352  OWLVAR_STRING_FULL( "exposure" /* %OwlVarStub */, "",
353                      "none,opstaff,realm-visible,realm-announced,net-visible,net-announced",
354                      "controls who can zlocate you",
355                      "The exposure level, defaulting to the value of default_exposure,\n"
356                      "can be one of the following (from least exposure to widest exposure,\n"
357                      "as listed in zctl(1)):\n"
358                      "\n"
359                      "   none            - This completely disables Zephyr for the user. \n"
360                      "                     The user is not registered with Zephyr.  No user\n"
361                      "                     location information is retained by Zephyr.  No\n"
362                      "                     login or logout announcements will be sent.  No\n"
363                      "                     subscriptions will be entered for the user, and\n"
364                      "                     no notices will be displayed by zwgc(1).\n"
365                      "   opstaff         - The user is registered with Zephyr.  No login or\n"
366                      "                     logout announcements will be sent, and location\n"
367                      "                     information will only be visible to Operations\n"
368                      "                     staff.  Default subscriptions and any additional\n"
369                      "                     personal subscriptions will be entered for the\n"
370                      "                     user.\n"
371                      "   realm-visible   - The user is registered with Zephyr.  User\n"
372                      "                     location information is retained by Zephyr and\n"
373                      "                     made available only to users within the user’s\n"
374                      "                     Kerberos realm.  No login or logout\n"
375                      "                     announcements will be sent.  This is the system\n"
376                      "                     default.  Default subscriptions and any\n"
377                      "                     additional personal subscriptions will be\n"
378                      "                     entered for the user.\n"
379                      "   realm-announced - The user is registered with Zephyr.  User\n"
380                      "                     location information is retained by Zephyr and\n"
381                      "                     made available only to users authenticated\n"
382                      "                     within the user’s Kerberos realm.  Login and\n"
383                      "                     logout announcements will be sent, but only to\n"
384                      "                     users within the user’s Kerberos realm who have\n"
385                      "                     explicitly requested such via subscriptions. \n"
386                      "                     Default subscriptions and any additional\n"
387                      "                     personal subscriptions will be entered for the\n"
388                      "                     user.\n"
389                      "   net-visible     - The user is registered with Zephyr.  User\n"
390                      "                     location information is retained by Zephyr and\n"
391                      "                     made available to any authenticated user who\n"
392                      "                     requests such.  Login and logout announcements\n"
393                      "                     will be sent only to users within the user’s\n"
394                      "                     Kerberos realm who have explicitly requested\n"
395                      "                     such via subscriptions.  Default subscriptions\n"
396                      "                     and any additional personal subscriptions will\n"
397                      "                     be entered for the user.\n"
398                      "   net-announced   - The user is registered with Zephyr.  User\n"
399                      "                     location information is retained by Zephyr and\n"
400                      "                     made available to any authenticated user who\n"
401                      "                     requests such.  Login and logout announcements\n"
402                      "                     will be sent to any user has requested such. \n"
403                      "                     Default subscriptions and any additional\n"
404                      "                     personal subscriptions will be entered for the\n"
405                      "                     user.\n",
406                      NULL, owl_variable_exposure_set, NULL /* use default for get */ );
407}
408
409/**************************************************************************/
410/*********************** SPECIFIC TO VARIABLES ****************************/
411/**************************************************************************/
412
413
414/* commonly useful */
415
416int owl_variable_int_validate_gt0(const owl_variable *v, int newval)
417{
418  return !(newval < 1);
419}
420
421int owl_variable_int_validate_positive(const owl_variable *v, int newval)
422{
423  return !(newval < 0);
424}
425
426/* typewinsize */
427int owl_variable_typewinsize_set(owl_variable *v, int newval)
428{
429  int rv;
430  rv = owl_variable_int_set_default(v, newval);
431  if (0 == rv) owl_mainpanel_layout_contents(&g.mainpanel);
432  return(rv);
433}
434
435/* debug (cache value in g->debug) */
436int owl_variable_debug_set(owl_variable *v, bool newval)
437{
438  g.debug = newval;
439  return owl_variable_bool_set_default(v, newval);
440}
441
442int owl_variable_colorztext_set(owl_variable *v, bool newval)
443{
444  int ret = owl_variable_bool_set_default(v, newval);
445  /* flush the format cache so that we see the update, but only if we're done initializing BarnOwl */
446  if (owl_global_get_msglist(&g) != NULL)
447    owl_messagelist_invalidate_formats(owl_global_get_msglist(&g));
448  if (owl_global_get_mainwin(&g) != NULL) {
449    owl_function_calculate_topmsg(OWL_DIRECTION_DOWNWARDS);
450    owl_mainwin_redisplay(owl_global_get_mainwin(&g));
451  }
452  return ret;
453}
454
455int owl_variable_pseudologins_set(owl_variable *v, bool newval)
456{
457  static guint timer = 0;
458  if (newval) {
459    owl_function_zephyr_buddy_check(0);
460    if (timer == 0) {
461      timer = g_timeout_add_seconds(180, owl_zephyr_buddycheck_timer, NULL);
462    }
463  } else {
464    if (timer != 0) {
465      g_source_remove(timer);
466      timer = 0;
467    }
468  }
469  return owl_variable_bool_set_default(v, newval);
470}
471
472/* note that changing the value of this will clobber
473 * any user setting of this */
474int owl_variable_disable_ctrl_d_set(owl_variable *v, int newval)
475{
476  if (!owl_context_is_startup(owl_global_get_context(&g))) {
477    if (newval == 2) {
478      owl_function_command_norv("bindkey editmulti C-d command edit:delete-next-char");
479    } else if (newval == 1) {
480      owl_function_command_norv("bindkey editmulti C-d command edit:done-or-delete");
481    } else {
482      owl_function_command_norv("bindkey editmulti C-d command edit:done");
483    }
484  } 
485  return owl_variable_int_set_default(v, newval);
486}
487
488int owl_variable_tty_set(owl_variable *v, const char *newval)
489{
490  owl_zephyr_set_locationinfo(g_get_host_name(), newval);
491  return owl_variable_string_set_default(v, newval);
492}
493
494int owl_variable_default_exposure_set(owl_variable *v, const char *newval)
495{
496  return owl_zephyr_set_default_exposure(newval);
497}
498
499const char *owl_variable_default_exposure_get(const owl_variable *v)
500{
501  return owl_zephyr_get_default_exposure();
502}
503
504int owl_variable_exposure_set(owl_variable *v, const char *newval)
505{
506  int ret = owl_zephyr_set_exposure(newval);
507  if (ret != 0)
508    return ret;
509  return owl_variable_string_set_default(v, owl_zephyr_normalize_exposure(newval));
510}
511
512/**************************************************************************/
513/****************************** GENERAL ***********************************/
514/**************************************************************************/
515
516void owl_variable_dict_setup(owl_vardict *vd) {
517  owl_dict_create(vd);
518  owl_variable_add_defaults(vd);
519}
520
521CALLER_OWN GClosure *owl_variable_make_closure(owl_variable *v,
522                                               GCallback fn,
523                                               GClosureMarshal marshal) {
524  GClosure *closure = g_cclosure_new_swap(fn, v, NULL);
525  g_closure_set_marshal(closure,marshal);
526  g_closure_ref(closure);
527  g_closure_sink(closure);
528  return closure;
529}
530
531void owl_variable_dict_add_variable(owl_vardict * vardict,
532                                    owl_variable * var) {
533  char *oldvalue = NULL;
534  owl_variable *oldvar = owl_variable_get_var(vardict, var->name);
535  /* Save the old value as a string. */
536  if (oldvar) {
537    oldvalue = owl_variable_get_tostring(oldvar);
538  }
539  owl_dict_insert_element(vardict, var->name, var, (void (*)(void *))owl_variable_delete);
540  /* Restore the old value. */
541  if (oldvalue) {
542    owl_variable_set_fromstring(var, oldvalue, 0);
543    g_free(oldvalue);
544  }
545}
546
547static owl_variable *owl_variable_newvar(int type, const char *name, const char *summary, const char *description, const char *validsettings) {
548  owl_variable *var = g_slice_new0(owl_variable);
549  var->type = type;
550  var->name = g_strdup(name);
551  var->summary = g_strdup(summary);
552  var->description = g_strdup(description);
553  var->validsettings = g_strdup(validsettings);
554  return var;
555}
556
557static void owl_variable_dict_newvar_int_full(owl_vardict *vd, const char *name, int default_val, const char *summary, const char *description, const char *validsettings, validate_int_t validate_fn, set_int_t set_fn, get_int_t get_fn)
558{
559  owl_variable *var = owl_variable_newvar(OWL_VARIABLE_INT, name, summary,
560                                          description, validsettings);
561  var->takes_on_off = false;
562  var->get_fn = G_CALLBACK(get_fn ? get_fn : owl_variable_int_get_default);
563  var->set_fn = G_CALLBACK(set_fn ? set_fn : owl_variable_int_set_default);
564  var->validate_fn = G_CALLBACK(validate_fn ? validate_fn : owl_variable_int_validate_default);
565
566  var->get_tostring_fn = owl_variable_make_closure(
567      var, G_CALLBACK(owl_variable_int_get_tostring_default),
568      g_cclosure_user_marshal_STRING__VOID);
569  var->set_fromstring_fn = owl_variable_make_closure(
570      var, G_CALLBACK(owl_variable_int_set_fromstring_default),
571      g_cclosure_user_marshal_INT__STRING);
572
573  g_value_init(&var->val, G_TYPE_INT);
574  owl_variable_set_int(var, default_val);
575
576  var->default_str = owl_variable_get_tostring(var);
577  owl_variable_dict_add_variable(vd, var);
578}
579
580void owl_variable_dict_newvar_int(owl_vardict *vd, const char *name, int default_val, const char *summary, const char *description) {
581  owl_variable_dict_newvar_int_full(vd, name, default_val, summary, description,
582                                    "<int>", NULL, NULL, NULL);
583}
584
585static void owl_variable_dict_newvar_bool_full(owl_vardict *vd, const char *name, bool default_val, const char *summary, const char *description, validate_bool_t validate_fn, set_bool_t set_fn, get_bool_t get_fn)
586{
587  owl_variable *var = owl_variable_newvar(OWL_VARIABLE_BOOL, name, summary,
588                                          description, "on,off");
589  var->takes_on_off = true;
590  var->get_fn = G_CALLBACK(get_fn ? get_fn : owl_variable_bool_get_default);
591  var->set_fn = G_CALLBACK(set_fn ? set_fn : owl_variable_bool_set_default);
592  var->validate_fn = G_CALLBACK(validate_fn ? validate_fn : owl_variable_bool_validate_default);
593
594  var->get_tostring_fn = owl_variable_make_closure(
595      var, G_CALLBACK(owl_variable_bool_get_tostring_default),
596      g_cclosure_user_marshal_STRING__VOID);
597  var->set_fromstring_fn = owl_variable_make_closure(
598      var, G_CALLBACK(owl_variable_bool_set_fromstring_default),
599      g_cclosure_user_marshal_INT__STRING);
600
601  g_value_init(&var->val, G_TYPE_BOOLEAN);
602  owl_variable_set_bool(var, default_val);
603
604  var->default_str = owl_variable_get_tostring(var);
605  owl_variable_dict_add_variable(vd, var);
606}
607
608void owl_variable_dict_newvar_bool(owl_vardict *vd, const char *name, bool default_val, const char *summary, const char *description) {
609  owl_variable_dict_newvar_bool_full(vd, name, default_val, summary, description,
610                                     NULL, NULL, NULL);
611}
612
613static void owl_variable_dict_newvar_string_full(owl_vardict *vd, const char *name, const char *default_val, const char *summary, const char *description, const char *validsettings, validate_string_t validate_fn, set_string_t set_fn, get_string_t get_fn)
614{
615  owl_variable *var = owl_variable_newvar(OWL_VARIABLE_STRING, name, summary,
616                                          description, validsettings);
617  var->takes_on_off = false;
618  var->get_fn = G_CALLBACK(get_fn ? get_fn : owl_variable_string_get_default);
619  var->set_fn = G_CALLBACK(set_fn ? set_fn : owl_variable_string_set_default);
620  var->validate_fn = G_CALLBACK(validate_fn ? validate_fn : owl_variable_string_validate_default);
621
622  var->get_tostring_fn = owl_variable_make_closure(
623      var, G_CALLBACK(owl_variable_string_get_tostring_default),
624      g_cclosure_user_marshal_STRING__VOID);
625  var->set_fromstring_fn = owl_variable_make_closure(
626      var, G_CALLBACK(owl_variable_string_set_fromstring_default),
627      g_cclosure_user_marshal_INT__STRING);
628
629  g_value_init(&var->val, G_TYPE_STRING);
630  owl_variable_set_string(var, default_val);
631
632  var->default_str = owl_variable_get_tostring(var);
633  owl_variable_dict_add_variable(vd, var);
634}
635
636void owl_variable_dict_newvar_string(owl_vardict *vd, const char *name, const char *default_val, const char *summary, const char *description) {
637  owl_variable_dict_newvar_string_full(vd, name, default_val, summary, description,
638                                       "<string>", NULL, NULL, NULL);
639}
640
641void owl_variable_dict_newvar_path(owl_vardict *vd, const char *name, const char *default_val, const char *summary, const char *description) {
642  owl_variable_dict_newvar_string_full(vd, name, default_val, summary, description,
643                                       "<path>", NULL, NULL, NULL);
644}
645
646static void owl_variable_dict_newvar_enum_full(owl_vardict *vd, const char *name, int default_val, const char *summary, const char *description, const char *validsettings, validate_int_t validate_fn, set_int_t set_fn, get_int_t get_fn)
647{
648  owl_variable *var = owl_variable_newvar(OWL_VARIABLE_INT, name, summary,
649                                          description, validsettings);
650  var->takes_on_off = false;
651  var->get_fn = G_CALLBACK(get_fn ? get_fn : owl_variable_int_get_default);
652  var->set_fn = G_CALLBACK(set_fn ? set_fn : owl_variable_int_set_default);
653  var->validate_fn = G_CALLBACK(validate_fn ? validate_fn : owl_variable_enum_validate);
654
655  var->get_tostring_fn = owl_variable_make_closure(
656      var, G_CALLBACK(owl_variable_enum_get_tostring),
657      g_cclosure_user_marshal_STRING__VOID);
658  var->set_fromstring_fn = owl_variable_make_closure(
659      var, G_CALLBACK(owl_variable_enum_set_fromstring),
660      g_cclosure_user_marshal_INT__STRING);
661
662  g_value_init(&var->val, G_TYPE_INT);
663  owl_variable_set_int(var, default_val);
664
665  var->default_str = owl_variable_get_tostring(var);
666  owl_variable_dict_add_variable(vd, var);
667}
668
669void owl_variable_dict_newvar_enum(owl_vardict *vd, const char *name, int default_val, const char *summary, const char *description, const char *validset) {
670  owl_variable_dict_newvar_enum_full(vd, name, default_val, summary, description,
671                                     validset, NULL, NULL, NULL);
672}
673
674void owl_variable_dict_newvar_other(owl_vardict *vd, const char *name, const char *summary, const char *description, const char *validsettings, bool takes_on_off, GClosure *get_tostring_fn, GClosure *set_fromstring_fn)
675{
676  owl_variable *var = owl_variable_newvar(OWL_VARIABLE_OTHER, name, summary,
677                                          description, validsettings);
678  var->takes_on_off = takes_on_off;
679
680  var->get_tostring_fn = g_closure_ref(get_tostring_fn);
681  g_closure_sink(get_tostring_fn);
682
683  var->set_fromstring_fn = g_closure_ref(set_fromstring_fn);
684  g_closure_sink(set_fromstring_fn);
685
686  var->default_str = owl_variable_get_tostring(var);
687
688  /* Note: this'll overwrite any existing variable of that name, even a C one,
689     but it's consistent with previous behavior and commands. */
690  owl_variable_dict_add_variable(vd, var);
691}
692
693void owl_variable_dict_cleanup(owl_vardict *d)
694{
695  owl_dict_cleanup(d, (void (*)(void *))owl_variable_delete);
696}
697
698CALLER_OWN GPtrArray *owl_variable_dict_get_names(const owl_vardict *d) {
699  return owl_dict_get_keys(d);
700}
701
702void owl_variable_delete(owl_variable *v)
703{
704  g_free(v->name);
705  g_free(v->summary);
706  g_free(v->description);
707  g_free(v->default_str);
708  g_free(v->validsettings);
709  if (v->type != OWL_VARIABLE_OTHER)
710    g_value_unset(&(v->val));
711  g_closure_unref(v->get_tostring_fn);
712  g_closure_unref(v->set_fromstring_fn);
713
714  g_slice_free(owl_variable, v);
715}
716
717
718const char *owl_variable_get_name(const owl_variable *v)
719{
720  return v->name;
721}
722
723const char *owl_variable_get_description(const owl_variable *v) {
724  return v->description;
725}
726
727const char *owl_variable_get_summary(const owl_variable *v) {
728  return v->summary;
729}
730
731const char *owl_variable_get_validsettings(const owl_variable *v) {
732  return v->validsettings;
733}
734
735bool owl_variable_takes_on_off(const owl_variable *v) {
736  return v->takes_on_off;
737}
738
739int owl_variable_get_type(const owl_variable *v)
740{
741  return v->type;
742}
743
744/* returns 0 on success, prints a status msg if msg is true */
745int owl_variable_set_fromstring(owl_variable *v, const char *value, int msg) {
746  char *tostring;
747  GValue values[] = {G_VALUE_INIT, G_VALUE_INIT};
748  GValue return_box = G_VALUE_INIT;
749  int set_successfully;
750
751  g_value_init(&values[0], G_TYPE_POINTER);
752  g_value_set_pointer(&values[0], NULL);
753  g_value_init(&values[1], G_TYPE_STRING);
754  g_value_set_static_string(&values[1], value);
755  g_value_init(&return_box, G_TYPE_INT);
756  g_closure_invoke(v->set_fromstring_fn, &return_box, 2, values, NULL);
757
758  set_successfully = g_value_get_int(&return_box);
759  if (0 != set_successfully) {
760    if (msg) owl_function_error("Unable to set %s (must be %s)", owl_variable_get_name(v),
761                                owl_variable_get_validsettings(v));
762  } else if (msg) {
763    tostring = owl_variable_get_tostring(v);
764    if (tostring) {
765      owl_function_makemsg("%s = '%s'", owl_variable_get_name(v), tostring);
766    } else {
767      owl_function_makemsg("%s = <null>", owl_variable_get_name(v));
768    }
769    g_free(tostring);
770  }
771
772  g_value_unset(&return_box);
773  g_value_unset(&values[1]);
774  g_value_unset(&values[0]);
775  return set_successfully;
776}
777 
778int owl_variable_set_string(owl_variable *v, const char *newval)
779{
780  g_return_val_if_fail(v->type == OWL_VARIABLE_STRING, -1);
781
782  set_string_t cb = (set_string_t) v->set_fn;
783  return cb(v, newval);
784}
785
786int owl_variable_set_int(owl_variable *v, int newval)
787{
788  g_return_val_if_fail(v->type == OWL_VARIABLE_INT, -1);
789
790  set_int_t cb = (set_int_t) v->set_fn;
791  return cb(v, newval);
792}
793
794int owl_variable_set_bool(owl_variable *v, bool newval) {
795  g_return_val_if_fail(v->type == OWL_VARIABLE_BOOL, -1);
796
797  set_bool_t cb = (set_bool_t) v->set_fn;
798  return cb(v, newval);
799}
800
801int owl_variable_set_bool_on(owl_variable *v)
802{
803  if (v->type != OWL_VARIABLE_BOOL) return -1;
804  return owl_variable_set_bool(v, true);
805}
806
807int owl_variable_set_bool_off(owl_variable *v)
808{
809  if (v->type != OWL_VARIABLE_BOOL) return -1;
810  return owl_variable_set_bool(v, false);
811}
812
813CALLER_OWN char *owl_variable_get_tostring(const owl_variable *v)
814{
815  GValue instance = G_VALUE_INIT;
816  GValue tostring_box = G_VALUE_INIT;
817  char *ret = NULL;
818
819  g_value_init(&instance, G_TYPE_POINTER);
820  g_value_set_pointer(&instance, NULL);
821  g_value_init(&tostring_box, G_TYPE_STRING);
822  g_closure_invoke(v->get_tostring_fn, &tostring_box, 1, &instance, NULL);
823
824  ret = g_value_dup_string(&tostring_box);
825
826  g_value_unset(&tostring_box);
827  g_value_unset(&instance);
828  return ret;
829}
830
831const char *owl_variable_get_default_tostring(const owl_variable *v)
832{
833  return v->default_str;
834}
835
836owl_variable *owl_variable_get_var(const owl_vardict *d, const char *name)
837{
838  return owl_dict_find_element(d, name);
839}
840
841const char *owl_variable_get_string(const owl_variable *v)
842{
843  g_return_val_if_fail(v->type == OWL_VARIABLE_STRING, NULL);
844
845  get_string_t cb = (get_string_t) v->get_fn;
846  return cb(v);
847}
848
849int owl_variable_get_int(const owl_variable *v)
850{
851  g_return_val_if_fail(v->type == OWL_VARIABLE_INT, 0);
852
853  get_int_t cb = (get_int_t) v->get_fn;
854  return cb(v);
855}
856
857bool owl_variable_get_bool(const owl_variable *v)
858{
859  g_return_val_if_fail(v->type == OWL_VARIABLE_BOOL, FALSE);
860
861  get_bool_t cb = (get_bool_t) v->get_fn;
862  return cb(v);
863}
864
865void owl_variable_describe(const owl_variable *v, owl_fmtext *fm)
866{
867  const char *default_str = owl_variable_get_default_tostring(v);
868  char *default_buf;
869
870  if (default_str)
871    default_buf = g_strdup_printf("'%s'", default_str);
872  else
873    default_buf = g_strdup("<null>");
874  owl_fmtext_appendf_normal(fm, OWL_TABSTR "%-20s - %s (default: %s)\n",
875                            owl_variable_get_name(v),
876                            owl_variable_get_summary(v), default_buf);
877  g_free(default_buf);
878}
879
880void owl_variable_get_help(const owl_variable *v, owl_fmtext *fm) {
881  char *tostring;
882  const char *default_str;
883
884  owl_fmtext_append_bold(fm, "OWL VARIABLE\n\n");
885  owl_fmtext_append_normal(fm, OWL_TABSTR);
886  owl_fmtext_append_normal(fm, owl_variable_get_name(v));
887  owl_fmtext_append_normal(fm, " - ");
888  owl_fmtext_append_normal(fm, owl_variable_get_summary(v));
889  owl_fmtext_append_normal(fm, "\n\n");
890
891  owl_fmtext_append_normal(fm, "Current:        ");
892  tostring = owl_variable_get_tostring(v);
893  owl_fmtext_append_normal(fm, (tostring ? tostring : "<null>"));
894  g_free(tostring);
895  owl_fmtext_append_normal(fm, "\n\n");
896
897  default_str = owl_variable_get_default_tostring(v);
898  owl_fmtext_append_normal(fm, "Default:        ");
899  owl_fmtext_append_normal(fm, (default_str ? default_str : "<null>"));
900  owl_fmtext_append_normal(fm, "\n\n");
901
902  owl_fmtext_append_normal(fm, "Valid Settings: ");
903  owl_fmtext_append_normal(fm, owl_variable_get_validsettings(v));
904  owl_fmtext_append_normal(fm, "\n\n");
905
906  if (v->description && *v->description) {
907    owl_fmtext_append_normal(fm, "Description:\n");
908    owl_fmtext_append_normal(fm, owl_variable_get_description(v));
909    owl_fmtext_append_normal(fm, "\n\n");
910  }
911}
912
913
914
915
916/**************************************************************************/
917/*********************** GENERAL TYPE-SPECIFIC ****************************/
918/**************************************************************************/
919
920/* default common functions */
921
922const char *owl_variable_string_get_default(const owl_variable *v) {
923  return g_value_get_string(&(v->val));
924}
925
926int owl_variable_int_get_default(const owl_variable *v) {
927  return g_value_get_int(&(v->val));
928}
929
930bool owl_variable_bool_get_default(const owl_variable *v) {
931  return g_value_get_boolean(&(v->val));
932}
933
934/* default functions for booleans */
935
936int owl_variable_bool_validate_default(const owl_variable *v, bool newval) {
937  return (newval == 1) || (newval == 0);
938}
939
940int owl_variable_bool_set_default(owl_variable *v, bool newval) {
941  if (!((validate_bool_t)v->validate_fn)(v, newval))
942    return -1;
943
944  g_value_set_boolean(&(v->val), newval);
945  return(0);
946}
947
948int owl_variable_bool_set_fromstring_default(owl_variable *v, const char *newval, void *dummy) {
949  bool i;
950  if (!strcmp(newval, "on")) {
951    i = true;
952  } else if (!strcmp(newval, "off")) {
953    i = false;
954  } else {
955    return(-1);
956  }
957
958  return owl_variable_set_bool(v, i);
959}
960
961CALLER_OWN char *owl_variable_bool_get_tostring_default(const owl_variable *v, void *dummy)
962{
963  return g_strdup(owl_variable_get_bool(v) ? "on" : "off");
964}
965
966/* default functions for integers */
967
968int owl_variable_int_validate_default(const owl_variable *v, int newval)
969{
970  return (1);
971}
972
973int owl_variable_int_set_default(owl_variable *v, int newval) {
974  if (!((validate_int_t)v->validate_fn)(v, newval))
975    return -1;
976
977  g_value_set_int(&(v->val), newval);
978  return(0);
979}
980
981int owl_variable_int_set_fromstring_default(owl_variable *v, const char *newval, void *dummy) {
982  int i;
983  char *ep;
984  i = strtol(newval, &ep, 10);
985  if (*ep || ep==newval) return(-1);
986  return owl_variable_set_int(v, i);
987}
988
989CALLER_OWN char *owl_variable_int_get_tostring_default(const owl_variable *v, void *dummy)
990{
991  return g_strdup_printf("%d", owl_variable_get_int(v));
992}
993
994/* default functions for enums (a variant of integers) */
995
996int owl_variable_enum_validate(const owl_variable *v, int newval) {
997  char **enums;
998  int nenums, val;
999  enums = g_strsplit_set(v->validsettings, ",", 0);
1000  nenums = g_strv_length(enums);
1001  g_strfreev(enums);
1002  val = newval;
1003  if (val < 0 || val >= nenums) {
1004    return(0);
1005  }
1006  return(1);
1007}
1008
1009int owl_variable_enum_set_fromstring(owl_variable *v, const char *newval, void *dummy) {
1010  char **enums;
1011  int i, val=-1;
1012  if (newval == NULL) return(-1);
1013  enums = g_strsplit_set(v->validsettings, ",", 0);
1014  for (i = 0; enums[i] != NULL; i++) {
1015    if (0==strcmp(newval, enums[i])) {
1016      val = i;
1017    }
1018  }
1019  g_strfreev(enums);
1020  if (val == -1) return(-1);
1021  return owl_variable_set_int(v, val);
1022}
1023
1024CALLER_OWN char *owl_variable_enum_get_tostring(const owl_variable *v, void *dummy)
1025{
1026  char **enums;
1027  int nenums, i;
1028  char *tostring;
1029
1030  enums = g_strsplit_set(v->validsettings, ",", 0);
1031  nenums = g_strv_length(enums);
1032  i = owl_variable_get_int(v);
1033  if (i<0 || i>=nenums) {
1034    g_strfreev(enums);
1035    return g_strdup_printf("<invalid:%d>", i);
1036  }
1037  tostring = g_strdup(enums[i]);
1038  g_strfreev(enums);
1039  return tostring;
1040}
1041
1042/* default functions for stringeans */
1043
1044int owl_variable_string_validate_default(const owl_variable *v, const char *newval) {
1045  if (newval == NULL) return(0);
1046  else return (1);
1047}
1048
1049int owl_variable_string_set_default(owl_variable *v, const char *newval) {
1050  if (!((validate_string_t)v->validate_fn)(v, newval))
1051    return -1;
1052
1053  g_value_set_string(&(v->val), newval);
1054  return(0);
1055}
1056
1057int owl_variable_string_set_fromstring_default(owl_variable *v, const char *newval, void *dummy) 
1058{
1059  return owl_variable_set_string(v, newval);
1060}
1061
1062CALLER_OWN char *owl_variable_string_get_tostring_default(const owl_variable *v, void *dummy)
1063{
1064  return g_strdup(owl_variable_get_string(v));
1065}
1066
Note: See TracBrowser for help on using the repository browser.