Главная · Поиск книг · Поступления книг · Top 40 · Форумы · Ссылки · Читатели

Настройка текста
Перенос строк


    Прохождения игр    
Demon's Souls |#13| Storm King
Demon's Souls |#11| Мaneater part 2
Demon's Souls |#10| Мaneater (part 1)
Demon's Souls |#9| Heart of surprises

Другие игры...


liveinternet.ru: показано число просмотров за 24 часа, посетителей за 24 часа и за сегодня
Rambler's Top100
Образование - Богатырев А. Весь текст 1009.15 Kb

Хрестоматия по программированию на Си в Unix

Предыдущая страница Следующая страница
1 ... 64 65 66 67 68 69 70  71 72 73 74 75 76 77 ... 87
который при поступлении кода 033 начинает ожидать составную последовательность  -  мы
должны  выставлять таймаут, например alarm(1); и если по его истечении больше никаких
символов не поступило - выдавать код 033 как код клавиши Esc.
     Напишите распознаватель кодов, поступающих с клавиатуры. Коды обычных букв выда-
вать  как  есть  (0..0377),  коды  функциональных  клавиш выдавать как числа >= 0400.
Учтите, что разные типы дисплеев посылают разные последовательности от одних и тех же
функциональных  клавиш: предусмотрите настройку на систему команд ДАННОГО дисплея при
помощи библиотеки termcap. Распознаватель удобно строить при помощи сравнения  посту-
пающих  символов  с  ветвями дерева (спускаясь по нужной ветви дерева при поступлении
очередного символа. Как только достигли листа дерева -  возвращаем  код,  приписанный
этому листу):

    ---> '\033' ---> '[' ---> 'A' --> выдать 0400
                |        \--> 'B' -->        0401
                |        \--> 'C' -->        0402
                |        \--> 'D' -->        0403
                \--> 'X' ----------->        0404
                          ...

Нужное дерево стройте при настройке на систему команд данного дисплея.
     Библиотека curses уже имеет такой встроенный  распознаватель.   Чтобы  составные
последовательности склеивались в специальные коды, вы должны установить режим keypad:

    int c; WINDOW *window;
           ...
    keypad(window, TRUE);
           ...
    c = wgetch(window);

Без этого wgetch() считывает все символы поодиночке.   Символические  названия  кодов
для  функциональных  клавиш  перечислены в  и имеют вид KEY_LEFT, KEY_RIGHT
и.т.п.  Если вы работаете с единственным окном размером с весь экран, то  в  качестве
параметра  window вы должны использовать стандартное окно stdscr (это имя предопреде-
лено в include-файле curses.h).

    # ======================================== Makefile для getch
    getch: getch.o
            cc getch.o -o getch -ltermlib

    getch.o: getch.c getch.h
            cc -g -DUSG -c getch.c

А. Богатырев, 1992-95                  - 372 -                              Си в UNIX

    /* Разбор составных последовательностей клавиш с клавиатуры.  */
    /* ================================================== getch.h */
    #define FALSE   0
    #define TRUE    1
    #define BOOLEAN unsigned char
    #define INPUT_CHANNEL   0
    #define OUTPUT_CHANNEL  1

    #define KEY_DOWN      0400
    #define KEY_UP        0401
    #define KEY_LEFT      0402
    #define KEY_RIGHT     0403

    #define KEY_PGDN      0404
    #define KEY_PGUP      0405

    #define KEY_HOME      0406
    #define KEY_END       0407

    #define KEY_BACKSPACE 0410
    #define KEY_BACKTAB   0411

    #define KEY_DC        0412
    #define KEY_IC        0413

    #define KEY_DL        0414
    #define KEY_IL        0415

    #define KEY_F(n)      (0416+n)

    #define ESC           ' 33'

    extern char *tgetstr();

    void _put(char c);
    void _puts(char *s);
    void keyboard_access_denied(void);
    char *strdup(const char *s);
    void keyinit(void);
    int getc_raw(void);
    void keyreset(void);
    int getch(void);
    int lgetch(BOOLEAN);
    int ggetch(BOOLEAN);
    int kgetch(void);
    void _sigalrm(int n);
    void init_keytry(void);
    void add_to_try(char *str, short code);
    void keypad_on(void);
    void keypad_off(void);
    int dotest(void);
    void tinit(void);
    void main(void);

