[[oktatas:linux|< Linux]]
====== NCurses ======
* **Szerző:** Sallai András
* Copyright (c) Sallai András, 2003, 2015, 2020
* Licenc: GNU Free Documentation License 1.3
* Web: http://szit.hu
===== Bevezetés =====
Az [[wp>ncurses]] a POSIX szabványon alapuló operációs rendszereken használható.
Az ncurses programozói könyvtár megkönnyíti a szöveges alapú programok
létrehozását. Segítségével a GUI-hoz hasonló felület hozható létre,
amely terminál emulátorban fut. Könnyen létrehozhatunk vele vonalakat,
kereteket, menüket, szövegeket a képernyő különböző helyein.
Az ncurses "n" betűje a "new" szóból van. Az ncurses így
System V Release 4.0 (SVr4) curses és szabványos XPG4 curses (XSI curses)
klónja. Az első curses
megvalósítás a University of California egyetemen készült
Berkeleyben BSD operációs rendszerre, a screen orientált
játékok támogatására. Előtte a Termcap programozói könyvtárat
használták, amellyel a vi szövegszerkesztő is készült.
Az ncurseshez hasonló megoldás volt a DOS rendszerekre a
conio.h programozói könyvtár.
Az ncruses szabadon terjeszthető, nyílt forráskódú változat.
A kompatibilitás érdekében az "n" elhagyható a használat során.
===== Telepítés =====
apt-get install libncurses5-dev
A csomag települése után az /usr/include könyvtárba telepszik
a curses.h fejállomány. Az ncurses.h pedig egy link lesz a curses.h
állományra.
A magyar ékezetes karakterek ábrázolásához libncursesw könyvtárra van szükség:
apt-get install libncursesw5-dev
Telepítés után a használható könyvtárakat a következő helyen
találjuk:
/usr/include/ncursesw/
===== Helló Világ =====
#include
int main() {
initscr();
printw("Helló Világ");
refresh();
getch();
endwin();
return 0;
}
Fordítsuk le:
gcc program01.c -o program -lncurses
De írhatunk egy Makefile is:
CC=gcc
LIBS=ncurses
SRC=program01.c
BIN=program01
all:
${CC} ${SRC} -l${LIBS} -o ${BIN}
Az initscr() curses módba kapcsolja a terminált.
Néhány implementációban a képernyőt is törli ez az utasítás.
A printw() függvény hasonló a printf()-hez. A képernyőre küldi
a megadott karaktersorozatot, a bal felső sarokba, amely a 0,0
pozíció.
A printw() valójában egy képzeletbeli ablakba ír, amely
nem frissül azonnal. Az adatok elsőként egy ideiglenes
tárolóba kerülnek. A refresh()függvény kiüríti a tárolót,
az adatokat a képernyőre küldi.
Az endwin() befejezi a curses módot.
===== Alapfogalmak =====
Az ablak fogalma az ncurses-ben: Mindig létezik egy alapértelmezett ablak. Ez a képernyő teljes területe, alapesetben a 80x25-ös képernyő terület. Az alapértelmezett ablakot "stdscr" rövidítéssel jelöljük, vagyis így hivatkozunk rá. Az alapképernyőn (vagy ablakon) újabb ablakokat hozhatunk létre. Egy-egy újabb ablak névvel rendelkezik, így az egyes függvényekben ezzel a névvel tudunk rájuk hivatkozni. Ha egy ablakot nem kívánunk használni, akkor megszüntethető.
===== Ncurses program előkészítése =====
Van néhány program előkészítő függvény, amelyeket az initscr() után kell meghívni. Meghívásuk természetesen nem kötelező. A következőkben áttekintjük ezeket az előkészítő függvényeket.
===== raw() és cbreak() =====
Normál terminál meghajtó addig raktározza el a leütött karaktereket, amíg egy kocsi vissza vagy egy új sor karaktert nem ütünk. Csak azután férhetünk hozzá a leütött karakterekhez. Ezt nevezzük sorszerkesztő üzemmódnak. A programozó néha, a leütött billentyűket azonnal szeretné elkapni, még kocsi vissza vagy új sor karakter bevitele nélkül.
Két funkcióval szakítható meg a karakterek elraktározása, amelyek a következő vezérlőbillentyűkkel érhetők el: Ctrl + Z (megszakítás), Ctrl + C (kilépés). A cbreak() függvény meghívása kikapcsolja a sorszerkesztő üzemmódot, így a leütött karaktert azonnal felhasználhatjuk. A raw() ugyancsak letiltja a sorszerkesztő üzemmódot, viszont a függvény hatására a szignálok küldése is tiltva lesz. Tehát a Ctrl + C hatására a program nem kapja meg a kilépés szignált, helyette a Ctrl + C billentyűkombinációt adja vissza.
===== echo() és noecho() =====
A beütött karakterek képernyőre történő visszhangozását szabályozza. A noecho() kikapcsolja a visszhangot, az echo() pedig bekapcsolja a getch() függvény hívásánál. A leütött karakter után a kurzor poziciója sem változik.
===== keypad() =====
Engedélyezi a funkció, a kurzormozgató és a többi billentyű olvasását. A keypad-nek két paramétere van. Az első, az az ablak amelyben el akarjuk érni a hatást. Ez lehet az alapértelmezett képernyő is: stdscr. A második paraméter egy logikai kifejezés. Értéke TRUE ha bekapcsoljuk, és FALSE ha ki.
===== halfdelay() =====
Half-delay mód bekapcsolása. A függvény felfüggeszti a program futását a paraméterben megadott tizedmásodpercig. A függvénynek ez az egyetlen paramétere van, amely egy egész szám. Bármely billentyűnyomásra a program tovább lép. Jelszó promptnál lehet hasznos. Például:
halfdelay(30); /* három másodpercig vár */
===== Példa =====
A következő program bemutatja az eddig megismerteket:
#include
main() {
int ch;
initscr(); /* ncurses módba kapcsol */
raw(); /* kikapcsolja a sorszerkesztést */
keypad(stdscr, TRUE); /* engedélyezi a funkcióbillentyűk
figyelését */
noecho(); /* getch függvény használatakor a leütött
karaktereket, nem visszhangozza a képernyőre */
ch = getch(); /* ha a raw() függvény nincs meghívva, akkor
a leütött billentyűt csak egy Enter után
kapja meg a program */
if (ch == KEY_F(1)) /* az F1-s funkcióbillentyű lekérdezése */
printw("F1 lett lenyomva");
else
printw("A lenyomott billentyű %c", ch);
refresh(); /* a képernyőn való megjelenítés aktualizálása */
endwin(); /* kilépés a curses módból */
}
===== Egyéb különleges billentyűk =====
Más különleges billentyűk is elérhetők:
* KEY_DOWN
* KEY_UP
* KEY_LEFT
* KEY_RIGHT
* KEY_HOME
* KEY_BACKSPACE
* KEY_ENTER
* stb.
A Definiált állandók benne vannak a /usr/include/ncurses.h állományban.
Megjegyzés: A különleges billenytűk közzül nekem csak a funkcióbillentyűk működnek helyesen, grafikus felületen.
===== move() =====
A szabványos képernyőn beállíthatjuk a paranccsal a kurzor pozícióját. Az első paraméter a függőleges koordináta (hányadik sor), a második paraméter vízszintes koordináta (hányadik oszlop). (Figyelem! A DOS-os conio.h-ban ez fordítva van.)
#include
main() {
initscr();
move(10, 20);
printw("Szöveg");
refresh();
endwin()
}
===== Parancsok ablakokhoz rendelése =====
Alapesetben egy 80x25-ös szabványos képernyőn dolgozunk. Ennek a neve "stdscr", ezzel a névvel hivatkozunk rá, mint azt a példában szereplő keypad függvény argumentumaként is megadtuk. A legtöbb függvénynél a szabványos képernyőt nem kötelező jelezni. Ilyen a példákban megismert printw() függvény. Az alaphelyzetben meglévő 80x25-ös képernyőn belül mi magunk is definiálhatunk újabb ablakokat. Ezeket az ablakokat névvel látjuk el, később pedig ezzel a névvel hivatkozunk rájuk.
Példa:
A printf("Helló"); az alapértelmezett (80x25-ös) képernyőre írja a "Helló" szöveget, annak is az aktuális kurzorpozíciójába. Ha az alapképernyőn újabb ablakot jelölünk ki, az adott ablakon belüli képernyő kurzorpozíciójába az alábbi paranccsal írhatunk:
wprintw(foablak, "Helló");
Látjuk, hogy egy dupla w betűt írtunk a függvény neve elé, ezzel jelezzük, hogy paraméterként megkívánjuk adni az ablak nevét, amelyikbe írni akarunk. A fenti példában a "foablak" nevű ablak kurzorpozíciójától kezdve írjuk ki a "Helló" szöveget.
Ekkor a refresh() parancs helyett is ezt használjuk:
wrefresh(foablak);
Az alapképernyőre írással együtt meghatározhatjuk a kurzor helyét is "mv" tag elhelyezésével:
mvprintw(y, x, szoveg);
Ugyanez egy ablakra vonatkoztatva:
mvwprintw(foablak, y, x, szoveg);
===== Kiírató függvények =====
Minden kiírató függvénynél használhatjuk a már C-ben megismert escape szekvenciákat.
==== addch() ====
Egy karaktert ír a képernyőre. Pl. :
addch('a');
Ennek a teljes példaprogramja így néz ki:
#include
main() {
initscr();
addch('a');
refresh();
endwin();
}
==== mvaddch() ====
Egyetlen karaktert ír a képernyőre, de itt meg kell adni hova akarjuk kiírni. Valójában a move() függvény van beépítve. Például, ha az ötödik sor, tizedik oszlopába akarom kiíratni az 'a' karaktert, akkor azt így tehetem meg:
mvaddch(5, 10, 'a');
==== waddch() ====
Egyetlen karaktert ír a képernyőre, azonban egy ablakhoz is hozzárendeljük a kiírást.
Pl.:
waddch(ablak, 'A');
==== mvwaddch() ====
Egyetlen karakteret ír a képernyőre. Meg kell adnunk melyik ablakba akarunk írni, és az adott ablak milyen pozíciójába.
Pl.:
mvwaddch(ablak, 5, 5, 'A');
==== printw() ====
Fentebb már találkoztunk vele. Formázott adatkivitelt tesz lehetővé, mint a szabványos printf(). Ugyanúgy kell használni mint a printf() függvényt. Például:
#include
main() {
int ch='v';
initscr();
printw("ch tartalma %c", ch);
refresh();
endwin();
}
Beállíthatjuk a karakterek kiírásának stílusát. Lehet például vastagon írt, vagy aláhúzott. Ezeket a tulajdonságokat az addch() paramétereként adjuk meg, a kiírandó karakter után, attól "|" karakterrel elválasztva:
addch('a' | A_BOLD);
vagy
addch('a' | A_BOLD | A_UNDERLINE);
Ez azonban nekem karakteres felületen nem működik, csak a grafikus felület termináljában. Karakteres felületen a normál és a vastagbetűs írás más színnel jelenik meg. A megjelenítés stílusát állíthatjuk külön paranccsal is. Ezek az attrset(), attron() és attroff().
===== Linkek =====
* http://www.gnu.org/software/ncurses/
* http://tldp.org/HOWTO/NCURSES-Programming-HOWTO/init.html