Bugfix #4627: headerResize() was overflowing a string parameter and
[blender.git] / source / blender / src / transform_numinput.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version. The Blender
10  * Foundation also sells licenses for use in proprietary software under
11  * the Blender License.  See http://www.blender.org/BL/ for information
12  * about this.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software Foundation,
21  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22  *
23  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
24  * All rights reserved.
25  *
26  * The Original Code is: all of this file.
27  *
28  * Contributor(s): none yet.
29  *
30  * ***** END GPL/BL DUAL LICENSE BLOCK *****
31  */
32
33 #include <math.h>                       /* fabs */
34 #include <stdio.h>                      /* for sprintf          */
35
36 #include "BKE_global.h"         /* for G                        */
37 #include "BKE_utildefines.h"    /* ABS */
38
39 #include "mydevice.h"           /* for KEY defines      */
40
41 #include "transform.h"
42
43 /* ************************** Functions *************************** */
44
45 /* ************************** NUMINPUT **************************** */
46
47 void outputNumInput(NumInput *n, char *str)
48 {
49         char cur;
50         short i, j;
51
52         for (j=0; j<=n->idx_max; j++) {
53                 /* if AFFECTALL and no number typed and cursor not on number, use first number */
54                 if (n->flag & NUM_AFFECT_ALL && n->idx != j && n->ctrl[j] == 0)
55                         i = 0;
56                 else
57                         i = j;
58
59                 if (n->idx != i)
60                         cur = ' ';
61                 else
62                         cur = '|';
63
64                 if( n->val[i] > 1e10 || n->val[i] < -1e10 )
65                         sprintf(&str[j*20], "%.4e%c", n->val[i], cur);
66                 else
67                         switch (n->ctrl[i]) {
68                         case 0:
69                                 sprintf(&str[j*20], "NONE%c", cur);
70                                 break;
71                         case 1:
72                         case -1:
73                                 sprintf(&str[j*20], "%.0f%c", n->val[i], cur);
74                                 break;
75                         case 10:
76                         case -10:
77                                 sprintf(&str[j*20], "%.f.%c", n->val[i], cur);
78                                 break;
79                         case 100:
80                         case -100:
81                                 sprintf(&str[j*20], "%.1f%c", n->val[i], cur);
82                                 break;
83                         case 1000:
84                         case -1000:
85                                 sprintf(&str[j*20], "%.2f%c", n->val[i], cur);
86                                 break;
87                         case 10000:
88                         case -10000:
89                                 sprintf(&str[j*20], "%.3f%c", n->val[i], cur);
90                                 break;
91                         default:
92                                 sprintf(&str[j*20], "%.4e%c", n->val[i], cur);
93                         }
94         }
95 }
96
97 short hasNumInput(NumInput *n)
98 {
99         short i;
100
101         for (i=0; i<=n->idx_max; i++) {
102                 if (n->ctrl[i])
103                         return 1;
104         }
105
106         return 0;
107 }
108
109 void applyNumInput(NumInput *n, float *vec)
110 {
111         short i, j;
112         float val[3];
113
114         if (hasNumInput(n)) {
115                 convertDisplayNumToVec(n->val, val);
116
117                 for (j=0; j<=n->idx_max; j++) {
118                         /* if AFFECTALL and no number typed and cursor not on number, use first number */
119                         if (n->flag & NUM_AFFECT_ALL && n->idx != j && n->ctrl[j] == 0)
120                                 i = 0;
121                         else
122                                 i = j;
123
124                         if (n->ctrl[i] == 0 && n->flag & NUM_NULL_ONE) {
125                                 vec[j] = 1.0f;
126                         }
127                         else if (val[i] == 0.0f && n->flag & NUM_NO_ZERO) {
128                                 vec[j] = 0.0001f;
129                         }
130                         else {
131                                 vec[j] = val[i];
132                         }
133                 }
134         }
135 }
136
137 char handleNumInput(NumInput *n, unsigned short event)
138 {
139         float Val = 0;
140         short idx = n->idx, idx_max = n->idx_max;
141
142         switch (event) {
143         case BACKSPACEKEY:
144                 if (n->ctrl[idx] == 0) {
145                         n->val[0]               = 
146                                 n->val[1]       = 
147                                 n->val[2]       = 0.0f;
148                         n->ctrl[0]              = 
149                                 n->ctrl[1]      = 
150                                 n->ctrl[2]      = 0;
151                 }
152                 else {
153                         n->val[idx] = 0.0f;
154                         n->ctrl[idx] = 0;
155                 }
156                 break;
157         case PERIODKEY:
158         case PADPERIOD:
159                 if (n->flag & NUM_NO_FRACTION)
160                         break;
161
162                 switch (n->ctrl[idx])
163                 {
164                 case 0:
165                 case 1:
166                         n->ctrl[idx] = 10;
167                         break;
168                 case -1:
169                         n->ctrl[idx] = -10;
170                 }
171                 break;
172         case PADMINUS:
173                 if(G.qual & LR_ALTKEY)
174                         break;
175         case MINUSKEY:
176                 if (n->flag & NUM_NO_NEGATIVE)
177                         break;
178
179                 if (n->ctrl[idx]) {
180                         n->ctrl[idx] *= -1;
181                         n->val[idx] *= -1;
182                 }
183                 else
184                         n->ctrl[idx] = -1;
185                 break;
186         case TABKEY:
187                 idx++;
188                 if (idx > idx_max)
189                         idx = 0;
190                 n->idx = idx;
191                 break;
192         case PAD9:
193         case NINEKEY:
194                 Val += 1.0f;
195         case PAD8:
196         case EIGHTKEY:
197                 Val += 1.0f;
198         case PAD7:
199         case SEVENKEY:
200                 Val += 1.0f;
201         case PAD6:
202         case SIXKEY:
203                 Val += 1.0f;
204         case PAD5:
205         case FIVEKEY:
206                 Val += 1.0f;
207         case PAD4:
208         case FOURKEY:
209                 Val += 1.0f;
210         case PAD3:
211         case THREEKEY:
212                 Val += 1.0f;
213         case PAD2:
214         case TWOKEY:
215                 Val += 1.0f;
216         case PAD1:
217         case ONEKEY:
218                 Val += 1.0f;
219         case PAD0:
220         case ZEROKEY:
221                 if (!n->ctrl[idx])
222                         n->ctrl[idx] = 1;
223
224                 if (fabs(n->val[idx]) > 9999999.0f);
225                 else if (n->ctrl[idx] == 1) {
226                         n->val[idx] *= 10;
227                         n->val[idx] += Val;
228                 }
229                 else if (n->ctrl[idx] == -1) {
230                         n->val[idx] *= 10;
231                         n->val[idx] -= Val;
232                 }
233                 else {
234                         /* float resolution breaks when over six digits after comma */
235                         if( ABS(n->ctrl[idx]) < 10000000) {
236                                 n->val[idx] += Val / (float)n->ctrl[idx];
237                                 n->ctrl[idx] *= 10;
238                         }
239                 }
240                 break;
241         default:
242                 return 0;
243         }
244         
245         /* REDRAW SINCE NUMBERS HAVE CHANGED */
246         return 1;
247 }