]> git.llucax.com Git - z.facultad/75.06/emufs.git/blob - emufs_gui/form.c
* BUGFIX : En emufs_destruir habia un bug donde eliminaba mal y se colgaba
[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                 tmp->modificable = 1;
84                 if (f->primero == NULL) {
85                         f->primero = f->ultimo = tmp;
86                 } else {
87                         f->ultimo->sig = tmp;
88                         f->ultimo = tmp;
89                 }
90         }
91 }
92
93 void form_ejecutar(t_Form *f, int x, int y)
94 {
95         int offset = 0, my_y, salida, i;
96         t_Widget *tmp = f->primero;
97         my_y = y-1;
98         
99         /* Calculo cual es la etiqueta más larga de FORM */
100         while (tmp) {
101                 my_y++;
102                 if (strlen(tmp->nombre) > offset)
103                         offset = strlen(tmp->nombre);
104
105                 tmp = tmp->sig;
106         }
107         /* Agrego el ": " al offset*/
108         offset += 2;
109
110         tmp = f->primero;
111         my_y = y-1;
112         /* Agrego el etiqueta y el valor actual para cada elemento */
113         while (tmp) {
114                 ++my_y;
115                 mvwaddstr(f->win, my_y, x, tmp->nombre);
116                 waddch(f->win, ':');
117                 waddch(f->win, ' ');
118                 if (tmp->tipo == INPUT){
119                         for(i=0; i<tmp->max; i++)
120                                 mvwaddch(f->win, my_y, x+offset+i, ' ');
121                         mvwaddstr(f->win, my_y, x+offset, tmp->valor);
122                 } else {
123                         wmove(f->win, my_y, x+offset);
124                         for(i=0; i<tmp->max; i++) {
125                                 waddch(f->win, '(');
126                                 waddch(f->win, ' ');
127                                 waddch(f->win, ')');
128                                 waddstr(f->win, tmp->opciones[i]);
129                                 waddch(f->win, ' ');
130                         }
131                 }
132                 tmp = tmp->sig;
133         }
134         wrefresh(f->win);
135
136         tmp = f->primero;
137         my_y = y-1;
138         /* Ejecuto el formulario */
139         while (tmp) {
140                 ++my_y;
141                 wmove(f->win, my_y, x+offset);
142                 if (tmp->modificable)
143                         salida = tmp->ejecutar(f->win, x+offset, my_y, tmp);
144                 wrefresh(f->win);
145                 tmp = tmp->sig;
146         }
147 }
148
149 int form_obtener_valor_int(t_Form *f, const char *widget)
150 {
151         /* TODO : verificar errores */
152         return atoi(form_obtener_valor_char(f, widget));
153 }
154
155 float form_obtener_valor_float(t_Form *f, const char *widget)
156 {
157         /* TODO : verificar errores */
158         return atof(form_obtener_valor_char(f, widget));
159 }
160
161 char *form_obtener_valor_char(t_Form *f, const char *widget)
162 {
163         /* Busco el widget */
164         t_Widget *tmp = f->primero;
165         while (tmp) {
166                 if (strcmp(widget, tmp->nombre) == 0) {
167                         switch (tmp->tipo) {
168                                 case INPUT:
169                                         return tmp->valor;
170                                 case RADIO:
171                                         return tmp->opciones[tmp->actual];
172                         }
173                 }
174                 tmp = tmp->sig;
175         }
176         /* No hay nada. TODO : Retornar NULL? */
177         return "";
178 }
179
180 t_Widget *widget_input_create(t_Campo tipo, const char *nombre, unsigned int max, const char *defecto)
181 {
182         t_Widget *tmp = (t_Widget *)malloc(sizeof(t_Widget));
183
184         if (tmp == NULL) return NULL;
185
186         tmp->tipo = tipo;
187         tmp->nombre = (char *)malloc(sizeof(char)*(strlen(nombre)+1));
188         if (tmp->nombre == NULL) {
189                 free(tmp);
190                 return NULL;
191         }
192         strcpy(tmp->nombre, nombre);
193
194         tmp->max = max;
195         tmp->valor = (char *)malloc(sizeof(char)*(max+1));
196         if (tmp->valor == NULL) {
197                 free(tmp->nombre);
198                 free(tmp);
199                 return NULL;
200         }
201         tmp->valor[0] = '\0';
202         strcpy(tmp->valor, defecto);
203
204         tmp->sig = NULL;
205
206         tmp->ejecutar = form_input;
207         tmp->destruir = widget_free;
208         return tmp;
209 }
210
211 t_Widget *widget_radio_create(t_Campo tipo, const char *nombre, unsigned int max, const char *valores)
212 {
213         int ini, fin, actual;
214         t_Widget *tmp = (t_Widget *)malloc(sizeof(t_Widget));
215         if (tmp == NULL) {
216                 return NULL;
217         }
218
219         tmp->tipo = tipo;
220         tmp->nombre = (char *)malloc(sizeof(char)*(strlen(nombre)+1));
221         if (tmp->nombre == NULL) {
222                 free(tmp);
223                 return NULL;
224         }
225         strcpy(tmp->nombre, nombre);
226
227         tmp->max = max;
228         tmp->opciones = (char **)malloc(sizeof(char*)*(max));
229         if (tmp->opciones == NULL) {
230                 free(tmp->nombre);
231                 free(tmp);
232                 return NULL;
233         }
234
235         /* Parseo VALOR separado por comas */
236         actual = ini = 0;
237         fin = ini+1;
238         tmp->sig = NULL;
239         while (valores[fin] != '\0') {
240                 if (valores[fin] == ',') {
241                         tmp->opciones[actual] = (char *)malloc(sizeof(char)*(fin-ini+1));
242                         strncpy(tmp->opciones[actual], valores+ini, fin-ini);
243                         tmp->opciones[actual][fin-ini] = '\0';
244                         ini = fin+1;
245                         fin = ini+1;
246                         actual++;
247                 } else {
248                         fin++;
249                 }
250         }
251         /* Me queda el ultimo elemento */
252         tmp->opciones[actual] = (char *)malloc(sizeof(char)*(fin-ini+1));
253         strncpy(tmp->opciones[actual], valores+ini, fin-ini);
254         tmp->opciones[actual][fin-ini] = '\0';
255
256         tmp->ejecutar = form_radio;
257         tmp->destruir = widget_free;
258         return tmp;
259 }
260
261 void widget_free(t_Widget *w)
262 {
263         int i;
264         if (w == NULL) return ;
265
266         free(w->nombre);
267         switch (w->tipo) {
268                 case INPUT:
269                         free(w->valor);
270                 break;
271                 case RADIO:
272                         for(i=0; i<w->max; i++)
273                                 free(w->opciones[i]);
274                         free(w->opciones);
275         }
276         free(w);
277 }
278
279 int form_input(WINDOW *win, int x, int y, t_Widget *w)
280 {
281         char *tmp = w->valor;
282         int current = 0, c;
283         mvwaddstr(win, y, x, w->valor);
284         curs_set(1);
285         while ((*tmp) != '\0') {
286                 tmp++;
287                 current++;
288         }
289
290         wrefresh(win);
291         c = getch();
292         while ((c != KEY_ENTER) && (c != 13)) {
293                 /* Verifico si se apreto basckspace */
294                 if (c == KEY_BACKSPACE) {
295                         if (current > 0) {
296                                 w->valor[current--] = '\0';
297                         }
298                         wmove(win, y, x+current);
299                         waddch(win, ' ');
300                         /* Este va para dejar el cursor bien, ya que addch mueve el cursor*/
301                         wmove(win, y, x+current);
302                         wrefresh(win);
303                         c = getch();
304                         continue;
305                 }
306                 /* Si no entra mas, ignoro toda entrada */
307                 if (current >= w->max) {
308                         c = getch();
309                         continue;
310                 }
311                 
312                 wmove(win, y, x+current);
313                 waddch(win, c);
314                 w->valor[current++] = c;
315                 wrefresh(win);
316                 c = getch();
317         }
318         /* Cierro el string con el \0 */
319         w->valor[current] = '\0';
320         /* Retorno la tecla con la que se salio. */
321         /* De esa forma, ESC pasa al campo anterios. ENTER al siguiente */
322         return c;
323 }
324
325 int form_radio(WINDOW *win, int x, int y, t_Widget *w)
326 {
327         /* Por ahora solo pongo las cosas y me voy */
328         int i, actual, _x, c;
329         /* Array de posiciones para las Xs */
330         int xs[100]; /* TODO : Dinamizar!! */
331
332         curs_set(0);
333         wmove(win, y, x);
334         _x = x;
335         for(i=0; i<w->max; i++) {
336                 waddch(win, '('); _x++;
337                 waddch(win, ' '); xs[i] = _x; _x++;
338                 waddch(win, ')'); _x++;
339                 waddstr(win, w->opciones[i]); _x += strlen(w->opciones[i]);
340                 waddch(win, ' '); _x++;
341         }
342
343         actual = 0;
344         wmove(win, y, xs[actual]);
345         waddch(win, 'X');
346
347         wrefresh(win);
348         while ((c=getch()) != 13) {
349                 if (c == KEY_LEFT) {
350                         wmove(win, y, xs[actual]);
351                         waddch(win, ' ');       
352                         actual--;
353                         if (actual < 0) actual = 0;
354                         wmove(win, y, xs[actual]);
355                         waddch(win, 'X');       
356                 }
357                 if (c == KEY_RIGHT) {
358                         wmove(win, y, xs[actual]);
359                         waddch(win, ' ');       
360                         actual++;
361                         if (actual >= w->max) actual = w->max-1;
362                         wmove(win, y, xs[actual]);
363                         waddch(win, 'X');       
364                 }
365                 wrefresh(win);
366         }
367
368         w->actual = actual;
369         curs_set(1);
370         return 0;
371 }
372
373 void form_es_modificable(t_Form *f, const char *widget, int b)
374 {
375         /* Busco el widget */
376         t_Widget *tmp = f->primero;
377         while (tmp) {
378                 if (strcmp(widget, tmp->nombre) == 0) {
379                         tmp->modificable = b;
380                         break;
381                 }
382                 tmp = tmp->sig;
383         }
384 }
385
386 void form_set_valor(t_Form *f, const char *widget, const char *s)
387 {
388         /* Busco el widget */
389         t_Widget *tmp = f->primero;
390         while (tmp) {
391                 if (strcmp(widget, tmp->nombre) == 0) {
392                         strcpy(tmp->valor, s);
393                         break;
394                 }
395                 tmp = tmp->sig;
396         }
397 }
398