]> git.llucax.com Git - z.facultad/75.06/emufs.git/blob - emufs_gui/form.c
BUGFIX : en crear_input_widget habia un bug que hacia que se metiera basura
[z.facultad/75.06/emufs.git] / emufs_gui / form.c
1
2 #include "form.h"
3
4 /** Libera la memoria ocupada por un widget
5  *
6  *  \param w Widget a liberar
7  */
8 static void widget_free(t_Widget *w);
9 /** Crea un nuevo campo de entrada de texto
10  *
11  *  \param tipo Debe ser INPUT
12  *  \param nombre Nombre del control (también usada como etiqueta).
13  *  \param max Cantidad máxima de caracteres.
14  *  \param defecto Valor inicial del campo.
15  */
16 static t_Widget *widget_input_create(t_Campo tipo, const char *nombre, unsigned int max, const char *defecto);
17 /** Crea un nuevo RADIO Group
18  *
19  *  \param tipo Debe ser RADIO
20  *  \param nombre Nombre del campo
21  *  \param max Cantidad de opciones
22  *  \param valores Texto separado con comas con las opciones
23  */
24 static t_Widget *widget_radio_create(t_Campo tipo, const char *nombre, unsigned int max, const char *valores);
25 /** Ejecuta una consulta sobre un INPUT
26  *
27  *  Permite ingresar texto en el INPUT hasta que se presiona ENTER
28  */
29 static int form_input(WINDOW *win, int x, int y, t_Widget *w);
30 /** Ejecuta una consulta sobre un RADIO
31  *
32  *  Permite seleccionar una de las múltiples opciones del control.
33  *  Para seleccionar se utilizan las feclas <- y -> y ENTER
34  *  para aceptar.
35  */
36 static int form_radio(WINDOW *win, int x, int y, t_Widget *w);
37
38 t_Form *form_crear(WINDOW *win)
39 {
40         t_Form *tmp = (t_Form *)malloc(sizeof(t_Form));
41         if (tmp == NULL) {
42                 return NULL;
43         }
44         tmp->primero = tmp->ultimo = NULL;
45         tmp->win = win;
46
47         return tmp;
48 }
49
50 int form_destruir(t_Form *f)
51 {
52         t_Widget *tmp;
53         if (f == NULL) return 0;
54
55         tmp = f->primero;
56
57         while (tmp) {
58                 f->primero = f->primero->sig;
59                 tmp->destruir(tmp);
60                 tmp = f->primero;
61         }
62         free(f);
63         return 1;
64 }
65
66 void form_agregar_widget(t_Form *f, t_Campo tipo, const char *nombre, unsigned int max, const char *defecto)
67 {
68         t_Widget *tmp = NULL;
69
70         if (f == NULL) return;
71
72         /* Creo el nuevo widget segun el tipo */
73         switch (tipo) {
74                 case INPUT:
75                         tmp = widget_input_create(tipo, nombre, max, defecto);
76                 break;
77                 case RADIO:
78                         tmp = widget_radio_create(tipo, nombre, max, defecto);
79         }
80
81         /* Si se creo wl widget, lo agrego al formulario al final */
82         if (tmp) {
83                 if (f->primero == NULL) {
84                         f->primero = f->ultimo = tmp;
85                 } else {
86                         f->ultimo->sig = tmp;
87                         f->ultimo = tmp;
88                 }
89         }
90 }
91
92 void form_ejecutar(t_Form *f, int x, int y)
93 {
94         int offset = 0, my_y, salida;
95         t_Widget *tmp = f->primero;
96         my_y = y-1;
97         
98         /* Calculo cual es la etiqueta más larga de FORM */
99         while (tmp) {
100                 my_y++;
101                 if (strlen(tmp->nombre) > offset)
102                         offset = strlen(tmp->nombre);
103
104                 tmp = tmp->sig;
105         }
106         /* Agrego el ": " al offset*/
107         offset += 2;
108
109         tmp = f->primero;
110         my_y = y-1;
111         /* Agrego el etiqueta y el valor actual para cada elemento */
112         while (tmp) {
113                 ++my_y;
114                 mvwaddstr(f->win, my_y, x, tmp->nombre);
115                 waddch(f->win, ':');
116                 waddch(f->win, ' ');
117                 /* TODO : VER QUE SI ES UNA OPCION ES DISTINTO!! */
118                 mvwaddstr(f->win, my_y, x+offset, tmp->valor);
119                 tmp = tmp->sig;
120         }
121         wrefresh(f->win);
122
123         tmp = f->primero;
124         my_y = y-1;
125         /* Ejecuto el formulario */
126         while (tmp) {
127                 ++my_y;
128                 wmove(f->win, my_y, x+offset);
129                 salida = tmp->ejecutar(f->win, x+offset, my_y, tmp);
130                 wrefresh(f->win);
131                 tmp = tmp->sig;
132         }
133 }
134
135 int form_obtener_valor_int(t_Form *f, const char *widget)
136 {
137         /* TODO : verificar errores */
138         return atoi(form_obtener_valor_char(f, widget));
139 }
140
141 float form_obtener_valor_float(t_Form *f, const char *widget)
142 {
143         /* TODO : verificar errores */
144         return atof(form_obtener_valor_char(f, widget));
145 }
146
147 char *form_obtener_valor_char(t_Form *f, const char *widget)
148 {
149         /* Busco el widget */
150         t_Widget *tmp = f->primero;
151         while (tmp) {
152                 if (strcmp(widget, tmp->nombre) == 0) {
153                         switch (tmp->tipo) {
154                                 case INPUT:
155                                         return tmp->valor;
156                                 case RADIO:
157                                         return tmp->opciones[tmp->actual];
158                         }
159                 }
160                 tmp = tmp->sig;
161         }
162         /* No hay nada. TODO : Retornar NULL? */
163         return "";
164 }
165
166 t_Widget *widget_input_create(t_Campo tipo, const char *nombre, unsigned int max, const char *defecto)
167 {
168         t_Widget *tmp = (t_Widget *)malloc(sizeof(t_Widget));
169
170         if (tmp == NULL) return NULL;
171
172         tmp->tipo = tipo;
173         tmp->nombre = (char *)malloc(sizeof(char)*(strlen(nombre)+1));
174         if (tmp->nombre == NULL) {
175                 free(tmp);
176                 return NULL;
177         }
178         strcpy(tmp->nombre, nombre);
179
180         tmp->max = max;
181         tmp->valor = (char *)malloc(sizeof(char)*(max+1));
182         if (tmp->valor == NULL) {
183                 free(tmp->nombre);
184                 free(tmp);
185                 return NULL;
186         }
187         tmp->valor[0] = '\0';
188         strcpy(tmp->valor, defecto);
189
190         tmp->sig = NULL;
191
192         tmp->ejecutar = form_input;
193         tmp->destruir = widget_free;
194         return tmp;
195 }
196
197 t_Widget *widget_radio_create(t_Campo tipo, const char *nombre, unsigned int max, const char *valores)
198 {
199         int ini, fin, actual;
200         t_Widget *tmp = (t_Widget *)malloc(sizeof(t_Widget));
201         if (tmp == NULL) {
202                 return NULL;
203         }
204
205         tmp->tipo = tipo;
206         tmp->nombre = (char *)malloc(sizeof(char)*(strlen(nombre)+1));
207         if (tmp->nombre == NULL) {
208                 free(tmp);
209                 return NULL;
210         }
211         strcpy(tmp->nombre, nombre);
212
213         tmp->max = max;
214         tmp->opciones = (char **)malloc(sizeof(char*)*(max));
215         if (tmp->opciones == NULL) {
216                 free(tmp->nombre);
217                 free(tmp);
218                 return NULL;
219         }
220
221         /* Parseo VALOR separado por comas */
222         actual = ini = 0;
223         fin = ini+1;
224         tmp->sig = NULL;
225         while (valores[fin] != '\0') {
226                 if (valores[fin] == ',') {
227                         tmp->opciones[actual] = (char *)malloc(sizeof(char)*(fin-ini+1));
228                         strncpy(tmp->opciones[actual], valores+ini, fin-ini);
229                         tmp->opciones[actual][fin-ini] = '\0';
230                         ini = fin+1;
231                         fin = ini+1;
232                         actual++;
233                 } else {
234                         fin++;
235                 }
236         }
237         /* Me queda el ultimo elemento */
238         tmp->opciones[actual] = (char *)malloc(sizeof(char)*(fin-ini+1));
239         strncpy(tmp->opciones[actual], valores+ini, fin-ini);
240         tmp->opciones[actual][fin-ini] = '\0';
241
242         tmp->ejecutar = form_radio;
243         tmp->destruir = widget_free;
244         return tmp;
245 }
246
247 void widget_free(t_Widget *w)
248 {
249         int i;
250         if (w == NULL) return ;
251
252         free(w->nombre);
253         switch (w->tipo) {
254                 case INPUT:
255                         free(w->valor);
256                 break;
257                 case RADIO:
258                         for(i=0; i<w->max; i++)
259                                 free(w->opciones[i]);
260                         free(w->opciones);
261         }
262         free(w);
263 }
264
265 int form_input(WINDOW *win, int x, int y, t_Widget *w)
266 {
267         char *tmp = w->valor;
268         int current = 0, c;
269         mvwaddstr(win, y, x, w->valor);
270         curs_set(1);
271         while ((*tmp) != '\0') {
272                 tmp++;
273                 current++;
274         }
275
276         wrefresh(win);
277         c = getch();
278         while ((c != KEY_ENTER) && (c != 13)) {
279                 /* Verifico si se apreto basckspace */
280                 if (c == KEY_BACKSPACE) {
281                         if (current > 0) {
282                                 w->valor[current--] = '\0';
283                         }
284                         wmove(win, y, x+current);
285                         waddch(win, ' ');
286                         /* Este va para dejar el cursor bien, ya que addch mueve el cursor*/
287                         wmove(win, y, x+current);
288                         wrefresh(win);
289                         c = getch();
290                         continue;
291                 }
292                 /* Si no entra mas, ignoro toda entrada */
293                 if (current >= w->max) {
294                         c = getch();
295                         continue;
296                 }
297                 
298                 wmove(win, y, x+current);
299                 waddch(win, c);
300                 w->valor[current++] = c;
301                 wrefresh(win);
302                 c = getch();
303         }
304         /* Cierro el string con el \0 */
305         w->valor[current] = '\0';
306         /* Retorno la tecla con la que se salio. */
307         /* De esa forma, ESC pasa al campo anterios. ENTER al siguiente */
308         return c;
309 }
310
311 int form_radio(WINDOW *win, int x, int y, t_Widget *w)
312 {
313         /* Por ahora solo pongo las cosas y me voy */
314         int i, actual, _x, c;
315         /* Array de posiciones para las Xs */
316         int xs[100]; /* TODO : Dinamizar!! */
317
318         curs_set(0);
319         wmove(win, y, x);
320         _x = x;
321         for(i=0; i<w->max; i++) {
322                 waddch(win, '('); _x++;
323                 waddch(win, ' '); xs[i] = _x; _x++;
324                 waddch(win, ')'); _x++;
325                 waddstr(win, w->opciones[i]); _x += strlen(w->opciones[i]);
326                 waddch(win, ' '); _x++;
327         }
328
329         actual = 0;
330         wmove(win, y, xs[actual]);
331         waddch(win, 'X');
332
333         wrefresh(win);
334         while ((c=getch()) != 13) {
335                 if (c == KEY_LEFT) {
336                         wmove(win, y, xs[actual]);
337                         waddch(win, ' ');       
338                         actual--;
339                         if (actual < 0) actual = 0;
340                         wmove(win, y, xs[actual]);
341                         waddch(win, 'X');       
342                 }
343                 if (c == KEY_RIGHT) {
344                         wmove(win, y, xs[actual]);
345                         waddch(win, ' ');       
346                         actual++;
347                         if (actual >= w->max) actual = w->max-1;
348                         wmove(win, y, xs[actual]);
349                         waddch(win, 'X');       
350                 }
351                 wrefresh(win);
352         }
353
354         w->actual = actual;
355         curs_set(1);
356         return 0;
357 }
358