Úvod do programovania v jazyku C

Doc. Ing. Pavel Horovčák, CSc., Prof. RNDr. Igor Podlubný, CSc.

Táto on-line príručka vznikla v rámci riešenia výskumného projektu KEGA č. 112/97 "uniWWWerzita"

  1. Úvod
  2. Preprocesor jazyka C
  3. Premenné
  4. Lexikálne prvky jazyka
  5. Riadiace štruktúry
  6. Štandardný vstup a výstup
  7. Reťazce
  8. Súbory
  9. Smerníky
  10. Datové štruktúry
  11. Triedenie
  12. Terminálové funkcie (QNX)
  13. Doporučená literatúra

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;
}