1 /***************************************************************************
2                           value.c  -  description
3                              -------------------
4     begin                : Sun Sep 23 2001
5     copyright            : (C) 2001 by Michael Speck
6     email                : kulkanie@gmx.net
7  ***************************************************************************/
8 
9 /***************************************************************************
10  *                                                                         *
11  *   This program is free software; you can redistribute it and/or modify  *
12  *   it under the terms of the GNU General Public License as published by  *
13  *   the Free Software Foundation; either version 2 of the License, or     *
14  *   (at your option) any later version.                                   *
15  *                                                                         *
16  ***************************************************************************/
17 
18 #include <ctype.h>
19 #include "manager.h"
20 
21 /*
22 ====================================================================
23 Locals
24 ====================================================================
25 */
26 
27 /*
28 ====================================================================
29 Update val_str if not ITEM_VALUE
30 ====================================================================
31 */
value_update_str(Value * value)32 void value_update_str( Value *value )
33 {
34     switch ( value->type ) {
35         case VALUE_RANGE_INT: sprintf( value->val_str, "%i", *value->val_int ); break;
36         case VALUE_RANGE_STR: sprintf( value->val_str, "%s", value->names[*value->val_int] ); break;
37         case VALUE_KEY:
38             if ( value->grab ) { strcpy( value->val_str, "???" ); break; }
39             switch ( *value->val_int ) {
40                 case SDLK_SPACE: strcpy( value->val_str, _("Space") ); break;
41                 case SDLK_LEFT: strcpy( value->val_str, _("Left") ); break;
42                 case SDLK_RIGHT: strcpy( value->val_str, _("Right") ); break;
43                 case SDLK_UP: strcpy( value->val_str, _("Up") ); break;
44                 case SDLK_DOWN: strcpy( value->val_str, _("Down") ); break;
45                 case SDLK_RSHIFT: strcpy( value->val_str, _("Right Shift") ); break;
46                 case SDLK_LSHIFT: strcpy( value->val_str, _("Left Shift") ); break;
47                 case SDLK_RCTRL: strcpy( value->val_str, _("Right Ctrl") ); break;
48                 case SDLK_LCTRL: strcpy( value->val_str, _("Left Ctrl") ); break;
49                 case SDLK_RALT: strcpy( value->val_str, _("Right Alt") ); break;
50                 case SDLK_LALT: strcpy( value->val_str, _("Left Alt") ); break;
51                 case SDLK_BACKSPACE: strcpy( value->val_str, _("BackSpace") ); break;
52                 default:
53                     if ( *value->val_int >= SDLK_a && *value->val_int <= SDLK_z )
54                         sprintf( value->val_str, "'%c'", (char)toupper( *value->val_int ) );
55                     else
56                         sprintf( value->val_str, "%i", *value->val_int );
57                     break;
58             }
59             break;
60     }
61 }
62 
63 /*
64 ====================================================================
65 Create basic value
66 ====================================================================
67 */
value_create_basic(int type,int * val_int)68 Value *value_create_basic( int type, int *val_int )
69 {
70     Value *value = calloc( 1, sizeof( Value ) );
71     value->type = type;
72     value->val_int = val_int;
73     /* if not VALUE_EDIT create val_str which carries translated val_int */
74     if ( type != VALUE_EDIT ) value->val_str = calloc( 256, sizeof( char ) );
75     return value;
76 }
77 
78 /*
79 ====================================================================
80 Publics
81 ====================================================================
82 */
83 
84 /*
85 ====================================================================
86 Auxiliary functions to setup a key filter.
87 ====================================================================
88 */
filter_clear(int * filter)89 void filter_clear( int *filter )
90 {
91     memset( filter, 0, sizeof( int ) * SDLK_LAST );
92 }
filter_set(int * filter,int first,int last,int allowed)93 void filter_set( int *filter, int first, int last, int allowed )
94 {
95     int i;
96     for ( i = first; i <= last; i++ )
97         filter[i] = allowed;
98 }
99 
100 /*
101 ====================================================================
102 Create a value. names and filter are duplicated and freed by
103 value_delete().
104 Return Value: value
105 ====================================================================
106 */
value_create_empty()107 Value *value_create_empty()
108 {
109     return value_create_basic( VALUE_NONE, 0 );
110 }
value_create_range_int(int * val_int,int min,int max,int step)111 Value *value_create_range_int( int *val_int, int min, int max, int step )
112 {
113     Value *value = value_create_basic( VALUE_RANGE_INT, val_int );
114     value->min = min; value->max = max; value->step = step;
115     value_update_str( value );
116     return value;
117 }
value_create_range_str(int * val_int,char ** names,int count)118 Value *value_create_range_str( int *val_int, char **names, int count )
119 {
120     int i;
121     Value *value = value_create_basic( VALUE_RANGE_STR, val_int );
122     value->min = 0; value->max = count - 1; value->step = 1;
123     /* duplicate names */
124     value->name_count = count;
125     value->names = calloc( count, sizeof( char* ) );
126     for ( i = 0; i < count; i++ )
127         value->names[i] = strdup( names[i] );
128     value_update_str( value );
129     return value;
130 }
value_create_key(int * val_int,int * filter)131 Value *value_create_key( int *val_int, int *filter )
132 {
133     int i;
134     Value *value = value_create_basic( VALUE_KEY, val_int );
135     /* duplicate filter */
136     value->filter = calloc( SDLK_LAST, sizeof( int ) );
137     for ( i = 0; i < SDLK_LAST; i++ ) value->filter[i] = filter[i];
138     value_update_str( value );
139     /* list of other key values */
140     value->other_keys = list_create( LIST_NO_AUTO_DELETE, LIST_NO_CALLBACK );
141     return value;
142 }
value_create_edit(char * val_str,int limit)143 Value *value_create_edit( char *val_str, int limit )
144 {
145     Value *value = value_create_basic( VALUE_EDIT, 0 );
146     value->val_str = val_str;
147     value->max = limit;
148     return value;
149 }
150 /*
151 ====================================================================
152 Delete a value
153 ====================================================================
154 */
value_delete(Value * value)155 void value_delete( Value *value )
156 {
157     int i;
158     if ( !value ) return;
159     if ( value->filter ) free( value->filter );
160     if ( value->names ) {
161         for ( i = 0; i < value->name_count; i++ )
162             if ( value->names[i] ) free( value->names[i] );
163         free( value->names );
164     }
165     if ( value->type != VALUE_EDIT && value->val_str ) free( value->val_str );
166     if ( value->other_keys ) list_delete( value->other_keys );
167     free( value );
168 }
169 /*
170 ====================================================================
171 Increase, decrease if range.
172 ====================================================================
173 */
value_dec(Value * value)174 void value_dec( Value *value )
175 {
176     *value->val_int -= value->step;
177     if ( *value->val_int < value->min ) *value->val_int = value->max;
178     value_update_str( value );
179 }
value_inc(Value * value)180 void value_inc( Value *value )
181 {
182     *value->val_int += value->step;
183     if ( *value->val_int > value->max ) *value->val_int = value->min;
184     value_update_str( value );
185 }
186 /*
187 ====================================================================
188 Grab input of VALUE_KEY
189 ====================================================================
190 */
value_grab(Value * value)191 void value_grab( Value *value )
192 {
193     if ( value->type == VALUE_KEY ) {
194         value->grab = 1;
195         value_update_str( value );
196     }
197 }
198 /*
199 ====================================================================
200 Set key value if VALUE_KEY and clear grab flag
201 ====================================================================
202 */
value_set_key(Value * value,int val_int)203 void value_set_key( Value *value, int val_int )
204 {
205     Value *other_key;
206     if ( !value->filter[val_int] ) return;
207     list_reset( value->other_keys );
208     while ( ( other_key = list_next( value->other_keys ) ) )
209         if ( *other_key->val_int == val_int ) return;
210     /* ok, set */
211     *value->val_int = val_int;
212     value->grab = 0;
213     value_update_str( value );
214 }
215 /*
216 ====================================================================
217 Edit string if VALUE_EDIT
218 ====================================================================
219 */
value_edit(Value * value,int code,int unicode)220 void value_edit( Value *value, int code, int unicode )
221 {
222     int length = strlen( value->val_str );
223 	if ( code == SDLK_BACKSPACE && length > 0 )
224 		value->val_str[length - 1] = 0;
225 	else
226 		if ( unicode >= 32 && unicode < 128 && length < value->max )
227 			value->val_str[length] = unicode;
228 }
229 /*
230 ====================================================================
231 Add another dynamically restricted key (as VALUE_KEY) to other_key
232 list.
233 ====================================================================
234 */
value_add_other_key(Value * value,Value * other_key)235 void value_add_other_key( Value *value, Value *other_key )
236 {
237     if ( value->type != VALUE_KEY ) return;
238     list_add( value->other_keys, other_key );
239 }
240 /*
241 ====================================================================
242 Set a new name list (and update position) for VALUE_RANGE_STR.
243 ====================================================================
244 */
value_set_new_names(Value * value,char ** names,int count)245 void value_set_new_names( Value *value, char **names, int count )
246 {
247     int i;
248     if ( value->type != VALUE_RANGE_STR ) return;
249     if ( value->names ) {
250         for ( i = 0; i < value->name_count; i++ )
251             if ( value->names[i] ) free( value->names[i] );
252         free( value->names );
253     }
254     value->name_count = count;
255     value->max = count - 1;
256     if ( *value->val_int > value->max ) *value->val_int = 0;
257     value->names = calloc( count, sizeof( char* ) );
258     for ( i = 0; i < count; i++ )
259         value->names[i] = strdup( names[i] );
260     value_update_str( value );
261 }
262