Puhverdatud funktsioonid on väga töökindlad. Nad kasutavad BIOSi ja DOSi funktsioone ning töötavad seega igal arvutil, millele DOS on installeeritud. Sageli on nad aga natuke aeglased, seda eriti ekraanile väljastamisel. Mitte puhverdamine, aga just BIOSi ja DOSi funktsioonid on ekraanile väljastamisel veidi aeglased. Nad ootavad enne väljastamist, kuni ekraanipinda uuendav elektronkiir on antud kohast möödunud. See tehnika väldib vanematel kuvaritel (CGA) nn. lumesaju efekti tekkimist, kuid EGA ja VGA kuvaritel on ta täiesti tarbetu. Seepärast kasutavad paljud programmid tõsiasja, et tekstirezhiimis salvestatakse ekraanisisu teatud mälupiirkoda, mille aadress on täpselt teada. Mustvalgetel monitoridel algab ekraanipuhver aadressilt B000:0000 hex, graafilistel monitoridel aga aadressilt B800:0000 hex. VGA ja EGA monitoridel algab tekstipuhver aadressilt A000:0000, väljaarvatud siis, kui nad on CGA rezhiimis, millal ka nende tekstipuhver algab aadressilt B800:0000. Ekraanipuhvri aadressi saab uurida järgi ka DOSi andmesegmendist või spetsiaalse funktsiooni abil.
Otseselt ekraanimälusse kirjutamiseks ei ole aga hoopiski vaja kasutada assemblerkeelt. Ka programmeerimiskeel C sisaldab funktsioone, mis kirjutavad otseselt ekraanile. Nende funktsioonide deklaratsioonid asuvad päisefailis CONIO.H.
Funktsioonid cgets() ja cputs() kirjutavad soovi korral ekraanile kas otse või BIOSi funktsiooni abil sõltuvalt globaalse muutuja directvideo väärtusest.
char *cgets(char *buffer); int cputs(char *string); int directvideo;
Muutuja directvideo väärtus on algselt 0, mis tähendab et kasutatakse BIOSi funktsioone. Kui te soovite otse ekraanile väljastada, siis omistage sellele muutujale mingi nullist erinev väärtus.
Need funktsioonid omavad ka muid erinevusi. Enne funktsiooni cgets() kasutamist seadke puhvri buffer esimese elemendi (buffer[0]) väärtuseks maksimaalne sümbolite arv, mis puhvrisse mahub. Funktsioon cgets() salvestab tegelikult loetud sümbolite arvu puhvri teise elementi (buffer[1]) . Sümbolid salvestatakse alates kolmandast elemendist. Seega peab puhver mahutama peale sümbolite veel kaks elementi ja lõpumärgina nulli. Funktsioon cputs() ei konverteeri üleantud revahetusmärke '\n' DOSi failide vastavateks sümbolitepaariks ASCII(10) ja ASCII(13). Nimetatud funktsioonid kirjutavad ainult ekraanile või loevad klaviatuurilt ja nende sisendit või väljundit ei saa faili ümber juhatada. Need funktsioonid ei vasta ka ANSI C standardile.
Sama võib mainida ka funktsioonide cscanf() ja cprintf() kohta. Ka nemad ei ole standardsed, kuid on üsna kasulikud.
int cscanf(const char *format, [, argument ...]); int cprintf(const char *format, [, argument ...]);
Need funktsioonid kasutavad samu parameetreid, nagu eelmises peatükis vaadeldud vastavad funktsioonid, kuid kirjutavad otse ekraanile või loevad klaviatuurilt vastavalt muutuja directvideo väärtusele.
Päisefail CONIO.H sisaldab veel palju muid kasulikke funktsioone tekstirezhiimis programmide jaoks. Enamik neist funktsioonidest ei ole standardsed. Need funktsioonid väljastavad otse ekraanile või loevad klaviatuurilt. Ekraanile väljastamisel kasutatakse nn. akent. Tavaline VGA kuvar mahutab harilikus tekstirezhiimis 25 rida teksti, millest igaüks on 80 sümboli laiune. Vastavalt kuvari ja graafikakaardi tüübile võib kasutada olla ka suurema või väikesema lahutusvõimega tekstirezhiime. Te võite ka ise piirata programmi poolt väljastatud andmeid mingisse ekraanipiirkonda. Selleks tuleb taoline piirkond (aken) luua funktsiooniga window().
void window(int x1, int y1, int x2, int y2);
See funktsioon loob ekraanile piirkonna (akna), mille vasakpoolne ülemine nurk asub punktis (x1, y1) ja parempoolne alumine nurk punktis (x2, y2). Kuvari vasakpoolne ülemine nurk omab koordinaate (1, 1). X- telg on suunatud vasakult paremale ja Y - telg ülevalt alla. Näiteks käsk window(1, 1, 80, 25) loob tavaliselt tervet ekraani hõlmava akna. Kõik järgnevalt väljastatud andmed esitatakse sellesse aknasse. Kui andmete väljastamisega on jõutud akna viimasele reale, siis nihutatakse akna sisu automaatselt ühe rea võrra ülespoole ja akna alumisele äärele ilmub uus vaba rida. Kui funktsioonile window() üleantud koordinaadid on kehtetud (näiteks liiga suured), siis ei oma funktsioon mingit toimet ja akna endine suurus jääb kehtima. Väikseim võimalik aken on ühe rea ja ühe tulba laiune. Selle funktsiooniga saate korraga luua vaid ühe akna, mis siis kehtib kõigile ekraanile väljastavatele funktsioonidele. Kui te olete, näiteks, loonud ekraani keskel väikese akna, siis peate muu ekraanipiirkonna muutmiseks looma uue akna, mis seda piirkonda sisaldab.
Aknas kehtivad uued koordinaadid. Akna vasakpoolne ülemine nurk omab alati koordinaate (1, 1). Funktsioonid cputs() ja cprintf() kasutavad nn. hetkelist positsiooni, s.t. nad väljastavad oma andmed eelmiste andmete järele ning nihutavad hetkelise positsiooni enda poolt väljastatud andmete lõppu. Hetkelise positsiooni saab teada funktsioonide wherex() ja wherey() abil.
int wherex( void ); int wherey( void );
Need koordinaadid kehtivad hetkelise akna sees ja mitte kogu ekraani ulatuses. Hetkelist posistsiooni saab muuta funktsiooniga gotoxy().
void gotoxy(int x, int y);
Seejärel väljastavad järgmised funktsioonid oma andmed ekraanile alates sellest aknapunktist.
Ekraanile esitatud andmed võivad olla normaalse heledusega, heledamad või tumedamad. Heledusega näidatakse tavaliselt teksti, mis omab mingit erilist tähendust. Funktsioonid normvideo(), highvideo() ja lowvideo() muudavad järgnevalt väljastatava teksti heldust.
void normvideo( void ); void highvideo( void ); void lowvideo( void );
Funktsioon highvideo() muudab temaga väljastatava teksti heledamaks, lowvideo() muudab selle tumedamaks ja normvideo() taastab hariliku heleduse.
Tekstirezhiimis kasutatakse kahte värvi: eesplaani - ja tagaplaani värvi. Eesplaani värviga esitatakse sümbolid ja tagaplaani värviga täidetakse sümbolite vahed. Need värvid võivad olla erinevad iga ekraanile esitatava sümboli jaoks. Nende värvide muutmiseks kasutatakse funktsioone textcolor(), textbackground() ja textattr().
void textcolor(int newcolor); void textbackground(int newcolor); void textattr(int newattr);
Sümbolid reserveerivad ekraanimälus kaks baiti. Esimene neist sisaldab sümboli atribuudi ja teine tema ASCII koodi. Sümboli atribuut määrab nii sümboli eesplaani kui ka tagaplaani värvi ning selle, kas sümbol vilgub või mitte. Joonisel 10 näete sümboli atribuudi bittide tähendust.

