]> git.llucax.com Git - z.facultad/75.06/emufs.git/blob - gui/form.c
* Mejoro documentacion.
[z.facultad/75.06/emufs.git] / 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  */
15 static t_Widget *widget_input_create(t_Campo tipo, const char *nombre, unsigned int max);
16 /** Crea un nuevo RADIO Group
17  *
18  *  \param tipo Debe ser RADIO
19  *  \param nombre Nombre del campo
20  *  \param max Cantidad de opciones
21  *  \param valores Texto separado con comas con las opciones
22  */
23 static t_Widget *widget_radio_create(t_Campo tipo, const char *nombre, unsigned int max, const char *valores);
24 /** Ejecuta una consulta sobre un INPUT
25  *
26  *  Permite ingresar texto en el INPUT hasta que se presiona ENTER
27  */
28 static int form_input(WINDOW *win, int x, int y, t_Widget *w);
29 /** Ejecuta una consulta sobre un RADIO
30  *
31  *  Permite seleccionar una de las múltiples opciones del control.
32  *  Para seleccionar se utilizan las feclas <- y -> y ENTER
33  *  para aceptar.
34  */
35 static int form_radio(WINDOW *win, int x, int y, t_Widget *w);
36
37 t_Form *form_crear(WINDOW *win)
38 {
39         t_Form *tmp = (t_Form *)malloc(sizeof(t_Form));
40         tmp->primero = tmp->ultimo = NULL;
41         tmp->win = win;
42
43         /* TODO : El error se debe verificar afuera? */
44         return tmp;
45 }
46
47 int form_destruir(t_Form *f)
48 {
49         t_Widget *tmp = f->primero;
50
51         while (tmp) {
52                 f->primero = f->primero->sig;
53                 tmp->destruir(tmp);
54                 tmp = f->primero;
55         }
56         free(f);
57         return 1;
58 }
59
60 void form_agregar_widget(t_Form *f, t_Campo tipo, const char *nombre, unsigned int max, const char *defecto)
61 {
62         t_Widget *tmp = NULL;
63
64         /* Creo el nuevo widget segun el tipo */
65         switch (tipo) {
66                 case INPUT:
67                         tmp = widget_input_create(tipo, nombre, max);
68                 break;
69                 case RADIO:
70                         tmp = widget_radio_create(tipo, nombre, max, defecto);
71         }
72
73         /* Si se creo wl widget, lo agrego al formulario al final */
74         if (tmp) {
75                 if (f->primero == NULL) {
76                         f->primero = f->ultimo = tmp;
77                 } else {
78                         f->ultimo->sig = tmp;
79                         f->ultimo = tmp;
80                 }
81         }
82 }
83
84 void form_ejecutar(t_Form *f, int x, int y)
85 {
86         int offset = 0, my_y, salida;
87         t_Widget *tmp = f->primero;
88         my_y = y-1;
89         /* Pongo las etiquetas de los campos, y me fijo el mayor offset */
90         while (tmp) {
91                 my_y++;
92                 mvwaddstr(f->win, my_y, x, tmp->nombre);
93                 waddch(f->win, ':');
94                 waddch(f->win, ' ');
95                 if (strlen(tmp->nombre) > offset)
96                         offset = strlen(tmp->nombre);
97
98                 tmp = tmp->sig;
99         }
100         /* Agrego el ": " al offset*/
101         x += offset + 2;
102
103         tmp = f->primero;
104         my_y = y-1;
105         while (tmp) {
106                 ++my_y;
107                 wmove(f->win, my_y, x);
108                 salida = tmp->ejecutar(f->win, x, my_y, tmp);
109                 tmp = tmp->sig;
110         }
111 }
112
113 char *form_obtener_valor(t_Form *f, const char *widget)
114 {
115         /* Busco el widget */
116         t_Widget *tmp = f->primero;
117         while (tmp) {
118                 if (strcmp(widget, tmp->nombre) == 0) {
119                         switch (tmp->tipo) {
120                                 case INPUT:
121                                         return tmp->valor;
122                                 case RADIO:
123                                         return tmp->opciones[tmp->actual];
124                         }
125                 }
126                 tmp = tmp->sig;
127         }
128         /* No hay nada. TODO : Retornar NULL? */
129         return "";
130 }
131
132 t_Widget *widget_input_create(t_Campo tipo, const char *nombre, unsigned int max)
133 {
134         t_Widget *tmp = (t_Widget *)malloc(sizeof(t_Widget));
135
136         tmp->tipo = tipo;
137         tmp->nombre = (char *)malloc(sizeof(char)*(strlen(nombre)+1));
138         strcpy(tmp->nombre, nombre);
139
140         tmp->max = max;
141         tmp->valor = (char *)malloc(sizeof(char)*(max+1));
142         tmp->valor[0] = '\0';
143
144         tmp->sig = NULL;
145
146         tmp->ejecutar = form_input;
147         tmp->destruir = widget_free;
148         return tmp;
149 }
150
151 t_Widget *widget_radio_create(t_Campo tipo, const char *nombre, unsigned int max, const char *valores)
152 {
153         int ini, fin, actual;
154         t_Widget *tmp = (t_Widget *)malloc(sizeof(t_Widget));
155
156         tmp->tipo = tipo;
157         tmp->nombre = (char *)malloc(sizeof(char)*(strlen(nombre)+1));
158         strcpy(tmp->nombre, nombre);
159
160         tmp->max = max;
161         tmp->opciones = (char **)malloc(sizeof(char*)*(max));
162         /* Parseo VALOR separado por comas */
163         actual = ini = 0;
164         fin = ini+1;
165         tmp->sig = NULL;
166         while (valores[fin] != '\0') {
167                 if (valores[fin] == ',') {
168                         tmp->opciones[actual] = (char *)malloc(sizeof(char)*(fin-ini+1));
169                         strncpy(tmp->opciones[actual], valores+ini, fin-ini);
170                         tmp->opciones[actual][fin-ini] = '\0';
171                         ini = fin+1;
172                         fin = ini+1;
173                         actual++;
174                 } else {
175                         fin++;
176                 }
177         }
178         /* Me queda el ultimo elemento */
179         tmp->opciones[actual] = (char *)malloc(sizeof(char)*(fin-ini+1));
180         strncpy(tmp->opciones[actual], valores+ini, fin-ini);
181         tmp->opciones[actual][fin-ini] = '\0';
182
183         tmp->ejecutar = form_radio;
184         tmp->destruir = widget_free;
185         return tmp;
186 }
187
188 void widget_free(t_Widget *w)
189 {
190         int i;
191         free(w->nombre);
192         switch (w->tipo) {
193                 case INPUT:
194                         free(w->valor);
195                 break;
196                 case RADIO:
197                         for(i=0; i<w->max; i++)
198                                 free(w->opciones[i]);
199                         free(w->opciones);
200         }
201         free(w);
202 }
203
204 int form_input(WINDOW *win, int x, int y, t_Widget *w)
205 {
206         char *tmp = w->valor;
207         int current = 0, c;
208         mvwaddstr(win, y, x, w->valor);
209
210         while ((*tmp) != '\0') {
211                 tmp++;
212                 current++;
213         }
214
215         while ((c=getch()) != 13) {
216                 /* Verifico si se apreto basckspace */
217                 if (c == KEY_BACKSPACE) {
218                         if (current > 0) {
219                                 w->valor[current--] = '\0';
220                         }
221                         wmove(win, y, x+current);
222                         waddch(win, ' ');
223                         /* Este va para dejar el cursor bien, ya que addch mueve el cursor*/
224                         wmove(win, y, x+current);
225                         continue;
226                 }
227                 /* Si no entra mas, ignoro toda entrada */
228                 if (current >= w->max) continue;
229
230                 wmove(win, y, x+current);
231                 waddch(win, c);
232                 w->valor[current++] = c;
233         }
234         /* Cierro el string con el \0 */
235         w->valor[current+1] = '\0';
236
237         /* Retorno la tecla con la que se salio. */
238         /* De esa forma, ESC pasa al campo anterios. ENTER al siguiente */
239         return c;
240 }
241
242 int form_radio(WINDOW *win, int x, int y, t_Widget *w)
243 {
244         /* Por ahora solo pongo las cosas y me voy */
245         int i, actual, _x, c;
246         /* Array de posiciones para las Xs */
247         int xs[100]; /* TODO : Dinamizar!! */
248
249         curs_set(0);
250         wmove(win, y, x);
251         _x = x;
252         for(i=0; i<w->max; i++) {
253                 waddch(win, '('); _x++;
254                 waddch(win, ' '); xs[i] = _x; _x++;
255                 waddch(win, ')'); _x++;
256                 waddstr(win, w->opciones[i]); _x += strlen(w->opciones[i]);
257                 waddch(win, ' '); _x++;
258         }
259
260         actual = 0;
261         wmove(win, y, xs[actual]);
262         waddch(win, 'X');
263
264         while ((c=getch()) != 13) {
265                 if (c == KEY_LEFT) {
266                         wmove(win, y, xs[actual]);
267                         waddch(win, ' ');       
268                         actual--;
269                         if (actual < 0) actual = 0;
270                         wmove(win, y, xs[actual]);
271                         waddch(win, 'X');       
272                 }
273                 if (c == KEY_RIGHT) {
274                         wmove(win, y, xs[actual]);
275                         waddch(win, ' ');       
276                         actual++;
277                         if (actual >= w->max) actual = w->max-1;
278                         wmove(win, y, xs[actual]);
279                         waddch(win, 'X');       
280                 }
281         }
282
283         w->actual = actual;
284         curs_set(1);
285         return 0;
286 }
287