source: set.c @ e41cc40

Last change on this file since e41cc40 was 434ffa2, checked in by dequis <dx@…>, at 2015-01-16T19:50:24Z

set_setint: use g_strdup_printf instead of relying on a char s[24];

  • Property mode set to 100644
File size: 5.9 KB
Line 
1  /********************************************************************\
2  * BitlBee -- An IRC to other IM-networks gateway                     *
3  *                                                                    *
4  * Copyright 2002-2013 Wilmer van der Gaast and others                *
5  \********************************************************************/
6
7/* Some stuff to register, handle and save user preferences             */
8
9/*
10  This program is free software; you can redistribute it and/or modify
11  it under the terms of the GNU General Public License as published by
12  the Free Software Foundation; either version 2 of the License, or
13  (at your option) any later version.
14
15  This program is distributed in the hope that it will be useful,
16  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  GNU General Public License for more details.
19
20  You should have received a copy of the GNU General Public License with
21  the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL;
22  if not, write to the Free Software Foundation, Inc., 51 Franklin St.,
23  Fifth Floor, Boston, MA  02110-1301  USA
24*/
25
26#define BITLBEE_CORE
27#include "bitlbee.h"
28
29/* Used to use NULL for this, but NULL is actually a "valid" value. */
30char *SET_INVALID = "nee";
31
32set_t *set_add( set_t **head, const char *key, const char *def, set_eval eval, void *data )
33{
34        set_t *s = set_find( head, key );
35       
36        /* Possibly the setting already exists. If it doesn't exist yet,
37           we create it. If it does, we'll just change the default. */
38        if( !s )
39        {
40                if( ( s = *head ) )
41                {
42                        /* Sorted insertion. Special-case insertion at the start. */
43                        if( strcmp( key, s->key ) < 0 )
44                        {
45                                s = g_new0( set_t, 1 );
46                                s->next = *head;
47                                *head = s;
48                        }
49                        else
50                        {
51                                while( s->next && strcmp( key, s->next->key ) > 0 )
52                                        s = s->next;
53                                set_t *last_next = s->next;
54                                s->next = g_new0( set_t, 1 );
55                                s = s->next;
56                                s->next = last_next;
57                        }
58                }
59                else
60                {
61                        s = *head = g_new0( set_t, 1 );
62                }
63                s->key = g_strdup( key );
64        }
65       
66        if( s->def )
67        {
68                g_free( s->def );
69                s->def = NULL;
70        }
71        if( def ) s->def = g_strdup( def );
72       
73        s->eval = eval;
74        s->data = data;
75       
76        return s;
77}
78
79set_t *set_find( set_t **head, const char *key )
80{
81        set_t *s = *head;
82       
83        while( s )
84        {
85                if( g_strcasecmp( s->key, key ) == 0 ||
86                    ( s->old_key && g_strcasecmp( s->old_key, key ) == 0 ) )
87                        break;
88                s = s->next;
89        }
90       
91        return s;
92}
93
94char *set_getstr( set_t **head, const char *key )
95{
96        set_t *s = set_find( head, key );
97       
98        if( !s || ( !s->value && !s->def ) )
99                return NULL;
100       
101        return set_value( s );
102}
103
104int set_getint( set_t **head, const char *key )
105{
106        char *s = set_getstr( head, key );
107        int i = 0;
108       
109        if( !s )
110                return 0;
111       
112        if( sscanf( s, "%d", &i ) != 1 )
113                return 0;
114       
115        return i;
116}
117
118int set_getbool( set_t **head, const char *key )
119{
120        char *s = set_getstr( head, key );
121       
122        if( !s )
123                return 0;
124       
125        return bool2int( s );
126}
127
128int set_isvisible( set_t *set )
129{
130        /* the default value is not stored in value, only in def */
131        return !( ( set->flags & SET_HIDDEN ) ||
132                  ( ( set->flags & SET_HIDDEN_DEFAULT ) &&
133                    ( set->value == NULL ) ) );
134}
135
136int set_setstr( set_t **head, const char *key, char *value )
137{
138        set_t *s = set_find( head, key );
139        char *nv = value;
140       
141        if( !s )
142                /*
143                Used to do this, but it never really made sense.
144                s = set_add( head, key, NULL, NULL, NULL );
145                */
146                return 0;
147       
148        if( value == NULL && ( s->flags & SET_NULL_OK ) == 0 )
149                return 0;
150       
151        /* Call the evaluator. For invalid values, evaluators should now
152           return SET_INVALID, but previously this was NULL. Try to handle
153           that too if NULL is not an allowed value for this setting. */
154        if( s->eval && ( ( nv = s->eval( s, value ) ) == SET_INVALID ||
155                         ( ( s->flags & SET_NULL_OK ) == 0 && nv == NULL ) ) )
156                return 0;
157       
158        if( s->value )
159        {
160                g_free( s->value );
161                s->value = NULL;
162        }
163       
164        /* If there's a default setting and it's equal to what we're trying to
165           set, stick with s->value = NULL. Otherwise, remember the setting. */
166        if( !s->def || ( strcmp( nv, s->def ) != 0 ) )
167                s->value = g_strdup( nv );
168       
169        if( nv != value )
170                g_free( nv );
171       
172        return 1;
173}
174
175int set_setint( set_t **head, const char *key, int value )
176{
177        char *s = g_strdup_printf( "%d", value );
178        int retval = set_setstr( head, key, s );
179        g_free( s );
180        return retval;
181}
182
183void set_del( set_t **head, const char *key )
184{
185        set_t *s = *head, *t = NULL;
186       
187        while( s )
188        {
189                if( g_strcasecmp( s->key, key ) == 0 )
190                        break;
191                s = (t=s)->next;
192        }
193        if( s )
194        {
195                if( t )
196                        t->next = s->next;
197                else
198                        *head = s->next;
199               
200                g_free( s->key );
201                g_free( s->old_key );
202                g_free( s->value );
203                g_free( s->def );
204                g_free( s );
205        }
206}
207
208int set_reset( set_t **head, const char *key )
209{
210        set_t *s;
211       
212        s = set_find( head, key );
213        if( s )
214                return set_setstr( head, key, s->def );
215       
216        return 0;
217}
218
219char *set_eval_int( set_t *set, char *value )
220{
221        char *s = value;
222       
223        /* Allow a minus at the first position. */
224        if( *s == '-' )
225                s ++;
226       
227        for( ; *s; s ++ )
228                if( !g_ascii_isdigit( *s ) )
229                        return SET_INVALID;
230       
231        return value;
232}
233
234char *set_eval_bool( set_t *set, char *value )
235{
236        return is_bool( value ) ? value : SET_INVALID;
237}
238
239char *set_eval_list( set_t *set, char *value )
240{
241        GSList *options = set->eval_data, *opt;
242       
243        for( opt = options; opt; opt = opt->next )
244                if( strcmp( value, opt->data ) == 0 )
245                        return value;
246       
247        /* TODO: It'd be nice to show the user a list of allowed values,
248                 but we don't have enough context here to do that. May
249                 want to fix that. */
250       
251        return NULL;
252}
253
254char *set_eval_to_char( set_t *set, char *value )
255{
256        char *s = g_new( char, 3 );
257       
258        if( *value == ' ' )
259                strcpy( s, " " );
260        else
261                sprintf( s, "%c ", *value );
262       
263        return s;
264}
265
266char *set_eval_oauth( set_t *set, char *value )
267{
268        account_t *acc = set->data;
269       
270        if( bool2int( value ) && strcmp( acc->pass, PASSWORD_PENDING ) == 0 )
271                *acc->pass = '\0';
272       
273        return set_eval_bool( set, value );
274}
Note: See TracBrowser for help on using the repository browser.