Copy Link
Add to Bookmark
Report
SET 031 0x0C
-[ 0x0C ]--------------------------------------------------------------------
-[ NCURSES ]-----------------------------------------------------------------
-[ by blackngel ]----------------------------------------------------SET-31--
@ @
@@@ blackngel_hack@hotmail.com @@@
IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
III @@@@ @ @@@@@ @@@@@ @ @ @@ @ @@@@@ @@@@@ @ III
III @ @ @ @ @ @ @ @ @ @ @ @ @ @ III
III @@@@@ @ @@@@@ @ @@@ @ @ @ @ @@@ @@@@ @ III
III @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ III
III @@@@ @@@@@ @ @ @@@@@ @ @ @ @@ @@@@@ @@@@@ @@@@@ III
IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
@@@ @@@
@ @
%%%%%%%%%%%%%%%%%%%%&%%%
%%%==================%%%
%%% NCURSES 1ª PARTE %%%
%%%==================%%%
%%%%%%%%%%%%%%%%%%%%%&%%
"Bienvenidos al mundo de lo real..."
_*#*__*#*__*#*__*#*__*#*_
_*#*_ 00. INDICE _*#*_
_*#*__*#*__*#*__*#*__*#*_
*_#_**_#_**_#_**_#_**_#_**_#_**_#_**_#_*
*_#_* 00 - INDICE *_#_*
*_#_*______________________________*_#_*
*_#_* 01 - PROLOGO *_#_*
*_#_*______________________________*_#_*
*_#_* 02 - INTRODUCCION *_#_*
*_#_*______________________________*_#_*
*_#_* 03 - COMPILACION *_#_*
*_#_*______________________________*_#_*
*_#_* 04 - CONCEPTOS BASICOS *_#_*
*_#_*______________________________*_#_*
*_#_* 05 - VENTANAS *_#_*
*_#_*______________________________*_#_*
*_#_* 06 - PANELES *_#_*
*_#_*______________________________*_#_*
*_#_* 07 - MENUS *_#_*
*_#_*______________________________*_#_*
*_#_* 08 - PROGRAMA EJEMPLO *_#_*
*_#_*______________________________*_#_*
*_#_* 09 - DESPEDIDA *_#_*
*_#_**_#_**_#_**_#_**_#_**_#_**_#_**_#_*
_*#*__*#*__*#*__*#*__*#*_
_*#*_ 01. PROLOGO _*#*_
_*#*__*#*__*#*__*#*__*#*_
Con ganas de trabajar un poco y a cuento de aprender un poco mas,
aqui estoy otra vez, con un nuevo articulo que no hara mas feliz al
lector pero si a su escritor (deseo equivocarme).
Pregunta mas obvia: porque NCURSES?
Pues bien, sinceramente, no soy muy amigo de hacer aplicaciones con
GUI's (Interfaces Graficas de Usuario), no obstante, cada vez que
programo alguna pequeña utilidad a la vieja usanza, se me queda el
gusanillo de porque esta no puede ser mas facil de controlar y a la
vez mas atractiva al usuario. Desde luego, navegar con las flechas
del teclado por un menu es mucho mas comodo que una lista de opciones
de la que tienes que escribir el numero de la que deseas escojer.
Hace tiempo que escuche hablar de ncurses, pero quizas por las vagas
introducciones que he leido en revistas o quizas por mi costumbre de
hacer las cosas como en el siglo XV, no me habia parado a investigar
mas.
Todo ha cambiado, he decidido ponerme las pilas y he encontrado
informacion no poco valiosa. Un poco enamorado de ncurses? porque
negarlo, cuando programas algo y los resultados son satisfactorios,
la recompensa moral es indescriptible.
Intentare hacer esto lo mas ameno e inteligible que pueda para el lector,
sin dejar a un lado los detalles tecnicos e invitar al programador no
solo a programar sino a entender y amar su codigo.
Puede que yo no tenga todas las respuestas pero, sin duda alguna,
internet es la fuente de informacion mas poderosa, como siempre, el
problema es "saber buscar".
_*#*__*#*__*#*__*#*__*#*__*#*_
_*#*_ 02. INTRODUCCION _*#*_
_*#*__*#*__*#*__*#*__*#*__*#*_
Que es ncurses?
Ncurses es una API que nos proporciona unos servicios con los que
podremos crear ventanas, posicionar el cursor, hacer uso de colores
y un largo etc pero, lo mas importante, es que tiene unas liberias
complementarias conocidas con los nombres de panel, menu y form
respectivamente, que nos permitiran controlar las ventanas de un
modo mucho mas preciso, nos ayudaran a crear menus y a realizar
formularios con los que el usuario se sentira mucho mas comodo.
Ncurses es una liberia mejorada de lo que fue en sus tiempos curses.
Quien creo ncurses?
Pues el encargado de tal tarea fue Pavel Curtis. Hoy en dia, los
encargados de mantener el paquete son:
- Zeyd Ben-Halim
- Eric S. Raymon
- Thomas Dickey
- Juergen Pfeifer
En la version que dispongo yo actualmente de ncurses (5.3-110), estos
son los autores que aparecen citados en los fuentes:
/****************************************************************************
* Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 *
* and: Eric S. Raymond <esr@snark.thyrsus.com> *
* and: Thomas E. Dickey 1996-on *
****************************************************************************/
Juergen Pfeifer es el encargado de las librerias "menu" y "form".
La primera direccion de correo la he visto cambiada en otro sitio por:
<zmbenhal@clark.net>
_*#*__*#*__*#*__*#*__*#*__*#*_
_*#*_ 03. COMPILACION _*#*_
_*#*__*#*__*#*__*#*__*#*__*#*_
Para poder hacer uso de estas librerias debemos de añadir a nuestros
fuentes ciertos includes y agregar alguna opcion a la hora de compilar
para que nuestros programas puedan funcionar perfectamente.
Principalmente añadiremos a los fuentes las siguientes directivas segun
las librerias que vayamos a utilizar:
ncurses -> #include <ncurses.h>
panel -> #include <panel.h>
menu -> #include <menu.h>
form -> #include <form.h>
El sistema posee una liberia estatica y otra dinamica para cada servicio:
La primera aumentara el tamaño del programa pero nos asegurara que
esta funcione en cualquier ordenador aunque no tenga instalado el paquete
citado.
La segunda solo añadira lo indispensable a nuestra aplicacion pero para
ejecutarse, asume que el ordenador en el que se inicia, cuenta con tales
librerias.
Esta ultima es la mas utilizada pero, es el programador quien debe decidir
cual va ser el ambito de la aplicacion y escoger la opcion mas conveniente.
Las librerias son las siguientes:
ESTATICA DINAMICA
ncurses -> libncurses.a libncursesw.so.X.Y
panel -> libpanel.a libpanel.so.X.Y
menu -> libmenu.a libmenu.so.X.Y
form -> libform.a libform.so.X.Y
X e Y -> Version de las librerias.
Si queremos hacer el enlace estatico debemos ponder la liberia deseada como
un modulo mas de nuestra aplicacion, por ejemplo:
gcc programa.c /usr/lib/libncurses.a -o programa
Si por el contrario queremos el enlace dinamico el comando seria asi:
gcc -lncurses programa.c programa
Aqui expongo un ejemplo de makefile en el que utilizo la libreria ncurses
de modo estatico y el resto de forma dinamica:
<++>
LDFLAGS=-lpanel -lmenu -lform
all: programa
programa: programa.o /usr/lib/libncurses.a
clean:
rm programa.o programa
<-->
Cualquier duda para compilar un programa podeis hacermelo saber en mi
correo, cuanta mas informacion me deis mas facil sera de solucionar el
problema.
_*#*__*#*__*#*__*#*__*#*__*#*__*#*_
_*#*_ 04. CONCEPTOS BASICOS _*#*_
_*#*__*#*__*#*__*#*__*#*__*#*__*#*_
Antes de nada me gustaria que conocieseis algunas de las variables mas
importantes ya declaradas por la libreria:
stdscr -> Puntero a la ventana principal (pantalla completa).
curscr -> Puntero a la ventana actual.
newscr -> Puntero a una ventana nueva.
LINES -> Lineas de la ventana del terminal.
COLS -> Columnas de la ventana del terminal.
TABSIZE -> Tamaño del tabulador (espacios que contiene).
COLORS -> Numero de colores individuales.
La primera funcion a utilizar cuando programamos con ncurses es initscr(),
cuyo prototipo veremos a continuacion.
Su objetivo es determinar el tipo de terminal del que disponemos y de
borrar el contenido existente en la pantalla mediante una llamada a la
funcion refresh(). Alguien pensaria que iva a decir system("clear"), pero
recordar que no estamos trabajando con la biblioteca estandar.
Realmente initscr() realiza una llamada a la funcion newterm() que se
encarga de la mayor parte del trabajo. Si trabaja sobre multiples terminales
puede utilizar newterm() directamente, de todas formas, esta funcion no nos
concierno ahora.
extern NCURSES_EXPORT(WINDOW *) initscr (void);
Como se puede comprobar, si todo ha salido bien, esta funcion devuelve un
puntero WINDOW que representa a la pantalla completa.
Ahora tendremos a nuestra disposicion una lista de funciones que
utilizaremos segun nuestras necesidades y que describire seguidamente.
raw() -> Con ella le diremos al programa que recoja el contenido de las
teclas segun van siendo pulsadas sin esperar un "Intro", ademas
de caracteres, esta funcion reconocera teclas especiales como
flechas y combinaciones.
keypad() -> Esta es realmente la funcion encargada de detectar la pulsacion
de teclas de desplazamiento o de funcion(Fx). Necesita dos
argumentos al ser invocada:
1- Puntero WINDOW de la ventana a la que afectara. Utilice la
variable "stdscr" para la principal.
2- TRUE o FALSE para activar o desactivar.
has_colors() -> Indica si nuestro terminal soporta la capacidad de utilizar
colores. El valor devuelto sera 0 si no puede y distinto de
0 si puede.
start_color() -> Facil de deducir, si en nuestra aplicacion vas hacer uso de
colores, esta se encargara de inicializar un conjunto de
ellos para que esten disponibles.
init_pair() -> Asocia a un indice (un entero) una pareja de colores, que
seran
utilizados por la siguiente funcion para establecerlos en una
ventana.
wcolor_set() -> Establece una pareja de colores (indicada por su indice en
el
segundo parametro) como predeterminada para una ventana
(cuyo
puntero WINDOW se facilita como primer parametro). Como tercer
parametro utilizaremos NULL.
wbkgd() -> Funciona igual que la anterior pero solo requiere dos parametros,
el primero es la ventana y el segundo es una directiva llamada
COLOR_PAIR() cuyo argumento sera el indice de una pareja de colores.
echo() -> Permite que las teclas pulsadas en el teclado se vean en el teclado,
su correspondiente es noecho().
nodelay() -> Provoca que el programa no se bloquee si hay una funcion que esta
esperando la pulsacion de una tecla. Precisa de los mismos
parametros que keypad().
curses_version() -> Informa de la version de esta libreria.
endwin() -> Siempre hay que llamar a esta funcion antes de la finalizacion del
programa ya que es la encargada de devolver los atributos del
terminal a su estado original y que todo siga su transcurso normal.
Antes de pasar al siguiente apartado quisiera dar un ejemplo del uso de las
funciones init_pair() y wcolor_set() para que no le queden dudas al lector:
init_pair(1,COLOR_CYAN,COLOR_BLUE); // 1 es el indice
wcolor_set(ventana, 1, NULL); // Tambien vale:
wbkgd(ventana,COLOR_PAIR(1));
IMPRIMIR EN PANTALLA
--------------------
Las funciones de salida estandar no nos seran nada utiles cuando programamos
con ncurses porque en memoria se mantienen unas imagenes que representan
el contenido de cada ventana, incluso de la principal, por lo tanto las
funciones que utilizaremos para enviar informacion al terminal, escribiran
en estas imagenes y luego seran enviadas a la pantalla cuando se utilice la
funcion refresh().
Que funciones debo utilizar entonces?
wprintw() -> Funciona igual que printf() pero necesita como primer parametro
un puntero WINDOW con la ventana en la que se desea escribir.
Ej: wprintw(ventana, "Numero %d", 5);
printw() -> Lo mismo que la anterior pero no necesita el puntero WINDOW ya
que esta solo trabaja sobre "stdscr".
Debo mencionar que para actualizar una ventana especifica hay que utilizar
la funcion wrefresh() a la que se pasa como primer argumento la ventana
deseada. Refresh() como printw() es para "stdscr".
Tambien cabe mencionar que tanto refresh() como wrefresh() llaman a la
funcion doupdate(), por ello no debemos de escribirla nosotros.
Doy por sabido que las siguientes funciones trabajan sobre la ventana
indicada como primer parametro:
waddch() -> Escribe un caracter en la posicion actual del cursor.
mvwaddch() -> Escribe un caracter en la posicion indicada como
parametros 2 y 3.
waddstr()-> Escribe una cadena en la posicion actual del cursor.
mvwaddstr() -> Escribe una cadena en la posicion indicada como
parametros 2 y 3.
Si a cada una de estas funciones le quitamos la "w" de su nombre, tendremos
las funciones complementarias que trabajan sobre "stdscr". El programador
no se puede quejar de la mnemotecnica de ncurses.
Otras funciones:
wmove() -> Mueve el cursor a la posicion deseada.
Parametro 2: fila.
Parametro 3: columna.
wclear() -> Borra el contenido de la ventana.
ENTRADA DE DATOS
----------------
Las funciones mas usadas a la hora de obtener datos del teclado son las
siguientes:
getch() -> Recoge un caracter del teclado y, si el "eco" esta activo,
llama a addch para imprimirlo en pantalla.
wgetstr -> Recoge una cadena del teclado.
wscanw -> Complementaria a wprintw(), recoge una cadena con formato.
Seguro que se me quedan otras tantas funciones en el saco pero estas son
las mas importantes para empezar. De cualquier modo, teneis los fuentes
para ver los demas prototipos.
_*#*__*#*__*#*__*#*__*#*_
_*#*_ 05. VENTANAS _*#*_
_*#*__*#*__*#*__*#*__*#*_
Las propiedades de una ventana vienen definidas en "struct _win_st" y
no son muy complicadas de comprender. Ha sido definido un tipo de dato
llamado WINDOW que utilizaremos para definir nuevas variables para
crear ventanas.
Aqui muestro parte del codigo:
typedef struct _win_st WINDOW; // Definicion de tipo
struct _win_st // Estructura de una ventana
{
NCURSES_SIZE_T _cury, _curx; /* current cursor position */
/* window location and size */
NCURSES_SIZE_T _maxy, _maxx; /* maximums of x and y,
NOT window size */
NCURSES_SIZE_T _begy, _begx; /* screen coords of
upper-left-hand corner */
short _flags; /* window state flags */
/* attribute tracking */
attr_t _attrs; /* current attribute for
non-space character */
chtype _bkgd; /* current background
char/attribute pair */
/* option values set by user */
bool _notimeout; /* no time out on
function-key entry? */
bool _clear; /* consider all data
in the window invalid? */
bool _leaveok; /* OK to not reset
cursor on exit? */
bool _scroll; /* OK to scroll
this window? */
bool _idlok; /* OK to use
insert/delete line? */
bool _idcok; /* OK to use
insert/delete char? */
bool _immed; /* window in immed mode?
(not yet used) */
bool _sync; /* window in sync mode? */
bool _use_keypad; /* process function keys
into KEY_ symbols? */
int _delay; /* 0 = nodelay, <0 = blocking,
>0 = delay */
struct ldat *_line; /* the actual line data */
/* global screen state */
NCURSES_SIZE_T _regtop; /* top line of scrolling region */
NCURSES_SIZE_T _regbottom; /* bottom line of scrolling
region */
/* these are used only if this is a sub-window */
int _parx; /* x coordinate of this window
in parent */
int _pary; /* y coordinate of this window
in parent */
WINDOW *_parent; /* pointer to parent if a
sub-window */
/* these are used only if this is a pad */
struct pdat
{
NCURSES_SIZE_T _pad_y, _pad_x;
NCURSES_SIZE_T _pad_top, _pad_left;
NCURSES_SIZE_T _pad_bottom, _pad_right;
} _pad;
NCURSES_SIZE_T _yoffset; /* real begy is _begy + _yoffset */
#ifdef _XOPEN_SOURCE_EXTENDED
cchar_t _bkgrnd; /* current background
char/attribute pair */
#endif
};
Los comentarios en ingles faciles de traducir no?
Algunos los he dividido en dos lineas por eso del formato de 80
caracteres maximo por linea del articulo.
Para crear una ventana llamaremos a la funcion newwin() con los
siguientes parametros:
1- Numero de filas
2- Numero de columnas
3 y 4- Coordenadas donde se situara la esquina superior izquierda de la
ventana.
Esta funcion nos devolvera un puntero WINDOW que utilizaremos a lo largo
de la aplicacion para controlar dicha ventana.
Ej:
WINDOW *miventana;
miventa = newwin(7,4,0,0);
En este caso la ventana se situara en la esquina superior izquierda de la
pantalla.
Son muchas las limitaciones que tenemos con ncurses con respecto al control
de ventanas pero, para solucionarlo y alegrar el dia al programador, se ha
creado la libreria "panel" con la que conseguiremos unos resultados mas que
satisfactorios. Pasemos a explicar entonces su funcionamiento.
_*#*__*#*__*#*__*#*__*#*_
_*#*_ 06. PANELES _*#*_
_*#*__*#*__*#*__*#*__*#*_
Por decirlo de alguna manera digamos que un panel es el manejador de una
ventana, una vez asociado a la misma podemos controlarla y realizar todo
tipo de operaciones con ella. Un panel es lo que le da poder a una ventana,
es el que la convierte en un objeto dinamico con el que se puede
interactuar.
Crear un panel es cosa de niños, simplemente llamaremos a la funcion
new_panel() con el parametro WINDOW de la ventana a la que queremos asociar
el panel. La funcion retorna un puntero del tipo PANEL el cual usaremos
apartir de ahora con muchas y muy variadas funciones.
Ej:
WINDOW *miventana;
PANEL *mipanel;
miventana = newwin(4,7,0,0);
mipanel = new_panel(miventana);
Las ultimas dos instrucciones se podrian haber resumido en algo mas simple
como : mipanel = new_panel(newwin(4,7,0,0));
Tras realizar la llamada a new_panel(), por defecto, el nuevo panel sera
visible y no habra que llamar explicitamente a la funcion show_panel().
Como ya hice anteriormente, asumire que saben que el primer parametro de las
siguientes funciones siempre es el puntero PANEL de la ventana a controlar:
panel_hidden() -> Nos indica si el panel esta oculto o no.
show_panel() -> Hace visible un panel.
hide_panel() -> Oculta un panel.
move_panel() -> Mueve el panel a las cordenadas indicadas como segundo y
tercer parametro.
top_panel() -> Superpone el panel sobre el resto.
bottom_panel() -> Pone el panel debajo del resto.
panel_above() -> Devuelve un puntero tipo PANEL del panel que esta sobre
el que hemos indicado como primer argumento. Si este ya
era el primero devuelve NULL como valor de retorno.
panel_below() -> Opuesta a la anterior, devuelve el que esta debajo.
Devuelve NULL si no existe.
panel_window() -> Nos devuelve el puntero WINDOW de la ventana asociada
al panel.
replace_panel() -> Asocia un panel a una ventana proporcionada como segundo
argumento. Un panel puede reutilizarse para tantas
ventanas
como se desee.
del_panel() -> Desace la asociacion entre el panel y la ventana
eliminandolo.
Hay algunas funciones mas que tambien son importantes pero no me gustaria
liaros mientras os estais iniciando en esta materia. Si necesitais mas
informacion, personalmente la puedo proporcionar o buscar si me escribis a
mi correo.
Para conseguir que los cambios efectuados con las funciones anteriores
tengan un reflejo visible en pantalla, habra que llamar a las funciones
update_panels() y doupdate().
En este caso update_panels() no conlleva una llamada a doupdate() por
lo tanto la llamaremos desde la aplicacion como otra orden mas.
_*#*__*#*__*#*__*#*__*#*_
_*#*_ 07. MENUS _*#*_
_*#*__*#*__*#*__*#*__*#*_
Ha llegado el momento de combinar lo bonito con lo comodo. Con esta
libreria conseguiremos hacer listas de opciones navegables con las flechas
del teclado y que tambien podran dar paso a otras sublistas (submenus).
Lo mas util de todo esto es que conseguiremos que cuando una opcion sea
seleccionada y presionemos INTRO u otra tecla que queramos, haga las
operaciones que mas deseemos (generalmente llamar a una funcion).
La primera estructura que debemos conocer se conoce por el nombre de MENU,
no la copiare aqui para no alargar demasiado el articulo. Contiene toda
la informacion necesaria para controlar el menu.
La segunda estructura mas importante a la hora de conocer la programacion
de menus, es conocida como ITEM (en realidad es un tipo de dato definido).
Cada puntero de este tipo hara referencia a una opcion del menu. Todas las
opciones del menu seran almacenadas en un array (matriz o arreglo) de
punteros ITEM.
typedef struct tagITEM
{
TEXT name; /* name of menu item
*/
TEXT description; /* description of item, optional in display
*/
struct tagMENU *imenu; /* Pointer to parent menu
*/
void *userptr; /* Pointer to user defined per item data
*/
Item_Options opt; /* Item options
*/
short index; /* Item number if connected to a menu
*/
short y; /* y and x location of item in menu
*/
short x;
bool value; /* Selection value
*/
struct tagITEM *left; /* neighbour items
*/
struct tagITEM *right;
struct tagITEM *up;
struct tagITEM *down;
} ITEM;
De nuevo un contenido facil de descifrar si tenemos unos minimos
conocimientos
de ingles y estamos un poco avispados.
Las funciones que mas nos interesan por el momento son:
new_item() -> Nos devuelve un puntero ITEM a partir de un nombre y una
descripcion que le entregaremos como primer y segundo
parametro
respectivamente.
new_menu() -> Toma como unico parametro la matriz de punteros ITEM que hemos
ido rellenado con cada llamada a new_item() y nos devuelve un
puntero de tipo MENU con el que controlaremos el mismo.
Para que la funcion se ejecute con exito, la matriz debe acabar
con un puntero ITEM nulo (NULL).
Como crear un menu?
Primero declaramos el array de punteros ITEM que sea una unidad mayor que
la cantidad de opciones que vaya a tener el menu y, tambien declaramos un
puntero tipo MENU con el que se controlara el mismo:
MENU *menu;
ITEM *ops[6];
Luego debemos crear una matriz normal de tipo char* en la que introduciremos
uno a uno los nombres de las opciones que queremos posea el menu:
char *opciones[5] = { "Nuevo", "Abrir", "Guardar", "Cerrar", "Salir" };
Lo siguiente es crear los punteros ITEM que seran almacenados en la matriz
que hemos creado para tal objetivo. Agregamos tambien el puntero nulo:
for(i=0; i < 5; i++)
ops[i] = new_item(opciones[i], "");
ops[5] = (ITEM *)NULL; // Realizamos un typecast para que el valor NULL
sea tomado tambien como un ITEM mas.
Por fin llega el momento de crear el menu:
menu = new_menu(ops);
Todo correcto pero, si nuestro programa fuera asi, el menu todavia no se
visualizaria en pantalla, como siempre, necesitamos un par de llamadas mas:
post_menu(menu); // Hace que el menu sea visible, su opuesto unpost_menu()
refresh(); // Llamada casi obligatoria despues de todo cambio
Bien, todo ha salido como esperabamos.
Cabe decir que antes de que la aplicacion termine, el menu debe ser
eliminado al igual que todas sus opciones para dejar limpia la memoria.
Utilizariamos otras dos funciones de esta forma:
free_menu(menu);
for(i=0; i < 5; i++)
free_item(ops[i]);
El tema de la creacion y acceso a submenus sera explicado en la siguiente
parte de este articulo.
DESPLAZARSE POR EL MENU
-----------------------
Un menu en pantalla sobre el que no podamos interactuar no seria de
verdadera utilidad, no es cierto?
Pues bien, para todos (creo yo) lo mas comodo es utilizar las flechas
del teclado y alguna que otra tecla con funcion de navegacion.
Antes de empezar debemos de conocer unas constantes que seran las
encargadas de la navegacion por la lista de opciones.
#define REQ_LEFT_ITEM // Moverse a la opcion de la izquierda
#define REQ_RIGHT_ITEM // Moverse a la opcion de la derecha
#define REQ_UP_ITEM // Moverse a la opcion de arriba
#define REQ_DOWN_ITEM // Moverse a la opcion de abajo
#define REQ_FIRST_ITEM // Moverse a la primera opcion
#define REQ_LAST_ITEM // Moverse a la ultima opcion
#define REQ_NEXT_ITEM // Moverse a la opcion siguiente
#define REQ_PREV_ITEM // Moverse a la opcion anterior
He omitido varias que de momento no nos seran de utilidad pero ser
conscientes de su existencia. Recordad, los fuentes nunca mienten.
Todas estas constantes seran utiles a la hora de ejecutar la funcion
menu_driver(), que necesita como primer parametro el menu sobre el
que va a operar y como segundo una de las constantes anteriores.
El segundo parametro tambien puede ser un caracter a partir del cual
buscara el patron de coincidencia en el menu pero no me voy a meter
mas a dentro para no dificultar la tarea.
Los valores de retorno de esta funcion son dos:
E_OK -> Todo ha salido bien.
E_REQUEST_DENIED -> La opcion requerida no se ha podido realizar.
Ahora solo tenemos que hacer que nuestro programa identifique las
teclas que son pulsadas y asocie a cada una de ellas una de las
constantes anteriores.
Las constantes para reconocer las teclas de navegacion son:
#define KEY_DOWN // Flecha abajo
#define KEY_UP // Flecha arriba
#define KEY_LEFT // Flecha izquierda
#define KEY_RIGHT // Flecha derecha
#define KEY_HOME // Tecla Inicio
#define KEY_END // Tecla Fin
Hay una tirada de ellas mas pero soy asi de tacaño.
Primero prepararemos la funcion que detecta la tecla pulsada y
devuelve como valor de retorno la constante apropiada.
Acordaros que para que nuestra aplicacion reconozca estas teclas
especiales tendremos que llamar primero a keypad() con sus
correspondientes argumentos.
int identecla(){
int tecla;
tecla = getch();
switch(tecla){
case KEY_UP: return REQ_PREV_ITEM;
case KEY_DOWN: return REQ_NEXT_ITEM;
case KEY_HOME: return REQ_FIRST_ITEM;
case KEY_END: return REQ_LAST_ITEM;
default: return tecla;
}
}
Y ahora solo queda llamar a la funcion menu_driver() con los parametros
necesarios, en nuestro caso:
menu_driver(menu, identecla());
Ya puede navegar comodamente por su menu, pero no nos detengamos aqui y
sigamos aprendiendo un poco mas.
ACTUACION DE LAS OPCIONES
-------------------------
Cuando una opcion es seleccionada y presionamos la tecla INTRO es de
suponer que una funcion (o trabajo) que nosotros hayamos decido se
ejecute.
Para este objetivo tenemos a nuestra disposicion un par de funciones
interesantes que usadas conjuntamente arrojan una funcionalidad
importante.
La primera de ellas es llamada current_item() que nos devuelve el
puntero ITEM de la opcion que actualmente esta seleccionada.
La segunda es item_index() que ofreciendole como unico parametro
un puntero del tipo ITEM devuelve como valor de retorno el indice
(entero) que ocupa esa opcion en el menu.
A partir de este indice cualquiera de nosotros es capaz de asociarle
una funcion adecuada.
Lo que mas rapido se me viene a la mente es una clausula switch()
que tome como parametro item_index(current_item()) y que dependiendo
del valor devuelto se ejecute la funcion requerida.
De todas formas hay muchas y muy variadas formas de hacer todo esto
y seran explicadas en profundidad en la segunda parte del articulo.
_*#*__*#*__*#*__*#*__*#*_ _*#*_ _*#*_
_*#*_ 08. PROGRAMA EJEMPLO _*#*_
_*#*__*#*__*#*__*#*__*#*_ _*#*_ _*#*_
Mi objetivo era que el programa ejemplo llegara a tiempo, pero debido a mis
estudios en estos momentos mis escasos minutos libres como programador no
estan teniendo su espacio.
De cualquier manera, el programa va incluir formularios, tematica extensa
de la segunda parte de este articulo. Por tal motivo el programa estara
a vuestro alcance y disposicion en la segunda parte.
El programa que demuestra las aplicaciones de Ncurses pretende ser como
un almacen de informacion donde guardar la topologia y caracteristicas
tanto de una red como de los ordenadores que la forman.
Por el momento queria que el programa solo manejara redes de tipo Ethernet,
pero nadie quita (y sera lo mas seguro) que trate con redes wireless y de
cualquier otro tipo, ya que ese es el objetivo del programa.
De todas formas, os animo a ir escribiendo aplicaciones pequeñitas con
Ncurses para coger algo de practica y que saqueis buenos resultados,
con la parte final del articulo tendreis bastante mas experiencia y las
ideas empezaran a brotar de vuestras propias mentes.
Pido disculpas por mis escusas.
_*#*__*#*__*#*__*#*__*#*_
_*#*_ 09. DESPEDIDA _*#*_
_*#*__*#*__*#*__*#*__*#*_
Otro hasta luego mas para la coleccion, pero rocordad que nos vemos en la
segunda parte de este articulo que espero salgo a la luz lo antes posible.
Como siempre, mi idea era la de que los que leeis esto llevarais lo aqui
escrito a la practica pero tambien sois vosotros los que debeis elegir con
que herramientas luchar.
Si, la vida es un combate por la supervivencia, el que tenga mas informacion
tendra el poder pero, solo el que sepa utilizarla alcanzara la victoria. Los
de ahi arriba tienen el poder pero sin nosotros nunca alcanzaran la
victoria,
somos la revolucion...
Hasta la proxima chic@s.
by blackngel
*EOF*