![]() ![]() ![]() ![]() ![]() ![]() AngoLinux |
Tutorial su Curses |
![]() |
prof. Marcello Missiroli Versione 0.1 - Maggio 2001 [Versione stampabile in PDF (206.191 byte)] Copyright ©2002 MARCELLO MISSIROLI.Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.1 or any later version published by the Free Software Foundation; A copy of the license is included in the chapter entitled "GNU Free Documentation License".
Contents |
![]() |
1 L'interfaccia utenteAgli albori dell'informatica, tutti gli utenti di computer erano essi stessi programmatori; non ci si si preoccupava molto degli utenti inesperti poiché questi, per definizione, non lo utilizzavano per niente. Nel corso degli anni, le cose sono profonamente cambiate e oggi il programmatore è costretto sempre a pensare in temini di utilizzo per utente finale: ogni programma deve esser chiaro, utilizzare comandi semplici e chiari, possbilmente essere predisposto per essere programmato per più paesi (``internationalization'', o i18n) e più lingue (``localization'', o l8n). Tutto questo non fa altro che spostare la difficoltà dall'utente finale, che prima era costretto a impararsi comandi astrusi e diversi da programma a programma al programmatore che dovrà ``pensare'' di non conoscere per nulla il proprio software e cercare di immaginare come si comporterebbe un utente alle prime armi che - per inciso - ha pochissima voglia di leggere i manuali.
1 Tipi di interfaccia utentePossiamo differenziare a quattro diversi tipi di interfaccia utente, al momento attuale
|
![]() |
2 L'interfaccia testualeAnche se questo tipo di interfaccia appare in declino, vi sono diversi casi in cui non è possibile fare altrimenti e si è costretti ad utilizzare questo strumento. In ogni caso è possibile fornire alcune indicazioni base quali:
1 EsempioQuesto semplice esempio mostra come gestire un semplice menu di scelta, con opzioni controllate.
|
![]() |
3 L'interfaccia semigrafica (ncurses) -base
1 Cos'è ncurses?Ncurses è la libreria che permette di
2 Come si usa la libreria?Supponendo di avere installato correttamente ncurses, la cosa migliore è utilizzare il seguente file-scheletro
3 Come si compila un programma con ncurses?In linea di massima come un programma normale, tranne per il fatto che occorre segnalare al compilatore che si intende utilizzare la libreria in questione. Il comando tipico diventa quindi
![]()
4 Rilevazione di erroriIn linea di massima, tutte le funzioni di ncurses restituiscono un tipo intero. Se la funzione è andata a buon fine, il valore restituito è OK, altrimenti è ERR - fanno eccezione alcune funzioni che creano le finestre. Risulta così piuttsto semplice controllare se una funzione ha generato errori
5 Schermo e cursoreUna volta eseguito initscr(), lo schemo viene totalmente cancellato. Dal punto di vista di ncurses, lo schermo è una matrice di dimensione variabile, a seconda del computer, del sistema operativo e del programma che state utilizzando. L'angolo in alto a sinistra ha sempre le coordinate x=0 e y=0(1). Dato che le dimensioni dello schermo sono variabili, ncurses possiede due variabili intere, LINES e COLS che contengono, rispettivamente le dimensioni, in caratteri, delle linee e delle colonne del terminale. L'angolo in basso a destra avrà quindi le coordinate x=COLS e y=LINES. Il sistema prevede anche un cursore, che normalmente è invisibile, che indica la posizione dello schermo in cui si scriverà con la prossima istruzione. Dopo l'inizializzazione, tale punto è sempre (0,0), ma è facile spostarlo con varie istruzioni.
1 int curs_set(int visibilità);La funzione permette di stabilire se si vuole un cursore invisibile, visibile o molto visibile ponendo come parametri 0,1 o 2.
6 Il refreshUno dei concetti fondamentali di ncurses è quello di refresh.L'idea è che tutti i comandi di output che invierete non sono visualizzati immediatamente, ma sono memorizzate in una speciale zona di memoria. Per visualizzare effettivamente le cose occorre utilizzare l'istruzione refresh(). Questo tipo di approccio permette di velocizzare l'output, poiché è possibile preparare svariate modifiche e visualizzarle contemporaneamente. I programmi con ncurses sono quindi costituiti da uno o più comandi di visualizzazione seguiti dall'istruzione refresh().
7 Scrivere e leggereLa prima cosa che occorre imparare è come scrivere sullo schermo. Dato che non possiamo ricorrere alle funzioni standard, ncurses ci fornisce alcune funzioni particolari molto semplici.
1 int printw(char *fmt [, arg] ...);Questa routine è la controparte di ncurses di printf, e richiede una stringa di formato (anche se non è necessario andare a capo a fine riga). La stampa viene effettuata a partire dalla posizione iniziale dello schermo. Esempio: printw(``Hello World!'') stampa la frase alla posizione corrente.
2 int scanw(char *fmt [, arg] ...);..e questa è l'equivalente di scanf. Esempio: scanw(``%c'',&i) legge la variabile i alla posizione corrente.
3 int mvprintw(int y, int x, char *fmt [, arg] ...);Simile alla precedente, ma permette di indicare le coordinate dello schermo. Notate che le coordinate orizzontali e verticale sono invertite rispetto alla loro posizione naturale. Esempio: mvprintw(3,3,``La variabile vale %d'', x) stampa la frase indicata alla posizione 3,3.
4 int mvscanw(int y, int x, char *fmt [, arg] ...);Per questa funzione potete attivare le vostre potenti abilità deduttive e capire che cosa fa!
5 int move(int y, int x);Si limita a spostare il cursore alla posizione indicata. Esempio: move( 10,10 );
6 int getch(void); int mvgetch(int y, int x);Questa routine funziona in modo assai simile alla getchar() di stdio, con la differenza che non servere premere ; anzi, se un tasto è già stato premuto, la funzione ritorna immediatamente. In realtà si tratta di una funzione estrememente configurabile: è possibile avere l'eco sullo schermo del carattere premuto, oppure richiedere l'uso di invio. mvgetch permette di spostare il cursore prima dell'input.
7 int addch(char ch); int mvaddch(int y,int x);Equivalente alla putchar di stdio. La seconda versione permette di spostare il cursore e stampare in un'unica operazione.
8 int noecho(void);Una volta avviato, ncurses fa in modo che i caratteri battuti in fase di input siano visibili sullo schermo. Dopo aver richiamato noecho(), invece, quello che si scrive non appare sullo schermo. La funzione inversa è echo().
9 int cbreak(void);Con questa funzione la pressione di un tasto viene immediatamente resa disponibile al programma, senza attendere l'invio. Il suo inverso è nocbreak();
10 int timeout(int delay);Questa importante funzione permette di regolare il comportamento del programma. Se si fornisce come parametro 0, getch() non aspetta che l'utente prema un tasto e prosegue, fornendo come valore di ritorno un errore (ERR). Se si fornisce un valore positivo n, il programma aspetta per n millisecondi e poi prosegue. Se si fornisce un valore negativo, il programma funziona in modo regolare, attendendo indefinitamente l'input dell'utente.
11 int napms(int ritardo);Questa funzione si limita a bloccare il programma per un certo numero di millisecondi.
8 Un primo esempio: ruota dei ventiQuesto semplice programma inizializza le librerie e stampa quattro parole ai quattro angoli del terminale. Se site in modalità grafica, provate a ridimesionare la finestra: noterete che le parole sono sempre corretamente posizionate (a patto di avere una finestra di almeno 2x13 caratteri).
9 Usare i ColoriDato che stiamo lavorando sullo schermo a caratteri, occorre tenere presente che in ncurses si intende una coppia di colori, piuttosto che un colore singolo: un colore rappresenta il colore del carattere, il secondo il colore dello sfondo. Per utilizzare i colori occorre
1 int start_color(void);È obbligatorio richiamare questa funzione se si intendono utilizzare i colori. È buona norma richiamarla subito dopo initscr().
2 int init_pair(short pair, short f, short b);Questa funzione permette di creare le coppie di colori che poi saranno utilizzate per scrivere con i colori. Il primo parametro è un valore da 1 a 7 (il valore 0 è riservato al bianco su nero e non può essere - solitamente - modificato); il secondo è il colore del cattere, il terzo il colore dello sfondo. Anche se è possbile utilizzare qualsiasi colore, definendone le componeti rosso, verde e blu con la funzione init_color, per la maggior parte degli scopi è più semplice utilizzare gli otto colori predefiniti che sono: COLOR_BLACK, COLOR_RED, COLOR_GREEN, COLOR_YELLOW, COLOR_BLUE, COLOR_MAGENTA, COLOR_CYAN e COLOR_WHITE. Per definire la coppia di colori bianco su blu occorrerà quindi usare un'istruzione come
3 int attron(int attibuti);E' la funzione che dice quale coppia di colori utilizzare per le prossime istruzioni. All'interno è possibile specificare molitssimi attributi, ma quello che ci interessa è cambiare i colori con la macro COLOR_PAIR(n).
4 bkgd(int attributi);Cambia colori in un sol colpo all'intera finestra.
10 Un secondo esempio: fantasmagoriaQuesto secondo programma mostra un semplice uso dei colori. Si noti, fra l'altro, che all'interno di printw il carattere '\n' mantiene il suo usuale significato di ``a capo''; lo stesso vale per altri caratteri non stampabili
11 CancellareCancellare sembra facile, ma in realtà non lo è, perché abbiamo a disposizione tantissime possibilità.
1 int delch(void);Cancella il carattere che si trova sotto il cursore e spostano i caratteri che lo seguono sulla riga verso sinistra. Inutile dire che esiste la versione mvdelch che permette di spostare il cursore e cancellare.
2 int deleteln(void);Cancella la riga su cui si trova il cursore e sposta in alto le linee seguenti.
3 int insertln();Inserisce una riga vuota alla posizione attuale del cursore, spingendo in basso le altre. In questo modo, di fatto, si cancella l'ultima riga in basso.
4 int clrtoeol(void);Cancella tutti i caratteri sulla stessa linea alla destra del cursore
5 int erase(void);Copia spazi bianchi in ogni posizione dello schermo, cancellandolo tutto. Si tratta in generale di una routine lenta, da utilizzare con circospezione. |
![]() |
4 Interfaccia semigrafica ncurses - avanzato
1 Le finestreCome abbiamo visto, ncurses non lavora direttamente sulla memoria video ma su una copia inmemoria dei dati; la visualizzazione avviene solo esplicitamente quando si richiama la funzione refresh(). In realtà il meccanismo è molto più potente di quanto descritto finora e permette ulteriori livelli di flessibilità, quali i pannelli e le finestre di dialogo. Finora abbiamo utilizzato solo le funzioni più semplici, e quindi abbiamo lasciato gestire tutto internamente a ncurses. Ma se volessimo un programma in cui l'output è presentato in diverse sezioni piuttosto indipendenti? Certo, possiamo gestire tutto tenendo conto delle posizioni delle righe e delle colonne, ma dopo qualche tentativo vi apparirà ovvio che il gioco non vale la candela: l'ideale sarebbe lasciare gestire tutto al calcolatore.
1 la struct WINDOWSNcurses lavora con una struttura fondamentale chiamata, con poca fantasia, WINDOW, che rappresenta la copia in memoria di una finestra. Tutte le funzioni ncurses fanno riferimento a una finestra; se ciò non pare subito evidente, è perché anche l'intero schermo è considerato una finestra. È però possibile creare una nuova finestra e quindi poter lavorare separatamente su questa nuova entità. Per gestire questi dati occorre dichiarare una variabile strutturata di tipo WINDOWS in questo modo
2 WINDOW *newwin (int nlinee, int ncols, int inizio_y, int inizio_x);Questa funzione crea una nuova finestra alta un certo numero di linee, larga un certo numero di colonne, posizionata alla riga y e colonna x. Risulta completamente indipendente dalla finestra
3 int delwin (WINDOW *finestra);Questa elimina dalla memoria la finestra, mettendo lo spazio di nuovo a disposizione del sistema. Va chiamata quando si ha finito di lavorare con una finestra.
2 Funzioni relative alle finestreOra dovremmo vedere come si opera sulle finestre, ma fortunatamente la struttura di ncurses è tale che... le conosciamo già. In pratica per ognuna delle funzioni che abbiamo visto ne esiste un'euivalente che funziona solo su una finestra. I nomi delle funzioni sono esattamente gli stessi delle funzioni già note, con una w aggiunta all'inizio del nome e la variabile della finestra come primo parametro. Per cui avremo wprintw(), wscanw(), wrefresh(), wmvaddch() ecc.
3 Bordi e lineePotete creare dei bordi attorno alle vostre finestre per dare un aspetto migliore al vostro programma.
1 int box (WINDOW *finestra, char car_vert, char car_orizz);Questa è una delle poche funzioni per la quale non è prevista la versione con la 'w' davanti, dato che richiede sempre il puntatore a una finestra. I caratteri car_vert e car_orizz sono i caratteri da utilizzare per creare i bordi. Potete semplicemente utilizzare un asterisco, ma la forma più diffusa ed elegante è la seguente, che usa i caratteri semigrafici disponibili.
4 Tasti FunzioneE' possibile utilizzare i tasti funzione con ncurses ma, come nel caso del colore, occore chiamare un'appostita funzione per l'attivazione.
1 int keypad(WINDOW *finestra, int vero_o_falso);Questa funzione attiva o disattiva la gestione dei tasti funzione. Una volta attivato le funzioni come scanw ricevono i tasti funzione, ma perché la cosa funzioni occorre che i dati siano memorizzati in un int anziché un char, dato che i valori dei tasti funzione sono superiori ai vlaori standard ASCII. Non è, per fortuna, necessario impararsi il codice dei tasti freccia, poiché sono disponibili nel manuale di getch (man getch). In ogni caso, eccone alcuni tra i più significativi.
5 Terzo esempio : printshow.Questo esempio dimostra come sia (relativamente) semplice utilizzare ncurses per realizzare semplici animazioni e dialoghi a comparsa.
6 Estensioni di ncursesNcurses può offrire funzioni ancora più accurate, incluso l'interfacciamento con il mouse. In aggiunta esistono funzioni già pronte per l'uso dei dialoghi (forms library) e dei menù (menu library). Tali capacità esulano dalla portate di questa presentazione, ma possono facilmente essere provate consultando la documentazione di ncurses (solitamente posta sotto /usr/doc o /usr/share/doc).
7 Compatibilità conio-ncursesConio è una libreria di vasto utilizzo nel mondo windows e fornisce un sottoinsieme delle funzionalità di ncurses. In linea di massima è molto semplice trasporre un programma scritto per conio in ncurses e anche il contrario. E' anche possibile, ma alquanto laborioso, scrivere programmi che possano essere compliati indifferentemente con conio e ncurses, anche se le librerie sono abbastanza simili per farlo. Un metodo pratico consiste nello scrivere un file chiamato conio.h sotto linux che ridefinisce i comandi conio con ncurses. Esempio di un possibile conio.h
8 Esercizi
Bibliography |
![]() |
About this document ...Appunti di sistemi
Footnotes
Marcello Missiroli 2002-07-23 [Home Page dell'ITIS "Fermi"] [Indice Quarta] [Precedente] [Successivo] |