Хрестоматия по программированию на Си в Unix
* по longjmp( cs_stack, code ); где code != 0
*/
interrupt( code ); /* пришло прерывание */
} /* else setjmp() возвращает 0,
* если это УСТАНОВКА контрольной точки (то есть
* сохранение регистров SP, PC и других в буфер cs_stack),
* а не прыжок на нее.
*/
signal( SIGINT, sig_vec ); /* вызывать по прерыванию */
if( killable ){
killable = 0;
fprintf( stderr,
"\7Теперь сигналы INTR обрабатываются особым образом\n\n\n" );
}
body(); /* основная программа */
}
}
body(){
static int n = 0; int i;
fprintf( stderr, "\tВошли в тело %d-ый раз\n", ++n );
ecs();
for( i=0; i < 10 ; i++ ){
fprintf( stderr, "- %d\n",i); Delay();
}
lcs();
for( i=0; i < 10 ; i++ ){
fprintf( stderr, "+ %d\n",i); Delay();
}
}
/* запоминание полученных сигналов */
void sig_vec(nsig){
if( in_cs ){ /* we're in critical section */
#ifdef IGN
signal( SIGINT, SIG_IGN ); /* игнорировать */
fprintf( stderr, "Дальнейшие прерывания будут игнорироваться\n" );
#else
signal( SIGINT, sig_vec );
fprintf( stderr, "Дальнейшие прерывания будут подсчитываться\n" );
#endif
fprintf( stderr, "Получен сигнал и отложен\n" );
sig_recd++ ; /* signal received */
/* пометить, что сигнал пришел */
}else{
signal( SIGINT, sig_vec );
fprintf( stderr, "Получен разрешенный сигнал: прыгаем на рестарт\n" );
longjmp( cs_stack, 1);
}
}
ecs(){ /* enter critical section */
fprintf( stderr, "Откладываем прерывания\n" );
sig_recd = 0; in_cs = 1;
}
lcs(){ /* leave critical section */
fprintf( stderr, "Разрешаем прерывания\n" );
in_cs = 0;
if( sig_recd ){
fprintf( stderr,
"Прыгаем на рестарт, т.к. есть отложенный сигнал (%d раз)\n",
sig_recd );
sig_recd = 0;
signal( SIGINT, sig_vec );
longjmp( cs_stack, 2);
}
}
/* Пример 15 */
/* Команда для изменения скорости обмена в линии (baud).*/
/* Пример вызова в XENIX: baud /dev/tty1a 9600 */
/* /dev/tty1a - это коммуникационный последов. порт #1 */
/* Про управление модами терминала смотри man termio */
#include
#include
struct termio old, new; int fd = 2; /* stderr */
struct baudrate{ int speed; char *name;} br[] = {
{ B0, "HANGUP" }, { B1200, "1200" }, { B9600, "9600" },
{ B600, "600" }, { B2400, "2400" }, { EXTA, "19200" },
};
#define RATES (sizeof br/sizeof br[0])
main(ac, av) char *av[];
{ register i; char *newbaud;
if( ac == 3 ){
if((fd = open(av[1], O_RDWR)) < 0 ){
printf("Не могу открыть %s\n", av[1]); exit(1);
} newbaud = av[2];
} else newbaud = av[1];
if( ioctl(fd, TCGETA, &old) < 0 ){
printf("Попытка управлять не терминалом и не портом.\n");
exit(2);
}
if(newbaud == (char*)0) newbaud = "<не задано>";
new=old;
for(i=0; i < RATES; i++)
if((old.c_cflag & CBAUD) == br[i].speed) goto ok;
printf("Неизвестная скорость\n"); exit(3);
ok: printf("Было %s бод\n", br[i].name);
for(i=0; i < RATES; i++)
if( !strcmp(newbaud, br[i].name)){
new.c_cflag &= ~CBAUD; /* побитное "или" всех масок B... */
new.c_cflag |= br[i].speed;
if( ioctl(fd, TCSETA, &new) < 0) perror("ioctl");
/* Скорость обмена может не измениться, если терминал
* не открыт ни одним процессом (драйвер не инициализирован).
*/ exit(0);
}
printf("Неверная скорость %s\n", newbaud); exit(4);
}
/* Пример 16 */
/*#!/bin/cc -DUSG wins.c -o wins -lncurses -lx
Просмотр двух файлов в перекрывающихся окнах.
Редактирование содержимого окон.
*/
/* _______________________ файл wcur.h __________________________ */
#include "curses.h"
/* Макросы, зависимые от реализации curses */
/* число колонок и строк в окне: */
# define wcols(w) ((w)-> _maxx+1 )
# define wlines(w) ((w)-> _maxy+1 )
/* верхний левый угол окна: */
# define wbegx(w) ((w)-> _begx )
# define wbegy(w) ((w)-> _begy )
/* координаты курсора в окне: */
# define wcurx(w) ((w)-> _curx )
# define wcury(w) ((w)-> _cury )
/* доступ к памяти строк окна: */
# define wtext(w) ((w)-> _line) /* chtype **_line; */
/* в других реализациях: ((w)-> _y) */
/* Псевдографика: Для curses Для IBM PC MS DOS */
#define HOR_LINE '\200' /* 196 */
#define VER_LINE '\201' /* 179 */
#define UPPER_LEFT '\210' /* 218 */
#define LOWER_LEFT '\202' /* 192 */
#define UPPER_RIGHT '\212' /* 191 */
#define LOWER_RIGHT '\204' /* 217 */
#define LEFT_JOIN '\205' /* 195 */
#define RIGHT_JOIN '\207' /* 180 */
#define TOP_JOIN '\211' /* 194 */
#define BOTTOM_JOIN '\203' /* 193 */
#define MIDDLE_CROSS '\206' /* 197 */
#define BOX '\272' /* 219 */
#define BOX_HATCHED '\273' /* 177 */
#define LABEL '\274' /* 3 */
#define RIGHT_TRIANG '\234' /* 16 */
#define LEFT_TRIANG '\235' /* 17 */
#define YES 1
#define NO 0
#define MIN(a,b) (((a) < (b)) ? (a):(b))
#define MAX(a,b) (((a) > (b)) ? (a):(b))
#define A_ITALICS A_ALTCHARSET /* в этой версии curses-а - курсив */
#ifndef ESC
# define ESC '\033' /* escape */
#endif
#define ctrl(c) (c & 037)
/* перерисовка экрана */
#define RedrawScreen() { vidattr(curscr->_attrs = A_NORMAL); \
wrefresh(curscr); }
/* curscr - служебное окно - копия текущего состояния экрана дисплея
* для сравнения со сформированным НОВЫМ образом экрана - newscr.
* Поле _attrs в структуре окна содержит текущие атрибуты окна,
* именно это поле изменяется wattrset(), wattron(), wattroff();
*/
/* _______________________ файл wins.c __________________________ */
#include "wcur.h"
#include
WINDOW *wbase1, *wbase2; /* окна рамки (фоновые окна) */
WINDOW *w1, *w2; /* окна для текста */
/* Размеры и расположение окон */
/* COLS - предопределенная переменная: число колонок */
/* LINES - // - : число строк на экране */
#define W1ysize (LINES/2) /* высота */
#define W1xsize (COLS/3*2) /* ширина */
#define W1y 5 /* y верхнего левого угла на экране */
#define W1x 20 /* x верхнего левого угла на экране */
#define W2ysize (LINES/2)
#define W2xsize (COLS/3*2)
#define W2y 10
#define W2x 5
FILE *fp1, *fp2; /* просматриваемые файлы */
/* Завершить работу */
void die(sig){ /* аргумент - номер сигнала */
/* Восстановление режимов терминала */
echo(); /* эхо-отображение вводимых букв */
nocbreak(); /* ввод с системным редактированием строки */
mvcur( -1, -1, LINES-1, 0 ); /* курсор в нижн. левый угол */
endwin(); /* окончание работы с curses-ом */
putchar('\n');
exit(sig); /* завершение работы с кодом sig. 0 - успешно */
}
int run;
void stop(nsig){ signal(SIGINT, SIG_IGN); run = 0; beep(); }
char label[3][5] = { /* Демонстрация псевдографики */
{ UPPER_LEFT, TOP_JOIN, UPPER_RIGHT, HOR_LINE, '\0' },
{ LEFT_JOIN, MIDDLE_CROSS, RIGHT_JOIN, VER_LINE, '\0' },
{ LOWER_LEFT, BOTTOM_JOIN, LOWER_RIGHT, BOX, '\0' }
};
/* Нарисовать рамку, название и фон окна */
wborder( w, name ) WINDOW *w; char *name;
{ register i, j;
for(i=1; i < wlines(w)-1; i++ ){
/* поставить курсор и выдать символ */
mvwaddch(w, i, 0, VER_LINE );
/* mvwaddch(w,y,x,c) = wmove(w,y,x); waddch(w,c); */
/* wmove(w,y,x) - логич. курсор в позицию (y,x) */
/* waddch(w,c) - выдать символ в позиции курсора,
продвинуть курсор. Аналог putchar */
mvwaddch(w, i, wcols(w)-1, VER_LINE );
}
for(j=1; j < wcols(w)-1; j++ ){
mvwaddch(w, 0, j, HOR_LINE );
mvwaddch(w, wlines(w)-1, j, HOR_LINE );
} /* Углы */
mvwaddch(w, 0, 0, UPPER_LEFT);
mvwaddch(w, wlines(w)-1, 0, LOWER_LEFT);
mvwaddch(w, wlines(w)-1, wcols(w)-1, LOWER_RIGHT);
mvwaddch(w, 0, wcols(w)-1, UPPER_RIGHT);
/* Рисуем заголовки вверху и внизу на рамке.
* Заголовки выдаем в центре рамки.
*/
if( (j = (wcols(w) - strlen(name))/2 ) > 0 ){
/* логический курсор - в 0 строку, позицию j */
wmove(w, 0, j);
/* задать режимы выделений */
wattrset( w, A_BOLD | A_BLINK | A_REVERSE );
waddstr( w, name ); /* выдать строку в окно */
wmove( w, wlines(w)-1, j);
wattrset( w, A_ITALICS | A_STANDOUT );
waddstr ( w, name );
wattrset( w, A_NORMAL ); /* нормальные атрибуты */
}
}
/* режим редактирования текста в окнах */
int mode = 0; /* 0 - замена, 1 - вставка */
main( ac, av ) char **av;
{
char buffer[512];
int need1, need2;
int c; void (*save)();
WINDOW *w; /* активное окно */
if( ac < 3 ){
fprintf( stderr, "Вызов: %s file1 file2\n", av[0] );
exit( 1 );
}
if((fp1 = fopen( av[1], "r" )) == NULL ){
fprintf( stderr, "Не могу читать %s\n", av[1] );
exit( 2 );
}
if((fp2 = fopen( av[2], "r" )) == NULL ){
fprintf( stderr, "Не могу читать %s\n", av[2] );
exit( 2 );
}
/* Инициализировать curses */
initscr();
signal( SIGINT, die ); /* по ctrl/C - умереть */
signal( SIGQUIT,die );
/* Создать окна */
/* высота ширина Y и X верх.левого угла */
wbase1 = newwin( W1ysize, W1xsize, W1y, W1x);
if( wbase1 == NULL ){
fprintf( stderr, "Не могу создать wbase1\n" );
goto bad;
}
wbase2 = newwin( W2ysize, W2xsize, W2y, W2x);
if( wbase2 == NULL ){
fprintf( stderr, "Не могу создать wbase2\n" );
goto bad;
}
/* Создать подокна для текста */
/* база высота ширина Y угла X угла */
w1 = subwin( wbase1, W1ysize - 2, W1xsize - 2, W1y+1, W1x+1);
w2 = subwin( wbase2, W2ysize - 2, W2xsize - 2, W2y+1, W2x+1);
scrollok( w1, TRUE ); /* разрешить роллирование окон */
scrollok( w2, TRUE );
wattrset( w2, A_REVERSE ); /*установить атрибуты текста в окнах*/
wattrset( stdscr, A_STANDOUT );
wborder( wbase1, av[1] );
wborder( wbase2, av[2] ); /* рамки */
werase( w1 ); werase( w2 ); /* очистить окна */
/* фон экрана */
werase( stdscr );
/* функции без буквы w... работают с окном stdscr (весь экран) */
for(c=0; c < 3; c++)
mvwaddstr(stdscr, c, COLS-5, &label[c][0]);
move( 1, 10 ); addstr( "F1 - переключить окна" );
mvaddstr( 2, 10, "F5 - переключить режим вставки/замены" );