А. Богатырев, 1992-95                  - 373 -                              Си в UNIX

    /* ===================================================== getch.c
     *      The source version of getch.c file was
     *      written by Pavel Curtis.
     *
     */

    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include "getch.h"

    #define keypad_local   S[0]
    #define keypad_xmit    S[1]

    #define key_backspace  S[2]
    #define key_backtab    S[3]

    #define key_left       S[4]
    #define key_right      S[5]
    #define key_up         S[6]
    #define key_down       S[7]

    #define key_ic         S[8]
    #define key_dc         S[9]
    #define key_il        S[10]
    #define key_dl        S[11]

    #define key_f1        S[12]
    #define key_f2        S[13]
    #define key_f3        S[14]
    #define key_f4        S[15]
    #define key_f5        S[16]
    #define key_f6        S[17]
    #define key_f7        S[18]
    #define key_f8        S[19]
    #define key_f9        S[20]
    #define key_f10       S[21]     /*  f0 */
    #define key_f11       S[22]     /* f11 */
    #define key_f12       S[23]     /* f12 */
    #define key_home      S[24]
    #define key_end       S[25]
    #define key_npage     S[26]
    #define key_ppage     S[27]

    #define TOTAL 28

А. Богатырев, 1992-95                  - 374 -                              Си в UNIX

    /* descriptors for keys */
    char *KEYS[TOTAL+1] = {
            "ke", "ks",

            "kb", "kB",
            "kl", "kr", "ku", "kd",
            "kI", "kD", "kA", "kL",

            "f1", "f2", "f3", "f4", "f5",
            "f6", "f7", "f8", "f9", "f0",
            "f.", "f-",

            "kh", "kH", "kN", "kP",

            NULL

    }, *S[TOTAL];

    void _put (char c)  { write( INPUT_CHANNEL, &c, 1 ); }
    void _puts(char *s) { tputs ( s, 1, _put ); }

    static int  _backcnt = 0;
    static char _backbuf[30];

    static struct try {
            struct try *child;
            struct try *sibling;
            char ch;
            short value;
    }       *_keytry;

    BOOLEAN keypadok = FALSE;

    struct termios new_modes;

    void keyboard_access_denied(){ printf( "Клавиатура недоступна.\n" ); exit(1); }
    char *strdup(const char *s)  { return strcpy((char *) malloc(strlen(s)+1), s); }

А. Богатырев, 1992-95                  - 375 -                              Си в UNIX

    /* Инициализация таблицы строк */
    void keyinit(){
            char *key, nkey[80], *p;
            register i;

            keyreset();
            for( i=0; i < TOTAL; i++ ){
                    p = nkey;
                    printf("tgetstr(%s)...", KEYS[i]);
                    key = tgetstr(KEYS[i], &p);

                    if(S[i]) free(S[i]);
                    if(key == NULL){
                            S[i] = NULL;   /* No such key */
                            printf("клавиша не определена.\n");
                    }else{
                            /* Decrypted string */
                            S[i] = strdup(key);
                            printf("считано.\n");
                    }
            }

            init_keytry();
            if( tcgetattr(INPUT_CHANNEL, &new_modes) < 0 ){
                    keyboard_access_denied();
            }

            /* input flags */

            /* отменить преобразование кода '\r' в '\n' на вводе */
            new_modes.c_iflag &= ~ICRNL;
            if ((new_modes.c_cflag & CSIZE) == CS8)  /* 8-битный код */
                 new_modes.c_iflag &= ~ISTRIP;       /* отменить & 0177 на вводе */

            /* output flags */

            /* отменить TAB3 - замену табуляций '\t' на пробелы */
            /* отменить ONLCR - замену '\n' на пару '\r\n' на выводе */
            new_modes.c_oflag &= ~(TAB3 | ONLCR);

            /* local flags */

            /* выключить режим ICANON, включить CBREAK */
            /* выключить эхоотображение набираемых символов */
            new_modes.c_lflag &= ~(ICANON | ECHO);

            /* control chars */      /* при вводе с клавиш ждать не более ... */
            new_modes.c_cc[VMIN]  = 1;  /* 1 символа и */
            new_modes.c_cc[VTIME] = 0;  /* 0 секунд    */
            /* Это соответствует режиму CBREAK */

            /* Символы, нажатие которых заставляет драйвер терминала послать сигнал
             * либо отредактировать набранную строку. Значение 0 означает,
             * что соответствующего символа не будет */
            new_modes.c_cc[VINTR]  = '\0'; /* символ, генерящий SIGINT  */
            new_modes.c_cc[VQUIT]  = '\0'; /* символ, генерящий SIGQUIT */
            new_modes.c_cc[VERASE] = '\0'; /* забой (отмена последнего символа)*/
            new_modes.c_cc[VKILL]  = '\0'; /* символ отмены строки      */
    }

