12 Terminálové funkcie (QNX)
Sú určené pre prácu v textovom režime pod OS QNX na realizáciu "oknových techník". Predstavujú určitú analógiu funkcií jednotky CRT v Turbo Pascale. Z hľadiska normy jazyka C to nie sú štandardné funkcie, preto ich prenositeľnosť medzi systémami a kompilátormi nie je zaručená. Jednotlivé terminálové funkcie sú podrobne popísané v knižnici jazyka C86. Ich spoločným znakom je to, že ich názvy sa vždy začínajú predponou term.
S celou skupinou terminálových funkcií sú spojené dve inicializačné funkcie. Funkcia term_load načítava charakteristiky terminálu z tabuľky (/config/tcap.dbase). Tieto charakteristiky zahrňujú aj niektoré Escape postupnosti pre zefektívnenie práce terminálu (napr. čistenie obrazovky). Môžu obsahovať aj údaje o rozšírenom súbore znakov.
Druhá funkcia term_video_on vykonáva inicializáciu premenných a alokáciu bufrov, používaných ostatnými terminálovými fukciami. Prítomnosť týchto bufrov umožňuje "čítanie z obrazovky" (napr. funkcie term_save_image, term_get_line). Po vyvolaní funkcie term_video_on môže program užívať iba terminálové funkcie, až dokedy neobnovíme pôvodný režim obrazovky (obyčajne na konci programu).
Viacero terminálových funkcií vyžaduje vypnutie nastavenia ECHO a EDIT na terminále, čo možno vykonať napr. takto:
stary_stav = get_option(stdin); set_option(stdin,stary_stav & ~(EDIT | EDIT));
Po ukončení práce s terminálovými funkciami je potrebné definovať východzí stav
set_option(stary_stav);
Orientácia riadkov a stĺpcov na obrazovke je daná tým, že horný riadok a ľavý stĺpec sú číslované ako 0. *Nie všetky terminály vracajú kurzor po čistení obrazovky do tohoto bodu. V mnohých terminálových funkciách sa užíva parameter argument s týmto významom jednotlivých bitov:
e enable color farba
bc background color farba pozadia
fc forground color farba popredia
p position cursor
at end of text kurzor na koniec textu
f flush after output vyprázdniť po výstupe
u underline podčiarknúť
i inverse video inerzia
h highlight zvýraznenie
b blink blikanie
Nie všetky atribúty (bity) je možné použiť pre každú funkciu (viď popis funkcií C86). Priradenie farieb je následovné
0 black čierna
1 blue modrá
2 green zelená
3 cyan fialová
4 red červená
5 magenta svetlomodrá
6 yellow žltá
7 white biela
Na termináloch sú podporované iba farby popredia, na konzolách všetky. Príklad p11_1.c ilustruje niekoľko terminálových funkcií - pre menu, text v okne, blikanie, uloženie časti obrazovky do bufra a jej vrátenie. Prácu s menu pozri tiež v príklade pop.c v adresári cii/samples, z ktorého je aj náš príklad odvodený.
/* priklad p11_1.c
** pop - popup window demonstration program
** Copyright 1986 by Quantum Software Systems, Ltd.
** Copyright 1989 by Computer Innovations, Inc.
** ukazka menu,nadpis,inicializacia,okno,text v okne,blikanie */
#include <STDIO.H>
#include <DEV.H>
#include <TCAP.H>
#include <STDLIB.H>
#include <STRING.H>
#define MAX_SCREENS 5
/* maximum # of screens that can be saved */
struct screen_save {/* structure to contain saved windows */
int cursor_x, cursor_y;
int x, y, width, length;
char *data;
};
int blik=0; /* prepinac na blikanie */
int bytes=0; /* # of bytes / saved character */
int top_screen=0; /* number of top window */
struct screen_save screens[MAX_SCREENS];
/* array of saved screens */
unsigned ef=4<<12|7<<8|1<<3|1|0x8000, nf=7<<12|0<<8|0x8000,pf;
char *a_menu[]={ "Init ","Okno ", "Prikaz_okno ", "Text ", "VText/prikaz ", "Blik ", "Quit ", NULL };
char *b_menu[]={ "Ayyy ", "Byyy ", "Cyyy ", "Dyyy ", "Eyyy ", "Quit ", NULL };
char *c_menu[]={ "Azzz ", "Bzzz ", "Czzz ", "Dzzz ", "Ezzz ", "Quit ", NULL };
/* prototypes for the support functions */
void submenu1(char ch, int row);
void submenu2(char ch, int row);
void pop_up(int y, int x, int width, int length, unsigned attr);
void pop_down(void);
int main(int argc, char **argv)
{
char *cp;
if(!term_load(stdout))
error( "pop: Unable to load tcap entry.\n");
term_video_on(); /* enable terminal shadow image */
term_colour(0x17); /* set screen colors (white on blue)*/
if(!strcmp(tcap_entry.term_name, "qnx")){
fput("\033!71\033@71",8,stdout);
fflush(stdout);
}
term_clear(_CLS_SCRH);
/* set screen buffer to a known state */
set_option(stdin, get_option(stdin) & ~(EDIT|ECHO));
term_printf(1,5,nf,
"UKAZKA ZAKLADNYCH PRINCIPOV
PRACE S <TERM_...> FUNCIAMI");
pop_up(3, 7, 59, 3, 0xb102); /* uloz vyrez pre menu */
cp=*a_menu;
for(;;){
cp=term_menu(4, 9, a_menu, cp, 0xb100, NULL, 1);
if((*cp=='Q')||(cp==NULL)) break;
else /*submenu1(*cp, 5+*cp-'A'); */
{
if(*cp=='B'){ if(blik==0){pf=ef;blik=1;}
else {pf=nf;blik=0;}
term_printf(1,5,pf,
"UKAZKA ZAKLADNYCH PRINCIPOV
PRACE S <TERM_...> FUNCIAMI");
}
if(*cp=='I') {
pop_up(7, 5, 73, 7, 0xe402); /* uloz vyrez Init*/
term_box_fill(7,5,73,7,6<<12|7<<8|0x8000,1,219);
term_printf(8,7,7<<12|0<<8|0x8000,
"if(!term_load(stdout))
error( \"pop: Unable to load tcap entry.\\n\");");
term_printf(9,7,7<<12|0<<8|0x8000,
"term_video_on(); /* enable terminal shadow image */ ");
term_printf(10,7,7<<12|0<<8|0x8000,
"term_colour(0x17);
/* set screen colors (white on blue) */ ");
term_printf(11,7,7<<12|0<<8|0x8000,
"term_clear(_CLS_SCRH);
/* set screen buffer to a known state */");
term_printf(12,7,7<<12|0<<8|0x8000,
"set_option(stdin,
get_option(stdin) & ~(EDIT|ECHO));");
}
if(*cp=='O') {
pop_down(); /* obnov vyrez - (zrus) Init */
term_box_fill(15,5,20,4,7<<12|7<<8|0x8000,1,219);
}
if(*cp=='P') {
term_box_fill(15,28,50,3,7<<12|7<<8|0x8000,1,219);
term_printf(16,29,7<<12|0<<8|0x8000,
"term_box_fill(15,5,20,4,7<<12|7<<8|0x8000,1,219);");
}
if(*cp=='T') {
term_box_fill(20,5,16,4,5<<12|7<<8|0x8000,1,219);
term_printf(21,6,7<<12|0<<8|0x8000,"Tu som v okne");
}
if(*cp=='V') {
term_box_fill(20,23,55,4,5<<12|7<<8|0x8000,1,219);
term_printf(21,25,7<<12|0<<8|0x8000,
"term_box_fill(20,5,16,4,5<<12|7<<8|0x8000,1,219);");
term_printf(22,25,7<<12|0<<8|0x8000,
"term_printf(21,6,7<<12|0<<8|0x8000,
\"Tu som v okne\");");
}
}
}
pop_down(); /* obnov vyrez pod menu */
if(!strcmp(tcap_entry.term_name, "qnx"))
fput("\033R", 2, stdout);
/* restore original screen colours */
term_clear(_CLS_SCRH);
return 0;
}
void submenu1(char ch, int row)
{
char *cp;
pop_up(row, 13, 20, 8, 0xe402);
cp=*b_menu;
term_type(row, 15, &ch, 1, 0xe402);
for(;;){
cp=term_lmenu(row+1, 15, b_menu, cp, 0xe400, NULL, 1);
if((*cp=='Q')||(cp==NULL)) break;
else submenu2(*cp, row+*cp-'A'+2);
}
pop_down();
}
void submenu2(char ch, int row)
{
char *cp;
pop_up(row, 18, 20, 8, 0xf102);
cp=*c_menu;
term_type(row, 20, &ch, 1, 0xf102);
for(;;){
cp=term_lmenu(row+1, 20, c_menu, cp, 0xf100, NULL, 1);
if((*cp=='Q')||(cp==NULL)) break;
}
pop_down();
}
void pop_up(int y, int x, int width, int length,
unsigned attr)
{
int i;
struct screen_save *s;
char *p;
struct state_entry vstate;
unsigned offset;
if(top_screen>=MAX_SCREENS)
error("pop: Not enough screen buffers.\n");
if(!bytes){
bytes=term_save_image(0, 0, NULL, 0);
memset(screens, 0, sizeof(screens));
}
offset=width*bytes;
term_get_state(&vstate);
if((screens[top_screen].data=calloc(offset,length))==NULL)
error( "pop: Out of memory\n" );
s=&screens[top_screen];
s->cursor_x=vstate.state_cursor_x;
s->cursor_y=vstate.state_cursor_y;
s->x=x;
s->length=length;
s->y=y;
s->width=width;
p=s->data;
for(i=y; i<LENGTH+Y; p="s-" s="&screens[top_screen];" buffer.\n?); screen unused restore to Attempt error(?pop: if(screens[top_screen].data="=NULL)" screens\n?); many too Restored if(--top_screen<0) offset; length, width, y, x, unsigned *p; char *s; screen_save struct i; int { pop_down() void } ?); ? _BOX_FRAME, attr, term_box_fill(y, ++top_screen; p+="offset;" width); p, term_save_image(i, * window the of line each save ++i){>data;
x=s->x;
y=s->y;
length=s->length;
width=s->width;
offset=width*bytes;
for(i=y; i<Y+LENGTH; restore x, } p+="offset;" width); p, * window the of line each ++i){ term_cur(s- term_restore_image(i,>cursor_y, s->cursor_x);
free(s->data);
s->data=NULL;
}