Joonis 10: Ekraanile kuvatud sümboli atribuudi bittide tähendused
Nagu näete, on eesplaani värvi määramiseks 4 bitti, aga tagaplaani värvuse jaoks vaid 3 bitti. Seega saab määrata kuni 16 erinevat eesplaani ja 8 tagaplaani värvi. Kui atribuudi viimane bitt on 1, siis tekst vilgub ekraanil. Te võite soovitud andmed seada korraga funktsiooniga textattr() või kasutada funktsioone textcolor() ja textbackground() ning värvide määramiseks failis CONIO.H defineerituid sümboolseid konstante. Neid konstante näete tabelis 13.
| Konstant | Number | Tähendus |
|---|---|---|
| BLACK | 0 | Must. Sobib nii ees- kui tagaplaani jaoks. |
| BLUE | 1 | Sinine. Sobib nii ees- kui tagaplaani jaoks. |
| GREEN | 2 | Roheline. Sobib nii ees- kui tagaplaani jaoks. |
| CYAN | 3 | Tumelilla. Sobib nii ees- kui tagaplaani jaoks. |
| RED | 4 | Punane. Sobib nii ees- kui tagaplaani jaoks. |
| MAGENTA | 5 | Roosa. Sobib nii ees- kui tagaplaani jaoks. |
| BROWN | 6 | Pruun. Sobib nii ees- kui tagaplaani jaoks. |
| LIGHTGRAY | 7 | Helehall. Sobib nii ees- kui tagaplaani jaoks. |
| DARKGRAY | 8 | Tumehall. Sobib ainult eesplaani jaoks. |
| LIGHTBLUE | 9 | Helesinine. Sobib ainult eesplaani jaoks. |
| LIGHTGREEN | 10 | Heleroheline. Sobib ainult eesplaani jaoks. |
| LIGHTCYAN | 11 | Helelilla. Sobib ainult eesplaani jaoks. |
| LIGHTRED | 12 | Helepunane. Sobib ainult eesplaani jaoks. |
| LIGHTMAGENTA | 13 | Heleroosa. Sobib ainult eesplaani jaoks. |
| YELLOW | 14 | Kollane. Sobib ainult eesplaani jaoks. |
| WHITE | 15 | Valge. Sobib ainult eesplaani jaoks. |
| BLINK | 128 | Vilkuv. Sümboli muutmiseks vilkuvaks liitke see konstant eesplaanivärvusele . |
Tabel 13: Sümboolsed konstandid tekstivärvuse määramiseks
Niimoodi määratud värvused kehtivad kõigile järgnevalt väljastatavatele andmetele. Iga kord, kui soovite väljastada andmeid teiste värvidega, peate neid muutma ja hiljem jälle tagasi muutma.
Hetkeliste värvuste, atribuudi jms. teada saamiseks kasutage funktsiooni gettextinfo().
void gettextinfo(struct text_info *andmed);
Selle funktsiooni ainus parameeter osutab andmestruktuurile textinfo, kuhu vajalikud andmed salvestatakse.
struct text_info {
unsigned char winleft; /* akna vasak piir (x1) */
unsigned char wintop; /* akna ülemine piir (y1) */
unsigned char winright; /* akna parempoolne piir (x2) */
unsigned char winbottom; /* akna alumine piir (y2) */
unsigned char attribute; /* teksti atribuut */
unsigned char normattr; /* harilik atribuut */
unsigned char currmode; /* hetkeline tekstirezhiim:
BW40, BW80, C40, C80, või C4350 */
unsigned char screenheight; /* ekraani kõrgus */
unsigned char screenwidth; /* ekraani laius */
unsigned char curx; /* hetkeline X koordinaat */
unsigned char cury; /* hetkeline Y koordinaat */
};
Selle sturktuuri element currmode näitab, millises tekstirezhiimis ekraan parajasti asub. Tekstirezhiimid erinevad lubatud värvuste ja korraga esitatavate sümbolite hulga poolest. Järgmises tabelis näete teksti kuvamisrezhiimide lühiiseloomustust.
| Tekstirezhiim | Omadused |
|---|---|
| BW40 | Mustvalge rezhiim. Ekraanile mahub 25 rida, igas 40 sümbolit. See rezhiim on tüüpiline CGA monitoridele. |
| BW80 | Mustvalge rezhiim. Ekraanile mahub 25 rida, igas 80 sümbolit. See rezhiim on tüüpiline mustvalgetele EGA ja VGA monitoridele. |
| C40 | Värviline rezhiim. Ekraanile mahub 25 rida, igas 40 sümbolit. |
| C80 | Värviline rezhiim. Ekraanile mahub 25 rida, igas 80 sümbolit. |
| C4350 | Värviline rezhiim. Ekraanile mahub 43 (EGA) või 50 (VGA) rida, igas 80 sümbolit. |
| LASTMODE | Viimatikasutatud tekstirezhiim. |
Tabel 14 : Tekstirezhiimide omadused
Nimetatud tekstirezhiime saate valida funktsiooniga textmode().
void textmode(int newmode);
Funktsioon viib ekraani soovitud tekstirezhiimi (kui antud monitor seda suudab) ja taastab harilikud tekstiatribuudid. Seejuures määratakse selline aken, mis hõlmab tervet ekraani, määratakse harilik tekstiheledus (nagu funktsiooniga normvideo()) ja harilikud värvid. Seda funktsiooni tohib kasutada vaid siis, kui ekraan on juba tekstirezhiimis. Kui te olete enne viinud ekraani graafilisse rezhiimi, siis tuleb kõigepealt taastada tekstirezhiim funktsiooniga restorecrtmode() ja alles siis kasutada funktsiooni textmode().
Päisefail CONIO.H sisaldab ka rohkesti funktsioone ekraani osaliseks või täielikuks puhastamiseks.
void clrscr( void ); void clreol( void ); void delline( void );
Funktsioon clrscr() puhastab kogu hetkelise akna sisu. Funktsioon clreol() puhastab ekraani hetkelisest positsioonist kuni rea lõpuni, nihutamata seejuures hetkelist positsiooni. Funktsioon delline() puhastab kogu hetkelise rea ja nihutab alumisi ridu ühe rea võrra ülespoole.
Funktsioon insline() seevastu sisestab hetkelisele positsioonile uue tühja rea ja nihutab kõik ülejäänud read ühe võrra allapoole.
void insline( void );
Üksiku sümboli lugemiseks klaviatuurilt kasutage funktsioone getch() ja getche().
int getch( void ); int getche( void );
Mõlemad funktsioonid loevad üheainsa sümboli otse klaviatuurilt, kuid funktsioon getche() väljastab loetud sümboli ekraanile ja funktsioon getch() mitte. Kui see sümbol osutus ebavajalikuks või teda on vaja uuesti töödelda, siis võib ühe sümboli funktsiooniga ungetch() "klaviatuurile taastada" .
int ungetch(int ch);
See funktsioon salvestab talle üleantud sümboli eraldi puhvris, nii et järgmine funktsioon getch() või getche() loovutab just selle sümboli. Nii saab salvestada aga ainult ühe sümboli. Seda funktsiooni kasutatakse sageli näiteks translaatorite loomisel.
Funktsioon kbhit() uurib, kas kasutaja on vajutanud mingile klahvile, kuid ei eemalda seda sümbolit operatsioonisüsteemi vastavast puhvrist.
int kbhit( void );
Kui te teate, et kasutaja on vajutanud mingile klahvile, siis võite selle sümboli lugeda funktsiooniga getch() või getche(). Nii võite luua tsükli, mis kontrollib, kas mingit klahvi on vajutatud ja alles seejärel loeb selle sümboli klaviatuuri- puhvrist.
Ühe sümboli väljastamiseks ekraanile kasutage funktsiooni putch().
int putch(int ch);
Selleks, et lihtsustada ekraanile mitmete nihutatavate akende moodustamist, sisaldab Borland C/C++ ka funktsioone gettext() ja puttext().
int puttext(int x1, int y1, int x2, int y2, const char *puhver); int gettext(int x1, int y1, int x2, int y2, char *puhver);
Funktsioon gettext() kopeerib ekraaniristküliku (x1, y1) (x2, y2) parameetri puhver poolt osutatud puhvrisse. Iga sümboli jaoks on vaja 2 baiti (tähe kood ja atribuut). Puhver peab seega mahutama ((x2 - x1) * (y2 - y1)) * 2 baiti. Kopeeritud andmed salvestatakse puhvrisse järjestikku rida rea järel. Funktsioon puttext() kopeerib sellise puhvri sisu uuesti ekraanile. Kui iga aken salvestab oma tagapõhja enne selle muutmist ja taastab ta ekraanilt kustutamisel, siis saab neid aknaid ekraanil nihutada ilma seda muutmata. Seda aga vaid tingimusel, et aknad ei kattu või et selline teisi aknaid varjav aken saab ekraanil viibida vaid ajutiselt (dialoog).
Päisefailis CONIO.H on defineeritud ka funktsioonid sisend- ja väljundportide kasutamiseks. Neid porte ei tohi ära vahetada järjestikuste ja paralleelsete portidega (COM1 ... COM4, LPT, LPT2). Arvuti protsessor on otseselt seotud vaid mäluga. Kõigi sisend- ja väljundseadmetega on aga protsessor seotud portide kaudu. Nii on ka graafikakaart, kettaajurite kontroller jms. seotud teatud portidega. Pordid on nummerdatud. Arvuti omab 256 porti. Port on nagu teatud kindel aadress, mille väljastatud andmed antakse üle temaga seotud seadmele. Tavaliselt ei vaja te otsest portidele väljastamist või neilt lugemist. Hiire kasutamine nõuab andmete lugemist pordilt (mis on omakorda sisend- väljundkontrolleri kaudu seotud ühe järjestikulise pordiga). Kogu selle töö teeb aga hiire ohjurprogramm. Nii on hiire kasutamiseks küllaldane ohjurprogrammi funktsioonide kasutamine kindlate katkestuste abil
int inp(unsigned portno); unsigned inpw(unsigned portno); int outp(unsigned portno, int value); unsigned outpw(unsigned portno, unsigned value);