А. Богатырев, 1992-95                  - 376 -                              Си в UNIX

    /* Чтение одного символа непосредственно с клавиатуры */
    int getc_raw(){
            int n; char c;

            n = read(INPUT_CHANNEL, &c, 1);
            if (n <= 0) return EOF;
            return (c & 0xFF);
    }

    static BOOLEAN  _getback  = FALSE;
    static char     _backchar = '\0';

    /* Чтение символа - либо из буфера (если не пуст), либо с клавиатуры */
    #define nextc()       (_backcnt > 0  ?  _backbuf[--_backcnt]         : \
                           _getback      ?  _getback = FALSE, _backchar  : \
                                             getc_raw())

    #define putback(ch)   _backbuf[_backcnt++] = ch

    void keyreset(){
            _backcnt = 0; _backchar = '\0';
            _getback = FALSE;
    }

    /* Функция чтения составного символа */
    int getch(){
            int c = lgetch(TRUE);
            keypad_off();
            return c;
    }

    /*
            ВНИМАНИЕ!
                    Если в процессе будет получен сигнал,
                    в то время как процесс находится внутри вызова getch(),
                    то системный вызов read() вернет 0 и errno == EINTR.
                    В этом случае getch() вернет '\0'.
                    Чтобы избежать этой ситуации используется функция lgetch()
    */
    int lgetch(BOOLEAN kpad) {
            int c;

            while((c = ggetch(kpad)) <= 0);
            return c;
    }

    int ggetch(BOOLEAN kpad) {
            int kgetch();

            if( kpad ) keypad_on();
            else       keypad_off();

            return keypadok ? kgetch() : nextc();
    }

А. Богатырев, 1992-95                  - 377 -                              Си в UNIX

    /*
    **      int kgetch()
    **
    **      Get an input character, but take care of keypad sequences, returning
    **      an appropriate code when one matches the input.  After each character
    **      is received, set a one-second alarm call.  If no more of the sequence
    **      is received by the time the alarm goes off, pass through the sequence
    **      gotten so far.
    **
    */

    #define CRNL(c)    (((c) == '\r') ? '\n' : (c))

    /* борьба с русской клавиатурой */
    #if !defined(XENIX) || defined(VENIX)
    # define unify(c) ( (c)&(( (c)&0100 ) ? ~0240 : 0377 ))
    #else
    # define unify(c) (c)
    #endif

А. Богатырев, 1992-95                  - 378 -                              Си в UNIX

    /* ==================================================================== */
    #if !defined(XENIX) && !defined(USG) && !defined(M_UNIX) && !defined(unix)

            /* Для семейства BSD */

    static BOOLEAN   alarmed;
    jmp_buf          jbuf;

    int kgetch()
    {
            register struct try  *ptr;
            int         ch;
            char        buffer[10];     /* Assume no sequences longer than 10 */
            register char        *bufp = buffer;
            void        (*oldsig)();
            void         _sigalrm();

            ptr = _keytry;

            oldsig = signal(SIGALRM, _sigalrm);
            alarmed = FALSE;

            if( setjmp( jbuf )) /* чтоб свалиться сюда с read-а */
Предыдущая страница Следующая страница
1 ... 64 65 66 67 68 69 70  71 72 73 74 75 76 77 ... 87
Ваша оценка:
Комментарий:
  Подпись:
(Чтобы комментарии всегда подписывались Вашим именем, можете зарегистрироваться в Клубе читателей)
  Сайт:
 

Реклама