[[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